EEPROM configuration

This commit is contained in:
Mark Qvist 2019-02-08 13:18:49 +01:00
parent b3b1a9b253
commit 474f3ad4d2
13 changed files with 429 additions and 131 deletions

View File

@ -6,7 +6,7 @@ TARGET = images/OpenModem
OPT = s OPT = s
FORMAT = ihex FORMAT = ihex
SRC = main.c hardware/Serial.c hardware/AFSK.c hardware/VREF.c hardware/LED.c hardware/UserIO.c hardware/SD.c hardware/sdcard/diskio.c hardware/sdcard/ff.c hardware/sdcard/ffsystem.c hardware/sdcard/ffunicode.c hardware/Bluetooth.c hardware/GPS.c hardware/Crypto.c hardware/crypto/AES.c hardware/crypto/HMAC_MD5.c hardware/crypto/MD5.c hardware/crypto/MD5_sbox.c util/CRC-CCIT.c protocol/AX25.c protocol/KISS.c SRC = main.c util/Config.c hardware/Serial.c hardware/AFSK.c hardware/VREF.c hardware/LED.c hardware/UserIO.c hardware/SD.c hardware/sdcard/diskio.c hardware/sdcard/ff.c hardware/sdcard/ffsystem.c hardware/sdcard/ffunicode.c hardware/Bluetooth.c hardware/GPS.c hardware/Crypto.c hardware/crypto/AES.c hardware/crypto/HMAC_MD5.c hardware/crypto/MD5.c hardware/crypto/MD5_sbox.c util/CRC-CCIT.c protocol/AX25.c protocol/KISS.c
# TODO: Try hardware/crypto/MD5_asm.S # TODO: Try hardware/crypto/MD5_asm.S
# List Assembler source files here. # List Assembler source files here.

View File

@ -3,6 +3,10 @@
#ifndef DEVICE_CONFIGURATION #ifndef DEVICE_CONFIGURATION
#define DEVICE_CONFIGURATION #define DEVICE_CONFIGURATION
// Version info
#define MAJ_VERSION 0x01
#define MIN_VERSION 0x00
// CPU settings // CPU settings
#define TARGET_CPU m1284p #define TARGET_CPU m1284p
#define F_CPU 20000000UL #define F_CPU 20000000UL
@ -10,12 +14,12 @@
// Voltage references // Voltage references
// TODO: Determine best defaults // TODO: Determine best defaults
#define CONFIG_ADC_REF 255 #define CONFIG_ADC_REF 128
#define CONFIG_DAC_REF 128 #define CONFIG_DAC_REF 128
// TODO: Change this back to default // TODO: Change this back to default
#define CONFIG_LED_INTENSITY 35
//#define CONFIG_LED_INTENSITY 192 //#define CONFIG_LED_INTENSITY 192
#define CONFIG_LED_INTENSITY 37
#define CONFIG_COM_LED_TIMEOUT_MS 40 #define CONFIG_COM_LED_TIMEOUT_MS 40
#define CONFIG_LED_UPDATE_INTERVAL_MS 40 #define CONFIG_LED_UPDATE_INTERVAL_MS 40
@ -34,7 +38,8 @@
// CSMA Settings // CSMA Settings
#define CONFIG_FULL_DUPLEX false // TODO: Actually implement fdx #define CONFIG_FULL_DUPLEX false // TODO: Actually implement fdx
#define CONFIG_CSMA_P 255 #define CONFIG_CSMA_P_DEFAULT 255
#define CONFIG_CSMA_SLOTTIME_DEFAULT 20
#define AX25_MIN_FRAME_LEN 1 #define AX25_MIN_FRAME_LEN 1
#define AX25_MAX_FRAME_LEN 611 #define AX25_MAX_FRAME_LEN 611

View File

