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.
759 lines
26 KiB
C++
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);}
|
|
}
|