#include "A7169_hal.h" #include "A7169reg.h" /********************************************************************* ** Global Variable Declaration *********************************************************************/ uint8_t timer; uint8_t TimeoutFlag; uint16_t RxCnt; uint32_t Err_ByteCnt; uint32_t Err_BitCnt; uint16_t TimerCnt0; uint8_t *Uartptr; uint8_t UartSendCnt; uint8_t CmdBuf[11]; uint8_t tmpbuf[64]; uint8_t fb; uint16_t BODF; bool fb_ok; const uint8_t BitCount_Tab[16]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; const uint8_t ID_Tab[8]={0x34,0x75,0xC5,0x8C,0xC7,0x33,0x45,0xE7}; //ID const 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 }; // This table are 64bytes PN9 pseudo random code. A7169Config_ts A7169ConfigBuffer; void A7169_delayMs(uint32_t time) { uint32_t i, j; i = time; while (i --) { for ( j = 0; j < 1000; j++) { ; } } } void A7169_delayUs(uint32_t time) { uint32_t i, j; i = time; while (i --) { for ( j = 0; j < 1; j++) { ; } } } /********************************************************************* ** Strobe Command *********************************************************************/ void StrobeCMD(uint8_t cmd) { BOARD_A7169_SCS_L(); myRadioSpi_wByte(cmd); BOARD_A7169_SCS_H(); } /************************************************************************ ** A7169_WriteReg ************************************************************************/ void A7169_WriteReg(uint8_t address, uint16_t dataWord) { BOARD_A7169_SCS_L(); address |= CMD_Reg_W; myRadioSpi_wByte(address); //send word myRadioSpi_wByte((dataWord >> 8) & 0x00ff); myRadioSpi_wByte(dataWord & 0x00ff); BOARD_A7169_SCS_H(); } /************************************************************************ ** A7169_ReadReg ************************************************************************/ uint16_t A7169_ReadReg(uint8_t address) { uint16_t tmp; BOARD_A7169_SCS_L(); address |= CMD_Reg_R; myRadioSpi_wByte(address); //read code tmp = (uint16_t)myRadioSpi_rByte() << 8; tmp |= ((uint16_t)myRadioSpi_rByte() & 0x00ff); BOARD_A7169_SCS_H(); return tmp; } /************************************************************************ ** A7169_WritePageA ************************************************************************/ void A7169_WritePageA(uint8_t address, uint16_t dataWord) { uint16_t tmp; tmp = address; tmp = ((tmp << 12) | A7169ConfigBuffer.config[CRYSTAL_REG]); A7169_WriteReg(CRYSTAL_REG, tmp); A7169_WriteReg(PAGEA_REG, dataWord); } /************************************************************************ ** A7169_ReadPageA ************************************************************************/ uint16_t A7169_ReadPageA(uint8_t address) { uint16_t tmp; tmp = address; tmp = ((tmp << 12) | A7169ConfigBuffer.config[CRYSTAL_REG]); A7169_WriteReg(CRYSTAL_REG, tmp); tmp = A7169_ReadReg(PAGEA_REG); return tmp; } /************************************************************************ ** A7169_WritePageB ************************************************************************/ void A7169_WritePageB(uint8_t address, uint16_t dataWord) { uint16_t tmp; tmp = address; if ( tmp & 0x20 ) { tmp = ( ( ( tmp & 0x1F ) << 7 ) | (A7169ConfigBuffer.config[CRYSTAL_REG]&~0x0F80) ); A7169_WriteReg ( CRYSTAL_REG, tmp ); A7169_WriteReg ( PIN_REG,((A7169ConfigBuffer.config[PIN_REG]&~0x0001) | 0x01) ); } else { tmp = ( ( ( tmp & 0x1F ) << 7 ) | (A7169ConfigBuffer.config[CRYSTAL_REG]&~0x0F80) ); A7169_WriteReg ( CRYSTAL_REG, tmp ); A7169_WriteReg ( PIN_REG, (A7169ConfigBuffer.config[PIN_REG]&~0x0001)); } A7169_WriteReg(PAGEB_REG, dataWord); } /************************************************************************ ** A7169_ReadPageB ************************************************************************/ uint16_t A7169_ReadPageB(uint8_t address) { uint16_t tmp; tmp = address; if ( tmp & 0x20 ) { tmp = ( ( ( tmp & 0x1F ) << 7 ) | (A7169ConfigBuffer.config[CRYSTAL_REG]&~0x0F80) ); A7169_WriteReg ( CRYSTAL_REG, tmp ); A7169_WriteReg ( PIN_REG, ((A7169ConfigBuffer.config[PIN_REG]&~0x0001) | 0x01) ); } else { tmp = ( ( ( tmp & 0x1F ) << 7 ) | (A7169ConfigBuffer.config[CRYSTAL_REG]&~0x0F80) ); A7169_WriteReg ( CRYSTAL_REG, tmp ); A7169_WriteReg ( PIN_REG, (A7169ConfigBuffer.config[PIN_REG]&~0x0001) ); } tmp = A7169_ReadReg(PAGEB_REG); return tmp; } /********************************************************************* ** A7169_POR *********************************************************************/ void A7169_POR(void) { //power on only A7169_delayMs(10); //for regulator settling time (power on only) StrobeCMD(CMD_RF_RST); //reset A7169 chip while(A7169_WriteID()) //check SPI { StrobeCMD(CMD_RF_RST); //reset A7169 chip } A7169_WritePageA(PM_PAGEA, A7169ConfigBuffer.pageA[PM_PAGEA] | 0x1000); //STS=1 A7169_delayMs(2); entry_deep_sleep_mode(); //deep sleep A7169_delayMs(2); wake_up_from_deep_sleep_mode(); //wake up StrobeCMD(CMD_RF_RST); //reset A7169 chip while(A7169_WriteID()) //check SPI { StrobeCMD(CMD_RF_RST); //reset A7169 chip } A7169_WritePageA(PM_PAGEA, A7169ConfigBuffer.pageA[PM_PAGEA] | 0x1000); //STS=1 A7169_delayMs(2); } /********************************************************************* ** InitRF *********************************************************************/ uint8_t InitRF(void) { //initial pin A7169_delayMs(1); //delay 1ms for regulator stabilized StrobeCMD(CMD_RF_RST); //reset A7169 chip A7169_delayMs(1); if(A7169_Config()) //config A7169 chip return 1; A7169_delayUs(800); //delay 800us for crystal stabilized if(A7169_WriteID()) //write ID code return 1; if(A7169_Cal()) //IF and VCO Calibration return 1; return 0; } /********************************************************************* ** A7169_Config *********************************************************************/ uint8_t A7169_Config(void) { uint8_t i; uint16_t tmp = 0; for(i=0; i<8; i++) A7169_WriteReg(i, A7169ConfigBuffer.config[i]); for(i=10; i<16; i++) { if((i == 14) && (fb_ok == 1)) A7169_WriteReg(i, A7169ConfigBuffer.config[i] | (1<<4)); //MIFS=1(Manual) else A7169_WriteReg(i, A7169ConfigBuffer.config[i]); } for(i=0; i<16; i++) A7169_WritePageA(i, A7169ConfigBuffer.pageA[i]); for(i=0; i<53; i++) A7169_WritePageB(i, A7169ConfigBuffer.pageB[i]); //for check tmp = A7169_ReadReg(SYSTEMCLOCK_REG); if(tmp != A7169ConfigBuffer.config[SYSTEMCLOCK_REG]) { return 1; } return 0; } /************************************************************************ ** WriteID ************************************************************************/ uint8_t A7169_WriteID(void) { uint8_t i; uint8_t d1, d2, d3, d4; BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_ID_W); for(i=0; i<4; i++) myRadioSpi_wByte(ID_Tab[i]); BOARD_A7169_SCS_H(); BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_ID_R); d1=myRadioSpi_rByte(); d2=myRadioSpi_rByte(); d3=myRadioSpi_rByte(); d4=myRadioSpi_rByte(); BOARD_A7169_SCS_H(); if((d1!=ID_Tab[0]) || (d2!=ID_Tab[1]) || (d3!=ID_Tab[2]) || (d4!=ID_Tab[3])) { return 1; } return 0; } /********************************************************************* ** A7169_Cal *********************************************************************/ uint8_t A7169_Cal(void) { uint8_t i; uint8_t fb_old, fcd, fbcf;//IF Filter uint8_t vb,vbcf; //VCO Current uint8_t vcb, vccf; //VCO Band uint16_t tmp; bool fb_fail; StrobeCMD(CMD_STBY); //IF calibration procedure @STB state if(fb_ok == 1) { A7169_WriteReg(MODE_REG, A7169ConfigBuffer.config[MODE_REG] | 0x0800); //VCO Current Calibration do{ tmp = A7169_ReadReg(MODE_REG); }while(tmp & 0x0800); tmp = (A7169ConfigBuffer.config[CALIBRATION_REG] & 0xFFE0); tmp = tmp | fb | (1<<4); A7169_WriteReg(CALIBRATION_REG, tmp); } else { //IF calibration procedure @STB state fb_fail=0; for(i=0;i<3;i++) { A7169_WriteReg(MODE_REG, A7169ConfigBuffer.config[MODE_REG] | 0x0802); //IF Filter & VCO Current Calibration do{ tmp = A7169_ReadReg(MODE_REG); }while(tmp & 0x0802); //for check(IF Filter) tmp = A7169_ReadReg(CALIBRATION_REG); fb = tmp & 0x0F; fcd = (tmp>>11) & 0x1F; fbcf = (tmp>>4) & 0x01; if((fb<3) || (fb>11)) fb_fail = 1; else { if(i==0) fb_old = fb; else { if(fb != fb_old) { if(fb > fb_old) { if((fb-fb_old)!=1) fb_fail = 1; } else { if((fb_old-fb)!=1) fb_fail = 1; } } } } if((fbcf) || (fb_fail) || (fcd>6)) { return 1; } } } tmp = 0; tmp = ( fb - 2 ) | 0x0010; A7169_WriteReg ( CALIBRATION_REG, A7169ConfigBuffer.config[CALIBRATION_REG] | tmp ); //for check(VCO Current) tmp = A7169_ReadPageA(VCB_PAGEA); vcb = tmp & 0x0F; vccf = (tmp>>4) & 0x01; if(vccf) { return 1; } //RSSI Calibration procedure @STB state A7169_WriteReg(ADC_REG, 0x4C00); //set ADC average=64 A7169_WriteReg(MODE_REG, A7169ConfigBuffer.config[MODE_REG] | 0x9000); //RSSI Calibration do{ tmp = A7169_ReadReg(MODE_REG); }while(tmp & 0x1000); A7169_WriteReg(ADC_REG, A7169ConfigBuffer.config[ADC_REG]); //VCO calibration procedure @STB state A7169_WriteReg(PLL1_REG, A7169ConfigBuffer.config[PLL1_REG]); A7169_WriteReg(PLL2_REG, A7169ConfigBuffer.config[PLL2_REG]); A7169_WriteReg(MODE_REG, A7169ConfigBuffer.config[MODE_REG] | 0x0004); //VCO Band Calibration do{ tmp = A7169_ReadReg(MODE_REG); }while(tmp & 0x0004); //for check(VCO Band) tmp = A7169_ReadReg(CALIBRATION_REG); vb = (tmp >>5) & 0x07; vbcf = (tmp >>8) & 0x01; if(vbcf) { return 1; } fb_ok = 1; return 0; } /********************************************************************* ** A7169_WriteFIFO *********************************************************************/ void A7169_WriteFIFO(void) { uint8_t i; StrobeCMD(CMD_TFR); //TX FIFO address pointer reset BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_FIFO_W); //TX FIFO write command for(i=0; i <64; i++) myRadioSpi_wByte(PN9_Tab[i]); BOARD_A7169_SCS_H(); } /********************************************************************* ** A7169_FifoWrite *********************************************************************/ void A7169_FifoWrite(uint8_t *src, uint16_t len) { uint8_t i; StrobeCMD(CMD_TFR); //TX FIFO address pointer reset BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_FIFO_W); //TX FIFO write command for(i=0; i < len; i++) { myRadioSpi_wByte(src[i]); } BOARD_A7169_SCS_H(); } /********************************************************************* ** RxPacket *********************************************************************/ void RxPacket(void) { uint8_t i; uint8_t recv; uint8_t tmp; RxCnt++; StrobeCMD(CMD_RFR); //RX FIFO address pointer reset BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_FIFO_R); //RX FIFO read command for(i=0; i <64; i++) { tmpbuf[i] = myRadioSpi_rByte(); } BOARD_A7169_SCS_H(); for(i=0; i<64; i++) { recv = tmpbuf[i]; tmp = recv ^ PN9_Tab[i]; if(tmp!=0) { Err_ByteCnt++; Err_BitCnt += (BitCount_Tab[tmp>>4] + BitCount_Tab[tmp & 0x0F]); } } } /********************************************************************* ** RxPacket *********************************************************************/ void RxPacket_ReadFifo(uint8_t *fuffer, uint16_t len) { uint8_t i; uint8_t recv; uint8_t tmp; RxCnt++; StrobeCMD(CMD_RFR); //RX FIFO address pointer reset BOARD_A7169_SCS_L(); myRadioSpi_wByte(CMD_FIFO_R); //RX FIFO read command for(i=0; i <64; i++) { fuffer[i] = myRadioSpi_rByte(); } BOARD_A7169_SCS_H(); } /********************************************************************* ** Err_State *********************************************************************/ void Err_State(void) { //ERR display //Error Proc... //... while(1); } /********************************************************************* ** entry_deep_sleep_mode *********************************************************************/ void entry_deep_sleep_mode(void) { StrobeCMD(CMD_RF_RST); //RF reset A7169_WriteReg(PIN_REG, A7169ConfigBuffer.config[PIN_REG] | 0x0800); //SCMDS=1 A7169_WritePageA(PM_PAGEA, A7169ConfigBuffer.pageA[PM_PAGEA] | 0x0010); //QDS=1 StrobeCMD(CMD_SLEEP); //entry sleep mode A7169_delayUs(600); //delay 600us for VDD_A shutdown, C load=0.1uF StrobeCMD(CMD_DEEP_SLEEP); //entry deep sleep mode A7169_delayUs(200); //delay 200us for VDD_D shutdown, C load=0.1uF } /********************************************************************* ** wake_up_from_deep_sleep_mode *********************************************************************/ void wake_up_from_deep_sleep_mode(void) { StrobeCMD(CMD_STBY); //wake up A7169_delayMs(2); //delay 2ms for VDD_D stabilized //InitRF(); } /********************************************************************* ** BODF_Detect *********************************************************************/ uint8_t BODF_Detect(void) { uint16_t tmp; tmp = A7169_ReadPageB(TCODE_PAGEB); BODF = ((tmp>>12) & 0x01); if(BODF) { return 1; } return 0; } void A7169_SetConfig(A7169Config_ts config) { A7169ConfigBuffer = config; }