#include "a7131.h"
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

#define SPI_CS SPI_CS_Pin
#define SPI_CS_PORT SPI_CS_GPIO_Port
extern SPI_HandleTypeDef hspi1;

volatile HAL_LockTypeDef txLock;
volatile HAL_LockTypeDef rxLock;

extern volatile HAL_LockTypeDef spiLock;
extern osSemaphoreId rxSemHandle;

static const uint8_t PageTab[8]={0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70};

static uint8_t ID_Tab[] =
{
    0x54, 0x75, 0xC5, 0x2A
};

const uint8_t A7131_Addr2A_Config[]=
{
	0x34, //page0,
	0x49, //page1,
	0x00, //Page2,
	0x80, //page3,
	0x80, //page4,
	0x00, //page5,
	0x5A, //page6,
	0x00, //page7,
};

const uint8_t A7131_Addr38_Config[]=
{
	0x00, //page0,
	0x10, //page1,
	0x20, //page2,
	0x24, //page3,
	0x20, //page4,
};

static uint8_t PN9_Tab[]=
{   0xFF,0x83,0xDF,0x17,0x32,0x09,0x4E,0xD1,
    0xE7,0xCD,0x8A,0x91,0xC6,0xD5,0xC4,0xC4,
    0x40,0x21,0x18,0x4E,0x55,0x86,0xF4,0xDC,
    0x8A,0x15,0xA7,0xEC,0x92,0xDF,0x93,0x53,
    0x30,0x18,0xCA,0x34,0xBF,0xA2,0xC7,0x59,
    0x67,0x8F,0xBA,0x0D,0x6D,0xD8,0x2D,0x7D,
    0x54,0x0A,0x57,0x97,0x70,0x39,0xD2,0x7A,
    0xEA,0x24,0x33,0x85,0xED,0x9A,0x1D,0xE0
};


// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//                                   NOTE                                    !!
// !!         THIS CONFIG TABLE ONLY USE ON RF CRYSTAL = 16MHz               !!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const uint8_t A7131Config[] =
{
    //      address   name              Descript
    //      -------   ----              ---------
    0x00,   //0x00  ; MODE_REG          only reset, not use on config
    0x62,   //0x01  ; MODE_CONTROL_REG  FIFO mode, Enable ARSSI, Enable AIF
    0x00,   //0x02  ; CALIBRATION_REG
    0x3F,   //0x03  ; FIFO1_REG         
    0x00,   //0x04  ; FIFO2_REG
    0x00,   //0x05  ; FIFO_REG
    0x00,   //0x06  ; IDCODE_REG
    0x00,   //0x07  ; RCOSC1_REG
    0x00,   //0x08  ; RCOSC2_REG
    0x00,   //0x09  ; RCOSC3_REG
    0x00,   //0x0A  ; CKO_REG
    0x19,   //0x0B  ; GIO1 register,    (0x01)WTR (0x19)SDO
    0x01,   //0x0C  ; GIO2 register,    (0x01)WTR (0x19)SDO 
    0x9F,   //0x0D  ; DATARATE_REG      
    0x00,   //0x0E  ; PLL1_REG
    0x0E,   //0x0F  ; PLL2_REG          RFbase 2400.001MHz
    0x96,   //0x10  ; PLL3_REG
    0x00,   //0x11  ; PLL4_REG
    0x04,   //0x12  ; PLL5_REG
    0x3C,   //0x13  ; ChannelGroup1 register
    0x78,   //0x14  ; ChannelGroup2 register
    0xAF,   //0x15  ; TX1_REG           
    0x40,   //0x16  ; TX2_REG
    0x10,   //0x17  ; DELAY1_REG        
    0x60,   //0x18  ; DELAY2_REG        
    0x72,   //0x19  ; RX_REG            
    0x6F,   //0x1A  ; RXGAIN1
    0xC2,   //0x1B  ; RXGAIN2
    0x3D,   //0x1C  ; RXGAIN3
    0xE7,   //0x1D  ; RXGAIN4
    0x00,   //0x1E  ; RSSI_REG
    0xF1,   //0x1F  ; ADC_REG
    0x07,   //0x20  ; CODE1_REG         
    0x06,   //0x21  ; CODE2_REG
    0x2A,   //0x22  ; CODE3_REG
    0x60,   //0x23  ; IFCAL1_REG
    0xFF,   //0x24  ; IFCAL2_REG
    0x80,   //0x25  ; VCOCCAL_REG       
    0xD0,   //0x26  ; VCOCAL1_REG
    0x00,   //0x27  ; VCOCAL2_REG
    0x70,   //0x28  ; VCO deviation 1 register
    0x00,   //0x29  ; VCO deviation 2 register
    0x00,   //0x2A  ; DSA register
    0xDC,   //0x2B  ; VCO Modulation delay register
    0xF0,   //0x2C  ; BATTERY_REG       
    0x3F,   //0x2D  ; TXTEST_REG        
    0x47,   //0x2E  ; RXDEM1_REG
    0xF7,   //0x2F  ; RXDEM2_REG
    0xF0,   //0x30  ; CPC1_REG           
    0x37,   //0x31  ; CPC2_REG           
    0x55,   //0x32  ; CRYSTALTEST_REG
    0x15,   //0x33  ; PLLTEST_REG
    0x15,   //0x34  ; VCOTEST1_REG
    0x00,   //0x35  ; RF Analog register
    0x00,   //0x36  ; Key data register
    0x77,   //0x37  ; Channel select register
    0x00,   //0x38  ; ROM register
    0x00,   //0x39  ; DataRate register
    0x00,   //0x3A  ; FCR register
    0x00,   //0x3B  ; ARD register
    0x00,   //0x3C  ; AFEP register
    0x00,   //0x3D  ; FCB register
    0x00,   //0x3E  ; KEYC register
    0x00,   //0x3F  ; USID register
};

