/**
  * @file ${obj.name.lower()}_slave.c
  * @author generated by mrt-device utility 
  * @link [https://github.com/uprev-mrt/mrtutils/wiki/mrt-device]
  * @brief Device driver for ${obj.name} device
  *
  */

#include "${obj.name.lower()}_slave.h"

${obj.name.lower()}_slave_t REGS; 

uint8_t* DATA = (uint8_t*)&REGS.mData;


static void go_to_register(addr_t addr)
{   
    addr_t i;
    REGS.mCurrentReg = 0;
    REGS.mCursor =  addr; 

    for( i = 0; i < ${obj.name.upper()}_REG_COUNT; i++)
    {
        if( addr < REGS.mRegs[i+1].mAddr)
        {
            REGS.mCurrentReg = &REGS.mRegs[i];     //Set current reg
        }
    }
}

static void slave_reg_init(slave_reg_t* reg, addr_t addr, addr_t size, uint8_t flags)
{
    reg->mAddr = addr;
    reg->mSize = size;
    reg->mFlags = flags;
}

/**
 * @brief initializes ${obj.name} slave registers
 * @param fifoDepth size of rxFifo to use
 */
void ${obj.prefix.lower()}_slave_init( )
{
 % for key,reg in obj.regs.items():
    slave_reg_init(&REGS.mRegs[${loop.index}],${reg.addr},${reg.size}, SLAVE_REG_PERM_${reg.perm} ); //${key}
    % if reg.hasDefault:
    REGS.mData.${"m" + obj.camelCase(reg.name)} = ${reg.getDefaultMacro(58)}; 
    % endif
% endfor    

    REGS.mCurrentReg = 0;
    REGS.mCursor = 0;
    REGS.mAddrBytes = 0;
    REGS.mState = SLAVE_STATE_ADDRESS;
    REGS.mFlags = 0;
}

/**
 * @brief feed byte into fifo
 * @param dev ptr to ${obj.name} device
 * @param data byte to feed 
 */
void ${obj.prefix.lower()}_slave_put( uint8_t data )
{
    switch (REGS.mState)
    {
        case SLAVE_STATE_ADDRESS:
            REGS.mAddress = (REGS.mAddress << 8) | data;
            REGS.mAddrBytes++;
            if(REGS.mAddrBytes == ${obj.name.upper()}_REG_ADDR_SIZE)
            {
                go_to_register(REGS.mAddress);
                REGS.mState = SLAVE_STATE_DATA;
            }
            break;
        case SLAVE_STATE_DATA:
            if(REGS.mCurrentReg->mFlags & SLAVE_REG_PERM_W)
            {
                DATA[REGS.mCursor] = data;
                REGS.mCurrentReg->mFlags |= SLAVE_REG_ACESS_W;
                REGS.mFlags |= SLAVE_REG_ACESS_W;
                REGS.mCursor++;
                if(REGS.mCursor == REGS.mCurrentReg->mAddr + REGS.mCurrentReg->mSize)
                {
                    REGS.mCurrentReg += sizeof(slave_reg_t);
                }
            }
        default:

            break;
    }
}

uint8_t ${obj.prefix.lower()}_slave_get(void)
{
     if(REGS.mCurrentReg->mFlags & SLAVE_REG_PERM_R)
     {
        REGS.mCurrentReg->mFlags |= SLAVE_REG_ACESS_R;   //Mark as Read
        REGS.mFlags |= SLAVE_REG_ACESS_R;
        return DATA[REGS.mCursor++];                   //Return data
     }
    
     return 0;
}

void ${obj.prefix.lower()}_slave_end_transaction(void)
{
    REGS.mState = SLAVE_STATE_ADDRESS;
    REGS.mAddrBytes = 0;
}


/*user-block-bottom-start*/
/*user-block-bottom-end*/

