#include <stdint.h>
#include "am7202a.h"

void am7202a_reset(am7202a_t *fifo)
{
        fifo->wp = 0;
        fifo->rp = 0;
}

void am7202a_init(am7202a_t *fifo, void (*set_ef)(int state, void *p), void (*set_ff)(int state, void *p), void (*set_hf)(int state, void *p), void *p)
{
        fifo->p = p;
        fifo->set_ef = set_ef;
        fifo->set_ff = set_ff;
        fifo->set_hf = set_hf;

        am7202a_reset(fifo);
}

void am7202a_write(am7202a_t *fifo, uint16_t val)
{
        if ((fifo->wp - fifo->rp) == 1024) /*FIFO full?*/
                return;

        if (fifo->set_ef && fifo->wp == fifo->rp)
                fifo->set_ef(0, fifo->p); /*Clear empty flag*/

//        lark_log("am7202a_write: val=%02x rp=%03x wp=%03x\n", val, fifo->rp, fifo->wp);
        fifo->data[fifo->wp & 0x3ff] = val;
        fifo->wp++;
        
        if (fifo->set_ff && (fifo->wp - fifo->rp) == 1024)
                fifo->set_ff(1, fifo->p); /*Set full flag*/

        if (fifo->set_hf && (fifo->wp - fifo->rp) == 512)
                fifo->set_hf(1, fifo->p); /*Set half full flag*/
}

uint16_t am7202a_read(am7202a_t *fifo)
{
        uint16_t val;
        
        if (fifo->wp == fifo->rp)
                return 0; /*FIFO empty*/

        if (fifo->set_ff && (fifo->wp - fifo->rp) == 1024)
                fifo->set_ff(0, fifo->p); /*Clear full flag*/

        if (fifo->set_hf && (fifo->wp - fifo->rp) == 512)
                fifo->set_hf(0, fifo->p); /*Clear half full flag*/

        val = fifo->data[fifo->rp & 0x3ff];
//        lark_log("am7202a_read: val=%02x rp=%03x wp=%03x\n", val, fifo->rp, fifo->wp);
        fifo->rp++;

        if (fifo->set_ef && fifo->wp == fifo->rp)
                fifo->set_ef(1, fifo->p); /*Set empty flag*/

        return val;
}
