// 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 #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; // unsigned 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); }