//===================================================================================//
//  * @file           RF.c
//  * @author         Shi Zheng
//  * @version        V1.1
//  * @date           Aug/12/2013
//  * @brief          Main program body
//  * @modify user:   liuhaibing
//  * @modify date:   2019/12/19
//===================================================================================//
#include "RF.H"
#include "spi.h"

uint8_t TX_ADDRESS_DEF[5] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC};

uint8_t TxPayloadLength = PAYLOAD_WIDTH;
const uint8_t AckPayloadLength = 0x00;
uint32_t Payload_Count = 0;
uint16_t tx_only_count = 0;
uint16_t time_out_count = 0;

static void delay_us(uint32_t delay_us)
{
    uint32_t i = 0;
    uint32_t j = 0;
    for (i = 0; i < delay_us; i++)
    {
        for (j = 0; j < 10; j++)
        {
            ;
        }
    }
}

/******************************************************************************/
//            RF_WriteReg
//                Write Data(1 Byte Address ,1 byte data)
/******************************************************************************/
static void RF_WriteReg(uint8_t reg, uint8_t wdata)
{
    RF_SPI_NSS_L();
    SpiWrite(reg);
    SpiWrite(wdata);
    RF_SPI_NSS_H();
}

/******************************************************************************/
//            RF_ReadReg
//                Read Data(1 Byte Address ,1 byte data return)
/******************************************************************************/
static uint8_t RF_ReadReg(uint8_t reg)
{
    uint8_t tmp;

    RF_SPI_NSS_L();
    SpiWrite(reg);
    tmp = SpiRead();
    RF_SPI_NSS_H();

    return tmp;
}

/******************************************************************************/
//            RF_WriteBuf
//                Write Buffer
/******************************************************************************/
static void RF_WriteBuf(uint8_t reg, uint8_t *pBuf, uint8_t length)
{
    uint8_t j;
    RF_SPI_NSS_L();
    j = 0;
    SpiWrite(reg);
    for (j = 0; j < length; j++)
    {
        SpiWrite(pBuf[j]);
    }
    j = 0;
    RF_SPI_NSS_H();
}

/******************************************************************************/
//            RF_ReadBuf
//                Read Data(1 Byte Address ,length byte data read)
/******************************************************************************/
void RF_ReadBuf(uint8_t reg, unsigned char *pBuf, uint8_t length)
{
    uint8_t byte_ctr;

    RF_SPI_NSS_L();
    SpiWrite(reg);
    for (byte_ctr = 0; byte_ctr < length; byte_ctr++)
        pBuf[byte_ctr] = SpiRead();
    RF_SPI_NSS_H();
}

static void CE_HIGH()
{
    RF_WriteReg(CE_FSPI_ON, 0);
}
static void CE_LOW()
{
    RF_WriteReg(CE_FSPI_OFF, 0);
}

/******************************************************************************/
//            RF_TxMode
//                Set RF into TX mode
/******************************************************************************/
void RF_TxMode(void)
{
    CE_LOW();
    RF_WriteReg(W_REGISTER + CONFIG, 0X8E); // ��RF���ó�TXģʽ
    CE_HIGH();
    delay_us(1 * 1000);
}

/******************************************************************************/
//            RF_RxMode
//            ��RF���ó�RXģʽ��׼����������
/******************************************************************************/
void RF_RxMode(void)
{
    CE_LOW();
    RF_WriteReg(W_REGISTER + CONFIG, 0X8F); // ��RF���ó�RXģʽ
    CE_HIGH();
    delay_us(1 * 1000);
}

/******************************************************************************/
//            RF_GetStatus
//            read RF IRQ status,3bits return
/******************************************************************************/
uint8_t RF_GetStatus(void)
{
    return RF_ReadReg(STATUS) & 0x70; // ��ȡRF��״̬
}

/******************************************************************************/
//            RF_ClearStatus
//                clear RF IRQ
/******************************************************************************/
void RF_ClearStatus(void)
{
    RF_WriteReg(W_REGISTER + STATUS, 0x70); // ���RF��IRQ��־
}

/******************************************************************************/
//            RF_ClearFIFO
//                clear RF TX/RX FIFO
/******************************************************************************/
void RF_ClearFIFO(void)
{
    RF_WriteReg(FLUSH_TX, 0); // ���RF �� TX FIFO
    RF_WriteReg(FLUSH_RX, 0); // ���RF �� RX FIFO
}

/******************************************************************************/
//            RF_SetChannel
//                Set RF TX/RX channel:Channel
/******************************************************************************/
void RF_SetChannel(uint8_t Channel)
{
    RF_WriteReg(W_REGISTER + RF_CH, Channel);
}

