283 lines
No EOL
10 KiB
C++
283 lines
No EOL
10 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 "config_flash.h"
|
|
#include "mbed.h"
|
|
#include "global_variables.h"
|
|
#include "Eth_IPv4.h"
|
|
#include "HMI_telnet.h"
|
|
#include "TDMA.h"
|
|
#include "trng_api.h"
|
|
|
|
static unsigned char raw_config_data[260];
|
|
static unsigned int config_index;
|
|
|
|
unsigned int virt_EEPROM_read(unsigned char* out_data) { //reads 256 Bytes of virtual eeprom data
|
|
FlashIAP my_loc_flash;
|
|
unsigned char loc_index_char[6];
|
|
unsigned int loc_index_int, highest_index_seen;
|
|
unsigned int loc_address;
|
|
int i;
|
|
my_loc_flash.init();
|
|
highest_index_seen = 0;
|
|
//for (i=0; i<256; i++) {
|
|
for (i=0; i<64; i++) {
|
|
my_loc_flash.read(loc_index_char, NFPR_config_addr_begin+(i*256), 4);
|
|
loc_index_int = (loc_index_char[0] << 24) + (loc_index_char[1] << 16) + (loc_index_char[2] << 8) + loc_index_char[3];
|
|
if ( (loc_index_int != 0xFFFFFFFF) && (loc_index_int > highest_index_seen) ) {
|
|
highest_index_seen = loc_index_int;
|
|
}
|
|
}
|
|
if (highest_index_seen != 0) { //valid entry found
|
|
//loc_address = NFPR_config_addr_begin + (highest_index_seen & 0xFF)*256;
|
|
loc_address = NFPR_config_addr_begin + (highest_index_seen & 0x3F)*256;
|
|
my_loc_flash.read(out_data, loc_address, 256);
|
|
}
|
|
my_loc_flash.deinit();
|
|
return highest_index_seen;
|
|
}
|
|
|
|
unsigned int virt_EEPROM_write(unsigned char* in_data, unsigned int previous_index) {
|
|
unsigned int new_index;
|
|
unsigned int loc_address;
|
|
FlashIAP my_loc_flash;
|
|
if (previous_index == 0) {
|
|
previous_index = 0xFF; //next index will be 0x100, errase first sector
|
|
}
|
|
new_index = previous_index + 1;
|
|
//loc_address = NFPR_config_addr_begin + (new_index & 0xFF)*256; //previous config 64kB
|
|
loc_address = NFPR_config_addr_begin + (new_index & 0x3F)*256; //previous config
|
|
my_loc_flash.init();
|
|
if ((new_index & 7) == 0) { //new sector, errase sector
|
|
HMI_printf ("errase sector:%X\r\n", loc_address);
|
|
my_loc_flash.erase(loc_address, 2048);
|
|
}
|
|
// writes new index
|
|
in_data[0] = (new_index & 0xFF000000) >> 24;
|
|
in_data[1] = (new_index & 0xFF0000) >> 16;
|
|
in_data[2] = (new_index & 0xFF00) >> 8;
|
|
in_data[3] = new_index & 0xFF;
|
|
my_loc_flash.program(in_data, loc_address, 256);
|
|
HMI_printf("write success\r\n");
|
|
my_loc_flash.deinit();
|
|
return new_index;
|
|
}
|
|
|
|
//void virt_EEPROM_debug_read(void) {
|
|
// int i;
|
|
// unsigned int loc_address;
|
|
// unsigned char loc_data[260];
|
|
// FlashIAP my_loc_flash;
|
|
// my_loc_flash.init();
|
|
// //for (i=0; i<256; i++) {
|
|
// for (i=0; i<64; i++) {
|
|
// //loc_address = NFPR_config_addr_begin + (i & 0xFF)*256;
|
|
// loc_address = NFPR_config_addr_begin + (i & 0x3F)*256;
|
|
// my_loc_flash.read(loc_data, loc_address, 256);
|
|
// HMI_printf("addr:%X data:%02X %02X %02X %02X %02X %02X %02X %02X\r\n", loc_address, loc_data[0], loc_data[1], loc_data[2], loc_data[3], loc_data[4], loc_data[5], loc_data[6], loc_data[7]);
|
|
// wait_ms(10);
|
|
// }
|
|
// my_loc_flash.deinit();
|
|
//}
|
|
|
|
void virt_EEPROM_errase_all(void) {
|
|
FlashIAP my_loc_flash;
|
|
my_loc_flash.init();
|
|
//my_loc_flash.erase(NFPR_config_addr_begin, 0x10000); //previous config 64kB
|
|
my_loc_flash.erase(NFPR_config_addr_begin, 0x4000); //config 16kB
|
|
my_loc_flash.deinit();
|
|
}
|
|
|
|
// higher level functions
|
|
|
|
void NFPR_config_read(void) {
|
|
int i;
|
|
unsigned char default_config[260] = NFPR_default_config;
|
|
uint8_t random[2];
|
|
|
|
config_index = virt_EEPROM_read(raw_config_data);
|
|
if (config_index == 0) { //no previous config found
|
|
for (i=0; i<256; i++) {
|
|
raw_config_data[i] = default_config[i];
|
|
}
|
|
|
|
//MAC random 2 LSB values
|
|
NFPR_random_generator(random, sizeof(random));
|
|
raw_config_data[58] = random[0];
|
|
raw_config_data[59] = random[1];
|
|
raw_config_data[5] = raw_config_data[58];//callsign 1st char
|
|
raw_config_data[6] = raw_config_data[59];//callsign 2nd char
|
|
config_index = virt_EEPROM_write (raw_config_data, config_index);//save the MAC
|
|
}
|
|
apply_config_from_raw_string(raw_config_data);
|
|
if (is_TDMA_master == 1) {
|
|
my_client_radio_connexion_state = 2;
|
|
} else {
|
|
my_client_radio_connexion_state = 1;
|
|
my_radio_client_ID = 0x7E;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate and save random `size` bytes into the `rnd` array.
|
|
* This code uses the STM32 TRNG HW.
|
|
* Returns `true` if the resulting data are random.
|
|
*/
|
|
bool NFPR_random_generator(uint8_t *rnd, size_t size) {
|
|
trng_t trng_obj;
|
|
size_t random_length = 0;
|
|
|
|
trng_init(&trng_obj);
|
|
trng_get_bytes(&trng_obj, rnd, size, &random_length);
|
|
trng_free(&trng_obj);
|
|
|
|
if(random_length == size) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
unsigned int NFPR_config_save(void) {
|
|
if ( (CONF_radio_my_callsign[0] == 0) || (CONF_radio_my_callsign[2] == 0) ) {
|
|
HMI_printf("ERROR : not yet configured\r\n");
|
|
|
|
} else {
|
|
write_config_to_raw_string(raw_config_data);
|
|
config_index = virt_EEPROM_write (raw_config_data, config_index);
|
|
}
|
|
return config_index;
|
|
}
|
|
|
|
void apply_config_from_raw_string(unsigned char* data_r) {
|
|
int i;
|
|
unsigned char modul_temp;
|
|
is_TDMA_master = data_r[4];
|
|
for (i=0; i<16; i++) {
|
|
CONF_radio_my_callsign[i] = data_r[5+i];
|
|
}
|
|
CONF_radio_my_callsign[15] = 0;
|
|
is_telnet_active = data_r[21];
|
|
modul_temp = (data_r[22] & 0x3F);
|
|
if ( ((modul_temp>=11)&&(modul_temp<=14)) || ((modul_temp>=20)&&(modul_temp<=24)) ) {
|
|
CONF_radio_modulation = modul_temp;
|
|
} else {
|
|
CONF_radio_modulation = 24;
|
|
}
|
|
CONF_frequency_band = (data_r[22] & 0xC0) >> 6;
|
|
//printf("freq_band:%X modul:%i\r\n", CONF_frequency_band, modul_temp);
|
|
CONF_radio_frequency = data_r[23];
|
|
CONF_radio_network_ID = data_r[24];
|
|
|
|
//specific for clients
|
|
CONF_radio_static_IP_requested = data_r[25];
|
|
CONF_radio_IP_size_requested = IP_char2int(data_r+26);
|
|
LAN_conf_saved.DHCP_server_active = data_r[30];
|
|
LAN_conf_applied.DHCP_server_active = data_r[30];
|
|
|
|
//specific for master
|
|
LAN_conf_saved.LAN_modem_IP = IP_char2int(data_r+31);
|
|
LAN_conf_applied.LAN_modem_IP = IP_char2int(data_r+31);
|
|
LAN_conf_saved.LAN_subnet_mask = IP_char2int(data_r+35);
|
|
LAN_conf_applied.LAN_subnet_mask = IP_char2int(data_r+35);
|
|
CONF_radio_IP_size = IP_char2int(data_r+39);
|
|
LAN_conf_saved.LAN_DNS_activ = data_r[43];
|
|
LAN_conf_applied.LAN_DNS_activ = data_r[43];
|
|
LAN_conf_saved.LAN_DNS_value = IP_char2int(data_r+44);
|
|
LAN_conf_applied.LAN_DNS_value = IP_char2int(data_r+44);
|
|
LAN_conf_saved.LAN_def_route_activ = data_r[48];
|
|
LAN_conf_applied.LAN_def_route_activ = data_r[48];
|
|
LAN_conf_saved.LAN_def_route = IP_char2int(data_r+49);
|
|
LAN_conf_applied.LAN_def_route = IP_char2int(data_r+49);
|
|
CONF_radio_IP_start = IP_char2int(data_r+53);
|
|
is_telnet_routed = data_r[57];
|
|
CONF_modem_MAC[0] = 0x4E;//N
|
|
CONF_modem_MAC[1] = 0x46;//F
|
|
CONF_modem_MAC[2] = 0x50;//P
|
|
CONF_modem_MAC[3] = 0x52;//R
|
|
CONF_modem_MAC[4] = data_r[58];
|
|
CONF_modem_MAC[5] = data_r[59];
|
|
CONF_radio_default_state_ON_OFF = data_r[60];
|
|
CONF_radio_PA_PWR = data_r[61];
|
|
|
|
CONF_frequency_HD = ((data_r[64]) <<8 ) | data_r[65];
|
|
if ( (CONF_frequency_HD == 0x0000) || (CONF_frequency_HD > FREQ_MAX_RAW) ) {
|
|
CONF_frequency_HD = CONF_DEF_FREQ; // force to default frequency
|
|
}
|
|
CONF_freq_shift = ((data_r[66]) <<8) | data_r[67];
|
|
CONF_transmission_method = data_r[68];
|
|
CONF_master_FDD = data_r[69];
|
|
CONF_master_down_IP = IP_char2int(data_r+70);
|
|
if ((data_r[74] >= 0xF0) && (data_r[74] <= 0xF7)){
|
|
CONF_Eth_mode = data_r[74] - 0xF0;
|
|
}
|
|
else {
|
|
CONF_Eth_mode = 0x07;
|
|
}
|
|
if (LAN_conf_applied.DHCP_server_active == 1) {
|
|
LAN_conf_applied.DHCP_range_start = CONF_radio_IP_start;
|
|
LAN_conf_applied.DHCP_range_size = CONF_radio_IP_size_requested;
|
|
|
|
}
|
|
if ( (is_TDMA_master == 1) && (CONF_master_FDD == 1) ) { // FDD Master down
|
|
G_FDD_trig_pin->output();
|
|
}
|
|
if ( (is_TDMA_master == 1) && (CONF_master_FDD == 2) ) {// FDD master up
|
|
G_FDD_trig_IRQ->rise(&TDMA_FDD_up_top_measure);
|
|
}
|
|
}
|
|
|
|
void write_config_to_raw_string (unsigned char* data_r) {
|
|
int i;
|
|
data_r[4] = is_TDMA_master;
|
|
for (i=0; i<16; i++) {
|
|
data_r[5+i] = CONF_radio_my_callsign[i];
|
|
}
|
|
data_r[21] = is_telnet_active;
|
|
data_r[22] = ( (CONF_frequency_band << 6) & 0xC0) + (CONF_radio_modulation & 0x3F);
|
|
data_r[23] = CONF_radio_frequency;
|
|
data_r[24] = CONF_radio_network_ID;
|
|
|
|
//specific for clients
|
|
data_r[25] = CONF_radio_static_IP_requested;
|
|
IP_int2char(CONF_radio_IP_size_requested, data_r+26);
|
|
data_r[30] = LAN_conf_saved.DHCP_server_active;
|
|
|
|
//specific for master
|
|
IP_int2char(LAN_conf_saved.LAN_modem_IP, data_r+31);
|
|
IP_int2char(LAN_conf_saved.LAN_subnet_mask, data_r+35);
|
|
IP_int2char(CONF_radio_IP_size, data_r+39);
|
|
data_r[43] = LAN_conf_saved.LAN_DNS_activ;
|
|
IP_int2char(LAN_conf_saved.LAN_DNS_value, data_r+44);
|
|
data_r[48] = LAN_conf_saved.LAN_def_route_activ;
|
|
IP_int2char(LAN_conf_saved.LAN_def_route, data_r+49);
|
|
IP_int2char(CONF_radio_IP_start, data_r+53);
|
|
data_r[57] = is_telnet_routed;
|
|
data_r[58] = CONF_modem_MAC[4];
|
|
data_r[59] = CONF_modem_MAC[5];
|
|
data_r[60] = CONF_radio_default_state_ON_OFF;
|
|
data_r[61] = CONF_radio_PA_PWR;
|
|
|
|
data_r[64] = (CONF_frequency_HD & 0xFF00)>>8;
|
|
data_r[65] = (CONF_frequency_HD & 0x00FF);
|
|
data_r[66] = (CONF_freq_shift & 0xFF00)>>8;
|
|
data_r[67] = (CONF_freq_shift & 0x00FF);
|
|
data_r[68] = CONF_transmission_method;
|
|
data_r[69] = CONF_master_FDD;
|
|
IP_int2char(CONF_master_down_IP, data_r+70);
|
|
data_r[74] = CONF_Eth_mode + 0xF0;
|
|
} |