void Err_State(void)
{
    //A7131 error handler
    while(1){;}
}

void A7131_WriteReg2Byte(uint8_t addr, uint8_t dataByte1, uint8_t dataByte2)
{
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &addr, 1, 100);
    HAL_SPI_Transmit(&hspi1, &dataByte1, 1, 100);
    HAL_SPI_Transmit(&hspi1, &dataByte2, 1, 100);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
}

void A7131_WriteReg(uint8_t addr, uint8_t dataByte)
{
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &addr, 1, 100);
    HAL_SPI_Transmit(&hspi1, &dataByte, 1, 100);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
}

uint8_t A7131_ReadReg(uint8_t addr)
{
    uint8_t tmp;
    addr |= 0x40;
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &addr, 1, 100);
    HAL_SPI_Receive(&hspi1, &tmp, 1, 100);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
    return tmp;
}

void A7131_WriteReg_Page(uint8_t addr, uint8_t wbyte, uint8_t page)
{
	A7131_WriteReg(RFANALOG_REG, A7131Config[RFANALOG_REG] | PageTab[page]);
	A7131_WriteReg(addr, wbyte);
}

void A7131_Reset(void)
{
    A7131_WriteReg(MODE_REG, 0x00);
}

void A7131_WriteID(void)
{
    int i;
    uint8_t addr = IDCODE_REG;
    
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &addr, 1, 100);
    for (i=0; i < 4; i++)
        HAL_SPI_Transmit(&hspi1, &ID_Tab[i], 1, 100);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
}

void A7131_Config(void)
{
    int i;

    for (i=0x01; i<=0x04; i++)
        A7131_WriteReg(i, A7131Config[i]);
    
    for (i=0x07; i<=0x29; i++)
        A7131_WriteReg(i, A7131Config[i]);
    
    for (i=0; i<=7; i++)
        A7131_WriteReg_Page(0x2A, A7131_Addr2A_Config[i], i);
    for (i=0x2B; i<=0x35; i++)
        A7131_WriteReg(i, A7131Config[i]);
    
    A7131_WriteReg(0x37, A7131Config[0x37]);
    
    for (i=0; i<=4; i++)
        A7131_WriteReg_Page(0x38, A7131_Addr38_Config[i], i);
    
    for (i=0x39; i<=0x3C; i++)
        A7131_WriteReg(i, A7131Config[i]);
    
    A7131_WriteReg(0x3E, A7131Config[0x3E]);
}

void StrobeCmd(uint8_t src)
{
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&hspi1, &src, 1, 100);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
}

static void CHGroupCal(uint8_t ch)
{
    uint8_t tmp;
    uint8_t vb,vbcf;
    uint8_t deva,adev;
    
    A7131_WriteReg(PLL1_REG, ch);
    
    A7131_WriteReg(CALIBRATION_REG, 0x0C);
    do
    {
        tmp = A7131_ReadReg(CALIBRATION_REG);
        tmp &= 0x0C;
    }while (tmp);
    
    //for check
    tmp = A7131_ReadReg(VCOCAL1_REG);
    vb = tmp & 0x07;
    vbcf = (tmp >>3) & 0x01;
    
    tmp = A7131_ReadReg(VCODEVCAL1_REG);
    deva = tmp;
    
    tmp = A7131_ReadReg(VCODEVCAL2_REG);
    adev = tmp;

    if (adev<45 || adev >68)
        Err_State();
    
    if (vbcf)
        Err_State();
}