/******************************************************************************/
//            �������ݣ�
//            ������
//              1. ucPayload����Ҫ���͵������׵�ַ
//              2. length:  ��Ҫ���͵����ݳ���
//              Return:
//              1. MAX_RT: TX Failure  (Enhance mode)
//              2. TX_DS:  TX Successful (Enhance mode)
//              note: Only use in Tx Mode
//              length ͨ������ PAYLOAD_WIDTH
/******************************************************************************/
void RF_TxData(uint8_t *ucPayload, uint8_t length)
{
    CE_HIGH(); // write data to txfifo ��1Mbps ������ʱ1ms;250Kbps����ʱ2ms
    RF_WriteBuf(W_TX_PAYLOAD, ucPayload, length);
    CE_LOW(); // rf entery tx mode start send data                                                                       		//rf entery stb3
    delay_us(1 * 1000);
}

/******************************************************************************/
//            ucRF_DumpRxData
//            �������յ������ݣ�
//            ������
//              1. ucPayload���洢��ȡ�������ݵ�Buffer
//              2. length:    ��ȡ�����ݳ���
//              Return:
//              1. 0: û�н��յ�����
//              2. 1: ��ȡ���յ������ݳɹ�
//              note: Only use in Rx Mode
//              length ͨ������ PAYLOAD_WIDTH
/******************************************************************************/
uint8_t RF_DumpRxData(uint8_t *ucPayload, uint8_t length)
{
    uint8_t status = RF_GetStatus();
    if (!(status & RX_DR_FLAG))
    {
        return 0;
    }

    RF_ReadBuf(R_RX_PAYLOAD, ucPayload, length); // �����յ������ݶ�����ucPayload

    return 1;
}

/******************************************************************************/
//            ���ͽ��
//            ������ֻ����ǿģʽ�£�ʹ��ack��Payload��Ч
//                  1��ucAckPayload: AckPayload���׵�ַ
//                  2��length��AckPayload�ij���
/******************************************************************************/

void RF_TX_CheckResult(uint8_t *ucAckPayload, uint8_t length)
{
    switch (RF_GetStatus())
    {
    case TX_DS_FLAG:
        tx_only_count++;
        RF_ClearFIFO();
        RF_ClearStatus();
        break;

    case RX_TX_FLAG:
        RF_ReadBuf(R_RX_PAYLOAD, ucAckPayload, length);
        ++Payload_Count;
        RF_ClearFIFO();
        RF_ClearStatus();
        break;

    case MAX_RT_FLAG:
        time_out_count++;
        RF_ClearFIFO();
        RF_ClearStatus();
        break;
    default:
        break;
    }
}

////////////////////////////////////////////////////////////////////////////////

