NPR70/NPR_14/source/SI4463.cpp
Vlastimil Slinták 16140fd383 Initial commit with the original FW
This FW for the New Packet Radio project was taken from the Hackaday
project https://hackaday.io/project/164092-npr-new-packet-radio

The source code is original without any modifications, ver. 2020_06_29.
2025-03-11 23:20:01 +01:00

1403 lines
No EOL
47 KiB
C++

// This file is part of "NPR70 modem firmware" software
// (A GMSK data modem for ham radio 430-440MHz, at several hundreds of kbps)
// Copyright (c) 2017-2020 Guillaume F. F4HDK (amateur radio callsign)
//
// "NPR70 modem firmware" is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// "NPR70 modem firmware" is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with "NPR70 modem firmware". If not, see <http://www.gnu.org/licenses/>
#include "SI4463.h"
#include "mbed.h"
#include "global_variables.h"
#include "TDMA.h"
#include "HMI_telnet.h"
#include "L1L2_radio.h"
#ifdef FREQ_BAND_2M
#include "SI4463_config_20_2m.h"
#include "SI4463_config_11_2m.h"
#include "SI4463_config_21_2m.h"
#include "SI4463_config_12_2m.h"
#include "SI4463_config_22_2m.h"
#include "SI4463_config_13_2m.h"
#include "SI4463_config_23_2m.h"
#include "SI4463_config_14_2m.h"
#include "SI4463_config_24_2m.h"
#else
//#include "SI4463_config_10.h"
#include "SI4463_config_20.h"
//#include "radio_config_Si4463_20.h"
#include "SI4463_config_11.h"
//#include "radio_config_Si4463_11.h"
#include "SI4463_config_21.h"
//#include "SI4463_config_21_GMSK.h"
//#include "radio_config_Si4463_21.h"
#include "SI4463_config_12.h"
#include "SI4463_config_22.h"
//#include "radio_config_Si4463_22.h"
#include "SI4463_config_13.h"
//#include "radio_config_Si4463_13.h"
#include "SI4463_config_23.h"
//#include "radio_config_Si4463_23.h"
#include "SI4463_config_14.h"
#include "SI4463_config_24.h"
//#include "radio_config_Si4463_24.h"
#endif
//Timeout SI4463_prepa_TX_1_call;
Timeout SI4463_prepa_TX_2_call;
Timeout SI4463_1st_TX_call;
Timeout SI4463_RX_timeout_call; //2019_04_05
//Ticker SI4463_temp_check2_call;
//TX_buffer_struct* TX_buff; //data structure currently used to TX
static unsigned char SI_trash[150];
static unsigned char TX_temp_rframe[384];
static unsigned char* TX_frame_to_send;
static unsigned char TX_in_progress = 0;
static unsigned char TX_test_inprogress = 0;
//int TX_frame_pointer;
// Low level functions & drivers
void SI4463_send_command(SI4463_Chip* SI4463, unsigned char* data, int size) {
unsigned char loc_RX[30];
SI4463->cs->write(0);
SI4463->spi->transfer_2(data, size, loc_RX, size);
SI4463->cs->write(1);
wait_us(1);
}
int SI4463_CTS_read_answer(SI4463_Chip* SI4463, unsigned char* data, int size, int timeout) {
unsigned char loc_RX[10];
unsigned char loc_TX[10];
int answer;
int loops = 0;
loc_TX[0] = 0x44;
loops = 0;
SI4463->cs->write(0);
SI4463->spi->transfer_2(loc_TX, 2, loc_RX, 2);
while ((loc_RX[1] != 0xFF) && (loops < timeout)) {
SI4463->cs->write(1);
wait_us(20);
SI4463->cs->write(0);
SI4463->spi->transfer_2(loc_TX, 2, loc_RX, 2);
loops++;
}
if (size > 0) {
SI4463->spi->transfer_2(loc_TX, size, data, size);
}
SI4463->cs->write(1);
wait_us(1);
if (loops >= timeout) {
answer = 0;
} else {
answer =1;
}
//printf (" loc answer:%i ", answer);
return answer;
}
//** Higher level functions ***
// configures using RADIO_CONFIGURATION_DATA_ARRAY
//int SI4463_configure_from_10(SI4463_Chip* SI4463) {
// unsigned char radio_config_data_10[1400] = RADIO_CONFIGURATION_DATA_ARRAY_10;//22
// CONF_TDMA_frame_duration = 939000;
// CONF_TDMA_slot_duration = 53400;
// CONF_reduced_TDMA_slot_duration = 20400;
// CONF_TDMA_slot_margin = 300;
// CONF_TR_margain = 1300;
// CONF_TA_margain = 2000;
// CONF_preamble_duration_for_decide = 3100; //1090
// CONF_long_preamble_duration_for_TA = 3833;//1420
// CONF_byte_duration = 143;
// CONF_preamble_TX_long = 22;
// CONF_preamble_TX_short = 16;
// CONF_Tx_rframe_timeout = 30;
// CONF_radio_timeout_small = 10000000;//10sec
// CONF_signaling_period = 1;
// return SI4463_configure_from_h (SI4463, radio_config_data_10);
//}
int SI4463_configure_from_20(SI4463_Chip* SI4463) {
unsigned char radio_config_data_20[1250] = RADIO_CONFIGURATION_DATA_ARRAY_20;//22
//unsigned char radio_config_data_20[1400] = RADIO_CONFIGURATION_DATA_ARRAY;
CONF_TDMA_frame_duration = 560000;
CONF_TDMA_slot_duration = 31600;
CONF_reduced_TDMA_slot_duration = 12700;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 2670; //1090
CONF_long_preamble_duration_for_TA = 3751;//1420
CONF_byte_duration = 80;
CONF_preamble_TX_long = 20;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 120;//8sec
CONF_radio_timeout = 60000000;
CONF_radio_timeout_small = 10000000;//10sec previously 20
CONF_signaling_period = 2;//4 sec
return SI4463_configure_from_h (SI4463, radio_config_data_20);
}
int SI4463_configure_from_11(SI4463_Chip* SI4463) {
unsigned char radio_config_data_11[1250] = RADIO_CONFIGURATION_DATA_ARRAY_11;//22
//unsigned char radio_config_data_11[1400] = RADIO_CONFIGURATION_DATA_ARRAY;//22
CONF_TDMA_frame_duration = 537000;
CONF_TDMA_slot_duration = 30250;
CONF_reduced_TDMA_slot_duration = 11700;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 1650; //1090
CONF_long_preamble_duration_for_TA = 2473;//2292
CONF_byte_duration = 80;
CONF_preamble_TX_long = 25;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 120;//8sec
CONF_radio_timeout = 60000000;
CONF_radio_timeout_small = 10000000;//10sec previously 20
CONF_signaling_period = 2;//4sec
return SI4463_configure_from_h (SI4463, radio_config_data_11);
}
int SI4463_configure_from_21(SI4463_Chip* SI4463) {
unsigned char radio_config_data_21[1250] = RADIO_CONFIGURATION_DATA_ARRAY_21;//22
//unsigned char radio_config_data_21[1400] = RADIO_CONFIGURATION_DATA_ARRAY;//22
CONF_TDMA_frame_duration = 294500;
CONF_TDMA_slot_duration = 16300;
CONF_reduced_TDMA_slot_duration = 7050;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 1550; //1090
CONF_long_preamble_duration_for_TA = 2370;//1420
CONF_byte_duration = 30;
CONF_preamble_TX_long = 25;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 90;//6 sec
CONF_radio_timeout = 60000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;//2sec
return SI4463_configure_from_h (SI4463, radio_config_data_21);
}
int SI4463_configure_from_12(SI4463_Chip* SI4463) {
unsigned char radio_config_data_12[1250] = RADIO_CONFIGURATION_DATA_ARRAY_12;//22
CONF_TDMA_frame_duration = 312000;
CONF_TDMA_slot_duration = 17300;
CONF_reduced_TDMA_slot_duration = 7150;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 1030; //1090
CONF_long_preamble_duration_for_TA = 1765;//1420
CONF_byte_duration = 45;
CONF_preamble_TX_long = 32;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 100;//6sec
CONF_radio_timeout = 60000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;//2sec
return SI4463_configure_from_h (SI4463, radio_config_data_12);
}
int SI4463_configure_from_22(SI4463_Chip* SI4463) {
unsigned char radio_config_data_22[1250] = RADIO_CONFIGURATION_DATA_ARRAY_22;//22
//unsigned char radio_config_data_22[1400] = RADIO_CONFIGURATION_DATA_ARRAY;
CONF_TDMA_frame_duration = 176000;
CONF_TDMA_slot_duration = 9480;
CONF_reduced_TDMA_slot_duration = 4330;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 890; //1090
CONF_long_preamble_duration_for_TA = 1708;//1420
CONF_byte_duration = 23;
CONF_preamble_TX_long = 32;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 60;//4 sec
CONF_radio_timeout = 40000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;
return SI4463_configure_from_h (SI4463, radio_config_data_22);
}
int SI4463_configure_from_13(SI4463_Chip* SI4463) {
unsigned char radio_config_data_13[1250] = RADIO_CONFIGURATION_DATA_ARRAY_13;
CONF_TDMA_frame_duration = 197000;
CONF_TDMA_slot_duration = 10720;
CONF_reduced_TDMA_slot_duration = 4540;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 590;
CONF_long_preamble_duration_for_TA = 1400;
CONF_byte_duration = 27;
CONF_preamble_TX_long = 42;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 60;//4 sec
CONF_radio_timeout = 40000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;
return SI4463_configure_from_h (SI4463, radio_config_data_13);
}
int SI4463_configure_from_23(SI4463_Chip* SI4463) {
unsigned char radio_config_data_23[1250] = RADIO_CONFIGURATION_DATA_ARRAY_23;//23
//unsigned char radio_config_data_23[1500] = RADIO_CONFIGURATION_DATA_ARRAY;
CONF_TDMA_frame_duration = 117000;
CONF_TDMA_slot_duration = 6090;
CONF_reduced_TDMA_slot_duration = 3000;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 570;
CONF_long_preamble_duration_for_TA = 1365;
CONF_byte_duration = 14;//13.3
CONF_preamble_TX_long = 42;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 30;//30!!!
CONF_radio_timeout = 30000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;
return SI4463_configure_from_h (SI4463, radio_config_data_23);
}
int SI4463_configure_from_14(SI4463_Chip* SI4463) {
unsigned char radio_config_data_14[1250] = RADIO_CONFIGURATION_DATA_ARRAY_14;//14
CONF_TDMA_frame_duration = 130000;
CONF_TDMA_slot_duration = 6840;
CONF_reduced_TDMA_slot_duration = 3130;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 400;
CONF_long_preamble_duration_for_TA = 1206;
CONF_byte_duration = 16;
CONF_preamble_TX_long = 60;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 30;
CONF_radio_timeout = 30000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;
return SI4463_configure_from_h (SI4463, radio_config_data_14);
}
int SI4463_configure_from_24(SI4463_Chip* SI4463) {
unsigned char radio_config_data_24[1250] = RADIO_CONFIGURATION_DATA_ARRAY_24;//24
//unsigned char radio_config_data_24[1500] = RADIO_CONFIGURATION_DATA_ARRAY;//24
CONF_TDMA_frame_duration = 81300;//81300
CONF_TDMA_slot_duration = 4060;
CONF_reduced_TDMA_slot_duration = 2210;
CONF_TDMA_slot_margin = 300;
CONF_TR_margain = 1300;
CONF_TA_margain = 2000;
CONF_preamble_duration_for_decide = 390;
CONF_long_preamble_duration_for_TA = 1188;
CONF_byte_duration = 8;
CONF_preamble_TX_long = 60;
CONF_preamble_TX_short = 16;
CONF_Tx_rframe_timeout = 30;
CONF_radio_timeout = 30000000;
CONF_radio_timeout_small = 5000000;//5sec previously 10sec
CONF_signaling_period = 1;
return SI4463_configure_from_h (SI4463, radio_config_data_24);
}
int SI4463_configure_from_h(SI4463_Chip* SI4463, unsigned char* radio_config_data) {
int i=0;
int answer_loc;
int answer;
int current_command_length;
answer = 1;
do {
current_command_length = radio_config_data[i];
i++;
if (current_command_length>0) {
SI4463_send_command(SI4463, radio_config_data+i, current_command_length);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 30000);//15000 30000
if (answer_loc == 0) {answer = 0;}
}
i = i + current_command_length;
//
} while ( (current_command_length > 0) && (answer == 1) );
wait_ms(5);
// specific GLOBAL_CONFIG : SEQUENCER_MODE=GUARANTEED and FIFO_MODE=FIFO_129
unsigned char radio_config_bis[10] = {0x11, 0x00, 0x01, 0x03, 0x10};
SI4463_send_command(SI4463, radio_config_bis, 5);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 800);//200
if (answer_loc == 0) {answer = 0;}
wait_ms(5);//50
// specific Max size field 2
unsigned char radio_config_ter[10] = {0x11, 0x12, 0x02, 0x11, 0x00, 0xFF};
radio_config_ter[4] = (SI4463_CONF_max_field2_size & 0x1F00 )/ 0x100 ;
radio_config_ter[5] = SI4463_CONF_max_field2_size & 0x00FF;
SI4463_send_command(SI4463, radio_config_ter, 6);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 800);
if (answer_loc == 0) {answer = 0;}
wait_ms(5);//50
//specific FIFO Threshold
unsigned char radio_config_quart[10] = {0x11, 0x12, 0x02, 0x0B, 0x30, 0x64};
radio_config_quart[4] = SI4463_CONF_TX_FIFO_threshold & 0x7F;// ajout 30 mai
radio_config_quart[5] = SI4463_CONF_RX_FIFO_threshold & 0x7F;
SI4463_send_command(SI4463, radio_config_quart, 6);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 800);
if (answer_loc == 0) {answer = 0;}
wait_ms(5);//50
//specific SYNC WORD depending on 'radio network ID'
unsigned char hash_netID[20] = {0x33, 0x36, 0x39, 0x3c, 0x63, 0x66, 0x69, 0x6c, 0x93, 0x96, 0x99, 0x9c, 0xc3, 0xc6, 0xc9, 0xcc};
unsigned char radio_config_quint[12] = {0x11, 0x11, 0x01, 0x03, 0xCC};
radio_config_quint[4] = hash_netID[CONF_radio_network_ID];
SI4463_send_command(SI4463, radio_config_quint, 5);//10
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 800);
answer_loc = 1;
if (answer_loc == 0) {answer = 0;}
wait_ms(5);//5
//specific power
unsigned char radio_config_sixt[10] = {0x11, 0x22, 0x01, 0x01, 0x7F};
radio_config_sixt[4] = CONF_radio_PA_PWR & 0x7F;
SI4463_send_command(SI4463, radio_config_sixt, 5);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 800);
if (answer_loc == 0) {answer = 0;}
wait_ms(5);//5
return answer;
}
int SI4463_set_power(SI4463_Chip* SI4463) {
int answer, answer_loc;
unsigned char radio_config_sixt[10] = {0x11, 0x22, 0x01, 0x01, 0x7F};
radio_config_sixt[4] = CONF_radio_PA_PWR & 0x7F;
SI4463_send_command(SI4463, radio_config_sixt, 5);
answer_loc = SI4463_CTS_read_answer(SI4463, SI_trash, 0, 200);
if (answer_loc == 0) {answer = 0;}
wait_ms(5);
return answer;
}
void SI4463_print_version(SI4463_Chip* SI4463) {
int i;
unsigned char command [10];
unsigned char answer [12];
command[0] = 0x01;//part info
SI4463_send_command(SI4463, command, 1);
SI4463_CTS_read_answer(SI4463, answer, 8, 200);
HMI_printf("part info: ");
for (i=0; i<8; i++) {
HMI_printf("%02X ",answer[i]);
}
printf("\r\n");
command[0] = 0x10;//function info
SI4463_send_command(SI4463, command, 1);
SI4463_CTS_read_answer(SI4463, answer, 8, 200);
HMI_printf("function info: ");
for (i=0; i<6; i++) {
HMI_printf("%02X ",answer[i]);
}
printf("\r\n");
}
void SI4463_FIFO_status(SI4463_Chip* SI4463, int* RX_FIFO_count, int* TX_FIFO_count, int reset) {
unsigned char command[10];
unsigned char answer[10];
command[0] = 0x15;
if (reset == 1) {
command[1] = 0x03;
} else {
command[1] = 0x00;
}
SI4463_send_command (SI4463, command, 2);
SI4463_CTS_read_answer (SI4463, answer, 2, 5);
*RX_FIFO_count = answer[0];
*TX_FIFO_count = answer[1];
}
// a supprimer
void SI4463_FIFO_write(SI4463_Chip* SI4463, unsigned char* data, int size) {
static unsigned char trash [200];
unsigned char command[6];
command[0] = 0x66;
SI4463->cs->write(0);
SI4463->spi->transfer_2 (command, 1, trash, 1);
SI4463->spi->transfer_2 (data, size, trash, size);
SI4463->cs->write(1);
wait_us(1);
}
void SI4463_FIFO_read (SI4463_Chip* SI4463, unsigned char* data, int size) {
unsigned char trash [200]; //static
unsigned char command[6];
command[0] = 0x77;
SI4463->cs->write(0);
SI4463->spi->transfer_2 (command, 1, trash, 1);
SI4463->spi->transfer_2 (trash, size, data, size);
SI4463->cs->write(1);
wait_us(1);
}
//fin a supprimer
void SI4463_change_state (SI4463_Chip* SI4463, unsigned char new_state) {
unsigned char command[6];
command[0] = 0x34;
command[1] = new_state;
SI4463_send_command(SI4463, command, 2);
SI4463_CTS_read_answer (SI4463, command, 0, 30);
}
void SI4463_start_RX (SI4463_Chip* SI4463, unsigned char channel) {
static unsigned char command[12] = {0x32, 0, 0, 0, 0, 0x08, 0x08, 0x08};
command[1] = channel;
SI4463_send_command(SI4463, command, 8);
SI4463_CTS_read_answer (SI4463, command, 0, 55);
}
void SI4463_start_TX (SI4463_Chip* SI4463, unsigned char channel, unsigned int size) {
static unsigned char command[12] = {0x31, 0, 0x50, 0, 0, 0, 0};
command[1] = channel;
command[3] = (size & 0x1F00) >> 8;
command[4] = size & 0xFF;
SI4463_send_command(SI4463, command, 8);
}
void SI4463_read_FRR(SI4463_Chip* SI4463, unsigned char* data) {
unsigned char command[8];
unsigned char loc_answer[8];
int i;
command[0] = 0x50;
SI4463->cs->write(0);
SI4463->spi->transfer_2(command, 5, loc_answer, 5);
SI4463->cs->write(1);
wait_us(1);
for (i=0; i<4; i++) {
data[i] = loc_answer[i+1];
}
}
int SI4463_get_state(SI4463_Chip* SI4463) {
unsigned char command[8];
unsigned char loc_answer[8];
command[0] = 0x33;
SI4463_send_command(SI4463, command, 1);
SI4463_CTS_read_answer (SI4463, loc_answer, 2, 55);//!!! previous 5 / 2020_02_22
return loc_answer[0];
}
void SI4463_clear_IT(SI4463_Chip* SI4463, unsigned char PH_clear, unsigned char modem_clear) {
unsigned char command[8];
//unsigned char loc_answer[8];
command[0] = 0x20; // GET_INT
//command[1] = 0x00;
command[1] = PH_clear;
command[2] = modem_clear;
command[3] = 0x00;
SI4463_send_command(SI4463, command, 4);
//wait_us(20);
//SI4463_CTS_read_answer (SI4463, loc_answer, 2, 5);
//return loc_answer[0];
}
void SI4463_set_TX_preamble_length (SI4463_Chip* SI4463, unsigned char preamble_length_val) {
unsigned char trash [10];
unsigned char command_preamble_length[10] = {0x11, 0x10, 0x01, 0x00, 0x20};
command_preamble_length [4] = preamble_length_val;
SI4463_send_command(G_SI4463, command_preamble_length, 5);
wait_us(20); // !!!
SI4463_CTS_read_answer(G_SI4463, trash, 0, 20);
}
int SI4463_read_temperature(SI4463_Chip* SI4463) {
int temperature;
unsigned char answer_loc [10];
unsigned char command_temp_read[10] = {0x14, 0x10, 0xA0};
SI4463_send_command(SI4463, command_temp_read, 3);
//wait_ms(2);
wait_us(20);
if (SI4463_CTS_read_answer(SI4463, answer_loc, 6, 2000) ) {
temperature = answer_loc[4] * 256 + answer_loc[5];
temperature = temperature * 0.2195 - 293;
} else {
temperature = 0xFFFF;
}
return temperature;
}
static int previous_temperature = 300;
void SI4463_periodic_temperature_check(SI4463_Chip* SI4463) {
int need_recalibrate;
int delta_temperature;
int i;
//RADIO_off_if_necessary(0);
G_temperature_SI4463 = SI4463_read_temperature (SI4463);
if (previous_temperature == 300) {
previous_temperature = G_temperature_SI4463;
}
delta_temperature = G_temperature_SI4463 - previous_temperature;
if ( ( delta_temperature > 14) || (delta_temperature < -14) ) {
//if (1) {
need_recalibrate = 1;
i = SI4463_configure_all();
previous_temperature = G_temperature_SI4463;
if (i == 0) {//fail to recalibrate
NVIC_SystemReset();
}
} else {
need_recalibrate = 0;
}
//RADIO_restart_if_necessary(0, need_recalibrate, 0); //0,need,0
}
static unsigned int RX_size_remaining = 0;
void SI4463_periodic_temperature_check_2(void) {
unsigned long int timer_snapshot;
int delta_temperature;
int i;
unsigned char trash [10];
timer_snapshot = GLOBAL_timer.read_us();
if ( (is_TDMA_master) && (CONF_master_FDD == 2) && (CONF_radio_state_ON_OFF) ) {
SI4463_prepa_TX_1_call.attach_us(&SI4463_prepa_TX_1, 500000);//simulates TX transition
}
else if ( (is_TDMA_master) && (CONF_radio_state_ON_OFF) && ((timer_snapshot-last_rframe_seen) > (CONF_radio_timeout+1000000) ) ) {
//if (G_need_temperature_check == 1) {
G_need_temperature_check = 0;
if (previous_temperature == 300) {
previous_temperature = G_temperature_SI4463;
}
G_temperature_SI4463 = SI4463_read_temperature (G_SI4463);
delta_temperature = G_temperature_SI4463 - previous_temperature;
if ( ( delta_temperature > 14) || (delta_temperature < -14) ) {
previous_temperature = G_temperature_SI4463;
G_SI4463->RX_TX_state = 0;
//SI4463_change_state(G_SI4463, 0x03); //switch to ready
RX_FIFO_WR_point = RX_FIFO_last_received; // rewind WR_pointer to last complete packet
//SI4463_FIFO_status(G_SI4463, &toto, &toto, 1); //reset FIFO
//SI4463_clear_IT (G_SI4463, 0, 0);
i = SI4463_configure_all();
if (i == 0) {//fail to recalibrate
NVIC_SystemReset();
}
//SI4463_start_RX(G_SI4463, CONF_radio_frequency);
SI4463_start_RX(G_SI4463, CONF_channel_RX);
SI4463_clear_IT (G_SI4463, 0, 0);
SI4463_CTS_read_answer (G_SI4463, trash, 2, 5);// ADDED 2018 08 25
RX_size_remaining = 0;
G_SI4463->RX_TX_state = 1; // activate RX HW IRQ
}
//}
}
}
//void SI4463_temp_check_init(void) {
// SI4463_temp_check2_call.attach(&SI4463_periodic_temperature_check_2, 10);//periodic 10 seconds
//}
void SI4463_FIFO_RX_transfer(unsigned int size) {
//unsigned char trash[150]; //static
int size_to_read;
if ( ( (RX_FIFO_WR_point & RX_FIFO_mask) + size) > RX_FIFO_mask) { // to big for 1 step
size_to_read = (RX_FIFO_mask + 1 - (RX_FIFO_WR_point & RX_FIFO_mask) );
G_SI4463->spi->transfer_2 (SI_trash, size_to_read, RX_FIFO_data + (RX_FIFO_WR_point & RX_FIFO_mask), size_to_read);
RX_FIFO_WR_point = RX_FIFO_WR_point + size_to_read; // should become ZERO
//second step
size_to_read = size - size_to_read;
G_SI4463->spi->transfer_2 (SI_trash, size_to_read, RX_FIFO_data + (RX_FIFO_WR_point & RX_FIFO_mask), size_to_read);
RX_FIFO_WR_point = RX_FIFO_WR_point + size_to_read;
} else { //1 step is enough
G_SI4463->spi->transfer_2 (SI_trash, size, RX_FIFO_data + (RX_FIFO_WR_point & RX_FIFO_mask), size);
RX_FIFO_WR_point = RX_FIFO_WR_point + size;
}
}
void SI4463_FIFO_TX_transfer(unsigned int size) {
//unsigned char trash[150]; //static
unsigned char command[5];
int size_to_write;
G_SI4463->cs->write(0);
command[0] = 0x66;
G_SI4463->spi->transfer_2 (command, 1, SI_trash, 1);
G_SI4463->spi->transfer_2 (TX_frame_to_send, size, SI_trash, size);
TX_frame_to_send = TX_frame_to_send + size;
G_SI4463->cs->write(1);
}
void SI4463_RX_HOP(void) {
//G_SI4463->RX_LED->write(1);
SI4463_send_command(G_SI4463, CONF_SI4463_freq_conf_RX, 7);
wait_us(20);
SI4463_CTS_read_answer (G_SI4463, SI_trash, 0, 50);
wait_us(20);
//G_SI4463->RX_LED->write(0);
}
void SI4463_TX_HOP(void) {
//G_SI4463->RX_LED->write(1);
SI4463_send_command(G_SI4463, CONF_SI4463_freq_conf_TX, 9);
wait_us(20);
SI4463_CTS_read_answer (G_SI4463, SI_trash, 0, 50);
wait_us(20);
//G_SI4463->RX_LED->write(0);
}
// High level functions
//static unsigned int RX_size_remaining = 0;
static unsigned int time_STOP_TX_burst;
void SI4463_RX_IT() {
static unsigned char RX_small[10];
static unsigned char TX_small[10];
static unsigned char FRR[5];
static unsigned int RX_timer;
static unsigned char RSSI;
int IT_SYNC_detected;
int IT_FIFO_almost_full;
int IT_pckt_RX;
//What has been treated
int Treated_SYNC_detected;
int Treated_FIFO_almost_full;
int Treated_pckt_RX;
// synthesis
int Synth_SYNC_detected;
int Synth_FIFO_almost_full;
int Synth_pckt_RX;
unsigned int size_to_read;
int IT_state;
int toto;
unsigned int timer_snapshot;
int t_rehabilit_interrupt;
unsigned char clear_IT_PH;
unsigned char clear_IT_modem;
Treated_SYNC_detected = 0;
Treated_FIFO_almost_full = 0;
Treated_pckt_RX = 0;
timer_snapshot = GLOBAL_timer.read_us();
wait_us(10);//for RSSI propagation (measure at sync detect)
do {
SI4463_read_FRR (G_SI4463, FRR);
IT_SYNC_detected = FRR[1] & 0x01;
IT_FIFO_almost_full = FRR[0] & 0x01;
IT_pckt_RX = (FRR[0] & 0x10) / 0x10;
Synth_SYNC_detected = IT_SYNC_detected ^ Treated_SYNC_detected; //Xor
Synth_FIFO_almost_full = IT_FIFO_almost_full ^ Treated_FIFO_almost_full;
Synth_pckt_RX = IT_pckt_RX ^ Treated_pckt_RX;
toto = *(G_SI4463->interrupt);
if (Synth_SYNC_detected) {//Sync detected
RSSI = FRR[2];
RX_timer = timer_snapshot - CONF_long_preamble_duration_for_TA;
if ( (is_TDMA_master == 1) && (CONF_master_FDD == 2) ) {//Master UP
RX_timer = RX_timer - TDMA_slave_last_master_top;
}
Treated_SYNC_detected = 1;
RSSI_total_stat = RSSI_total_stat + RSSI;
RSSI_stat_pkt_nb++;
G_SI4463->RX_LED->write(1);
}
if (Synth_FIFO_almost_full || Synth_pckt_RX) { //FIFO full or RX complete
if ( (RX_size_remaining == 0) && (Treated_FIFO_almost_full == 0) && (Treated_pckt_RX == 0) ) { //beginning of new packet
// read first byte of packet : size
TX_small[0] = 0x77;
TX_small[1] = toto;
G_SI4463->cs->write(0);
G_SI4463->spi->transfer_2 (TX_small, 2, RX_small, 2);
RX_size_remaining = RX_small[1] + SI4463_offset_size;
if (RX_size_remaining > SI4463_CONF_max_field2_size ) {
RX_size_remaining = SI4463_CONF_max_field2_size;
}
if (RX_size_remaining > (SI4463_CONF_RX_FIFO_threshold - 1)) { //too big //+10
size_to_read = SI4463_CONF_RX_FIFO_threshold - 1; //+10
} else {
size_to_read = RX_size_remaining;
}
if (Synth_pckt_RX) { // force to read all remaining if full packet received
size_to_read = RX_size_remaining;
G_SI4463->RX_LED->write(0);
}
RX_FIFO_data[RX_FIFO_WR_point & RX_FIFO_mask] = RX_timer & 0xFF; //LSB
RX_FIFO_WR_point++;
RX_FIFO_data[RX_FIFO_WR_point & RX_FIFO_mask] = (RX_timer & 0xFF00) / 0x100;
RX_FIFO_WR_point++;
RX_FIFO_data[RX_FIFO_WR_point & RX_FIFO_mask] = (RX_timer & 0xFF0000) / 0x10000; //MSB
RX_FIFO_WR_point++;
RX_FIFO_data[RX_FIFO_WR_point & RX_FIFO_mask] = RSSI; //RSSI
RX_FIFO_WR_point++;
RX_FIFO_data[RX_FIFO_WR_point & RX_FIFO_mask] = RX_small[1]; //Size. Warning, with negative offset
RX_FIFO_WR_point++;
//read remaining
SI4463_FIFO_RX_transfer(size_to_read);
G_SI4463->cs->write(1);
wait_us(1);
RX_size_remaining = RX_size_remaining - size_to_read;
}
else { // middle or end of a packet
if (RX_size_remaining > SI4463_CONF_RX_FIFO_threshold ) { //too big //+10
size_to_read = SI4463_CONF_RX_FIFO_threshold ;//+10
} else {
size_to_read = RX_size_remaining;
}
if (Synth_pckt_RX) { // force to read all remaining if full packet received
size_to_read = RX_size_remaining;
G_SI4463->RX_LED->write(0);
}
if (RX_size_remaining > 0) { //avoid useless FIFO reading
TX_small[0] = 0x77;
G_SI4463->cs->write(0);
G_SI4463->spi->transfer_2 (TX_small, 1, RX_small, 1);
SI4463_FIFO_RX_transfer(size_to_read);
G_SI4463->cs->write(1);
wait_us(1);
RX_size_remaining = RX_size_remaining - size_to_read;
}
}
if (RX_size_remaining == 0) { //packet is full,
RX_FIFO_last_received = RX_FIFO_WR_point;
}
Treated_FIFO_almost_full = IT_FIFO_almost_full;
Treated_pckt_RX = IT_pckt_RX;
}
clear_IT_PH = ~(Treated_FIFO_almost_full * 0x01 + Treated_pckt_RX * 0x10);
clear_IT_modem = ~(Treated_SYNC_detected * 0x01);
SI4463_clear_IT(G_SI4463, clear_IT_PH, clear_IT_modem);
// checks if new IT has triggered in the meantime
if (IT_SYNC_detected) { //removed 2019_06_16
IT_state = 1; // impossible to have immediate new IT
} else {
t_rehabilit_interrupt = 0;
IT_state = G_SI4463->interrupt->read();
while ( (t_rehabilit_interrupt<18) && (IT_state == 0) ) {
wait_us(1);
IT_state = G_SI4463->interrupt->read();
t_rehabilit_interrupt++;
}
}
} while (IT_state == 0);
}
//static int already_inside_IT = 0;
static int TX_slot_frame_counter=0;
static int radio_lock_TX_pending = 0;
void SI4463_prepa_TX_1(void) {
unsigned long int timer_snapshot;
G_SI4463->RX_LED->write(0);
G_PTT_PA_pin->write(1);
timer_snapshot = GLOBAL_timer.read_us() + 50000;
//if ( (CONF_radio_state_ON_OFF) && (radio_lock_TX_pending == 0) ) {
if ( (CONF_radio_state_ON_OFF) ) {
radio_lock_TX_pending = 1;
G_SI4463->RX_TX_state = 0; //temporary inhibit actions from HW IRQ
if ( (is_TDMA_master) && (CONF_master_FDD<2) && (CONF_radio_state_ON_OFF) && (((timer_snapshot-last_rframe_seen)&0x7FFFFFFF) < CONF_radio_timeout) ) {
//if ( (is_TDMA_master) && (CONF_radio_state_ON_OFF) ) {
SI4463_prepa_TX_1_call.attach_us(&SI4463_prepa_TX_1, CONF_TDMA_frame_duration);//master_TDMA_period
//TDMA_top_measure();
}
SI4463_prepa_TX_2_call.attach_us(&SI4463_prepa_TX_2, 350); //300
if (is_TDMA_master) {
TDMA_master_allocation();
}
}
}
void SI4463_prepa_TX_2(void) {
int toto;
unsigned int loc_time;
unsigned int loc_time_offset;
unsigned char trash [10];
if (CONF_radio_state_ON_OFF) {
loc_time = GLOBAL_timer.read_us();
if (is_TDMA_master) {
loc_time_offset = 530; // 530
} else {
// //loc_time_offset = (time_next_TX_slave-loc_time) & 0xFFFFFF;
loc_time_offset = 530; // 530
}
time_STOP_TX_burst = (loc_time + loc_time_offset + time_max_TX_burst);// & 0xFFFFFF;
SI4463_1st_TX_call.attach_us(&SI4463_decide_new_TX_or_not, loc_time_offset);
SI4463_change_state(G_SI4463, 0x05); //switch to TX_TUNE (with CTS)
RX_FIFO_WR_point = RX_FIFO_last_received; // rewind WR_pointer to last complete packet
SI4463_FIFO_status(G_SI4463, &toto, &toto, 1); //reset FIFO (including CTS)
TX_slot_frame_counter = 0;
SI4463_clear_IT (G_SI4463, 0, 0);//without CTS
G_SI4463->RX_TX_state = 2; // activate TX HW IRQ
wait_us(20);
SI4463_CTS_read_answer(G_SI4463, trash, 0, 20);
SI4463_set_TX_preamble_length(G_SI4463, CONF_preamble_TX_long);
}
}
void SI4463_TX_to_RX_transition(void) {
int toto;
unsigned char trash[10];
SI4463_FIFO_status(G_SI4463, &toto, &toto, 1); //reset FIFO
G_SI4463->RX_TX_state = 0; // temporarly inhibit IRQ
radio_lock_TX_pending = 0;
if (G_need_temperature_check==1) {
SI4463_periodic_temperature_check(G_SI4463);//added 2019_05_31
G_need_temperature_check = 0;
}
SI4463_start_RX(G_SI4463, CONF_channel_RX); // with CTS
SI4463_RX_HOP();// with CTS
SI4463_clear_IT (G_SI4463, 0, 0);
SI4463_CTS_read_answer (G_SI4463, trash, 2, 5);// ADDED 2018 08 25
RX_size_remaining = 0;
G_PTT_PA_pin->write(0);
G_SI4463->RX_TX_state = 1; // activate RX HW IRQ
if ( (is_TDMA_master == 0) && (CONF_radio_modulation == 24) ) {
SI4463_RX_timeout_call.attach_us(&SI4463_RX_timeout, 10*CONF_TDMA_frame_duration);
}
TX_in_progress = 0;
}
void SI4463_RX_timeout (void) {
unsigned int timer_snapshot;
timer_snapshot = GLOBAL_timer.read_us();
if ( (timer_snapshot - last_rframe_seen) > 9*CONF_TDMA_frame_duration) {
SI4463_prepa_TX_1();
last_rframe_seen = timer_snapshot;
}
}
void Radio_purge_old_frames (void) {
int force_loop_exit = 0;
unsigned int loc_size;
unsigned char RX_frame_datation;
unsigned char loc_time_char;
unsigned int loc_time_int;
loc_time_int = GLOBAL_timer.read_us();
loc_time_char = (loc_time_int >> 16) & 0xFF;
while (force_loop_exit == 0) {
if (TX_buff_intern_RD_pointer < TX_buff_intern_last_ready) {//data available in FIFO
RX_frame_datation = TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128][0];
if ( (loc_time_char - RX_frame_datation) > CONF_Tx_rframe_timeout) {//CONF_Tx_rframe_timeout
loc_size = TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128][1];
loc_size = loc_size + 2 + SI4463_offset_size;
//+2 because timer byte and size byte
if (loc_size <= 128) {
TX_buff_intern_RD_pointer = TX_buff_intern_RD_pointer + 1;
} else if (loc_size <= 256) {
TX_buff_intern_RD_pointer = TX_buff_intern_RD_pointer + 2;
} else {
TX_buff_intern_RD_pointer = TX_buff_intern_RD_pointer + 3;
}
//printf("purged!\r\n");
//printf("date1 %i date2 %i\r\n", loc_time_char, RX_frame_datation);
}
else { //packet is recent
force_loop_exit = 1;
}
}
else { //no data available in FIFO
force_loop_exit = 1;
}
}
}
int TX_test_mode = 0;
void SI4463_decide_new_TX_or_not (void) { //decides if new frame must be transmitted, and which frame
unsigned int loc_size;
unsigned int loc_time;
unsigned char TDMA_sync;
int delta_end_burst; // >0 not enough time
int OK_send_PS;
int PS_data_available;
slave_new_burst_tx_pending = 0;
OK_send_PS = 0;
PS_data_available = 0;
Radio_purge_old_frames();
if (TX_buff_intern_RD_pointer < TX_buff_intern_last_ready) {//data available in TXPS
PS_data_available = 1;
loc_size = TX_intern_FIFO_get_lastfrzize();
} else {
loc_size = 120;
}
loc_time = GLOBAL_timer.read_us();
delta_end_burst = loc_time + (loc_size * CONF_byte_duration) + CONF_preamble_duration_for_decide - time_STOP_TX_burst - 50;
if (TX_slot_frame_counter == 0) {
delta_end_burst = delta_end_burst + CONF_additional_preamble;
}
//printf("%i\r\n", delta_end_burst);
if (delta_end_burst < 0) {
OK_send_PS = 1;
}
if (TX_slot_frame_counter == 0) {
TDMA_sync = 1;
} else {
TDMA_sync = 0;
}
if (CONF_radio_state_ON_OFF==0) {//radio off check for TX test
if (TX_test_inprogress == 1) {
TX_frame_to_send = TX_TDMA_intern_data;
SI4463_TX_new_frame(TDMA_sync);
} else {
SI4463_TX_to_RX_transition();
}
}
else { //normal operation
if (is_TDMA_master) {
if (CONF_master_FDD==2) {
SI4463_TX_to_RX_transition();//Master FDD up, go immediately to RX
}
else if (TX_slot_frame_counter == 0) { // systematically send TDMA signaling frame
TX_frame_to_send = TX_TDMA_intern_data;
TDMA_top_measure();
//G_PTT_PA_pin->write(1);
if (CONF_master_FDD == 1) {//Master FDD downlink
G_FDD_trig_pin->write(1);
}
SI4463_TX_new_frame(TDMA_sync);
SI4463_set_TX_preamble_length(G_SI4463, CONF_preamble_TX_short);
TX_slot_frame_counter++;
}
else if (PS_data_available && OK_send_PS) {
TX_intern_FIFO_read (TX_temp_rframe);
TX_frame_to_send = TX_temp_rframe;
SI4463_TX_new_frame(TDMA_sync);
TX_slot_frame_counter++;
}
else {
TX_slot_frame_counter = 0;
//G_PTT_PA_pin->write(0);
if (CONF_master_FDD == 1) {//Master FDD downlink
G_FDD_trig_pin->write(0);
}
SI4463_TX_to_RX_transition();
}
} else { // SLAVE
if ( (PS_data_available==0) && (TX_slot_frame_counter==0) && (my_client_radio_connexion_state==2) ) {//send a null frame
TX_frame_to_send = TX_TDMA_intern_data;
SI4463_TX_new_frame(TDMA_sync);
if (TX_slot_frame_counter == 0) {
SI4463_set_TX_preamble_length(G_SI4463, CONF_preamble_TX_short);
}
TX_slot_frame_counter++;
}
else if ( (PS_data_available) && (OK_send_PS) ) {
TX_intern_FIFO_read (TX_temp_rframe);
TX_frame_to_send = TX_temp_rframe;
SI4463_TX_new_frame(TDMA_sync);
if (TX_slot_frame_counter == 0) {
SI4463_set_TX_preamble_length(G_SI4463, CONF_preamble_TX_short);
}
TX_slot_frame_counter++;
}
else {
TX_slot_frame_counter = 0;
SI4463_TX_to_RX_transition();
}
}
}
}
static unsigned int TX_size_remaining = 0;
void SI4463_TX_new_frame(unsigned char synchro) {
//unsigned char timer_coarse;
unsigned int full_packet_size;
unsigned int size_to_send;
unsigned char trash[10];
TX_in_progress = 1;
//prefill TX FIFO with small amount of data
TX_frame_to_send++; //1st byte ignored timer coarse
TX_size_remaining = TX_frame_to_send[0] + 1 + SI4463_offset_size;
full_packet_size = TX_size_remaining;
TX_frame_to_send[1] = TDMA_byte_elaboration(synchro);
SI4463_FIFO_TX_transfer(30);
TX_size_remaining = TX_size_remaining - 30;
//start TX order
SI4463_start_TX (G_SI4463, CONF_channel_TX, full_packet_size);
//FIFO transfer
if (TX_size_remaining < 95) { //sent in 1 pass //95
size_to_send = TX_size_remaining;
} else {
size_to_send = 95; //95
}
SI4463_FIFO_TX_transfer(size_to_send);
//CTS
SI4463_CTS_read_answer (G_SI4463, trash, 0, 55);//TEST previously 5
TX_size_remaining = TX_size_remaining - size_to_send;
}
void SI4463_HW_TX_IT() {
static unsigned char FRR[5];
int size_to_write;
int IT_FIFO_almost_empty;
int IT_pckt_sent;
int Treated_FIFO_almost_empty;
int Treated_pckt_sent;
int Synth_FIFO_almost_empty;
int Synth_pckt_sent;
int IT_state;
int t_rehabilit_interrupt;
unsigned char clear_IT_PH;
Treated_FIFO_almost_empty = 0;
Treated_pckt_sent = 0;
do {
SI4463_read_FRR (G_SI4463, FRR);
IT_FIFO_almost_empty = (FRR[0] & 0x02 ) /0x02;
IT_pckt_sent = (FRR[0] & 0x20 ) /0x20;
Synth_FIFO_almost_empty = IT_FIFO_almost_empty ^ Treated_FIFO_almost_empty;
Synth_pckt_sent = IT_pckt_sent ^ Treated_pckt_sent;
if (Synth_pckt_sent) {
TX_in_progress = 0;
SI4463_decide_new_TX_or_not();
Treated_pckt_sent = 1;
Treated_FIFO_almost_empty = IT_FIFO_almost_empty; // trick
}
Synth_FIFO_almost_empty = IT_FIFO_almost_empty ^ Treated_FIFO_almost_empty;
if (Synth_FIFO_almost_empty) {
// FIFO almost empty
if (TX_size_remaining > 0) {//more data to send on this packet
if (TX_size_remaining > SI4463_CONF_TX_FIFO_threshold) {//not enough space in FIFO for full packet
size_to_write = SI4463_CONF_TX_FIFO_threshold;
} else {
size_to_write = TX_size_remaining;
}
SI4463_FIFO_TX_transfer (size_to_write);
TX_size_remaining = TX_size_remaining - size_to_write;
}
Treated_FIFO_almost_empty = 1; //even if nothing more to send
}
clear_IT_PH = ~(Treated_FIFO_almost_empty * 0x02 + Treated_pckt_sent * 0x20);
SI4463_clear_IT(G_SI4463, clear_IT_PH, 0x00);
//wait_us(25);
t_rehabilit_interrupt = 0;
IT_state = G_SI4463->interrupt->read();
while ( (t_rehabilit_interrupt<25) && (IT_state == 0) ) {
wait_us(1);
IT_state = G_SI4463->interrupt->read();
t_rehabilit_interrupt++;
}
} while (IT_state == 0);
}
void SI4463_HW_interrupt() {
if ( (G_SI4463->RX_TX_state == 1) && (CONF_radio_state_ON_OFF) ) { //Receive
SI4463_RX_IT();
}
if (G_SI4463->RX_TX_state == 2) { //transmit
SI4463_HW_TX_IT();
}
}
int SI4463_configure_all(void) {
int answer_loc = 0;
int i = 0;
G_SI4463->SDN->write(0);
wait_ms(10);//100
G_SI4463->SDN->write(1);
wait_ms(500);//100 20
G_SI4463->SDN->write(0);
wait_ms(200);//500 20
while ( (answer_loc == 0) && (i < 5) ) {
i++;
//if (CONF_radio_modulation == 10) {
// answer_loc = SI4463_configure_from_10(G_SI4463);
//}
if (CONF_radio_modulation == 20) {
answer_loc = SI4463_configure_from_20(G_SI4463);
}
if (CONF_radio_modulation == 11) {
answer_loc = SI4463_configure_from_11(G_SI4463);
}
if (CONF_radio_modulation == 21) {
answer_loc = SI4463_configure_from_21(G_SI4463);
}
if (CONF_radio_modulation == 12) {
answer_loc = SI4463_configure_from_12(G_SI4463);
}
if (CONF_radio_modulation == 22) {
answer_loc = SI4463_configure_from_22(G_SI4463);
}
if (CONF_radio_modulation == 13) {
answer_loc = SI4463_configure_from_13(G_SI4463);
}
if (CONF_radio_modulation == 23) {
answer_loc = SI4463_configure_from_23(G_SI4463);
}
if (CONF_radio_modulation == 14) {
answer_loc = SI4463_configure_from_14(G_SI4463);
}
if (CONF_radio_modulation == 24) {
answer_loc = SI4463_configure_from_24(G_SI4463);
}
RADIO_compute_freq_params();
}
return answer_loc;
}
void SI4463_radio_start(void) {
if (CONF_radio_state_ON_OFF == 0) {
//SI4463_change_state(G_SI4463, 0x03);//change state to ready
wait_ms(1);
G_SI4463->RX_TX_state = 0;
SI4463_clear_IT(G_SI4463, 0, 0);
//wait_ms(10);
SI4463_CTS_read_answer (G_SI4463, SI_trash, 0, 600);
CONF_radio_state_ON_OFF = 1;
if ( (is_TDMA_master) && (CONF_master_FDD < 2) ) {
SI4463_prepa_TX_1();
} else {
SI4463_TX_to_RX_transition();
}
//TDMA_init_all();
}
}
void RADIO_on(int need_disconnect, int need_radio_reconfigure, int HMI_output) {
last_rframe_seen = GLOBAL_timer.read_us();
wait_ms(50);//10
if (need_radio_reconfigure == 1) {
if (HMI_output) { HMI_printf("reconfiguring radio...\r\n"); }
SI4463_configure_all();
if (HMI_output) { HMI_printf("reconfiguring done; starting radio\r\n"); }
}
if (need_disconnect == 1) {
if (is_TDMA_master == 1) {
my_client_radio_connexion_state = 2;
} else {
my_client_radio_connexion_state = 1;
my_radio_client_ID = 0x7E;
}
}
TDMA_NULL_frame_init(70);
if (need_disconnect == 1) {
TDMA_init_all();
}
radio_flush_TX_FIFO();// A supprimer!
SI4463_radio_start();
//need_radio_reconfigure = 0;
}
void RADIO_off(int need_disconnect) {
int toto;
CONF_radio_state_ON_OFF = 0;
if ( (is_TDMA_master == 0 ) && (need_disconnect == 1) ) {
my_client_radio_connexion_state = 1;
my_radio_client_ID = 0x7E;
}
wait_ms(100);//400
SI4463_FIFO_status(G_SI4463, &toto, &toto, 1);//tentative
G_SI4463->RX_TX_state = 0;//tentative
G_SI4463->RX_LED->write(0);
wait_us(10);
SI4463_change_state(G_SI4463, 0x03);//change state to ready
wait_us(10);
SI4463_FIFO_status(G_SI4463, &toto, &toto, 1);//tentative
wait_us(10);
SI4463_clear_IT (G_SI4463, 0, 0);//tentative
wait_ms(10);
RX_FIFO_WR_point = RX_FIFO_last_received; //rewind FIFO pointer
G_PTT_PA_pin->write(0);
TX_in_progress = 0;
}
static int RADIO_previous_state;
void RADIO_off_if_necessary(int need_disconnect) {
if (CONF_radio_state_ON_OFF == 1) {
RADIO_previous_state = 1;
RADIO_off(need_disconnect);
} else {
RADIO_previous_state = 0;
}
}
void RADIO_restart_if_necessary(int need_disconnect, int need_radio_reconfigure, int HMI_output) {
if (RADIO_previous_state == 1) {
RADIO_on(need_disconnect, need_radio_reconfigure, HMI_output);
}
}
void SI4432_TX_test(unsigned int req_duration) { //duration in ms
int toto;
unsigned int timer_begin;
unsigned int timer_snapshot;
unsigned int real_duration;
unsigned char SI4463_state;
unsigned char loc_answer[8];
unsigned char trash[4];
TX_test_inprogress = 1;
TX_frame_to_send = TX_TDMA_intern_data;
req_duration = req_duration * 1000; //converts ms to microsec
SI4463_FIFO_status(G_SI4463, &toto, &toto, 1); //reset FIFO (including CTS)
SI4463_clear_IT (G_SI4463, 0, 0);//without CTS
G_SI4463->RX_TX_state = 2; // activate TX HW IRQ
wait_us(20);
SI4463_CTS_read_answer(G_SI4463, trash, 0, 20);
G_SI4463->RX_TX_state = 2;
TDMA_NULL_frame_init(230);
SI4463_TX_new_frame(0);
timer_begin = GLOBAL_timer.read_us();
do {
wait_ms(2);
timer_snapshot = GLOBAL_timer.read_us();
real_duration = (timer_snapshot - timer_begin);
} while (real_duration < (req_duration) ) ;
TX_test_inprogress = 0;
wait_ms(200);
RADIO_off(1);
}
void SI4463_set_frequency(float freq_base, float freq_step) {
unsigned char radio_config[15] = {0x11, 0x40, 0x06, 0x00};
unsigned int step_size_temp, FC_int, FC_frac_int, i;
float FC_int_float, FC_frac_float;
//FC_int_float = freq_base / 7.5;
FC_int_float = freq_base * SI4463_NOUTDIV / 60;
FC_int = (unsigned int)FC_int_float - 1;
FC_frac_float = (FC_int_float - (float)FC_int) * 524288;
FC_frac_int = (unsigned int)(FC_frac_float);
//printf ("\r\nfreq_base %f \r\nfreq step %f\r\n", freq_base, freq_step);
//printf ("\r\nFC_int_float %f\r\nFC_int %i\r\nFC_frac_float %f\r\nFC_frac_int%i\r\n", FC_int_float, FC_int, FC_frac_float, FC_frac_int);
step_size_temp = (unsigned int)(524288*freq_step/7.5);
radio_config [4] = FC_int & 0xFF; //FREQ_CONTROL_INTE
radio_config [5] = (FC_frac_int & 0xFF0000) >> 16; //FREQ_CONTROL_FRAC MSB
radio_config [6] = (FC_frac_int & 0x00FF00) >> 8; // ...
radio_config [7] = (FC_frac_int & 0x0000FF); //FREQ_CONTROL_FRAC LSB
radio_config [8] = (step_size_temp & 0xFF00) >> 8; //FREQ_CONTROL_STEP_SIZE MSB
radio_config [9] = step_size_temp & 0x00FF; //FREQ_CONTROL_STEP_SIZE LSB
//for (i=0; i<10; i++) {
// printf("i%i : %02X\r\n", i, radio_config[i]);
//}
SI4463_send_command(G_SI4463, radio_config, 10);
wait_ms(100);// 100us
SI4463_CTS_read_answer(G_SI4463, SI_trash, 0, 200);
wait_ms(100);// 100us
}
void RADIO_compute_freq_params() {
float freq_local, freq_shift_loc;
float loc_freq_float_RX;
float loc_freq_float_TX;
freq_local = FREQ_RANGE_MIN + ((float)CONF_frequency_HD)/1000;//unit MHz
freq_shift_loc = ((float)CONF_freq_shift)/1000;//unit MHz
if (is_TDMA_master == 1) {
loc_freq_float_RX = freq_local + freq_shift_loc;
loc_freq_float_TX = freq_local;//downlink
if(CONF_master_FDD == 1) {//artificially disables RX for Master down
loc_freq_float_RX = freq_local;
}
} else {
loc_freq_float_RX = freq_local;//downlink
loc_freq_float_TX = freq_local + freq_shift_loc;//uplink
}
unsigned int FC_int, FC_frac_int, VCO_CNT_int;
float FC_int_float, FC_frac_float, VCO_CNT_float;
//TX frequency
//FC_int_float = loc_freq_float_TX / 7.5;
FC_int_float = loc_freq_float_TX * SI4463_NOUTDIV / 60;
FC_int = (unsigned int)FC_int_float - 1;
FC_frac_float = (FC_int_float - (float)FC_int) * 524288;
FC_frac_int = (unsigned int)(FC_frac_float);
//VCO_CNT_float = loc_freq_float_TX * 256/60 + 0.5;
VCO_CNT_float = (loc_freq_float_TX*32/60) * SI4463_NOUTDIV;
VCO_CNT_int = (unsigned int)(VCO_CNT_float);
CONF_SI4463_freq_conf_TX[0] = 0x37;
CONF_SI4463_freq_conf_TX[1] = FC_int & 0xFF; //FREQ_CONTROL_INTE
CONF_SI4463_freq_conf_TX[2] = (FC_frac_int & 0xFF0000) >> 16;//FREQ_CONTROL_FRAC MSB
CONF_SI4463_freq_conf_TX[3] = (FC_frac_int & 0x00FF00) >> 8; // ...
CONF_SI4463_freq_conf_TX[4] = (FC_frac_int & 0x0000FF); //FREQ_CONTROL_FRAC LSB
CONF_SI4463_freq_conf_TX[5] = (VCO_CNT_int & 0xFF00) >> 8;// VCO CNT MSB
CONF_SI4463_freq_conf_TX[6] = (VCO_CNT_int & 0x00FF); // VCO CNT LSB
CONF_SI4463_freq_conf_TX[7] = 0x00;// PLL settle time MSB
CONF_SI4463_freq_conf_TX[8] = 0x64;// PLL settle time LSB (us)
//RX frequency
//FC_int_float = loc_freq_float_RX / 7.5;
FC_int_float = loc_freq_float_RX * SI4463_NOUTDIV / 60;
FC_int = (unsigned int)FC_int_float - 1;
FC_frac_float = (FC_int_float - (float)FC_int) * 524288;
FC_frac_int = (unsigned int)(FC_frac_float);
//VCO_CNT_float = loc_freq_float_RX * 256/60 -2 + 0.5;
VCO_CNT_float = (loc_freq_float_RX*32/60 - 32/128) * SI4463_NOUTDIV;
VCO_CNT_int = (unsigned int)(VCO_CNT_float);
CONF_SI4463_freq_conf_RX[0] = 0x36;
CONF_SI4463_freq_conf_RX[1] = FC_int & 0xFF; //FREQ_CONTROL_INTE
CONF_SI4463_freq_conf_RX[2] = (FC_frac_int & 0xFF0000) >> 16;//FREQ_CONTROL_FRAC MSB
CONF_SI4463_freq_conf_RX[3] = (FC_frac_int & 0x00FF00) >> 8; // ...
CONF_SI4463_freq_conf_RX[4] = (FC_frac_int & 0x0000FF); //FREQ_CONTROL_FRAC LSB
CONF_SI4463_freq_conf_RX[5] = (VCO_CNT_int & 0xFF00) >> 8;// VCO CNT MSB
CONF_SI4463_freq_conf_RX[6] = (VCO_CNT_int & 0x00FF); // VCO CNT LSB
CONF_channel_TX = 0;
CONF_channel_RX = 0;
SI4463_set_frequency(loc_freq_float_TX, 10);
}