@ -4,16 +4,9 @@
#include "hardware/LED.h" #include "hardware/LED.h"
#include "protocol/KISS.h" #include "protocol/KISS.h"
#include "hardware/SD.h" #include "hardware/SD.h"
#include "util/Config.h"
// TODO: Remove testing vars ////
#define SAMPLES_TO_CAPTURE 128
ticks_t capturedsamples = 0;
uint8_t samplebuf[SAMPLES_TO_CAPTURE];
/////////////////////////////////
extern volatile ticks_t _clock; extern volatile ticks_t _clock;
extern unsigned long custom_preamble;
extern unsigned long custom_tail;
bool hw_afsk_dac_isr = false; bool hw_afsk_dac_isr = false;
bool hw_5v_ref = false; bool hw_5v_ref = false;
@ -128,11 +121,11 @@ static void AFSK_txStart(Afsk *afsk) {
afsk->sending = true; afsk->sending = true;
afsk->sending_data = true; afsk->sending_data = true;
LED_TX_ON(); LED_TX_ON();
afsk->preambleLength = DIV_ROUND(custom_preamble * BITRATE, 8000); afsk->preambleLength = DIV_ROUND(config_preamble * BITRATE, 8000);
AFSK_DAC_IRQ_START(); AFSK_DAC_IRQ_START();
} }
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
afsk->tailLength = DIV_ROUND(custom_tail * BITRATE, 8000); afsk->tailLength = DIV_ROUND(config_tail * BITRATE, 8000);
} }
} }
@ -468,50 +461,12 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
#error No filters defined for specified samplerate! #error No filters defined for specified samplerate!
#endif #endif
// We put the sampled bit in a delay-line:
// First we bitshift everything 1 left
afsk->sampledBits <<= 1; afsk->sampledBits <<= 1;
// And then add the sampled bit to our delay line
afsk->sampledBits |= (afsk->iirY[1] > 0) ? 0 : 1; afsk->sampledBits |= (afsk->iirY[1] > 0) ? 0 : 1;
//afsk->sampledBits |= (freq_disc > 0) ? 0 : 1;
// Put the current raw sample in the delay FIFO
fifo_push(&afsk->delayFifo, currentSample); fifo_push(&afsk->delayFifo, currentSample);
// We need to check whether there is a signal transition.
// If there is, we can recalibrate the phase of our
// sampler to stay in sync with the transmitter. A bit of
// explanation is required to understand how this works.
// Since we have PHASE_MAX/PHASE_BITS = 8 samples per bit,
// we employ a phase counter (currentPhase), that increments
// by PHASE_BITS everytime a sample is captured. When this
// counter reaches PHASE_MAX, it wraps around by modulus
// PHASE_MAX. We then look at the last three samples we
// captured and determine if the bit was a one or a zero.
//
// This gives us a "window" looking into the stream of
// samples coming from the ADC. Sort of like this:
//
// Past Future
// 0000000011111111000000001111111100000000
// |________|
// ||
// Window
//
// Every time we detect a signal transition, we adjust
// where this window is positioned a little. How much we
// adjust it is defined by PHASE_INC. If our current phase
// phase counter value is less than half of PHASE_MAX (ie,
// the window size) when a signal transition is detected,
// add PHASE_INC to our phase counter, effectively moving
// the window a little bit backward (to the left in the
// illustration), inversely, if the phase counter is greater
// than half of PHASE_MAX, we move it forward a little.
// This way, our "window" is constantly seeking to position
// it's center at the bit transitions. Thus, we synchronise
// our timing to the transmitter, even if it's timing is
// a little off compared to our own.
if (SIGNAL_TRANSITIONED(afsk->sampledBits)) { if (SIGNAL_TRANSITIONED(afsk->sampledBits)) {
if (afsk->currentPhase < PHASE_THRESHOLD) { if (afsk->currentPhase < PHASE_THRESHOLD) {
afsk->currentPhase += PHASE_INC; afsk->currentPhase += PHASE_INC;
@ -523,25 +478,13 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
afsk->silentSamples++; afsk->silentSamples++;
} }
// We increment our phase counter
afsk->currentPhase += PHASE_BITS; afsk->currentPhase += PHASE_BITS;
// Check if we have reached the end of
// our sampling window.
if (afsk->currentPhase >= PHASE_MAX) { if (afsk->currentPhase >= PHASE_MAX) {
// If we have, wrap around our phase
// counter by modulus
afsk->currentPhase %= PHASE_MAX; afsk->currentPhase %= PHASE_MAX;
// Bitshift to make room for the next
// bit in our stream of demodulated bits
afsk->actualBits <<= 1; afsk->actualBits <<= 1;
// We determine the actual bit value by reading
// the last 3 sampled bits. If there is two or
// more 1's, we will assume that the transmitter
// sent us a one, otherwise we assume a zero
uint8_t bits = afsk->sampledBits & 0x07; uint8_t bits = afsk->sampledBits & 0x07;
if (bits == 0x07 || // 111 if (bits == 0x07 || // 111
bits == 0x06 || // 110 bits == 0x06 || // 110
@ -551,39 +494,6 @@ void AFSK_adc_isr(Afsk *afsk, int8_t currentSample) {
afsk->actualBits |= 1; afsk->actualBits |= 1;
} }
//// Alternative using six bits ////////////////
// uint8_t bits = afsk->sampledBits & 0x3F;
// uint8_t c = 0;
// c += bits & _BV(0);
// c += bits & _BV(1);
// c += bits & _BV(2);
// c += bits & _BV(3);
// c += bits & _BV(4);
// c += bits & _BV(5);
// if (c >= 3) afsk->actualBits |= 1;
/////////////////////////////////////////////////
// Now we can pass the actual bit to the HDLC parser.
// We are using NRZ-S coding, so if 2 consecutive bits
// have the same value, we have a 1, otherwise a 0.
// We use the TRANSITION_FOUND function to determine this.
//
// This is smart in combination with bit stuffing,
// since it ensures a transmitter will never send more
// than five consecutive 1's. When sending consecutive
// ones, the signal stays at the same level, and if
// this happens for longer periods of time, we would
// not be able to synchronize our phase to the transmitter
// and would start experiencing "bit slip".
//
// By combining bit-stuffing with NRZ-S coding, we ensure
// that the signal will regularly make transitions
// that we can use to synchronize our phase.
//
// We also check the return of the Link Control parser
// to check if an error occured.
if (!hdlcParse(&afsk->hdlc, !TRANSITION_FOUND(afsk->actualBits), &afsk->rxFifo)) { if (!hdlcParse(&afsk->hdlc, !TRANSITION_FOUND(afsk->actualBits), &afsk->rxFifo)) {
afsk->status |= 1; afsk->status |= 1;
if (fifo_isfull(&afsk->rxFifo)) { if (fifo_isfull(&afsk->rxFifo)) {

View File

@ -36,7 +36,6 @@ inline static uint8_t sinSample(uint16_t i) {
#define TRANSITION_FOUND(bits) BITS_DIFFER((bits), (bits) >> 1) #define TRANSITION_FOUND(bits) BITS_DIFFER((bits), (bits) >> 1)
#define DUAL_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x03) == 0x03) #define DUAL_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x03) == 0x03)
#define QUAD_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x0F) == 0x0F) #define QUAD_XOR(bits1, bits2) ((((bits1)^(bits2)) & 0x0F) == 0x0F)
#define CPU_FREQ F_CPU #define CPU_FREQ F_CPU

View File

@ -1,4 +1,5 @@
#include "Crypto.h" #include "Crypto.h"
#include "util/Config.h"
bool encryption_enabled = false; bool encryption_enabled = false;
uint8_t active_key[CRYPTO_KEY_SIZE]; uint8_t active_key[CRYPTO_KEY_SIZE];
@ -18,17 +19,39 @@ FRESULT crypto_fr; // Result codes
void crypto_init(void) { void crypto_init(void) {
encryption_enabled = false; encryption_enabled = false;
if (load_key()) { if (should_disable_enryption()) {
if (load_entropy_index() && load_entropy()) { if (config_crypto_lock) config_crypto_lock_disable();
encryption_enabled = true; } else {
if (load_key()) {
if (load_entropy_index() && load_entropy()) {
config_crypto_lock_enable();
encryption_enabled = true;
}
}
if (config_crypto_lock) {
if (encryption_enabled) {
LED_indicate_enabled_crypto();
} else {
LED_indicate_error_crypto();
}
} }
} }
}
if (encryption_enabled) { bool crypto_wait(void) {
LED_indicate_enabled_crypto(); size_t wait_timer = 0;
} else { size_t interval_ms = 100;
LED_indicate_error_crypto(); while (!crypto_enabled()) {
delay_ms(100);
wait_timer++;
sd_jobs();
if (wait_timer*interval_ms > CRYPTO_WAIT_TIMEOUT_MS) {
return false;
}
} }
return true;
} }
void crypto_generate_hmac(uint8_t *data, size_t length) { void crypto_generate_hmac(uint8_t *data, size_t length) {
@ -170,6 +193,19 @@ bool load_entropy(void) {
return false; return false;
} }
bool should_disable_enryption(void) {
if (sd_mounted()) {
crypto_fr = f_open(&crypto_fp, PATH_CRYPTO_DISABLE, FA_READ);
if (crypto_fr == FR_OK) {
f_close(&crypto_fp);
return true;
}
}
return false;
}
bool load_key(void) { bool load_key(void) {
if (sd_mounted()) { if (sd_mounted()) {
crypto_fr = f_open(&crypto_fp, PATH_AES_128_KEY, FA_READ); crypto_fr = f_open(&crypto_fp, PATH_AES_128_KEY, FA_READ);

View File

@ -13,6 +13,7 @@
#define PATH_ENTROPY_INDEX "OpenModem/entropy.index" #define PATH_ENTROPY_INDEX "OpenModem/entropy.index"
#define PATH_ENTROPY_SOURCE "OpenModem/entropy.source" #define PATH_ENTROPY_SOURCE "OpenModem/entropy.source"
#define PATH_AES_128_KEY "OpenModem/aes128.key" #define PATH_AES_128_KEY "OpenModem/aes128.key"
#define PATH_CRYPTO_DISABLE "OpenModem/aes128.disable"
#define CRYPTO_KEY_SIZE_BITS 128 #define CRYPTO_KEY_SIZE_BITS 128
#define CRYPTO_KEY_SIZE (CRYPTO_KEY_SIZE_BITS/8) #define CRYPTO_KEY_SIZE (CRYPTO_KEY_SIZE_BITS/8)
@ -20,9 +21,13 @@
#define CRYPTO_HMAC_SIZE (CRYPTO_HMAC_SIZE_BITS/8) #define CRYPTO_HMAC_SIZE (CRYPTO_HMAC_SIZE_BITS/8)
#define MAX_IVS_PER_ENTROPY_BLOCK 128 #define MAX_IVS_PER_ENTROPY_BLOCK 128
#define CRYPTO_WAIT_TIMEOUT_MS 2000
uint8_t crypto_work_block[CRYPTO_KEY_SIZE]; uint8_t crypto_work_block[CRYPTO_KEY_SIZE];
void crypto_init(void); void crypto_init(void);
bool crypto_wait(void);
bool crypto_enabled(void); bool crypto_enabled(void);
bool crypto_generate_iv(void); bool crypto_generate_iv(void);
uint8_t* crypto_get_iv(void); uint8_t* crypto_get_iv(void);
@ -35,6 +40,7 @@ void crypto_decrypt_block(uint8_t block[CRYPTO_KEY_SIZE]);
void crypto_test(void); void crypto_test(void);
bool should_disable_enryption(void);
bool load_key(void); bool load_key(void);
bool load_entropy(void); bool load_entropy(void);
bool load_entropy_index(void); bool load_entropy_index(void);

View File

@ -1,7 +1,5 @@
#include "VREF.h" #include "VREF.h"
#include "util/Config.h"
uint8_t adcReference = CONFIG_ADC_REF;
uint8_t dacReference = CONFIG_DAC_REF;
void VREF_init(void) { void VREF_init(void) {
// Enable output for OC2A and OC2B (PD7 and PD6) // Enable output for OC2A and OC2B (PD7 and PD6)
@ -14,17 +12,17 @@ void VREF_init(void) {
TCCR2B = _BV(CS20); TCCR2B = _BV(CS20);
OCR2A = adcReference; OCR2A = config_input_gain;
OCR2B = dacReference; OCR2B = config_output_gain;
} }
void vref_setADC(uint8_t value) { void vref_setADC(uint8_t value) {
adcReference = value; config_input_gain = value;
OCR2A = adcReference; OCR2A = config_input_gain;
} }
void vref_setDAC(uint8_t value) { void vref_setDAC(uint8_t value) {
dacReference = value; config_output_gain = value;
OCR2B = dacReference; OCR2B = config_output_gain;
} }

19
main.c
View File

@ -2,6 +2,7 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <util/atomic.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -18,11 +19,10 @@
#include "hardware/GPS.h" #include "hardware/GPS.h"
#include "protocol/AX25.h" #include "protocol/AX25.h"
#include "protocol/KISS.h" #include "protocol/KISS.h"
#include "util/Config.h"
#include "util/time.h" #include "util/time.h"
#include "util/FIFO.h" #include "util/FIFO.h"
uint8_t boot_vector = 0x00; uint8_t boot_vector = 0x00;
uint8_t OPTIBOOT_MCUSR __attribute__ ((section(".noinit"))); uint8_t OPTIBOOT_MCUSR __attribute__ ((section(".noinit")));
void resetFlagsInit(void) __attribute__ ((naked)) __attribute__ ((used)) __attribute__ ((section (".init0"))); void resetFlagsInit(void) __attribute__ ((naked)) __attribute__ ((used)) __attribute__ ((section (".init0")));
@ -39,6 +39,7 @@ static void ax25_callback(struct AX25Ctx *ctx) {
} }
void system_check(void) { void system_check(void) {
// Check boot vector
if (OPTIBOOT_MCUSR & (1<<PORF)) { if (OPTIBOOT_MCUSR & (1<<PORF)) {
boot_vector = START_FROM_POWERON; boot_vector = START_FROM_POWERON;
} else if (OPTIBOOT_MCUSR & (1<<BORF)) { } else if (OPTIBOOT_MCUSR & (1<<BORF)) {
@ -54,16 +55,30 @@ void system_check(void) {
} }
} }
// If encryption was previously enabled, require
// it to be initialised to start system.
if (config_crypto_lock) {
if (!crypto_wait()) {
// If initialising crypto times out,
// halt system and display error signal
LED_indicate_error_crypto();
}
}
// Give the green light if everything checks out
LED_STATUS_ON(); LED_STATUS_ON();
} }
void init(void) { void init(void) {
sei(); sei();
serial_init(&serial); serial_init(&serial);
stdout = &serial.uart0; stdout = &serial.uart0;
stdin = &serial.uart0; stdin = &serial.uart0;
config_init();
VREF_init(); VREF_init();
LED_init(); LED_init();
AFSK_init(&modem); AFSK_init(&modem);

View File

@ -7,6 +7,7 @@
#include "util/CRC-CCIT.h" #include "util/CRC-CCIT.h"
#include "hardware/AFSK.h" #include "hardware/AFSK.h"
#include "protocol/KISS.h" #include "protocol/KISS.h"
#include "util/Config.h"
#define countof(a) sizeof(a)/sizeof(a[0]) #define countof(a) sizeof(a)/sizeof(a[0])
#define MIN(a,b) ({ typeof(a) _a = (a); typeof(b) _b = (b); ((typeof(_a))((_a < _b) ? _a : _b)); }) #define MIN(a,b) ({ typeof(a) _a = (a); typeof(b) _b = (b); ((typeof(_a))((_a < _b) ? _a : _b)); })
@ -32,7 +33,7 @@ void ax25_poll(AX25Ctx *ctx) {
while ((c = fgetc(ctx->ch)) != EOF) { while ((c = fgetc(ctx->ch)) != EOF) {
if (!ctx->escape && c == HDLC_FLAG) { if (!ctx->escape && c == HDLC_FLAG) {
if (ctx->frame_len >= AX25_MIN_FRAME_LEN) { if (ctx->frame_len >= AX25_MIN_FRAME_LEN) {
if (ctx->crc_in == AX25_CRC_CORRECT || CONFIG_PASSALL) { if (ctx->crc_in == AX25_CRC_CORRECT || config_passall) {
ax25_decode(ctx); ax25_decode(ctx);
} }
} }

View File

@ -7,6 +7,7 @@
#include "hardware/Crypto.h" #include "hardware/Crypto.h"
#include "util/FIFO16.h" #include "util/FIFO16.h"
#include "util/time.h" #include "util/time.h"
#include "util/Config.h"
#include "KISS.h" #include "KISS.h"
uint8_t packet_queue[CONFIG_QUEUE_SIZE]; uint8_t packet_queue[CONFIG_QUEUE_SIZE];
@ -31,11 +32,10 @@ bool IN_FRAME;
bool ESCAPE; bool ESCAPE;
uint8_t command = CMD_UNKNOWN; uint8_t command = CMD_UNKNOWN;
unsigned long custom_preamble = CONFIG_AFSK_PREAMBLE_LEN;
unsigned long custom_tail = CONFIG_AFSK_TRAILER_LEN;
unsigned long slotTime = 200; //unsigned long custom_preamble = CONFIG_AFSK_PREAMBLE_LEN;
uint8_t p = CONFIG_CSMA_P; //unsigned long custom_tail = CONFIG_AFSK_TRAILER_LEN;
void kiss_init(AX25Ctx *ax25, Afsk *afsk, Serial *ser) { void kiss_init(AX25Ctx *ax25, Afsk *afsk, Serial *ser) {
ax25ctx = ax25; ax25ctx = ax25;
@ -89,6 +89,7 @@ void kiss_messageCallback(AX25Ctx *ctx) {
for (uint8_t i = 0; i < CRYPTO_HMAC_SIZE; i++) { for (uint8_t i = 0; i < CRYPTO_HMAC_SIZE; i++) {
if (hmac[i] != crypto_work_block[i]) { if (hmac[i] != crypto_work_block[i]) {
HMAC_ok = false; HMAC_ok = false;
break;
} }
} }
@ -145,7 +146,7 @@ void kiss_csma(void) {
if (!channel->hdlc.dcd) { if (!channel->hdlc.dcd) {
ticks_t timeout = last_serial_read + ms_to_ticks(CONFIG_SERIAL_TIMEOUT_MS); ticks_t timeout = last_serial_read + ms_to_ticks(CONFIG_SERIAL_TIMEOUT_MS);
if (timer_clock() > timeout) { if (timer_clock() > timeout) {
if (p == 255) { if (config_p == 255) {
kiss_flushQueue(); kiss_flushQueue();
} else { } else {
// TODO: Implement real CSMA // TODO: Implement real CSMA
@ -155,7 +156,7 @@ void kiss_csma(void) {
} }
#else #else
if (!channel->hdlc.dcd) { if (!channel->hdlc.dcd) {
if (p == 255) { if (config_p == 255) {
kiss_flushQueue(); kiss_flushQueue();
} else { } else {
// TODO: Implement real CSMA // TODO: Implement real CSMA
@ -302,16 +303,14 @@ void kiss_serialCallback(uint8_t sbyte) {
if (queue_cursor == CONFIG_QUEUE_SIZE) queue_cursor = 0; if (queue_cursor == CONFIG_QUEUE_SIZE) queue_cursor = 0;
} }
} }
} else if (command == CMD_TXDELAY) { } else if (command == CMD_PREAMBLE) {
custom_preamble = sbyte * 10UL; config_preamble = sbyte * 10UL;
} else if (command == CMD_TXTAIL) { } else if (command == CMD_TXTAIL) {
custom_tail = sbyte * 10; config_tail = sbyte * 10UL;
} else if (command == CMD_SLOTTIME) { } else if (command == CMD_SLOTTIME) {
slotTime = sbyte * 10; config_slottime = sbyte * 10UL;
} else if (command == CMD_P) { } else if (command == CMD_P) {
p = sbyte; config_p = sbyte;
} else if (command == CMD_FLUSHQUEUE) {
kiss_flushQueue();
} else if (command == CMD_LED_INTENSITY) { } else if (command == CMD_LED_INTENSITY) {
if (sbyte == FESC) { if (sbyte == FESC) {
ESCAPE = true; ESCAPE = true;

View File

@ -13,7 +13,7 @@
#define CMD_UNKNOWN 0xFE #define CMD_UNKNOWN 0xFE
#define CMD_DATA 0x00 #define CMD_DATA 0x00
#define CMD_TXDELAY 0x01 #define CMD_PREAMBLE 0x01
#define CMD_P 0x02 #define CMD_P 0x02
#define CMD_SLOTTIME 0x03 #define CMD_SLOTTIME 0x03
#define CMD_TXTAIL 0x04 #define CMD_TXTAIL 0x04

222
util/Config.c Normal file
View File

@ -0,0 +1,222 @@
#include <util/atomic.h>
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/wdt.h>
#include <string.h>
#include "Config.h"
#include "device.h"
#include "hardware/crypto/MD5.h"
#include "hardware/AFSK.h"
void config_init(void) {
config_source = CONFIG_SOURCE_NONE;
bool has_valid_eeprom_config = config_validate_eeprom();
if (has_valid_eeprom_config) {
config_load_from_eeprom();
} else {
config_load_defaults();
config_save_to_eeprom();
}
}
void config_wipe_eeprom(void) {
for (uint16_t i = 0; i < ADDR_E_END; i++) {
EEPROM_updatebyte(i, 0x00);
}
}
bool config_validate_eeprom(void) {
uint8_t config_size = ADDR_E_END;
uint8_t config_data_size = ADDR_E_END - CONF_CHECKSUM_SIZE;
uint8_t config_data[config_data_size];
uint8_t config_checksum[CONF_CHECKSUM_SIZE];
for (uint16_t addr = 0; addr < config_data_size; addr++) {
config_data[addr] = EEPROM_readbyte(addr);
}
for (uint16_t addr = config_data_size; addr < config_size; addr++) {
config_checksum[addr-config_data_size] = EEPROM_readbyte(addr);
}
md5_hash_t calculated_checksum;
md5(&calculated_checksum, &config_data, config_data_size*8);
bool checksums_match = true;
for (uint8_t i = 0; i < CONF_CHECKSUM_SIZE; i++) {
if (calculated_checksum[i] != config_checksum[i]) {
checksums_match = false;
break;
}
}
if (checksums_match) {
return true;
} else {
return false;
}
}
void config_save_to_eeprom(void) {
uint8_t i = 0;
uint8_t config_size = ADDR_E_END;
uint8_t config_data_size = ADDR_E_END - CONF_CHECKSUM_SIZE;
uint8_t config_data[config_size];
memset(config_data, 0x00, ADDR_E_END);
config_data[i++] = MAJ_VERSION;
config_data[i++] = MIN_VERSION;
config_data[i++] = CONF_VERSION;
config_data[i++] = config_p;
config_data[i++] = config_slottime/10;
config_data[i++] = config_preamble/10;
config_data[i++] = config_tail/10;
config_data[i++] = config_led_intensity;
config_data[i++] = config_output_gain;
config_data[i++] = config_input_gain;
config_data[i++] = config_passall;
config_data[i++] = config_log_packets;
config_data[i++] = config_crypto_lock;
config_data[i++] = config_gps_mode;
config_data[i++] = config_bluetooth_mode;
config_data[i++] = config_serial_baudrate;
md5_hash_t checksum;
md5(&checksum, &config_data, config_data_size*8);
for (uint8_t j = 0; j < CONF_CHECKSUM_SIZE; j++) {
config_data[i++] = checksum[j];
}
for (uint16_t addr = 0; addr < config_size; addr++) {
EEPROM_updatebyte(addr, config_data[addr]);
}
}
void config_load_defaults(void) {
config_p = CONFIG_CSMA_P_DEFAULT;
config_slottime = CONFIG_CSMA_SLOTTIME_DEFAULT;
config_preamble = CONFIG_AFSK_PREAMBLE_LEN;
config_tail = CONFIG_AFSK_TRAILER_LEN;
config_led_intensity = CONFIG_LED_INTENSITY;
config_output_gain = CONFIG_DAC_REF;
config_input_gain = CONFIG_ADC_REF;
config_passall = false;
config_log_packets = false;
config_crypto_lock = false;
config_gps_mode = CONFIG_GPS_AUTODETECT;
config_bluetooth_mode = CONFIG_BLUETOOTH_AUTODETECT;
config_serial_baudrate = CONFIG_BAUDRATE_115200;
config_source = CONFIG_SOURCE_DEFAULT;
}
void config_load_from_eeprom(void) {
uint8_t config_data_size = ADDR_E_END - CONF_CHECKSUM_SIZE;
uint8_t config_data[config_data_size];
for (uint16_t addr = 0; addr < config_data_size; addr++) {
config_data[addr] = EEPROM_readbyte(addr);
}
config_p = config_data[ADDR_E_P];
config_slottime = config_data[ADDR_E_SLOTTIME]*10UL;
config_preamble = config_data[ADDR_E_PREAMBLE]*10UL;
config_tail = config_data[ADDR_E_TAIL]*10UL;
config_led_intensity = config_data[ADDR_E_LED_INTENSITY];
config_output_gain = config_data[ADDR_E_OUTPUT_GAIN];
config_input_gain = config_data[ADDR_E_INPUT_GAIN];
config_passall = config_data[ADDR_E_PASSALL];
config_log_packets = config_data[ADDR_E_LOG_PACKETS];
config_crypto_lock = config_data[ADDR_E_CRYPTO_LOCK];
config_gps_mode = config_data[ADDR_E_GPS_MODE];
config_bluetooth_mode = config_data[ADDR_E_BLUETOOTH_MODE];
config_serial_baudrate = config_data[ADDR_E_SERIAL_BAUDRATE];
// printf("Configuration loaded from EEPROM:\r\n");
// printf("\tP\t\t%02X\r\n", config_p);
// printf("\tSlottime\t%lu\r\n", config_slottime);
// printf("\tPreamble\t%lu\r\n", config_preamble);
// printf("\tTail\t\t%lu\r\n", config_tail);
// printf("\tLEDs\t\t%02X\r\n", config_led_intensity);
// printf("\tOut gain\t%02X\r\n", config_output_gain);
// printf("\tIn gain\t\t%02X\r\n", config_input_gain);
// printf("\tPassall\t\t%02X\r\n", config_passall);
// printf("\tLog pkts\t%02X\r\n", config_log_packets);
// printf("\tCrypto lock\t%02X\r\n", config_crypto_lock);
// printf("\tGPS mode\t%02X\r\n", config_gps_mode);
// printf("\tBT Mode\t\t%02X\r\n", config_bluetooth_mode);
// printf("\tBaudrate\t%02X\r\n", config_serial_baudrate);
}
bool config_validate_sd(void) {
// TODO: Implement
return false;
}
void config_save_to_sd(void) {
// TODO: Implement
}
void config_load_from_sd(void) {
// TODO: Implement
return;
}
void config_crypto_lock_enable(void) {
config_crypto_lock = true;
config_save_to_eeprom();
}
void config_crypto_lock_disable(void) {
config_crypto_lock = false;
config_save_to_eeprom();
wdt_enable(WDTO_15MS);
while(true) { }
}
void EEPROM_writebyte(uint16_t addr, uint8_t data) {
// Disable interrupts
cli();
// Wait for EEPROM ready
while(EECR & (1<<EEPE));
// Set up address and data registers
EEAR = addr;
EEDR = data;
// Set EEPROM write enable bit
EECR |= (1<<EEMPE);
// Start EEPROM write, interrupts
// are enabled after write
sei();
EECR |= (1<<EEPE);
}
uint8_t EEPROM_readbyte(uint16_t addr) {
// Disable interrupts
cli();
// Wait for EEPROM ready
while(EECR & (1<<EEPE));
// Set up address and data registers
EEAR = addr;
EECR |= (1<<EERE);
// Enable interrupts and fetch result
sei();
uint8_t byte = EEDR;
return byte;
}
void EEPROM_updatebyte(uint16_t addr, uint8_t data) {
uint8_t byte = EEPROM_readbyte(addr);
if (byte != data) {
EEPROM_writebyte(addr, data);
}
}

107
util/Config.h Normal file
View File

@ -0,0 +1,107 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stdint.h>
#include <stdbool.h>
#define CONF_VERSION 0x01
#define ADDR_E_MAJ_VERSION 0x00
#define ADDR_E_MIN_VERSION 0x01
#define ADDR_E_CONF_VERSION 0x02
#define ADDR_E_P 0x03
#define ADDR_E_SLOTTIME 0x04
#define ADDR_E_PREAMBLE 0x05
#define ADDR_E_TAIL 0x06
#define ADDR_E_LED_INTENSITY 0x07
#define ADDR_E_OUTPUT_GAIN 0x08
#define ADDR_E_INPUT_GAIN 0x09
#define ADDR_E_PASSALL 0x0A
#define ADDR_E_LOG_PACKETS 0x0B
#define ADDR_E_CRYPTO_LOCK 0x0C
#define ADDR_E_GPS_MODE 0x0D
#define ADDR_E_BLUETOOTH_MODE 0x0E
#define ADDR_E_SERIAL_BAUDRATE 0x0F
#define ADDR_E_CHECKSUM 0x10
#define ADDR_E_END 0x20
#define CONFIG_GPS_OFF 0x00
#define CONFIG_GPS_AUTODETECT 0x01
#define CONFIG_GPS_REQUIRED 0x02
#define CONFIG_BLUETOOTH_OFF 0x00
#define CONFIG_BLUETOOTH_AUTODETECT 0x01
#define CONFIG_BLUETOOTH_REQUIRED 0x02
#define CONFIG_BAUDRATE_1200 0x01
#define CONFIG_BAUDRATE_2400 0x02
#define CONFIG_BAUDRATE_4800 0x03
#define CONFIG_BAUDRATE_9600 0x04
#define CONFIG_BAUDRATE_14400 0x05
#define CONFIG_BAUDRATE_19200 0x06
#define CONFIG_BAUDRATE_28800 0x07
#define CONFIG_BAUDRATE_38400 0x08
#define CONFIG_BAUDRATE_57600 0x09
#define CONFIG_BAUDRATE_76800 0x0A
#define CONFIG_BAUDRATE_115200 0x0B
#define CONFIG_BAUDRATE_230400 0x0C
#define CONFIG_SOURCE_NONE 0x00
#define CONFIG_SOURCE_DEFAULT 0x01
#define CONFIG_SOURCE_EEPROM 0x02
#define CONFIG_SOURCE_SD 0x03
#define CONF_CHECKSUM_SIZE 16
uint8_t config_source;
uint8_t config_p;
unsigned long config_slottime;
unsigned long config_preamble;
unsigned long config_tail;
uint8_t config_led_intensity;
uint8_t config_output_gain;
uint8_t config_input_gain;
bool config_passall;
bool config_log_packets;
bool config_crypto_lock;
uint8_t config_gps_mode;
uint8_t config_bluetooth_mode;
uint8_t config_serial_baudrate;
void config_init(void);
bool config_validate_eeprom(void);
bool config_validate_sd(void);
void config_wipe_eeprom(void);
void config_save_to_eeprom(void);
void config_save_to_sd(void);
void config_load_defaults(void);
void config_load_from_eeprom(void);
void config_load_from_sd(void);
void config_crypto_lock_enable(void);
void config_crypto_lock_disable(void);
void EEPROM_updatebyte(uint16_t addr, uint8_t data);
uint8_t EEPROM_readbyte(uint16_t addr);
void EEPROM_writebyte(uint16_t addr, uint8_t data);
#endif
/*
CSMA P
CSMA Slot Time
Preamble
Tail
LED intensity
Output gain
Input gain
Pass-all
Log packets
*/