580 lines
No EOL
25 KiB
C++
580 lines
No EOL
25 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 "signaling.h"
|
|
#include "mbed.h"
|
|
#include "Eth_IPv4.h"
|
|
#include "global_variables.h"
|
|
#include "L1L2_radio.h"
|
|
#include "DHCP_ARP.h"
|
|
#include "TDMA.h"
|
|
#include "HMI_telnet.h"
|
|
|
|
#include "ext_SRAM2.h"
|
|
|
|
static unsigned char rframe_TX[380];
|
|
static unsigned char TX_signal_frame_raw[260]; //300
|
|
static int TX_signal_frame_point = 0;
|
|
|
|
static int connect_state_machine_counter = 0;
|
|
static int time_counter_last_ack = 0;
|
|
|
|
void signaling_frame_exploitation (unsigned char* unFECdata, int unFECsize, int TA_input) {
|
|
int data_pos = 2;
|
|
unsigned char field_type;
|
|
unsigned char field_length;
|
|
unsigned char local_ID;
|
|
unsigned char* local_callsign;
|
|
unsigned long int local_IP_start;
|
|
unsigned long int local_IP_size;
|
|
unsigned char local_static_alloc;
|
|
unsigned char local_reason;
|
|
unsigned char local_RSSI;
|
|
unsigned short int local_BER;
|
|
short int local_TA;
|
|
//printf("signaling rx\r\n");
|
|
do {
|
|
field_type = unFECdata[data_pos];
|
|
field_length = unFECdata[data_pos+1];
|
|
switch (field_type) {
|
|
case 0x01 : // WHOIS
|
|
local_ID = unFECdata[data_pos + 2];
|
|
local_callsign = unFECdata + data_pos + 3;
|
|
local_callsign[15] = 0;//force null termination
|
|
local_IP_start = IP_char2int (unFECdata + data_pos + 19);
|
|
local_IP_size = IP_char2int (unFECdata + data_pos + 23);
|
|
local_RSSI = unFECdata[data_pos + 27];
|
|
local_BER = unFECdata[data_pos + 28] + (unFECdata[data_pos + 29] << 8);
|
|
local_TA = unFECdata[data_pos + 30] + (unFECdata[data_pos + 31] << 8);
|
|
signaling_whois_interpret (local_ID, local_callsign,
|
|
local_IP_start, local_IP_size,
|
|
local_RSSI, local_BER, local_TA);
|
|
break;
|
|
case 0x05 : // request new connection
|
|
local_callsign = unFECdata + data_pos + 2;
|
|
local_callsign[15] = 0;
|
|
local_IP_size = IP_char2int (unFECdata + data_pos + 18);
|
|
local_static_alloc = unFECdata[data_pos + 22];
|
|
if (is_TDMA_master) {
|
|
signaling_connect_req_process(local_callsign, local_IP_size, local_static_alloc, TA_input);
|
|
}
|
|
break;
|
|
case 0x06 : // ACK new connection
|
|
local_callsign = unFECdata + data_pos + 3;
|
|
local_callsign[15] = 0;
|
|
if ( (is_TDMA_master == 0) && (strcmp ((char*)local_callsign, CONF_radio_my_callsign) == 0) ) {
|
|
signaling_connect_ACK_process(unFECdata + data_pos + 2);
|
|
}
|
|
break;
|
|
case 0x07 : // NACK new connection
|
|
local_callsign = unFECdata + data_pos + 2;
|
|
local_callsign[15] = 0;
|
|
local_reason = unFECdata[data_pos + 18];
|
|
if ( (is_TDMA_master == 0) && (strcmp ((char*)local_callsign, CONF_radio_my_callsign) == 0) ) {
|
|
signaling_connect_NACK_process(local_reason);
|
|
}
|
|
break;
|
|
case 0x0B : // Request disconnection
|
|
local_ID = unFECdata[data_pos + 2];
|
|
local_callsign = unFECdata + data_pos + 3;
|
|
local_callsign[15] = 0;
|
|
if (is_TDMA_master) {
|
|
signaling_disconnect_req_process (local_ID, local_callsign);
|
|
}
|
|
break;
|
|
case 0x0C : // ACK disconnection
|
|
local_ID = unFECdata[data_pos + 2];
|
|
local_callsign = unFECdata + data_pos + 3;
|
|
local_callsign[15] = 0;
|
|
if ( (is_TDMA_master == 0) && (strcmp ((char*)local_callsign, CONF_radio_my_callsign) == 0) ) {
|
|
signaling_disconnect_ACK_process (local_ID, local_callsign);
|
|
}
|
|
break;
|
|
}
|
|
data_pos = data_pos + field_length + 2;
|
|
|
|
} while ( (field_type != 0xFF) && (data_pos < unFECsize ) );
|
|
|
|
}
|
|
|
|
void signaling_whois_interpret(unsigned char loc_ID, unsigned char* loc_callsign,
|
|
unsigned long int loc_IP_start, unsigned long int loc_IP_size,
|
|
unsigned char RSSI_loc, unsigned short int BER_loc, short int TA_loc) {
|
|
unsigned char IP_start_c[5];
|
|
|
|
IP_int2char (loc_IP_start, IP_start_c);
|
|
//printf("WHOIS ID:%i CALL:%s IP_start %i.%i.%i.%i IP_size %i\r\n", loc_ID, (char*)loc_callsign,
|
|
// IP_start_c[0], IP_start_c[1], IP_start_c[2], IP_start_c[3], loc_IP_size);
|
|
if (is_TDMA_master == 0) { //only useful for slaves
|
|
if (loc_ID == 0x7F) { //who entry for master
|
|
strcpy (CONF_radio_master_callsign, (char*)loc_callsign);
|
|
}
|
|
else if (loc_ID < radio_addr_table_size) {
|
|
CONF_radio_addr_table_date[loc_ID] = GLOBAL_timer.read_us();
|
|
CONF_radio_addr_table_status[loc_ID] = 2; //
|
|
strcpy (CONF_radio_addr_table_callsign[loc_ID], (char*)loc_callsign);
|
|
CONF_radio_addr_table_IP_begin[loc_ID] = loc_IP_start;
|
|
CONF_radio_addr_table_IP_size[loc_ID] = loc_IP_size;
|
|
G_radio_addr_table_RSSI[loc_ID] = RSSI_loc;
|
|
G_radio_addr_table_BER[loc_ID] = BER_loc;
|
|
TDMA_table_TA[loc_ID] = TA_loc;
|
|
}
|
|
}
|
|
}
|
|
|
|
unsigned long int signaling_lookfor_IP_range(unsigned long int req_size) {
|
|
int i, j;
|
|
unsigned long int answer = 0xFFFFFFFF;
|
|
unsigned long int current_tested_pos;
|
|
unsigned long int next_alloc_IP;
|
|
|
|
current_tested_pos = CONF_radio_IP_start;
|
|
next_alloc_IP = CONF_radio_IP_start + CONF_radio_IP_size;
|
|
for (j=0; j<radio_addr_table_size; j++) {//looking for next allocated IP
|
|
if ( (CONF_radio_addr_table_status[j]) && (CONF_radio_addr_table_IP_begin[j] >= current_tested_pos) && (CONF_radio_addr_table_IP_begin[j] < next_alloc_IP) ) {
|
|
next_alloc_IP = CONF_radio_addr_table_IP_begin[j];
|
|
}
|
|
}
|
|
if ( (next_alloc_IP - current_tested_pos) >= req_size) {
|
|
answer = current_tested_pos;
|
|
}
|
|
|
|
for (i=0; i<radio_addr_table_size; i++) {
|
|
if (CONF_radio_addr_table_status[i]) {
|
|
current_tested_pos = CONF_radio_addr_table_IP_begin[i] + CONF_radio_addr_table_IP_size[i];//beginning = end of previous
|
|
if (current_tested_pos < answer) { //only continue search if IP tested is below already found
|
|
next_alloc_IP = CONF_radio_IP_start + CONF_radio_IP_size;
|
|
for (j=0; j<radio_addr_table_size; j++) {//looking for next allocated IP
|
|
if ( (CONF_radio_addr_table_status[j]) && (CONF_radio_addr_table_IP_begin[j] >= current_tested_pos) && (CONF_radio_addr_table_IP_begin[j] < next_alloc_IP) ) {
|
|
next_alloc_IP = CONF_radio_addr_table_IP_begin[j];
|
|
}
|
|
}
|
|
if ( (next_alloc_IP - current_tested_pos) >= req_size) {
|
|
answer = current_tested_pos;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
return answer;
|
|
}
|
|
|
|
void signaling_connect_req_process (unsigned char* client_callsign, unsigned long int req_IP_size, unsigned char req_static_alloc, int TA_input) {
|
|
int loc_ack = 0;
|
|
int i;
|
|
int existing_entry = -1;
|
|
unsigned char client_ID = 0xFF;
|
|
static unsigned char raw_answer[60];
|
|
unsigned char NACK_reason;
|
|
unsigned long int proposed_IP;
|
|
unsigned char previous_status;
|
|
|
|
// 1) look for existing entry for this callsign
|
|
for (i=0; i<radio_addr_table_size; i++) {
|
|
if (strcmp((char*)client_callsign, CONF_radio_addr_table_callsign[i]) == 0) {
|
|
existing_entry = i;
|
|
}
|
|
}
|
|
//printf ("connect req received\r\n");
|
|
//printf ("found client entry %i\r\n", existing_entry);
|
|
if (existing_entry != -1) {
|
|
previous_status = CONF_radio_addr_table_status[existing_entry];
|
|
}
|
|
// 2) logic with 3 cases
|
|
// 2.1) existing entry matches both callsign and size
|
|
if ( (existing_entry != -1) && (req_IP_size == CONF_radio_addr_table_IP_size[existing_entry]) ) {
|
|
client_ID = existing_entry;
|
|
CONF_radio_addr_table_status[existing_entry] = 1;
|
|
CONF_radio_addr_table_date[existing_entry] = GLOBAL_timer.read_us();
|
|
loc_ack = 1; // Ack
|
|
//printf("existing entry matches\r\n");
|
|
}
|
|
// 2.2) existing entry with different size
|
|
if ( (existing_entry != -1) && (req_IP_size != CONF_radio_addr_table_IP_size[existing_entry]) ) {
|
|
CONF_radio_addr_table_status[existing_entry] = 0; //frees existing entry
|
|
proposed_IP = signaling_lookfor_IP_range (req_IP_size);
|
|
if (proposed_IP != 0xFFFFFFFF) {// IP valid found
|
|
client_ID = existing_entry;
|
|
CONF_radio_addr_table_status[client_ID] = 1;
|
|
CONF_radio_addr_table_IP_begin[client_ID] = proposed_IP;
|
|
CONF_radio_addr_table_IP_size[client_ID] = req_IP_size;
|
|
strcpy (CONF_radio_addr_table_callsign[client_ID], (char*)client_callsign);
|
|
CONF_radio_addr_table_date[client_ID] = GLOBAL_timer.read_us();
|
|
loc_ack = 1;
|
|
//printf("existing entry doesnt match, ok new\r\n");
|
|
} else { //no IP found
|
|
NACK_reason = 0x02;
|
|
loc_ack = 0;
|
|
//printf("existing entry doesnt match, no more IP\r\n");
|
|
}
|
|
}
|
|
if ( (existing_entry != -1) && (previous_status==0) && (loc_ack==1) ) {
|
|
TDMA_init_TA(client_ID, TA_input);
|
|
}
|
|
// 2.3) no previous entry
|
|
if (existing_entry == -1) {
|
|
// lookfor empty entry
|
|
for (i=radio_addr_table_size-1; i>=0; i--) {
|
|
if (CONF_radio_addr_table_status[i] <= 0) {
|
|
client_ID = i;
|
|
//printf("client ID search %i\r\n", client_ID);
|
|
}
|
|
}
|
|
if (client_ID == 0xFF) {
|
|
NACK_reason = 0x03; //max nb of clients reached
|
|
loc_ack = 0;
|
|
} else {
|
|
proposed_IP = signaling_lookfor_IP_range (req_IP_size);
|
|
if (proposed_IP != 0xFFFFFFFF) {// IP valid found
|
|
CONF_radio_addr_table_status[client_ID] = 1;
|
|
CONF_radio_addr_table_IP_begin[client_ID] = proposed_IP;
|
|
CONF_radio_addr_table_IP_size[client_ID] = req_IP_size;
|
|
strcpy (CONF_radio_addr_table_callsign[client_ID], (char*)client_callsign);
|
|
CONF_radio_addr_table_date[client_ID] = GLOBAL_timer.read_us();
|
|
TDMA_init_TA(client_ID, TA_input);
|
|
loc_ack = 1;
|
|
//printf("new, alloc OK\r\n");
|
|
} else { //no IP found
|
|
NACK_reason = 0x02;
|
|
loc_ack = 0;
|
|
//printf("new, no more IP\r\n");
|
|
}
|
|
}
|
|
}
|
|
// 3)send answer to client
|
|
if (loc_ack == 1) { // ACK
|
|
raw_answer[0] = 0x06; //signaling type = connection acknowledge
|
|
raw_answer[1] = 59; //size
|
|
raw_answer[2] = client_ID;
|
|
strcpy ((char*)(raw_answer + 3), (char*)client_callsign); // Client Callsign
|
|
IP_int2char (CONF_radio_addr_table_IP_begin[client_ID], raw_answer + 19); // IP start
|
|
IP_int2char (CONF_radio_addr_table_IP_size[client_ID], raw_answer + 23); // IP size
|
|
strcpy ((char*)(raw_answer + 27), CONF_radio_my_callsign); // Master callsign
|
|
IP_int2char (LAN_conf_applied.LAN_modem_IP, raw_answer + 43); // Modem IP
|
|
IP_int2char (LAN_conf_applied.LAN_subnet_mask, raw_answer + 47); // IP subnet mask
|
|
raw_answer[51] = LAN_conf_applied.LAN_def_route_activ; // active default route
|
|
IP_int2char (LAN_conf_applied.LAN_def_route, raw_answer + 52); // Default Route value
|
|
raw_answer[56] = LAN_conf_applied.LAN_DNS_activ; // Active DNS
|
|
IP_int2char (LAN_conf_applied.LAN_DNS_value, raw_answer + 57); // DNS value
|
|
signaling_TX_add_entry (raw_answer, 61);
|
|
signaling_frame_push();
|
|
//printf("\r\n ACK sent\r\n\r\n");
|
|
}
|
|
else { // NACK
|
|
raw_answer[0] = 0x07; //signaling type = connection NACK
|
|
raw_answer[1] = 33; //size
|
|
strcpy ((char*)(raw_answer + 2), (char*)client_callsign);
|
|
raw_answer[18] = NACK_reason;
|
|
strcpy ((char*)(raw_answer + 19), CONF_radio_my_callsign); // Master callsign;
|
|
signaling_TX_add_entry (raw_answer, 35);
|
|
signaling_frame_push();
|
|
//printf("\r\n NACK sent\r\n\r\n");
|
|
}
|
|
}
|
|
|
|
void signaling_connect_ACK_process(unsigned char* raw_data)
|
|
{
|
|
unsigned char local_client_ID;
|
|
unsigned long int local_IP_start;
|
|
unsigned long int local_IP_size;
|
|
unsigned long int local_modem_IP;
|
|
unsigned long int local_IP_subnet;
|
|
unsigned char local_default_route_activ;
|
|
unsigned long int local_default_route;
|
|
unsigned char local_DNS_activ;
|
|
unsigned long int local_DNS_value;
|
|
|
|
int need_LAN_reset = 0;
|
|
//Client ID
|
|
local_client_ID = raw_data[0];
|
|
my_radio_client_ID = local_client_ID;
|
|
TDMA_NULL_frame_init(70);
|
|
// IP Start
|
|
local_IP_start = IP_char2int(raw_data + 17);
|
|
if (local_IP_start != LAN_conf_applied.DHCP_range_start) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.DHCP_range_start = local_IP_start;
|
|
// IP Size
|
|
local_IP_size = IP_char2int(raw_data + 21);
|
|
if (local_IP_size != LAN_conf_applied.DHCP_range_size) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.DHCP_range_size = local_IP_size;
|
|
// Master Callsign
|
|
strcpy(CONF_radio_master_callsign, (char*)(raw_data + 25));
|
|
// Modem IP
|
|
local_modem_IP = IP_char2int(raw_data + 41);
|
|
if (local_modem_IP != LAN_conf_applied.LAN_modem_IP) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_modem_IP = local_modem_IP;
|
|
// IP subnet mask
|
|
local_IP_subnet = IP_char2int(raw_data + 45);
|
|
if (local_IP_subnet != LAN_conf_applied.LAN_subnet_mask) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_subnet_mask = local_IP_subnet;
|
|
// Default route active
|
|
local_default_route_activ = raw_data[49];
|
|
if (local_default_route_activ != LAN_conf_applied.LAN_def_route_activ) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_def_route_activ = local_default_route_activ;
|
|
// Default route value
|
|
local_default_route = IP_char2int(raw_data + 50);
|
|
if (local_default_route != LAN_conf_applied.LAN_def_route) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_def_route = local_default_route;
|
|
// DNS active
|
|
local_DNS_activ = raw_data[54];
|
|
if (local_DNS_activ != LAN_conf_applied.LAN_DNS_activ) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_DNS_activ = local_DNS_activ;
|
|
// DNS value
|
|
local_DNS_value = IP_char2int(raw_data + 55);
|
|
if (local_DNS_value != LAN_conf_applied.LAN_DNS_value) {need_LAN_reset = 1;}
|
|
LAN_conf_applied.LAN_DNS_value = local_DNS_value;
|
|
|
|
if (need_LAN_reset) {
|
|
HMI_force_exit();
|
|
reset_DHCP_table(&LAN_conf_applied);
|
|
W5500_re_configure();
|
|
need_LAN_reset = 0;
|
|
}
|
|
my_client_radio_connexion_state = 2;
|
|
connect_state_machine_counter = 0;
|
|
time_counter_last_ack = 0;
|
|
//printf("\r\n REQ ACK Received\r\n\r\n");
|
|
}
|
|
|
|
void signaling_connect_NACK_process (unsigned char reason_loc) {
|
|
//printf("NACK reason: %i\r\n", reason_loc);
|
|
G_connect_rejection_reason = reason_loc;
|
|
my_client_radio_connexion_state = 3;
|
|
connect_state_machine_counter = 0;
|
|
}
|
|
|
|
static unsigned char loc_data[40];
|
|
|
|
void signaling_connect_req_TX(void) {
|
|
//static unsigned char loc_data[30];
|
|
loc_data[0] = 0x05; // signaling type = connection request
|
|
loc_data[1] = 21; // field size
|
|
strcpy ((char*)(loc_data+2), CONF_radio_my_callsign); // callsign
|
|
IP_int2char (CONF_radio_IP_size_requested, loc_data + 18);
|
|
loc_data[22] = CONF_radio_static_IP_requested;
|
|
signaling_TX_add_entry (loc_data, 23);
|
|
signaling_frame_push();
|
|
//printf ("\r\nNEW REQUEST TX\r\n\r\n");
|
|
}
|
|
|
|
void signaling_disconnect_req_process (unsigned loc_ID, unsigned char* loc_callsign) {
|
|
int i;
|
|
int existing_entry = -1;
|
|
for (i=0; i<radio_addr_table_size; i++) {
|
|
if (strcmp((char*)loc_callsign, CONF_radio_addr_table_callsign[i]) == 0) {
|
|
existing_entry = i;
|
|
}
|
|
}
|
|
if (existing_entry != -1) {
|
|
CONF_radio_addr_table_status[existing_entry] = 0;
|
|
}
|
|
signaling_disconnect_ACK_TX(loc_ID, loc_callsign);
|
|
signaling_disconnect_ACK_TX(loc_ID, loc_callsign);//sends 2 times
|
|
}
|
|
|
|
void signaling_disconnect_ACK_process (unsigned loc_ID, unsigned char* loc_callsign) {
|
|
my_client_radio_connexion_state = 5;
|
|
my_radio_client_ID = 0x7E;
|
|
TDMA_NULL_frame_init(70);
|
|
}
|
|
|
|
void signaling_disconnect_req_TX (void) {
|
|
//static unsigned char loc_data[30]; // moved global
|
|
loc_data[0] = 0x0B; // signaling type = disconnect ACK
|
|
loc_data[1] = 17; // field size
|
|
loc_data[2] = my_radio_client_ID;
|
|
strcpy ((char*)(loc_data+3), CONF_radio_my_callsign);
|
|
signaling_TX_add_entry (loc_data, 19);
|
|
signaling_frame_push();
|
|
}
|
|
|
|
void signaling_disconnect_ACK_TX (unsigned loc_ID, unsigned char* loc_callsign) {
|
|
//static unsigned char loc_data[30]; // moved global
|
|
loc_data[0] = 0x0C; // signaling type = disconnect ACK
|
|
loc_data[1] = 17; // field size
|
|
loc_data[2] = loc_ID;
|
|
strcpy ((char*)(loc_data+3), (char*)loc_callsign);
|
|
signaling_TX_add_entry (loc_data, 19);
|
|
signaling_frame_push();
|
|
}
|
|
|
|
// TX part
|
|
//void signaling_frame_init(unsigned char* TX_signal_frame_raw) {
|
|
void signaling_frame_init(void) {
|
|
if (is_TDMA_master) {
|
|
TX_signal_frame_raw[0] = 0xFF; //broadcast address (plus parity bit)
|
|
} else {
|
|
TX_signal_frame_raw[0] = my_radio_client_ID + parity_bit_elab[(my_radio_client_ID & 0x7F)]; //addr slave
|
|
}
|
|
TX_signal_frame_raw[1] = 0x1E; // protocol = signaling
|
|
TX_signal_frame_point = 2;
|
|
}
|
|
|
|
//void signaling_single_whois_TX(unsigned char* TX_signal_frame_raw, unsigned char loc_ID, char* loc_callsign,
|
|
void signaling_single_whois_TX(unsigned char loc_ID, char* loc_callsign,
|
|
unsigned long int loc_IP_start, unsigned long int loc_IP_size,
|
|
unsigned char RSSI_loc, unsigned short int BER_loc, short int TA_loc) {
|
|
loc_data[0] = 0x01; //field type = who
|
|
loc_data[1] = 30; // field length previous 30
|
|
loc_data[2] = loc_ID;
|
|
|
|
strcpy ((char*)(loc_data+3), loc_callsign);
|
|
loc_data[18] = 0; //null termination of callsign
|
|
IP_int2char (loc_IP_start, loc_data + 19); // IP start
|
|
IP_int2char (loc_IP_size, loc_data + 23); // IP start
|
|
loc_data[27] = RSSI_loc; // RSSI uplink
|
|
loc_data[28] = BER_loc & 0xFF; // error rate uplink (lsB first)
|
|
loc_data[29] = (BER_loc & 0xFF00) >> 8;
|
|
loc_data[30] = TA_loc & 0xFF;
|
|
loc_data[31] = (TA_loc & 0xFF00) >> 8;
|
|
signaling_TX_add_entry (loc_data, 32); //previous 27
|
|
}
|
|
|
|
//void signaling_whois_TX(unsigned char* TX_signal_frame_raw) {
|
|
void signaling_whois_TX(void) {
|
|
int i;
|
|
unsigned int RSSI_loc;
|
|
if (is_TDMA_master) {
|
|
signaling_single_whois_TX (0x7F, CONF_radio_my_callsign, LAN_conf_applied.LAN_modem_IP, 0, 0, 0, 0); // master entry
|
|
for (i=0; i<radio_addr_table_size; i++) { // client entries
|
|
if (CONF_radio_addr_table_status[i]) {
|
|
RSSI_loc = (G_radio_addr_table_RSSI[i] & 0xFF00) >> 8;
|
|
signaling_single_whois_TX (i, CONF_radio_addr_table_callsign[i],
|
|
CONF_radio_addr_table_IP_begin[i], CONF_radio_addr_table_IP_size[i],
|
|
RSSI_loc, G_radio_addr_table_BER[i], (short int)(TDMA_table_TA[i] / 10) );
|
|
}
|
|
}
|
|
|
|
}
|
|
else if (my_client_radio_connexion_state == 2) { //Slave, only sends if really connected
|
|
signaling_single_whois_TX (my_radio_client_ID, CONF_radio_my_callsign, LAN_conf_applied.DHCP_range_start, LAN_conf_applied.DHCP_range_size, G_downlink_RSSI, G_downlink_BER, 0); // client's own entry
|
|
signaling_single_whois_TX (0x7F, CONF_radio_master_callsign, LAN_conf_applied.LAN_modem_IP, 0, 0, 0, 0); //MASTER entry
|
|
}
|
|
}
|
|
|
|
void signaling_TX_add_entry(unsigned char* raw_data, int size) {
|
|
if (TX_signal_frame_point == 0) {
|
|
signaling_frame_init();
|
|
}
|
|
if ( (TX_signal_frame_point + size) < 248) { //enough space for this entry in current frame
|
|
memcpy ((TX_signal_frame_raw + TX_signal_frame_point), raw_data, size);
|
|
TX_signal_frame_point = TX_signal_frame_point + size;
|
|
} else { // not enough space
|
|
signaling_frame_push(); // send previous entries
|
|
signaling_frame_init(); // initialize new frame
|
|
memcpy ((TX_signal_frame_raw + TX_signal_frame_point), raw_data, size);
|
|
TX_signal_frame_point = TX_signal_frame_point + size;
|
|
}
|
|
}
|
|
|
|
//void signaling_frame_push(unsigned char* TX_signal_frame_raw) {
|
|
void signaling_frame_push(void) {
|
|
// int rsize_needed;
|
|
int size_w_FEC;
|
|
int size_wo_FEC;
|
|
unsigned char rframe_length;
|
|
unsigned int timer_snapshot;
|
|
|
|
TX_signal_frame_raw[TX_signal_frame_point] = 0xFF; // END flag
|
|
TX_signal_frame_raw[TX_signal_frame_point + 1] = 0x00; // size 0
|
|
TX_signal_frame_point = TX_signal_frame_point + 2;
|
|
size_wo_FEC = TX_signal_frame_point;
|
|
if (size_wo_FEC < 69) {
|
|
size_wo_FEC = 69;
|
|
}
|
|
// rsize_needed = 100 + (size_wo_FEC * 1.4);
|
|
|
|
//printf("sig NO ext SRAM\r\n");
|
|
//if ((TXPS_FIFO->last_ready - TXPS_FIFO->RD_point) < (TXPS_FIFO_threshold_sig - rsize_needed) ) { //16380
|
|
if (TX_FIFO_full_global(0) == 0) {
|
|
timer_snapshot = GLOBAL_timer.read_us();
|
|
//TXPS_FIFO->data[TXPS_FIFO->WR_point & TXPS_FIFO->mask] = (timer_snapshot >> 16) & 0xFF; //timer
|
|
rframe_TX[0] = (timer_snapshot >> 16) & 0xFF;
|
|
//TXPS_FIFO->WR_point++;
|
|
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;}
|
|
//TXPS_FIFO->data[TXPS_FIFO->WR_point & TXPS_FIFO->mask] = rframe_length;
|
|
//TXPS_FIFO->WR_point++;
|
|
rframe_TX[1] = rframe_length;
|
|
//TXPS_FIFO->data[TXPS_FIFO->WR_point & TXPS_FIFO->mask] = 0x00; //TDMA byte
|
|
//TXPS_FIFO->WR_point++;
|
|
rframe_TX[2] = 0x00; //TDMA byte
|
|
//size_w_FEC = FEC_encode(TX_signal_frame_raw, TXPS_FIFO, size_wo_FEC);
|
|
size_w_FEC = FEC_encode2(TX_signal_frame_raw, rframe_TX+3, size_wo_FEC);
|
|
//TX_intern_FIFO_write(rframe_TX, size_w_FEC+3);
|
|
TX_FIFO_write_global(rframe_TX, size_w_FEC+3);
|
|
//TXPS_FIFO->last_ready = TXPS_FIFO->WR_point;
|
|
}
|
|
TX_signal_frame_point = 0;
|
|
}
|
|
|
|
void signaling_periodic_call() { // called every 2 to 6 seconds
|
|
int i;
|
|
unsigned int time_since_last_ack;
|
|
unsigned int timer_snapshot;
|
|
// CLIENT STATE MACHINE
|
|
if (is_TDMA_master == 0) {
|
|
if ( (my_client_radio_connexion_state==1) && (connect_state_machine_counter>2) ) {//waiting for connexion
|
|
signaling_connect_req_TX();
|
|
connect_state_machine_counter = 0;
|
|
timer_snapshot = GLOBAL_timer.read_us();
|
|
if ( (timer_snapshot - last_rframe_seen) > CONF_radio_timeout_small) {
|
|
SI4463_prepa_TX_1_call.attach_us(&SI4463_prepa_TX_1, 500000);
|
|
}
|
|
}
|
|
if ( (my_client_radio_connexion_state==2) && (connect_state_machine_counter>5) ) {//already connected periodic update
|
|
signaling_connect_req_TX();
|
|
// no counter reset, the ack reception does it
|
|
}
|
|
if ( (my_client_radio_connexion_state==3) && (connect_state_machine_counter>15) ) {//rejected, new attempt every 15
|
|
signaling_connect_req_TX();
|
|
connect_state_machine_counter = 0;
|
|
}
|
|
if ( (my_client_radio_connexion_state==2) && (time_counter_last_ack > CONNECTION_TIMEOUT) ) {//timeout, no ACK received for long time
|
|
// transition to state 1 "waiting for connection"
|
|
my_client_radio_connexion_state = 1;
|
|
radio_flush_TX_FIFO();
|
|
my_radio_client_ID = 0x7E;
|
|
TDMA_NULL_frame_init(70);
|
|
}
|
|
if ( (my_client_radio_connexion_state==4) && (connect_state_machine_counter>2) ) {//waiting for disconnection
|
|
signaling_disconnect_req_TX();
|
|
connect_state_machine_counter = 0;
|
|
}
|
|
connect_state_machine_counter++;
|
|
time_counter_last_ack++;
|
|
}
|
|
|
|
// MASTER : timeout management for clients
|
|
if (is_TDMA_master) {
|
|
timer_snapshot = GLOBAL_timer.read_us();
|
|
for (i=0; i< radio_addr_table_size; i++) {
|
|
time_since_last_ack = timer_snapshot - CONF_radio_addr_table_date[i];
|
|
if ( (CONF_radio_addr_table_status[i] == 1) && (time_since_last_ack > (2000000UL*CONNECTION_TIMEOUT*CONF_signaling_period)) ) {
|
|
CONF_radio_addr_table_status[i] = 0; // force disconnect
|
|
}
|
|
}
|
|
}
|
|
|
|
signaling_whois_TX();
|
|
if (TX_signal_frame_point >0) {
|
|
signaling_frame_push();
|
|
|
|
}
|
|
} |