Improve configuration and its documentation

pull/11/head
Mikael Nousiainen 2021-08-12 09:48:56 +03:00
rodzic d12c923594
commit 6d2416d307
7 zmienionych plików z 178 dodań i 85 usunięć

Wyświetl plik

@ -46,6 +46,12 @@ The main features this firmware aims to implement are:
* Support for more I²C sensors
* Configurable transmission frequencies and schedules based on location / altitude
## Configuring the firmware
1. Configure your amateur radio call sign, transmission schedule (time sync),
transmit frequencies and transmission mode parameters in `config.h`
2. Set up transmitted message templates in `config.c`, depending on the modes you use
## Building the firmware
Software requirements:
@ -63,9 +69,7 @@ dnf install arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++ arm-none-eabi-binutils
### Steps to build the firmware
1. Install the required software dependencies listed above
2. Configure your amateur radio call sign, transmit frequencies and transmission mode parameters in `config.h`
3. Configure scheduling of transmissions in `radio.c` by editing array `radio_transmit_schedule`
4. Build the firmware using the following commands
2. Build the firmware using the following commands
```
mkdir build
cd build

Wyświetl plik

@ -1,30 +1,7 @@
/**
* The tracker firmware will transmit each of the message templates
* defined here one by one, starting again from the beginning once the last message is transmitted.
*/
#include <stdlib.h>
#include "config.h"
bool leds_enabled = LEDS_ENABLE;
bool bmp280_enabled = SENSOR_BMP280_ENABLE;
bool si5351_enabled = RADIO_SI5351_ENABLE;
volatile bool system_initialized = false;
/**
* Allowed message lengths:
* The tracker firmware will transmit each of the message templates defined here in rotation, one by one,
* starting again from the beginning once the last message for a particular mode is transmitted.
*
* APRS comment - Free text up to 127 chars
* FT8 - Free text up to 13 chars (Type 0.0 free text message, Type 0.5 telemetry message)
* JT65 - Free text up to 13 chars (Plaintext Type 6 message)
* JT9 - Free text up to 13 chars (Plaintext Type 6 message)
* JT4 - Free text up to 13 chars (Plaintext Type 6 message)
* FSQ - Call sign up to 20 chars, free text up to 130 chars
* WSPR - Call sign up to 6 chars, locator 4 chars, output power in dBm
*/
/**
* Supported variable references in templates:
*
* $cs - Call sign
@ -48,8 +25,27 @@ volatile bool system_initialized = false;
* $gs - Ground speed in km/h (up to 3 chars)
* $cl - Climb in m/s (up to 2 chars)
* $he - Heading in degrees (up to 3 chars)
*
* Allowed message lengths:
*
* APRS comment - Free text up to 127 chars
* FT8 - Free text up to 13 chars (Type 0.0 free text message, Type 0.5 telemetry message)
* JT65 - Free text up to 13 chars (Plaintext Type 6 message)
* JT9 - Free text up to 13 chars (Plaintext Type 6 message)
* JT4 - Free text up to 13 chars (Plaintext Type 6 message)
* FSQ - Call sign up to 20 chars, free text up to 130 chars
* WSPR - Call sign up to 6 chars, locator 4 chars, output power in dBm
*/
#include <stdlib.h>
#include "config.h"
bool leds_enabled = LEDS_ENABLE;
bool bmp280_enabled = SENSOR_BMP280_ENABLE;
bool si5351_enabled = RADIO_SI5351_ENABLE;
volatile bool system_initialized = false;
/**
* APRS mode comment messages.
* Maximum length: depends on the packet contents, but keeping this under 100 characters is usually safe.

Wyświetl plik

@ -6,22 +6,39 @@
//#define SEMIHOSTING_ENABLE
//#define LOGGING_ENABLE
#include <stdbool.h>
/**
* Global configuration
*/
// Set the tracker amateur radio call sign here
#define CALLSIGN "MYCALL"
// Disabling LEDs will save power
// Red LED: Lit during initialization and transmit.
// Green LED: Blinking fast when there is no GPS fix. Blinking slowly when the GPS has a fix.
#define LEDS_ENABLE true
// Enable use of an externally connected I²C BMP280 atmospheric sensor
#define SENSOR_BMP280_ENABLE false
// Enable use of an externally connected I²C Si5351 clock generator chip for HF radio transmissions
#define RADIO_SI5351_ENABLE false
// Number of character pairs to include in locator
#define LOCATOR_PAIR_COUNT_FULL 6 // max. 6 (12 characters WWL)
// Delay after transmission for modes that do not use time synchronization
#define RADIO_POST_TRANSMIT_DELAY_MS 5000
// Threshold for time-synchronized modes regarding how far from scheduled transmission time the transmission is still allowed
#define RADIO_TIME_SYNC_THRESHOLD_MS 2000
/**
* Si4032 transmit power: 0..7
* 0 = -1dBm, 1 = 2dBm, 2 = 5dBm, 3 = 8dBm, 4 = 11dBm, 5 = 14dBm, 6 = 17dBm, 7 = 20dBm
* Built-in Si4032 radio chip transmission configuration
*/
// Si4032 transmit power: 0..7
// 0 = -1dBm, 1 = 2dBm, 2 = 5dBm, 3 = 8dBm, 4 = 11dBm, 5 = 14dBm, 6 = 17dBm, 7 = 20dBm
#define RADIO_SI4032_TX_POWER 7
// Which modes to transmit using the built-in Si4032 transmitter chip
@ -38,9 +55,11 @@
#define RADIO_SI4032_TX_FREQUENCY_HORUS_V1 432501000
/**
* Si5351 transmit power: 0..3
* Si5351 drive strength: 0 = 2mA, 1 = 4mA, 2 = 6mA, 3 = 8mA
* External Si5351 radio chip transmission configuration
*/
// Si5351 transmit power: 0..3
// Si5351 drive strength: 0 = 2mA, 1 = 4mA, 2 = 6mA, 3 = 8mA
#define RADIO_SI5351_TX_POWER 3
// Which modes to transmit using an externally connected Si5351 chip in the I²C bus
@ -59,19 +78,9 @@
#define RADIO_SI5351_TX_FREQUENCY_FSQ 14085000UL // Was: 7105350UL // Base freq is 1350 Hz higher than dial freq in USB
#define RADIO_SI5351_TX_FREQUENCY_FT8 14085000UL // Was: 14075000UL
#define LOCATOR_PAIR_COUNT_FULL 6 // max. 6 (12 characters WWL)
// WSPR settings
#define WSPR_CALLSIGN CALLSIGN
#define WSPR_LOCATOR_FIXED_ENABLED false
#define WSPR_LOCATOR_FIXED "AA00"
#define WSPR_DBM 10
// FSQ settings
#define FSQ_CALLSIGN_FROM CALLSIGN
#define FSQ_COMMENT "RS41ng radiosonde firmware test"
/**
* APRS mode settings
*
* APRS SSID:
*
* '0' = (-0) Your primary station usually fixed and message capable
@ -102,31 +111,72 @@
#define APRS_DESTINATION "APZ41N"
#define APRS_DESTINATION_SSID '0'
// Schedule transmission every N seconds, counting from beginning of an hour (based on GPS time). Set to zero to disable time sync.
#define APRS_TIME_SYNC_SECONDS 1
// Delay transmission for an N second offset after the scheduled time.
#define APRS_TIME_SYNC_OFFSET_SECONDS 0
/**
* Horus V1 4FSK mode settings
*/
// Use Horus payload ID 0 for tests (4FSKTEST)
#define HORUS_V1_PAYLOAD_ID 0
#define HORUS_V1_BAUD_RATE 100
#define HORUS_V1_FREQUENCY_OFFSET 0
#define HORUS_V1_PREAMBLE_LENGTH 16
// TODO: RTTY and CW settings (once modes are implemented)
// Schedule transmission every N seconds, counting from beginning of an hour (based on GPS time). Set to zero to disable time sync.
#define HORUS_V1_TIME_SYNC_SECONDS 1
// Delay transmission for an N second offset after the scheduled time.
#define HORUS_V1_TIME_SYNC_OFFSET_SECONDS 0
#define RTTY_LOCATOR_PAIR_COUNT 4 // max. 6 (12 characters WWL)
#define RTTY_7BIT 1 // if 0 --> 5 bits
/**
* TODO: CW settings (once implemented)
*/
#define CW_LOCATOR_PAIR_COUNT 4 // max. 6 (12 characters WWL)
#define RADIO_PAYLOAD_MAX_LENGTH 256
#define RADIO_SYMBOL_DATA_MAX_LENGTH 512
#define RADIO_PAYLOAD_MESSAGE_MAX_LENGTH 128
/**
* WSPR settings
*/
#define WSPR_CALLSIGN CALLSIGN
#define WSPR_LOCATOR_FIXED_ENABLED false
#define WSPR_LOCATOR_FIXED "AA00"
#define WSPR_DBM 10
extern bool leds_enabled;
extern bool bmp280_enabled;
extern bool si5351_enabled;
#define WSPR_TIME_SYNC_SECONDS 120
#define WSPR_TIME_SYNC_OFFSET_SECONDS 1
extern volatile bool system_initialized;
/**
* FSQ settings
*/
#define FSQ_CALLSIGN_FROM CALLSIGN
#define FSQ_COMMENT "RS41ng radiosonde firmware test"
extern char *aprs_comment_templates[];
extern char *fsq_comment_templates[];
extern char *ftjt_message_templates[];
#define FSQ_SUBMODE RADIO_DATA_MODE_FSQ_6
#define FSQ_TIME_SYNC_SECONDS 0
#define FSQ_TIME_SYNC_OFFSET_SECONDS 0
/**
* FT/JT mode settings
*/
// Schedule transmission every 15 seconds, counting from beginning of an hour (based on GPS time). Set to zero to disable time sync.
#define FT8_TIME_SYNC_SECONDS 15
// Delay transmission for 1 second after the scheduled time.
#define FT8_TIME_SYNC_OFFSET_SECONDS 1
#define JT9_TIME_SYNC_SECONDS 60
#define JT9_TIME_SYNC_OFFSET_SECONDS 1
#define JT4_TIME_SYNC_SECONDS 60
#define JT4_TIME_SYNC_OFFSET_SECONDS 1
#define JT65_TIME_SYNC_SECONDS 60
#define JT65_TIME_SYNC_OFFSET_SECONDS 1
#include "config_internal.h"
#endif

Wyświetl plik

@ -0,0 +1,20 @@
#ifndef __CONFIG_INTERNAL_H
#define __CONFIG_INTERNAL_H
#define RADIO_PAYLOAD_MAX_LENGTH 256
#define RADIO_SYMBOL_DATA_MAX_LENGTH 512
#define RADIO_PAYLOAD_MESSAGE_MAX_LENGTH 128
#include <stdbool.h>
extern bool leds_enabled;
extern bool bmp280_enabled;
extern bool si5351_enabled;
extern volatile bool system_initialized;
extern char *aprs_comment_templates[];
extern char *fsq_comment_templates[];
extern char *ftjt_message_templates[];
#endif

Wyświetl plik

@ -10,6 +10,11 @@
#define GPIO_SI_4032_CS GPIOC
#define GPIO_PIN_SI4032_CS GPIO_Pin_13
// TODO: For CW support:
// TODO: static const uint16_t radioSDIpin = GPIO_Pin_15; // @ GPIOB!
// TODO: Add methods to init SDI pin GPIO and to set SDI pin state -> Verify it can be used for OOK (CW), NSEL (CS) must be high
// TODO: Call uninitialization of PWM timer after use so that SDI pin is free to use
static inline uint8_t si4032_write(uint8_t reg, uint8_t value)
{
return spi_send_and_receive(GPIO_SI_4032_CS, GPIO_PIN_SI4032_CS, ((reg | SPI_WRITE_FLAG) << 8U) | value);

Wyświetl plik

@ -24,8 +24,8 @@ radio_transmit_entry radio_transmit_schedule[] = {
.enabled = RADIO_SI4032_TX_APRS,
.radio_type = RADIO_TYPE_SI4032,
.data_mode = RADIO_DATA_MODE_APRS_1200,
.time_sync_seconds = 1,
.time_sync_seconds_offset = 0,
.time_sync_seconds = APRS_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = APRS_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI4032_TX_FREQUENCY_APRS_1200,
.tx_power = RADIO_SI4032_TX_POWER,
.symbol_rate = 1200,
@ -36,8 +36,8 @@ radio_transmit_entry radio_transmit_schedule[] = {
.enabled = RADIO_SI4032_TX_HORUS_V1,
.radio_type = RADIO_TYPE_SI4032,
.data_mode = RADIO_DATA_MODE_HORUS_V1,
.time_sync_seconds = 1,
.time_sync_seconds_offset = 0,
.time_sync_seconds = HORUS_V1_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = HORUS_V1_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI4032_TX_FREQUENCY_HORUS_V1,
.tx_power = RADIO_SI4032_TX_POWER,
.symbol_rate = HORUS_V1_BAUD_RATE,
@ -47,74 +47,68 @@ radio_transmit_entry radio_transmit_schedule[] = {
{
.enabled = RADIO_SI5351_TX_WSPR,
.radio_type = RADIO_TYPE_SI5351,
.time_sync_seconds = 120,
.time_sync_seconds_offset = 1,
.time_sync_seconds = WSPR_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = WSPR_TIME_SYNC_OFFSET_SECONDS,
.data_mode = RADIO_DATA_MODE_WSPR,
.frequency = RADIO_SI5351_TX_FREQUENCY_WSPR,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_wspr_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_WSPR,
},
{
.enabled = RADIO_SI5351_TX_FT8,
.radio_type = RADIO_TYPE_SI5351,
.data_mode = RADIO_DATA_MODE_FT8,
.time_sync_seconds = 15,
.time_sync_seconds_offset = 0,
.time_sync_seconds = FT8_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = FT8_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI5351_TX_FREQUENCY_FT8,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_ft8_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_FT8,
},
{
.enabled = RADIO_SI5351_TX_JT9,
.radio_type = RADIO_TYPE_SI5351,
.data_mode = RADIO_DATA_MODE_JT9,
.time_sync_seconds = 60,
.time_sync_seconds_offset = 1,
.time_sync_seconds = JT9_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = JT9_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI5351_TX_FREQUENCY_JT9,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_jt9_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_JT9,
},
{
.enabled = RADIO_SI5351_TX_JT4,
.radio_type = RADIO_TYPE_SI5351,
.data_mode = RADIO_DATA_MODE_JT4,
.time_sync_seconds = 60,
.time_sync_seconds_offset = 1,
.time_sync_seconds = JT4_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = JT4_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI5351_TX_FREQUENCY_JT4,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_jt4_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_JT4,
},
{
.enabled = RADIO_SI5351_TX_JT65,
.radio_type = RADIO_TYPE_SI5351,
.data_mode = RADIO_DATA_MODE_JT65,
.time_sync_seconds = 60,
.time_sync_seconds_offset = 1,
.time_sync_seconds = JT65_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = JT65_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI5351_TX_FREQUENCY_JT65,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_jt65_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_JT65,
},
{
.enabled = RADIO_SI5351_TX_FSQ,
.radio_type = RADIO_TYPE_SI5351,
.data_mode = RADIO_DATA_MODE_FSQ_6,
.time_sync_seconds = 0,
.time_sync_seconds_offset = 0,
.data_mode = FSQ_SUBMODE,
.time_sync_seconds = FSQ_TIME_SYNC_SECONDS,
.time_sync_seconds_offset = FSQ_TIME_SYNC_OFFSET_SECONDS,
.frequency = RADIO_SI5351_TX_FREQUENCY_FSQ,
.tx_power = RADIO_SI5351_TX_POWER,
.payload_encoder = &radio_fsq_payload_encoder,
.fsk_encoder_api = &jtencode_fsk_encoder_api,
.jtencode_mode_type = JTENCODE_MODE_FSQ_6,
},
{
.end = true,
@ -165,6 +159,32 @@ radio_module_state radio_shared_state = {
.radio_current_symbol_delay_ms_100 = 0
};
static jtencode_mode_type radio_jtencode_mode_type_for(radio_data_mode mode)
{
switch (mode) {
case RADIO_DATA_MODE_WSPR:
return JTENCODE_MODE_WSPR;
case RADIO_DATA_MODE_FT8:
return JTENCODE_MODE_FT8;
case RADIO_DATA_MODE_JT9:
return JTENCODE_MODE_JT9;
case RADIO_DATA_MODE_JT65:
return JTENCODE_MODE_JT65;
case RADIO_DATA_MODE_JT4:
return JTENCODE_MODE_JT4;
case RADIO_DATA_MODE_FSQ_6:
return JTENCODE_MODE_FSQ_6;
case RADIO_DATA_MODE_FSQ_4_5:
return JTENCODE_MODE_FSQ_4_5;
case RADIO_DATA_MODE_FSQ_3:
return JTENCODE_MODE_FSQ_3;
case RADIO_DATA_MODE_FSQ_2:
return JTENCODE_MODE_FSQ_2;
default:
return 0;
}
}
static inline void radio_reset_next_symbol_counter()
{
if (radio_shared_state.radio_current_symbol_rate > 0) {
@ -241,6 +261,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
case RADIO_DATA_MODE_FSQ_4_5:
case RADIO_DATA_MODE_FSQ_6: {
char locator[5];
jtencode_mode_type jtencode_mode = radio_jtencode_mode_type_for(entry->data_mode);
if (wspr_locator_fixed_enabled) {
strlcpy(locator, WSPR_LOCATOR_FIXED, 4 + 1);
@ -249,8 +270,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
}
success = jtencode_encoder_new(&entry->fsk_encoder, sizeof(radio_current_symbol_data),
radio_current_symbol_data,
entry->jtencode_mode_type, WSPR_CALLSIGN, locator, WSPR_DBM, FSQ_CALLSIGN_FROM);
radio_current_symbol_data, jtencode_mode, WSPR_CALLSIGN, locator, WSPR_DBM, FSQ_CALLSIGN_FROM);
if (!success) {
return false;
}

Wyświetl plik

@ -49,8 +49,6 @@ typedef struct _radio_transmit_entry {
payload_encoder *payload_encoder;
fsk_encoder_api *fsk_encoder_api;
jtencode_mode_type jtencode_mode_type;
fsk_encoder fsk_encoder;
} radio_transmit_entry;