//          ���²�����RFͨ����أ��������޸�
////////////////////////////////////////////////////////////////////////////////
/******************************************************************************/
//            XN297L_Initial
//                Initial RF
/******************************************************************************/
void RF_Init(uint8_t __rfPower)
{
#if (DATA_RATE == DR_1M || DATA_RATE == DR_2M)
    uint8_t BB_cal_data[] = {0x0A, 0x6D, 0x67, 0x9C, 0x46};
    uint8_t RF_cal_data[] = {0xF6, 0x37, 0x5D};
    uint8_t RF_cal2_data[] = {0x45, 0x21, 0xef, 0x2C, 0x5A, 0x42};
    uint8_t Dem_cal_data[] = {0x01};
    uint8_t Dem_cal2_data[] = {0x0b, 0xDF, 0x02};
#elif (DATA_RATE == DR_250K)
    uint8_t BB_cal_data[] = {0x12, 0xec, 0x6f, 0xa1, 0x46};
    uint8_t RF_cal_data[] = {0xf6, 0x37, 0x5d};
    uint8_t RF_cal2_data[] = {0x45, 0x21, 0xeb, 0x2c, 0x5a, 0x42};
    uint8_t Dem_cal_data[] = {0x1F};
    uint8_t Dem_cal2_data[] = {0x0b, 0xdf, 0x02};
#endif

#if (CE_MODE == CE_MODE_HARD)
    uint8_t feature = 0x00;
#elif (CE_MODE == CE_MODE_SOFT)
    uint8_t feature = 0x20;
#endif

    RF_WriteReg(RST_FSPI, 0x5A); // Software Reset
    RF_WriteReg(RST_FSPI, 0XA5);

    RF_WriteReg(FLUSH_TX, 0);                                                     // CLEAR TXFIFO
    RF_WriteReg(FLUSH_RX, 0);                                                     // CLEAR  RXFIFO
    RF_WriteReg(W_REGISTER + STATUS, 0x70);                                       // CLEAR  STATUS
    RF_WriteReg(W_REGISTER + EN_RXADDR, 0x01);                                    // Enable Pipe0
    RF_WriteReg(W_REGISTER + SETUP_AW, 0x03);                                     // address witdth is 5 bytes
    RF_WriteReg(W_REGISTER + RF_CH, DEFAULT_CHANNEL);                             // 2478M HZ
    RF_WriteReg(W_REGISTER + RX_PW_P0, PAYLOAD_WIDTH);                            // 8 bytes
    RF_WriteBuf(W_REGISTER + TX_ADDR, TX_ADDRESS_DEF, sizeof(TX_ADDRESS_DEF));    // Writes TX_Address to XN297L
    RF_WriteBuf(W_REGISTER + RX_ADDR_P0, TX_ADDRESS_DEF, sizeof(TX_ADDRESS_DEF)); // RX_Addr0 same as TX_Adr for Auto.Ack

    RF_WriteBuf(W_REGISTER + BB_CAL, BB_cal_data, sizeof(BB_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL2, RF_cal2_data, sizeof(RF_cal2_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL, Dem_cal_data, sizeof(Dem_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL, RF_cal_data, sizeof(RF_cal_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL2, Dem_cal2_data, sizeof(Dem_cal2_data));
    RF_WriteReg(W_REGISTER + DYNPD, 0x00);
    RF_WriteReg(W_REGISTER + RF_SETUP, __rfPower |DATA_RATE); // 8dbm  1Mbps
    RF_WriteReg(ACTIVATE, 0x73);

#if (TRANSMIT_TYPE == TRANS_ENHANCE_MODE)
    RF_WriteReg(W_REGISTER + SETUP_RETR, 0x01); //  1 retrans...
    RF_WriteReg(W_REGISTER + EN_AA, 0x01);      // Enable Auto.Ack:Pipe0
#elif (TRANSMIT_TYPE == TRANS_BURST_MODE)
    RF_WriteReg(W_REGISTER + SETUP_RETR, 0x00); // Disable retrans...
    RF_WriteReg(W_REGISTER + EN_AA, 0x00);      // Disable AutoAck
#endif

#if (EN_DYNPLOAD == 1)
    feature |= 0x04;
    RF_WriteReg(W_REGISTER + DYNPD, 0x01); // ��̬ʹ��pipe0��̬����
#endif

#if (EN_ACK_PAYLOAD == 1)
    feature |= 0x02;
#endif
    if (PAYLOAD_WIDTH > 32)
        feature |= 0x18;

    RF_WriteReg(W_REGISTER + FEATURE, feature);

    uint8_t R_BB_cal_data[5] = {0};
    RF_ReadBuf(R_REGISTER + BB_CAL, R_BB_cal_data, sizeof(R_BB_cal_data));
    printf("R_BB_cal_data: %02x %02x %02x %02x %02x\n", R_BB_cal_data[0], R_BB_cal_data[1], R_BB_cal_data[2], R_BB_cal_data[3], R_BB_cal_data[4]);
    if (memcmp(R_BB_cal_data, BB_cal_data, sizeof(BB_cal_data)) != 0)
    {
        printf("BB_cal_data error\n");
        // while (1)
        //     ;
    }
    
}
void RF_Reset(void)
{
    RF_WriteReg(W_REGISTER + CONFIG, 0);
}
/******************************************************************************/
//            		�����ز�ģʽ
/******************************************************************************/
void RF_Carrier(uint8_t ucChannel_Set, uint8_t rfPower)
{
    uint8_t BB_cal_data[] = {0x0A, 0x6D, 0x67, 0x9C, 0x46};
    uint8_t RF_cal_data[] = {0xF6, 0x37, 0x5D};
    uint8_t RF_cal2_data[] = {0x45, 0x21, 0xEF, 0xAC, 0x5a, 0x50};
    uint8_t Dem_cal_data[] = {0xE1};
    uint8_t Dem_cal2_data[] = {0x0B, 0xDF, 0x02};
#if (CE_MODE == CE_MODE_HARD)
    uint8_t feature = 0x00;
#elif (CE_MODE == CE_MODE_SOFT)
    uint8_t feature = 0x20;
#endif
    RF_WriteReg(RST_FSPI, 0x5A); // Software Reset
    RF_WriteReg(RST_FSPI, 0XA5);

    RF_WriteReg(W_REGISTER + FEATURE, feature);

    CE_LOW();
    delay_us(500);                                  // delay 500us
    RF_WriteReg(W_REGISTER + CONFIG, 0X8E);         // tx mode
    RF_WriteReg(W_REGISTER + RF_CH, ucChannel_Set); // ���ز�Ƶ��
    RF_WriteReg(W_REGISTER + RF_SETUP, rfPower |DATA_RATE);   // 13dbm
    RF_WriteBuf(W_REGISTER + BB_CAL, BB_cal_data, sizeof(BB_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL2, RF_cal2_data, sizeof(RF_cal2_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL, Dem_cal_data, sizeof(Dem_cal_data));
    RF_WriteBuf(W_REGISTER + RF_CAL, RF_cal_data, sizeof(RF_cal_data));
    RF_WriteBuf(W_REGISTER + DEM_CAL2, Dem_cal2_data, sizeof(Dem_cal2_data));
    delay_us(500);
}

/***************************************end of file ************************************/