blob: 340905c17af751d22d53f7e9c2738f5343194905 [file] [log] [blame]
/******************************************************************************
* @file emi.c
*
* @brief for TLSR chips
*
* @author public@telink-semi.com;
* @date Sep. 30, 2010
*
* @attention
*
* Copyright (C) 2019-2020 Telink Semiconductor (Shanghai) Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include "emi.h"
#include "clock.h"
#include "timer.h"
#define STATE0 0x1234
#define STATE1 0x5678
#define STATE2 0xabcd
#define STATE3 0xef01
static unsigned char emi_rx_packet[64] __attribute__ ((aligned (4)));
static unsigned char emi_zigbee_tx_packet[48] __attribute__ ((aligned (4))) = {19,0,0,0,20,0,0};
static unsigned char emi_ble_tx_packet [48] __attribute__ ((aligned (4))) = {39, 0, 0, 0,0, 37};
static unsigned int emi_rx_cnt=0,emi_rssibuf=0;
static signed char rssi=0;
static unsigned int state0,state1;
/**
* @brief This function serves to set singletone power.
* @param level - the power level.
* @return none.
*/
void rf_set_power_level_index_singletone (RF_PowerTypeDef level)
{
unsigned char value;
if(level&BIT(7))
{
write_reg8(0x1225, (read_reg8(0x1225) & 0xbf) | ((0x01)<<6));//VANT
}
else
{
write_reg8(0x1225, (read_reg8(0x1225) & 0xbf));
}
write_reg8 (0xf02, 0x55); //tx_en
sleep_us(150);
value = (unsigned char)level&0x3f;
sub_wr(0x1378, 1, 6, 6); //TX_PA_PWR_OW
sub_wr(0x137c, value , 6, 1); //TX_PA_PWR 0x3f18
}
/**
* @brief This function serves to set singletone power and channel.
* @param power_level - the power level.
* @param rf_chn - the channel.
* @return none.
*/
void rf_emi_single_tone(RF_PowerTypeDef power_level,signed char rf_chn)
{
rf_multi_mode_drv_init(RF_MODE_ZIGBEE_250K);
rf_set_channel_singletone(rf_chn);//set freq
write_reg8 (0xf02, 0x45); //tx_en
rf_set_power_level_index_singletone(power_level);
}
/**
* @brief This function serves to close RF
* @param none.
* @return none.
*/
void rf_emi_stop(void)
{
write_reg8(0x1378, 0);
write_reg8(0x137c, 0);//TX_PA_PWR
rf_set_power_level_index (0);
rf_set_tx_rx_off();
}
/**
* @brief This function serves to set rx mode and channel.
* @param mode - mode of RF
* @param rf_chn - the rx channel.
* @return none.
*/
void rf_emi_rx(RF_ModeTypeDef mode,signed char rf_chn)
{
write_reg32 (0x408, 0x29417671); //accesscode: 1001-0100 1000-0010 0110-1110 1000-1110 29 41 76 71
write_reg8 (0x405, read_reg8(0x405)|0x80); //trig accesscode
rf_rx_buffer_set(emi_rx_packet,64,0);
rf_multi_mode_drv_init(mode);
rf_pn_disable();
rf_set_channel(rf_chn,0);//set freq
rf_set_tx_rx_off();
rf_set_rxmode();
sleep_us(150);
rssi = 0;
emi_rssibuf = 0;
emi_rx_cnt = 0;
}
/**
* @brief This function serves is receiving service program
* @param none.
* @return none.
*/
void rf_emi_rx_loop(void)
{
if(read_reg8(0xf20)&BIT(0))
{
if((read_reg8(0x44f)&0x0f)==0)
{
emi_rssibuf += (read_reg8(0x449));
if(emi_rx_cnt)
if(emi_rssibuf!=0)
emi_rssibuf>>=1;
rssi = emi_rssibuf-110;
emi_rx_cnt++;
}
write_reg8(0xf20, 1);
write_reg8(0xf00, 0x80);
}
}
/**
* @brief This function serves to get the number of packets received
* @param none.
* @return the number of packets received.
*/
unsigned int rf_emi_get_rxpkt_cnt(void)
{
return emi_rx_cnt;
}
/**
* @brief This function serves to get the RSSI of packets received
* @param none.
* @return the RSSI of packets received.
*/
char rf_emi_get_rssi_avg(void)
{
return rssi;
}
/**
* @brief This function serves to get the address of the received packets
* @param none.
* @return the address of the received packets
*/
unsigned char *rf_emi_get_rxpkt(void)
{
return emi_rx_packet;
}
/**
* @brief This function serves to generate random number.
* @param the old random number.
* @return the new random number.
*/
unsigned int pnGen(unsigned int state)
{
unsigned int feed = 0;
feed = (state&0x4000) >> 1;
state ^= feed;
state <<= 1;
state = (state&0xfffe) + ((state&0x8000)>>15);
return state;
}
/**
* @brief This function serves to Set the CD mode correlation register.
* @param none.
* @return none.
*/
static void rf_continue_mode_setup(void)
{
write_reg8(0x400,0x0a);
write_reg8(0x408,0x00);
write_reg8(0x401,0x80);//kick tx controller to wait data
state0 = STATE0;
state1 = STATE1;
}
/**
* @brief This function serves to continue to send CD mode.
* @param none.
* @return none.
*/
void rf_continue_mode_run(void)
{
if(read_reg8(0x408) == 1){
write_reg32(0x41c, 0x0f0f0f0f);
}else if(read_reg8(0x408)==2){
write_reg32(0x41c, 0x55555555);
}else if(read_reg8(0x408)==3){
write_reg32(0x41c, read_reg32(0x409));
}else if(read_reg8(0x408)==4){
write_reg32(0x41c, 0);
}else if(read_reg8(0x408)==5){
write_reg32(0x41c, 0xffffffff);
}else{
write_reg32(0x41c, (state0<<16)+state1);
state0 = pnGen(state0);
state1 = pnGen(state1);
}
while(read_reg8(0x41c) & 0x1){
}
}
/**
* @brief This function serves to init the CD mode.
* @param rf_mode - mode of RF.
* @param power_level - power level of RF.
* @param rf_chn - channel of RF.
* @param pkt_type - The type of data sent
* 0:random data
* 1:0xf0
* 2:0x55
* @return none.
*/
void rf_emi_tx_continue_setup(RF_ModeTypeDef rf_mode,RF_PowerTypeDef power_level,signed char rf_chn,unsigned char pkt_type)
{
rf_multi_mode_drv_init(rf_mode);//RF_MODE_BLE_1M
rf_pn_disable();
rf_set_channel(rf_chn,0);
write_reg8(0xf02, 0x45); //tx_en
rf_set_power_level_index_singletone (power_level);
rf_continue_mode_setup();
write_reg8(0x408, pkt_type);//0:pbrs9 1:0xf0 2:0x55
}
/**
* @brief This function serves to generate random packets that need to be sent in burst mode
* @param *p - the address of random packets.
* @param n - the number of random packets.
* @return none.
*/
static void rf_phy_test_prbs9 (unsigned char *p, int n)
{
//PRBS9: (x >> 1) | (((x<<4) ^ (x<<8)) & 0x100)
unsigned short x = 0x1ff;
int i;
int j;
for ( i=0; i<n; i++)
{
unsigned char d = 0;
for (j=0; j<8; j++)
{
if (x & 1)
{
d |= BIT(j);
}
x = (x >> 1) | (((x<<4) ^ (x<<8)) & 0x100);
}
*p++ = d;
}
}
/**
* @brief This function serves to init the burst mode.
* @param rf_mode - mode of RF.
* @param power_level - power level of RF.
* @param rf_chn - channel of RF.
* @param pkt_type - The type of data sent
* 0:random data
* 1:0xf0
* 2:0x55
* @return none.
*/
void rf_emi_tx_burst_setup(RF_ModeTypeDef rf_mode,RF_PowerTypeDef power_level,signed char rf_chn,unsigned char pkt_type)
{
//#if 0
unsigned char i;
unsigned char tx_data=0;
write_reg32(0x408,0x29417671 );//access code 0xf8118ac9
write_reg8 (0x405, read_reg8(0x405)|0x80);
write_reg8(0x13c,0x10); // print buffer size set
rf_set_channel(rf_chn,0);
rf_multi_mode_drv_init(rf_mode);
rf_pn_disable();
rf_set_power_level_index (power_level);
if(pkt_type==1) tx_data = 0x0f;
else if(pkt_type==2) tx_data = 0x55;
switch(rf_mode)
{
case RF_MODE_LR_S2_500K:
case RF_MODE_LR_S8_125K:
case RF_MODE_BLE_1M:
case RF_MODE_BLE_2M:
emi_ble_tx_packet[4] = pkt_type;//type
for( i=0;i<37;i++)
{
emi_ble_tx_packet[6+i]=tx_data;
}
break;
case RF_MODE_ZIGBEE_250K:
emi_zigbee_tx_packet[5] = pkt_type;//type
for( i=0;i<37;i++)
{
emi_zigbee_tx_packet[5+i]=tx_data;
}
break;
default:
break;
}
}
/**
* @brief This function serves to init the burst mode with PA ramp up/down.
* @param rf_mode - mode of RF.
* @param power_level - power level of RF.
* @param rf_chn - channel of RF.
* @param pkt_type - The type of data sent
* 0:random data
* 1:0xf0
* 2:0x55
* @return none.
*/
void rf_emi_tx_brust_setup_ramp(RF_ModeTypeDef rf_mode,RF_PowerTypeDef power_level,signed char rf_chn,unsigned char pkt_type)
{
//#if 0
unsigned char i;
unsigned char tx_data=0;
write_reg32(0x408,0x29417671 );//access code 0xf8118ac9
write_reg8 (0x405, read_reg8(0x405)|0x80);
write_reg8(0x13c,0x10); // print buffer size set
rf_set_channel(rf_chn,0);
rf_multi_mode_drv_init(rf_mode);
rf_pn_disable();
rf_set_tx_rx_off();
rf_set_power_level_index_singletone(power_level);
if(pkt_type==1) tx_data = 0x0f;
else if(pkt_type==2) tx_data = 0x55;
switch(rf_mode)
{
case RF_MODE_LR_S2_500K:
case RF_MODE_LR_S8_125K:
case RF_MODE_BLE_1M:
case RF_MODE_BLE_2M:
emi_ble_tx_packet[4] = pkt_type;//type
for( i=0;i<37;i++)
{
emi_ble_tx_packet[6+i]=tx_data;
}
break;
case RF_MODE_ZIGBEE_250K:
emi_zigbee_tx_packet[5] = pkt_type;//type
for( i=0;i<37;i++)
{
emi_zigbee_tx_packet[5+i]=tx_data;
}
break;
default:
break;
}
}
/**
* @brief This function serves to send packets in the burst mode with PA ramp up/down.
* @param rf_mode - mode of RF.
* @param pkt_type - The type of data sent
* 0:random data
* 1:0xf0
* 2:0x55
* @return none.
*/
void rf_emi_tx_burst_loop_ramp(RF_ModeTypeDef rf_mode,unsigned char pkt_type)
{
write_reg8(0xf00, 0x80); // stop SM
int power = (unsigned char)rf_power_Level_list[read_reg8(0x40008)];
if((rf_mode==RF_MODE_BLE_1M)||(rf_mode==RF_MODE_BLE_2M)||(rf_mode==RF_MODE_LR_S8_125K)||(rf_mode==RF_MODE_LR_S2_500K))//ble
{
for(int i=0;i<=power;i++)
{
sub_wr(0x137c, i , 6, 1);
}
rf_tx_pkt(emi_ble_tx_packet);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
for(int i=power;i>=0;i--)
{
sub_wr(0x137c, i , 6, 1);
}
sleep_ms(2);
if(pkt_type==0)
rf_phy_test_prbs9(&emi_ble_tx_packet[6],37);
}
else if(rf_mode==RF_MODE_ZIGBEE_250K)//zigbee
{
for(int i=0;i<=power;i++)
sub_wr(0x137c, i , 6, 1);
rf_tx_pkt(emi_zigbee_tx_packet);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
for(int i=power;i>=0;i--)
sub_wr(0x137c, i , 6, 1);
sleep_ms(4);
if(pkt_type==0)
rf_phy_test_prbs9(&emi_zigbee_tx_packet[5],37);
}
}
/**
* @brief This function serves to send packets in the burst mode
* @param rf_mode - mode of RF.
* @param pkt_type - The type of data sent
* 0:random data
* 1:0xf0
* 2:0x55
* @return none.
*/
void rf_emi_tx_burst_loop(RF_ModeTypeDef rf_mode,unsigned char pkt_type)
{
write_reg8(0xf00, 0x80); // stop SM
if((rf_mode==RF_MODE_BLE_1M)||(rf_mode==RF_MODE_BLE_2M))//ble
{
rf_start_stx ((void *)emi_ble_tx_packet, read_reg32(0x740) + 10);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
sleep_ms(2);//
// delay_us(625);//
if(pkt_type==0)
rf_phy_test_prbs9(&emi_ble_tx_packet[6],37);
}
else if(rf_mode==RF_MODE_LR_S8_125K)//ble
{
rf_start_stx ((void *)emi_ble_tx_packet, read_reg32(0x740) + 10);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
sleep_ms(2);//
if(pkt_type==0)
rf_phy_test_prbs9(&emi_ble_tx_packet[6],37);
}
else if(rf_mode==RF_MODE_LR_S2_500K)//ble
{
rf_start_stx ((void *)emi_ble_tx_packet, read_reg32(0x740) + 10);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
sleep_ms(2);//625*1.5
if(pkt_type==0)
rf_phy_test_prbs9(&emi_ble_tx_packet[6],37);
}
else if(rf_mode==RF_MODE_ZIGBEE_250K)//zigbee
{
rf_start_stx ((void *)emi_zigbee_tx_packet, read_reg32(0x740) + 10);
while(!rf_tx_finish());
rf_tx_finish_clear_flag();
sleep_us(625*2);//
if(pkt_type==0)
rf_phy_test_prbs9(&emi_zigbee_tx_packet[5],37);
}
}
/**
* @brief This function serves to set the channel in singletone mode.
* @param chn - channel of RF.
* @return none.
*/
void rf_set_channel_singletone (signed char chn)//general
{
unsigned short rf_chn =0;
unsigned char ctrim;
unsigned short chnl_freq;
rf_chn = chn+2400;
if (rf_chn >= 2550)
ctrim = 0;
else if (rf_chn >= 2520)
ctrim = 1;
else if (rf_chn >= 2495)
ctrim = 2;
else if (rf_chn >= 2465)
ctrim = 3;
else if (rf_chn >= 2435)
ctrim = 4;
else if (rf_chn >= 2405)
ctrim = 5;
else if (rf_chn >= 2380)
ctrim = 6;
else
ctrim = 7;
chnl_freq = rf_chn * 2 +1;
write_reg8(0x1244, ((chnl_freq & 0x7f)<<1) | 1 ); //CHNL_FREQ_DIRECT CHNL_FREQ_L
write_reg8(0x1245, ((read_reg8(0x1245) & 0xc0)) | ((chnl_freq>>7)&0x3f) ); //CHNL_FREQ_H
write_reg8(0x1229, (read_reg8(0x1229) & 0xC3) | (ctrim<<2) ); //FE_CTRIM
}