NPR70/NPR_14/source/L1L2_radio.cpp

759 lines
26 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 "L1L2_radio.h"
#include "mbed.h"
#include "global_variables.h"
#include "W5500.h"
#include "SI4463.h"
#include "Eth_IPv4.h"
#include "TDMA.h"
#include "signaling.h"
#include "ext_SRAM2.h"
//Timeout SI4463_prepa_TX_1_call;
static unsigned char trash[130];
static unsigned char data_RX[360];//260
static unsigned char rframe_TX[384];
void FDDup_RX_FIFO_dequeue(void) {
int rframe_lgth, i;
unsigned char data_temp;
unsigned long int timer_snapshot;
i = 0;
if (RX_FIFO_last_received > RX_FIFO_RD_point) {
for (i=0; i<=3; i++) {//4 bytes for timer and RSSI
data_RX[i] = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
RX_FIFO_RD_point++;
}
data_temp = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
RX_FIFO_RD_point++;
rframe_lgth = data_temp + SI4463_offset_size;
data_RX[4] = data_temp;
for (i=0; i<rframe_lgth; i++) {
data_RX[i+5] = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
RX_FIFO_RD_point++;
}
W5500_write_TX_buffer(W5500_p1, 4, data_RX, rframe_lgth+5, 0);
timer_snapshot = GLOBAL_timer.read_us();
last_rframe_seen = timer_snapshot;
//debug_counter++;
}
}
void FDDdown_RX_pckt_treat(unsigned char* in_data, int size) {
//puts raw RX radio packet from Ethernet to RX buffer
memcpy (RX_FIFO_data, in_data, size+4);
RX_FIFO_RD_point = 0;
RX_FIFO_last_received = size;
radio_RX_FIFO_dequeue(W5500_p1);
//debug_counter++;
}
// static int RX_FRAME_count_debug = 0;
void radio_RX_FIFO_dequeue (W5500_chip* W5500) {
static unsigned char ethernet_buffer[radio_addr_table_size][1600];
static int size_received[radio_addr_table_size];
static unsigned char prev_seg_counter[radio_addr_table_size];
static unsigned char curr_pkt_counter[radio_addr_table_size];
unsigned char seg_counter;
unsigned char pkt_counter;
unsigned char is_last_seg;
unsigned char client_addr;
unsigned char LID;
unsigned char protocol;
unsigned char protocol_byte;
unsigned char client_ID_byte;
unsigned char segmenter_byte;
//static unsigned char data_RX[260];
int TA_local = 100000;
int RSSI;
int rframe_lgth;
int size_w_FEC;
int size_wo_FEC;
int segment_size;
int client_ID_filter;
unsigned int loc_micro_BER;
unsigned int frame_timer;
static int rx_count = 0;
unsigned char TDMA_byte;
unsigned char is_downlink;
unsigned long int timer_snapshot;
// int i;
if (RX_FIFO_last_received > RX_FIFO_RD_point) { //something new in RX FIFO
timer_snapshot = GLOBAL_timer.read_us();
//printf ("something in RX FIFO\r\n");
//RX_FRAME_count_debug++;
//printf("%i RX:", RX_FRAME_count_debug);
//for (i=4; i<10; i++){
// printf("%02X.",RX_FIFO_data[(RX_FIFO_RD_point+i) & RX_FIFO_mask]);
//}
//printf("\r\n");
frame_timer = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
RX_FIFO_RD_point++;
frame_timer = (0x100 * RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask]) + frame_timer;
RX_FIFO_RD_point++;
frame_timer = (0x10000 * RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask]) + frame_timer;
RX_FIFO_RD_point++;
RSSI = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
RX_FIFO_RD_point++;
rframe_lgth = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask] + SI4463_offset_size;
RX_FIFO_RD_point++;
if (rframe_lgth > SI4463_CONF_max_field2_size) {
rframe_lgth = SI4463_CONF_max_field2_size;
}
TDMA_byte = RX_FIFO_data[RX_FIFO_RD_point & RX_FIFO_mask];
is_downlink = TDMA_byte & 0x40;
RX_FIFO_RD_point++;
client_ID_byte = RX_FIFO_data[ (RX_FIFO_RD_point ) & RX_FIFO_mask]; // +1
protocol_byte = RX_FIFO_data[ (RX_FIFO_RD_point + 1) & RX_FIFO_mask]; // +2
size_w_FEC = rframe_lgth - 1;
if (is_TDMA_master) {
TA_local = TDMA_TA_measure_single_frame(frame_timer, TDMA_byte, client_ID_byte, size_w_FEC);
if ( (timer_snapshot-last_rframe_seen) > (CONF_radio_timeout+1000000) ) {
last_rframe_seen = timer_snapshot;
wait_ms(20);//lets time for client to switch to RX
SI4463_prepa_TX_1();
}
}
last_rframe_seen = timer_snapshot;
// WITH FEC
size_wo_FEC = FEC_decode(data_RX, size_w_FEC, &loc_micro_BER);
//if (loc_micro_BER>0) {printf("err micro%i\r\n", loc_micro_BER);}
radio_save_RSSI_BER (client_ID_byte, is_downlink, RSSI, loc_micro_BER);
//printf("RSSI:%i BER:%i\r\n", RSSI, loc_micro_BER);
protocol = 0;
if ( size_wo_FEC > 0) {
client_addr = data_RX[0] & 0x7F; //inside FEC, non need to use parity bit
if (is_TDMA_master) {
LID = client_addr; //client_addr;
} else {
LID = 0;//only one RX buffer for clients
}
protocol = data_RX[1];
// client ID filter
client_ID_filter = 0;
if (is_TDMA_master) {
if ( (is_downlink == 0) && (client_addr < radio_addr_table_size) ) {
if (CONF_radio_addr_table_status[client_addr]) {
client_ID_filter = 1;
}
}
if ( (is_downlink == 0) && (client_addr == 0x7E) ) {
client_ID_filter = 1;
}
}
else if ( ( (client_addr == my_radio_client_ID) || (client_addr == 0x7F) ) && (is_downlink) ) {
client_ID_filter = 1;
}
if (client_ID_filter) {
/*
if ( (protocol == 0x01) && (LID < radio_addr_table_size) ) { //RAW ETHERNET
segment_size = size_wo_FEC - 3;
segmenter_byte = data_RX[2];
pkt_counter = (segmenter_byte & 0xF0) / 0x10;
is_last_seg = segmenter_byte & 0x08;
seg_counter = segmenter_byte & 0x07;
//printf("RX seg:%02X\r\n", segmenter_byte);
if (seg_counter == 0) {//beginning of a new pkt
curr_pkt_counter[LID] = pkt_counter;
memcpy (ethernet_buffer[LID], data_RX+3, segment_size);
size_received[LID] = segment_size;
//printf("1st seg\r\n");
}
else if ( (seg_counter == (prev_seg_counter[LID] + 1)) && (pkt_counter == curr_pkt_counter[LID]) ) {
//folowing segment
memcpy ( (ethernet_buffer[LID]+size_received[LID]), data_RX+3, segment_size);
size_received[LID] = size_received[LID] + segment_size;
//printf("follow seg\r\n");
}
else { //continuity error
size_received[LID] = 0;
}
prev_seg_counter[LID] = seg_counter;
if ( (is_last_seg == 0x08) && (size_received[LID] > 0) ) {
// Raw Ethernet... Not implemented yet
}
} */
if ( (protocol == 0x02) && (LID < radio_addr_table_size) ) { //IPv4 Access 0x02
//printf("IPv4 fr received\r\n");
segment_size = size_wo_FEC - 3;
segmenter_byte = data_RX[2];
pkt_counter = (segmenter_byte & 0xF0) / 0x10;
is_last_seg = segmenter_byte & 0x08;
seg_counter = segmenter_byte & 0x07;
//printf("RX seg:%02X\r\n", segmenter_byte);
if (seg_counter == 0) {//beginning of a new pkt
curr_pkt_counter[LID] = pkt_counter;
memcpy (ethernet_buffer[LID] + 14, data_RX+3, segment_size);
size_received[LID] = segment_size;
//printf("1st seg\r\n");
}
else if ( (seg_counter == (prev_seg_counter[LID] + 1)) && (pkt_counter == curr_pkt_counter[LID]) ) {
//folowing segment
memcpy ( (ethernet_buffer[LID] + size_received[LID] +14), data_RX+3, segment_size);
size_received[LID] = size_received[LID] + segment_size;
//printf("follow seg\r\n");
}
else { //continuity error
size_received[LID] = 0;
}
prev_seg_counter[LID] = seg_counter;
if ( (is_last_seg == 0x08) && (size_received[LID] > 0) ) {
IPv4_from_radio (ethernet_buffer[LID], size_received[LID] + 14);
G_downlink_bandwidth_temp = G_downlink_bandwidth_temp + size_received[LID];
RX_radio_IPv4_counter++;
//printf("pkt full\r\n");
}
}
else if (protocol == 0x1E) {
//printf("sig fr received\r\n");
signaling_frame_exploitation (data_RX, size_wo_FEC, TA_local);
}
else if ( (protocol == 0x1F) && (is_TDMA_master == 0) ) {
TDMA_slave_alloc_exploitation (data_RX, size_wo_FEC);
}
else if (protocol == 0x00) {
}
else {
if (super_debug) {
printf("ERR Protocol\r\n");
}
}
}
} else {
if (super_debug) {
printf("FEC error\r\n");
}
}
TDMA_byte_RX_interp (TDMA_byte, client_ID_byte, protocol_byte, frame_timer);
rx_count++;
}
}
void radio_signalisation_frame_building(void) {
}
int FEC_encode2 (unsigned char* data_in, unsigned char* data_out, int size_in) {
int size_out;
int size_single_bloc;
int size_single_bloc_pl1;
unsigned char CRC_1;
unsigned char CRC_2;
unsigned char CRC_3;
unsigned char CRC_4;
unsigned char data_field_1;
unsigned char data_field_2;
unsigned char data_field_3;
unsigned char data_field_4;
int i;
CRC_1 = 0;
CRC_2 = 0;
CRC_3 = 0;
CRC_4 = 0;
size_single_bloc = size_in/3;
if (size_in % 3) {
size_single_bloc++;
}
size_single_bloc_pl1 = size_single_bloc + 1;
size_out = 4 * size_single_bloc_pl1;
for (i=0; i<size_single_bloc; i++) {
data_field_1 = data_in[i];
data_field_2 = data_in[size_single_bloc + i];
data_field_3 = data_in[(2*size_single_bloc) + i];
data_field_4 = data_field_1 ^ data_field_2 ^ data_field_3;
CRC_1 = CRC_1 ^ data_field_1;
CRC_2 = CRC_2 ^ data_field_2;
CRC_3 = CRC_3 ^ data_field_3;
CRC_4 = CRC_4 ^ data_field_4;
data_out[i] = data_field_1;
data_out[size_single_bloc_pl1 + i] = data_field_2;
data_out[(2*size_single_bloc_pl1) + i] = data_field_3;
data_out[(3*size_single_bloc_pl1) + i] = data_field_4;
}
data_out[size_single_bloc] = CRC_1;
data_out[(2*size_single_bloc) + 1] = CRC_2;
data_out[(3*size_single_bloc) + 2] = CRC_3;
data_out[(4*size_single_bloc) + 3] = CRC_4;
return size_out;
}
int FEC_decode(unsigned char* data_out, int size_in, unsigned int* micro_BER) {
int size_out;
int size_single_bloc;
int size_single_bloc_pl1;
unsigned char CRC_check_1;
unsigned char CRC_check_2;
unsigned char CRC_check_3;
unsigned char CRC_check_4;
unsigned char data_temp;
unsigned int nb_errors;
int i;
size_single_bloc_pl1 = size_in / 4;
size_single_bloc = size_single_bloc_pl1 - 1;
CRC_check_1 = 0;
CRC_check_2 = 0;
CRC_check_3 = 0;
CRC_check_4 = 0;
for (i=0; i<size_single_bloc_pl1; i++) {
CRC_check_1 = CRC_check_1 ^ RX_FIFO_data [(RX_FIFO_RD_point + i) & RX_FIFO_mask];
CRC_check_2 = CRC_check_2 ^ RX_FIFO_data [(RX_FIFO_RD_point + size_single_bloc_pl1 + i) & RX_FIFO_mask];
CRC_check_3 = CRC_check_3 ^ RX_FIFO_data [(RX_FIFO_RD_point + (2*size_single_bloc_pl1) + i) & RX_FIFO_mask];
CRC_check_4 = CRC_check_4 ^ RX_FIFO_data [(RX_FIFO_RD_point + (3*size_single_bloc_pl1) + i) & RX_FIFO_mask];
}
nb_errors = 0;
if (CRC_check_1 != 0) { nb_errors++; }// printf("error 1 %X ;", CRC_check_1);}
if (CRC_check_2 != 0) { nb_errors++; }// printf("error 2 %X ;", CRC_check_2);}
if (CRC_check_3 != 0) { nb_errors++; }// printf("error 3 %X ;", CRC_check_3);}
if (CRC_check_4 != 0) { nb_errors++; }// printf("error 4 %X ;", CRC_check_4);}
//printf("\r\n");
//if (nb_errors>0) {printf("ERR%i\r\n", nb_errors);}
(*micro_BER) = nb_errors;
if (nb_errors>1) {
size_out = 0; //unrecoverable error
//printf("unrecoverable\r\n");
} else {
// OK
size_out = 3 * size_single_bloc;
// FIELD 1
if (CRC_check_1==0) {//field 1 OK
for (i=0; i<size_single_bloc; i++) {
data_out[i] = RX_FIFO_data [(RX_FIFO_RD_point + i) & RX_FIFO_mask];
}
} else {// field 1 corrupted, reconstruction from field 2, 3 and 4
for (i=0; i<size_single_bloc; i++) {
data_temp = RX_FIFO_data [(RX_FIFO_RD_point + size_single_bloc_pl1 + i) & RX_FIFO_mask];
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + (2*size_single_bloc_pl1) + i) & RX_FIFO_mask];
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + (3*size_single_bloc_pl1) + i) & RX_FIFO_mask];
data_out[i] = data_temp;
}
}
// FIELD 2
if (CRC_check_2==0) {//field 2 OK
for (i=0; i<size_single_bloc; i++) {
data_out[size_single_bloc + i] = RX_FIFO_data [(RX_FIFO_RD_point + size_single_bloc_pl1 + i) & RX_FIFO_mask];
}
} else {// field 2 corrupted, reconstruction from field 1, 3 and 4
for (i=0; i<size_single_bloc; i++) {
data_temp = RX_FIFO_data [(RX_FIFO_RD_point + i) & RX_FIFO_mask]; //field 1
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + (2*size_single_bloc_pl1) + i) & RX_FIFO_mask]; //field 3
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + (3*size_single_bloc_pl1) + i) & RX_FIFO_mask]; //field 4
data_out[size_single_bloc + i] = data_temp;
}
}
// FIELD 3
if (CRC_check_3==0) {//field 3 OK
for (i=0; i<size_single_bloc; i++) {
data_out[(2*size_single_bloc) + i] = RX_FIFO_data[(RX_FIFO_RD_point + (2*size_single_bloc_pl1) + i) & RX_FIFO_mask];
}
} else {// field 3 corrupted, reconstruction from field 1, 2 and 4
for (i=0; i<size_single_bloc; i++) {
data_temp = RX_FIFO_data [(RX_FIFO_RD_point + i) & RX_FIFO_mask]; //field 1
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + size_single_bloc_pl1 + i) & RX_FIFO_mask]; //field 2
data_temp = data_temp ^ RX_FIFO_data [(RX_FIFO_RD_point + (3*size_single_bloc_pl1) + i) & RX_FIFO_mask]; //field 4
data_out[(2*size_single_bloc) + i] = data_temp;
}
}
}
RX_FIFO_RD_point = RX_FIFO_RD_point + size_in;
return size_out;
}
int size_w_FEC_compute (int size_wo_FEC) {
int size_w_FEC;
size_w_FEC = size_wo_FEC/3;
if ((size_wo_FEC%3) > 0) { size_w_FEC++; }
size_w_FEC = 4*size_w_FEC + 4;
return size_w_FEC;
}
void segment_and_push (unsigned char* data_unsegmented, int total_size, unsigned char client_addr, unsigned char protocol) {
static unsigned char packet_counter = 0;
unsigned char segment_counter = 0;
unsigned char segmenter_byte;
unsigned char is_last_segment;
int size_wo_FEC;
int size_w_FEC;
int rframe_length;
int size_remaining;
int segment_size;
int size_to_send;
unsigned char data_wo_FEC[300];
#ifdef EXT_SRAM_USAGE
unsigned char radio_pckt[360];
#endif
int size_sent;
// unsigned int rsize_needed;
unsigned int timer_snapshot;
size_remaining = total_size;
if (size_remaining <63) {
size_remaining = 63;
}
segment_counter = 0;
size_sent = 0;
// rsize_needed = 100 + (total_size * 1.4);
if (total_size < 1510) {
if (TX_FIFO_full_global(1) == 0) {
G_uplink_bandwidth_temp = G_uplink_bandwidth_temp + total_size;
TX_radio_IPv4_counter++;
while (size_remaining > 0) {
if (size_remaining <= 252) {
segment_size = size_remaining;
is_last_segment = 0x08;
} else {
segment_size = 252;
is_last_segment = 0x00;
}
if (segment_size <63) {
size_to_send = 63;
} else {
size_to_send = segment_size;
}
timer_snapshot = GLOBAL_timer.read_us();
rframe_TX[0] = (timer_snapshot >> 16) & 0xFF;
size_wo_FEC = size_to_send + 3; //+ 3 inside FEC header
size_w_FEC = size_w_FEC_compute (size_wo_FEC);
rframe_length = size_w_FEC + 1 - SI4463_offset_size;
if (rframe_length < 0) {rframe_length = 0;}
rframe_TX[1] = rframe_length;
rframe_TX[2] = 0x01; //TDMA byte
segmenter_byte = (packet_counter & 0x0F) * 0x10 + is_last_segment + (segment_counter & 0x07);
data_wo_FEC[0] = client_addr + parity_bit_elab[(client_addr&0x7F)]; //client address
data_wo_FEC[1] = protocol; //protocol : raw ethernet
data_wo_FEC[2] = segmenter_byte; // segmenter byte
memcpy(data_wo_FEC+3, (data_unsegmented + size_sent), size_to_send);
size_sent = size_sent + size_to_send;
size_w_FEC = FEC_encode2(data_wo_FEC, rframe_TX+3, size_wo_FEC);
TX_FIFO_write_global(rframe_TX, size_w_FEC+3);//3 for timer & length & TDMA_byte
size_remaining = size_remaining - segment_size;
segment_counter++;
}
packet_counter++;
} else {
//if (super_debug) {
// printf ("FULL last_ready:%08X RD_point:%08X\r\n", TXPS_FIFO->last_ready, TXPS_FIFO->RD_point);
//}
}
}
}
//unsigned char TX_buff_intern_FIFOdata[42][384];
//unsigned int TX_buff_intern_WR_pointer=0;
//unsigned int TX_buff_intern_RD_pointer=0;
//unsigned int TX_buff_intern_last_ready=0;
void TX_FIFO_write_global(unsigned char* data, int size) {
if (is_SRAM_ext == 1) {
TX_ext_FIFO_write(data, size);
} else {
TX_intern_FIFO_write(data, size);
}
}
void TX_intern_FIFO_write(unsigned char* data, int size) {
if (size <= 128) {
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data, 128);//size
TX_buff_intern_WR_pointer++;
}
else if (size <= 256) {
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data, 128);
TX_buff_intern_WR_pointer++;
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data+128, 128);//size-128
TX_buff_intern_WR_pointer++;
}
else {
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data, 128);
TX_buff_intern_WR_pointer++;
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data+128, 128);
TX_buff_intern_WR_pointer++;
memcpy (TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], data+256, 128);//size-256
TX_buff_intern_WR_pointer++;
}
TX_buff_intern_last_ready = TX_buff_intern_WR_pointer;
}
void ext_SRAM_write2(ext_SRAM_chip* loc_SPI, unsigned char* loc_data, unsigned int address, int size) {
//static unsigned char trash[350];
static unsigned char command[6] = {0x02, 0x00, 0x00, 0x00};
loc_SPI->cs->write(0);
command[3] = address & 0xFF;
command[2] = (address & 0xFF00) >> 8;
command[1] = (address & 0xFF0000) >> 16;
loc_SPI->spi_port->transfer_2 (command, 4, trash, 4);
loc_SPI->spi_port->transfer_2 (loc_data, size, trash, size);
loc_SPI->cs->write(1);
}
void TX_ext_FIFO_write(unsigned char* data, int size) {
unsigned int loc_address;
//printf("size_wr_ext %i\n\r", size);
if (size <= 128) {
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data, loc_address, size);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = data[1];
TX_buff_ext_WR_pointer++;
}
else if (size <= 256) {
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data, loc_address, 128);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = data[1];
TX_buff_ext_WR_pointer++;
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data+128, loc_address, size-128);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = 0;
TX_buff_ext_WR_pointer++;
}
else {
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data, loc_address, 128);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = data[1];
TX_buff_ext_WR_pointer++;
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data+128, loc_address, 128);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = 0;
TX_buff_ext_WR_pointer++;
loc_address = (TX_buff_ext_WR_pointer & 1023)*128;
ext_SRAM_write2(SPI_SRAM_p, data+256, loc_address, size-256);
TX_buff_ext_sizes[TX_buff_ext_WR_pointer & 1023] = 0;
TX_buff_ext_WR_pointer++;
}
TX_buff_ext_last_ready = TX_buff_ext_WR_pointer;
}
int TX_intern_FIFO_get_lastfrzize(void) {
int size_loc;
size_loc = TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128][1];
size_loc = size_loc + 1 + SI4463_offset_size;
return size_loc;
}
int TX_intern_FIFO_read(unsigned char* data) {
int size_loc;
size_loc = TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128][1];//42
size_loc = size_loc + 1 + SI4463_offset_size;
size_loc = size_loc + 1;//for timer coarse
//printf("sizeread: %i\r\n", size_loc);
if (size_loc <= 128) {
memcpy(data, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);//size_loc
TX_buff_intern_RD_pointer++;
}
else if (size_loc<=256) {
memcpy(data, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);
TX_buff_intern_RD_pointer++;
memcpy(data+128, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);//size_loc-128
TX_buff_intern_RD_pointer++;
}
else {
memcpy(data, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);
TX_buff_intern_RD_pointer++;
memcpy(data+128, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);
TX_buff_intern_RD_pointer++;
memcpy(data+256, TX_buff_intern_FIFOdata[TX_buff_intern_RD_pointer % 128], 128);//size_loc-256
TX_buff_intern_RD_pointer++;
}
return size_loc;
}
unsigned int compute_TX_buff_size_global(void) {//for TDMA
unsigned int size_loc;
if (is_SRAM_ext == 1) {
size_loc = (TX_buff_intern_last_ready - TX_buff_intern_RD_pointer);
size_loc = size_loc + (TX_buff_ext_last_ready - TX_buff_ext_RD_pointer);
size_loc = size_loc/3;
} else {
size_loc = (TX_buff_intern_last_ready - TX_buff_intern_RD_pointer)/3;
}
return size_loc;
}
int TX_FIFO_full_global (int priority) {
if (is_SRAM_ext == 1) {
return TX_FIFO_full_withSRAM(priority);
} else {
return TX_FIFO_full_woSRAM(priority);
}
}
int TX_FIFO_full_woSRAM (int priority) {
//priority : 1= normal, 0=high priority (signaling)
int FIFO_filling;
int loc_threshold;
FIFO_filling = TX_buff_intern_WR_pointer - TX_buff_intern_RD_pointer;
if (priority == 1) {
loc_threshold = 110;//low priority
} else {
loc_threshold = 120;//high priority
}
if (FIFO_filling > loc_threshold) {//40
//printf("FIFO_full!\r\n");
return 1;
} else {
return 0;
}
}
int TX_FIFO_full_withSRAM (int priority) {
int FIFO_filling;
int loc_threshold;
FIFO_filling = TX_buff_ext_WR_pointer - TX_buff_ext_RD_pointer;
if (priority == 1) {
loc_threshold = 950;//low priority
} else {
loc_threshold = 1000;//high priority
}
if (FIFO_filling > loc_threshold) {//40
//printf("FIFO_fullext!\r\n");
return 1;
} else {
return 0;
}
}
void ext_SRAM_read2(ext_SRAM_chip* loc_SPI, unsigned char* loc_data, unsigned int address, int size) {
static unsigned char command[6] = {0x03, 0x00, 0x00, 0x00};
loc_SPI->cs->write(0);
command[3] = address & 0xFF;
command[2] = (address & 0xFF00) >> 8;
command[1] = (address & 0xFF0000) >> 16;
loc_SPI->spi_port->transfer_2 (command, 4, trash, 4);
loc_SPI->spi_port->transfer_2 (trash, size, loc_data, size);
loc_SPI->cs->write(1);
}
void ext_SRAM_periodic_call(void) {
int intern_FIFO_filling;
int ext_FIFO_filling;
int i, loc_size;
int loc_bloc_nb=1;
unsigned int loc_address;
unsigned int loc_time_int;
unsigned char RX_frame_datation;
unsigned char loc_time_char;
loc_time_int = GLOBAL_timer.read_us();
loc_time_char = (loc_time_int >> 16) & 0xFF;
intern_FIFO_filling = TX_buff_intern_WR_pointer - TX_buff_intern_RD_pointer;
ext_FIFO_filling = TX_buff_ext_WR_pointer - TX_buff_ext_RD_pointer;
while ( (ext_FIFO_filling > 0) && (intern_FIFO_filling <= 9) ) {
for (i=1; i<=loc_bloc_nb; i++) {
loc_address = (TX_buff_ext_RD_pointer & 1023) *128;
ext_SRAM_read2(SPI_SRAM_p, TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128], loc_address, 128);
if (i==1) {
RX_frame_datation = TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128][0];
loc_size = TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128][1];
loc_size = loc_size + SI4463_offset_size + 2;
//printf("size:%i\r\n", loc_size);
if (loc_size <= 128) {
loc_bloc_nb = 1;
} else if (loc_size <= 256) {
loc_bloc_nb = 2;
} else {
loc_bloc_nb = 3;
}
}
//if (TX_buff_ext_sizes[TX_buff_ext_RD_pointer & 1023] > 0) {
// TX_buff_intern_FIFOdata[TX_buff_intern_WR_pointer % 128][1] = TX_buff_ext_sizes[TX_buff_ext_RD_pointer & 1023];
//}
TX_buff_ext_RD_pointer++;
//printf("delay %i\r\n", (int)loc_time_char - (int)RX_frame_datation);
if ( (loc_time_char - RX_frame_datation) < CONF_Tx_rframe_timeout) {
//if (1) {
//purge old frames if condition false
TX_buff_intern_WR_pointer++;
}
//else {
// printf ("purged!\r\n");//!!!
// printf("date1 %i date2 %i\r\n", loc_time_char, RX_frame_datation);
//}
}
TX_buff_intern_last_ready = TX_buff_intern_WR_pointer;
intern_FIFO_filling = TX_buff_intern_WR_pointer - TX_buff_intern_RD_pointer;
ext_FIFO_filling = TX_buff_ext_WR_pointer - TX_buff_ext_RD_pointer;
}
}
//void radio_flush_TX_FIFO(void) {
// TXPS_FIFO->WR_point = 0;
// TXPS_FIFO->RD_point = 0;
// TXPS_FIFO->last_ready = 0;
//}
int ext_SRAM_detect(void) {
unsigned char data_1[4] = {0x3C, 0x4A, 0xF3, 0x12};
unsigned char data_2[4] = {0xFF, 0xFF, 0xFF, 0xFF};
int i;
int sram_detected = 1;
ext_SRAM_write2(SPI_SRAM_p, data_1, 2345, 4);
ext_SRAM_read2(SPI_SRAM_p, data_2, 2345, 4);
for (i=0; i<4; i++) {
if (data_2[i] != data_1[i]) {sram_detected = 0;}
}
return sram_detected;
}
void radio_flush_TX_FIFO(void) {
TX_buff_intern_WR_pointer=0;
TX_buff_intern_RD_pointer=0;
TX_buff_intern_last_ready=0;
TX_buff_ext_WR_pointer=0;
TX_buff_ext_RD_pointer=0;
TX_buff_ext_last_ready=0;
}
void radio_save_RSSI_BER (unsigned char client_byte, unsigned char is_downlink, unsigned char RSSI_loc, unsigned int micro_BER) {
unsigned char client_ID = 0xF0;
client_ID = client_byte & 0x7F;
if ( (is_TDMA_master) && (is_downlink == 0) && (parity_bit_check[client_byte]) && (client_ID < radio_addr_table_size) ) {
G_radio_addr_table_RSSI[client_ID] = (26 * RSSI_loc) + (0.9 * G_radio_addr_table_RSSI[client_ID]);
G_radio_addr_table_BER[client_ID] = (1250 * micro_BER) + (0.9 * G_radio_addr_table_BER[client_ID]);
}
if ( (is_TDMA_master == 0) && (is_downlink) ) {
G_downlink_RSSI = (26 * RSSI_loc) + (0.9 * G_downlink_RSSI);
G_downlink_BER = (1250 * micro_BER) + (0.9 * G_downlink_BER);
}
//if (micro_BER>0) {printf("err save%i %i\r\n", micro_BER, G_downlink_BER);}
}