void A7131_Cal(void)
{
    uint8_t tmp, loopCnt;
    uint8_t fb, fbcf, fcd, vcb, vccf, rhc, rlc;

    StrobeCmd(CMD_PLL); //calibration @PLL state
    
    //calibration IF procedure
    loopCnt = 0;
    A7131_WriteReg(RXGAIN3_REG, 0x1D);
    while(1)
    {
        A7131_WriteReg(CALIBRATION_REG, 0x02);
        do
        {
            tmp = A7131_ReadReg(CALIBRATION_REG);
            tmp &= 0x02;
        }while(tmp);
        
        tmp = A7131_ReadReg(IFCAL1_REG);
        fb = tmp & 0x0F;
        if (fb>3 && fb<10)
            break;
        loopCnt++;
        
        if (loopCnt>=10)
            break;
    }
    
    A7131_WriteReg(RXGAIN3_REG, 0x3D);
    
    if (loopCnt >=10)
        Err_State();
    
    //calibration RSSI, VCC procedure
    A7131_WriteReg(CALIBRATION_REG, 0x11);
    do
    {
        tmp = A7131_ReadReg(CALIBRATION_REG);
        tmp &= 0x11;
    }while(tmp);
	
    //calibration VBC,VDC procedure
    CHGroupCal(30); //calibrate channel group Bank I
    CHGroupCal(90); //calibrate channel group Bank II
    CHGroupCal(150); //calibrate channel group Bank III
    StrobeCmd(CMD_STBY); //return to STBY state
    
    //for check
    tmp = A7131_ReadReg(IFCAL1_REG);
    fb = tmp & 0x0F;
    fbcf = (tmp >>4) & 0x01;
    
    tmp = A7131_ReadReg(IFCAL2_REG);
    fcd = tmp & 0x1F;
    
    tmp = A7131_ReadReg(VCOCCAL_REG) & 0x1F;
    vcb = tmp & 0x0F;
    vccf = (tmp >>4) & 0x01;
    
    rhc = A7131_ReadReg(RXGAIN2_REG);
    rlc = A7131_ReadReg(RXGAIN3_REG);
    
    if (fbcf || vccf)
        Err_State();
}

void WriteFIFO(uint8_t length)
{
    uint8_t i, cmd;

    A7131_WriteReg( FIFO1_REG, length-1);
    StrobeCmd(CMD_TFR);
    
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_RESET);
    cmd = FIFO_REG;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    HAL_SPI_Transmit_DMA(&hspi1, PN9_Tab, 8);
    HAL_Delay(1);
    HAL_GPIO_WritePin(SPI_CS_PORT,SPI_CS,GPIO_PIN_SET);
}

void WriteFIFOExt(uint8_t length, uint8_t *pData)
{
    uint8_t i, cmd;
    
    SPI_CS_PORT->BRR = SPI_CS;
    cmd = FIFO_REG;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    txLock=HAL_LOCKED;
    HAL_SPI_Transmit_DMA(&hspi1, pData, length);
    while(txLock==HAL_LOCKED){}
    SPI_CS_PORT->BSRR = SPI_CS;
}

void WriteFIFOData(uint8_t length, uint8_t *pData)
{
    uint8_t cmd;

    A7131_WriteReg( FIFO1_REG, length-1);
    StrobeCmd(CMD_TFR);
    
    SPI_CS_PORT->BRR = SPI_CS;
    cmd = FIFO_REG;
    HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
    txLock=HAL_LOCKED;
    HAL_SPI_Transmit_DMA(&hspi1, pData, length);
    while(txLock==HAL_LOCKED){}
    SPI_CS_PORT->BSRR = SPI_CS;
}

void ReadFIFOData(uint8_t length, uint8_t *pData)
{
    uint8_t i, cmd, recv[100];

    SPI_CS_GPIO_Port->BRR = SPI_CS_Pin;
    cmd = FIFO_REG | 0x40;

    HAL_SPI_Transmit(&hspi1, &cmd, 1, 10);
    HAL_SPI_Receive_DMA(&hspi1, pData, length);

    rxLock = HAL_LOCKED;
    osSemaphoreWait(rxSemHandle,1);
    SPI_CS_GPIO_Port->BSRR = SPI_CS_Pin;
}

void A7131_init(void)
{
    A7131_Reset();
    A7131_WriteID();
    A7131_Config();
    A7131_Cal();
    
    StrobeCmd(CMD_STBY);

    A7131_WriteReg( IFCAL2_REG, 0xFF );
    A7131_WriteReg( TXTEST_REG, 0x3F );
    A7131_WriteReg( MODECTRL_REG, 0x62 );
    A7131_WriteReg( PLL1_REG, 100 );
    A7131_WriteReg( CODE1_REG, 0x17);
}


 void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
  txLock=HAL_UNLOCKED;
}

void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
  rxLock = HAL_UNLOCKED;
  osSemaphoreRelease(rxSemHandle); 
}

void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
{
}

