diff --git a/Makefile b/Makefile index 02f887d..78a128b 100755 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ TARGET = images/OpenModem OPT = s FORMAT = ihex -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/BME280.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 # List Assembler source files here. diff --git a/README.md b/README.md index 7d2a52a..09df68c 100755 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ Open Modem Firmware ========== -Open Modem Firmware is an open source firmware implementation of a AFSK modem supporting 300, 1200 and 2400 baud operation, suitable for communication over a wide variety of analogue mediums, both radio and wired. The firmware is designed for and compatible with [unsigned.io's OpenModem](https://unsigned.io/openmodem/), but can be used on any similar build. +Open Modem Firmware is an open source firmware implementation of a AFSK modem supporting 300, 1200 and 2400 baud operation, suitable for communication over a wide variety of analogue mediums, both radio and wired. The firmware is designed for and compatible with [unsigned.io's OpenModem](https://unsigned.io/projects/openmodem), but can be used on any similar build. -Complete modems are available from [the unsigned.io shop](http://unsigned.io/shop), or can be build from scratch by referring to the schematics and documentation on the [OpenModem page](https://unsigned.io/openmodem/) +Complete modems are available from [the unsigned.io shop](http://unsigned.io/shop), or can be build from scratch by referring to the schematics and documentation on the [OpenModem page](https://unsigned.io/projects/openmodem) ## A few highlights @@ -20,4 +20,4 @@ Complete modems are available from [the unsigned.io shop](http://unsigned.io/sho ## Usage -Please refer to the manual and instructions posted at the [OpenModem page](https://unsigned.io/openmodem/). The default serial connection settings are 115200 baud, 8N1. For configuring the modem, please see the OpenModem Config Utility. +Please refer to the manual and instructions posted at the [OpenModem page](https://unsigned.io/projects/openmodem). The default serial connection settings are 115200 baud, 8N1. For configuring the modem, please see the OpenModem Config Utility. diff --git a/device.h b/device.h index 62fe0c1..f89e2e0 100755 --- a/device.h +++ b/device.h @@ -5,7 +5,7 @@ // Version info #define MAJ_VERSION 0x01 -#define MIN_VERSION 0x05 +#define MIN_VERSION 0x04 // CPU settings #define TARGET_CPU m1284p @@ -56,14 +56,6 @@ // Packet settings #define CONFIG_PASSALL false -// User jobs -#define CONFIG_USER_JOBS_ENABLED true - -// External sensor support -#define CONFIG_SENSORS_ENABLED true -#define CONFIG_SENSORS_INTERVAL_MS 1000 -#define CONFIG_BME280_ENABLED true - // Port settings #if TARGET_CPU == m1284p #define ADC_PORT PORTA @@ -126,8 +118,4 @@ #define PATH_AES_128_KEY "OpenModem/aes128.key" #define PATH_CRYPTO_DISABLE "OpenModem/aes128.disable" -// User-scriptable forward function declarations -void user_init(void); -void user_jobs(void); - #endif \ No newline at end of file diff --git a/hardware/BME280.c b/hardware/BME280.c deleted file mode 100644 index 11b6d19..0000000 --- a/hardware/BME280.c +++ /dev/null @@ -1,295 +0,0 @@ -#include "BME280.h" -#include "hardware/LED.h" -#include "util/time.h" -#include "util/Config.h" - -void bme280_cs(bool val) { - if (!val) { - // Pull CS line low to enable bus - USR_IO_PORT &= ~(_BV(bme280_cs_usrio_pin)); - } else { - // Set CS line to high to disable bus - USR_IO_PORT |= _BV(bme280_cs_usrio_pin); - } -} - -uint8_t bme280_exchange(uint8_t tx) { - SPDR = tx; - while(!(SPSR & (1<> 8) | (value << 8); -} - -int16_t bme280_read16_s(uint8_t reg_addr) { - return (int16_t)bme280_read16(reg_addr); -} - -int16_t bme280_read16_s_le(uint8_t reg_addr) { - return (int16_t)bme280_read16_le(reg_addr); -} - -uint32_t bme280_read24(uint8_t reg_addr) { - uint32_t value; - - bme280_select(); - bme280_exchange(reg_addr | 0x80); // Bit 7 high for read mode - - value = bme280_exchange(0x00); - value = value << 8; - value |= bme280_exchange(0x00); - value = value << 8; - value |= bme280_exchange(0x00); - - bme280_deselect(); - return value; -} - -bool bme280_reading_calibration(void) { - uint8_t const status = bme280_read8(BME280_REGISTER_STATUS); - return (status & (1 << 0)) != 0; -} - -void bme280_read_coefficients(void) { - bme280_calibration.dig_T1 = bme280_read16_le(BME280_REGISTER_DIG_T1); - bme280_calibration.dig_T2 = bme280_read16_s_le(BME280_REGISTER_DIG_T2); - bme280_calibration.dig_T3 = bme280_read16_s_le(BME280_REGISTER_DIG_T3); - - bme280_calibration.dig_P1 = bme280_read16_le(BME280_REGISTER_DIG_P1); - bme280_calibration.dig_P2 = bme280_read16_s_le(BME280_REGISTER_DIG_P2); - bme280_calibration.dig_P3 = bme280_read16_s_le(BME280_REGISTER_DIG_P3); - bme280_calibration.dig_P4 = bme280_read16_s_le(BME280_REGISTER_DIG_P4); - bme280_calibration.dig_P5 = bme280_read16_s_le(BME280_REGISTER_DIG_P5); - bme280_calibration.dig_P6 = bme280_read16_s_le(BME280_REGISTER_DIG_P6); - bme280_calibration.dig_P7 = bme280_read16_s_le(BME280_REGISTER_DIG_P7); - bme280_calibration.dig_P8 = bme280_read16_s_le(BME280_REGISTER_DIG_P8); - bme280_calibration.dig_P9 = bme280_read16_s_le(BME280_REGISTER_DIG_P9); - - bme280_calibration.dig_H1 = bme280_read8(BME280_REGISTER_DIG_H1); - bme280_calibration.dig_H2 = bme280_read16_s_le(BME280_REGISTER_DIG_H2); - bme280_calibration.dig_H3 = bme280_read8(BME280_REGISTER_DIG_H3); - - bme280_calibration.dig_H4 = ((int8_t)bme280_read8(BME280_REGISTER_DIG_H4) << 4) | - (bme280_read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); - - bme280_calibration.dig_H5 = ((int8_t)bme280_read8(BME280_REGISTER_DIG_H5 + 1) << 4) | - (bme280_read8(BME280_REGISTER_DIG_H5) >> 4); - - bme280_calibration.dig_H6 = bme280_read8(BME280_REGISTER_DIG_H6); -} - - -void bme280_set_sampling(void) { - uint8_t humidity_control_reg_values = BME280_SAMPLING_X16; - uint8_t config_reg_values = BME280_STANDBY_MS_0_5 << 5 | BME280_FILTER_OFF << 2; - uint8_t control_reg_values = BME280_SAMPLING_X16 << 5 | BME280_SAMPLING_X16 << 2 | BME280_MODE_NORMAL; - - bme280_write8(BME280_REGISTER_CONTROLHUMID, humidity_control_reg_values); - bme280_write8(BME280_REGISTER_CONFIG, config_reg_values); - bme280_write8(BME280_REGISTER_CONTROL, control_reg_values); - -} - -bool bme280_read_temperature(void) { - int32_t var1, var2; - int32_t adc_temp = bme280_read24(BME280_REGISTER_TEMPDATA); - if (adc_temp == 0x800000) { - bme280_temperature = BME280_TEMP_UNDEFINED; - return false; - } else { - adc_temp >>= 4; - - var1 = ((((adc_temp >> 3) - ((int32_t)bme280_calibration.dig_T1 << 1))) * - ((int32_t)bme280_calibration.dig_T2)) >> - 11; - - var2 = (((((adc_temp >> 4) - ((int32_t)bme280_calibration.dig_T1)) * - ((adc_temp >> 4) - ((int32_t)bme280_calibration.dig_T1))) >> - 12) * - ((int32_t)bme280_calibration.dig_T3)) >> - 14; - - bme280_temperature_fine = var1 + var2 + bme280_temperature_fine_adjust; - - float temperature = (bme280_temperature_fine * 5 + 128) >> 8; - bme280_temperature = temperature / 100; - - return true; - } - -} - -bool bme280_read_pressure(void) { - int64_t var1, var2, p; - - bme280_read_temperature(); - int32_t adc_P = bme280_read24(BME280_REGISTER_PRESSUREDATA); - - if (adc_P == 0x800000) { - bme280_pressure = BME280_PRESSURE_UNDEFINED; - return false; - } - - adc_P >>= 4; - - var1 = ((int64_t)bme280_temperature_fine) - 128000; - var2 = var1 * var1 * (int64_t)bme280_calibration.dig_P6; - var2 = var2 + ((var1 * (int64_t)bme280_calibration.dig_P5) << 17); - var2 = var2 + (((int64_t)bme280_calibration.dig_P4) << 35); - var1 = ((var1 * var1 * (int64_t)bme280_calibration.dig_P3) >> 8) + - ((var1 * (int64_t)bme280_calibration.dig_P2) << 12); - var1 = - (((((int64_t)1) << 47) + var1)) * ((int64_t)bme280_calibration.dig_P1) >> 33; - - if (var1 == 0) { - return false; - } - - p = 1048576 - adc_P; - p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)bme280_calibration.dig_P9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)bme280_calibration.dig_P8) * p) >> 19; - - p = ((p + var1 + var2) >> 8) + (((int64_t)bme280_calibration.dig_P7) << 4); - - bme280_pressure = (float)p / 25600; - return true; -} - -bool bme280_read_humidity(void) { - int32_t v_x1_u32r; - - bme280_read_temperature(); - - int32_t adc_H = bme280_read16(BME280_REGISTER_HUMIDDATA); - - if (adc_H == 0x800000) { - bme280_humidity = BME280_PRESSURE_UNDEFINED; - return false; - } - - v_x1_u32r = (bme280_temperature_fine - ((int32_t)76800)); - - v_x1_u32r = (((((adc_H << 14) - (((int32_t)bme280_calibration.dig_H4) << 20) - - (((int32_t)bme280_calibration.dig_H5) * v_x1_u32r)) + - ((int32_t)16384)) >> - 15) * - (((((((v_x1_u32r * ((int32_t)bme280_calibration.dig_H6)) >> 10) * - (((v_x1_u32r * ((int32_t)bme280_calibration.dig_H3)) >> 11) + - ((int32_t)32768))) >> - 10) + - ((int32_t)2097152)) * - ((int32_t)bme280_calibration.dig_H2) + - 8192) >> - 14)); - - v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * - ((int32_t)bme280_calibration.dig_H1)) >> - 4)); - - v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; - v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; - float h = (v_x1_u32r >> 12); - bme280_humidity = h / 1024.0; - - return true; -} - -bool bme280_init(uint8_t cs_usrio_pin) { - bme280_installed = false; - bme280_ready = false; - bme280_cs_usrio_pin = cs_usrio_pin; - - bme280_temperature_fine_adjust = BME280_TEMPERATURE_ADJUSTMENT; - - USR_IO_DDR |= bme280_cs_usrio_pin; - - SPI_DDR |= _BV(SPI_MOSI) | _BV(SPI_CLK); - SPI_DDR &= ~(_BV(SPI_MISO)); - SPCR = (1< -#include -#include -#include -#include "device.h" -#include "util/time.h" - -#define BME280_TEMPERATURE_ADJUSTMENT 0 - -#define BME280_TEMP_UNDEFINED -274 -#define BME280_PRESSURE_UNDEFINED -1 -#define BME280_HUMIDITY_UNDEFINED -1 - -#define BME280_REGISTER_DIG_T1 0x88 -#define BME280_REGISTER_DIG_T2 0x8A -#define BME280_REGISTER_DIG_T3 0x8C -#define BME280_REGISTER_DIG_P1 0x8E -#define BME280_REGISTER_DIG_P2 0x90 -#define BME280_REGISTER_DIG_P3 0x92 -#define BME280_REGISTER_DIG_P4 0x94 -#define BME280_REGISTER_DIG_P5 0x96 -#define BME280_REGISTER_DIG_P6 0x98 -#define BME280_REGISTER_DIG_P7 0x9A -#define BME280_REGISTER_DIG_P8 0x9C -#define BME280_REGISTER_DIG_P9 0x9E -#define BME280_REGISTER_DIG_H1 0xA1 -#define BME280_REGISTER_DIG_H2 0xE1 -#define BME280_REGISTER_DIG_H3 0xE3 -#define BME280_REGISTER_DIG_H4 0xE4 -#define BME280_REGISTER_DIG_H5 0xE5 -#define BME280_REGISTER_DIG_H6 0xE7 -#define BME280_REGISTER_CHIPID 0xD0 -#define BME280_REGISTER_VERSION 0xD1 -#define BME280_REGISTER_SOFTRESET 0xE0 -#define BME280_REGISTER_CAL26 0xE1 // R calibration stored in 0xE1-0xF0 -#define BME280_REGISTER_CONTROLHUMID 0xF2 -#define BME280_REGISTER_STATUS 0XF3 -#define BME280_REGISTER_CONTROL 0xF4 -#define BME280_REGISTER_CONFIG 0xF5 -#define BME280_REGISTER_PRESSUREDATA 0xF7 -#define BME280_REGISTER_TEMPDATA 0xFA -#define BME280_REGISTER_HUMIDDATA 0xFD - -#define BME280_SAMPLING_NONE 0b000 -#define BME280_SAMPLING_X1 0b001 -#define BME280_SAMPLING_X2 0b010 -#define BME280_SAMPLING_X4 0b011 -#define BME280_SAMPLING_X8 0b100 -#define BME280_SAMPLING_X16 0b101 - -#define BME280_MODE_SLEEP 0b00 -#define BME280_MODE_FORCED 0b01 -#define BME280_MODE_NORMAL 0b11 - -#define BME280_FILTER_OFF 0b000 -#define BME280_FILTER_X2 0b001 -#define BME280_FILTER_X4 0b010 -#define BME280_FILTER_X8 0b011 -#define BME280_FILTER_X16 0b100 - -#define BME280_STANDBY_MS_0_5 0b000 -#define BME280_STANDBY_MS_10 0b110 -#define BME280_STANDBY_MS_20 0b111 -#define BME280_STANDBY_MS_62_5 0b001 -#define BME280_STANDBY_MS_125 0b010 -#define BME280_STANDBY_MS_250 0b011 -#define BME280_STANDBY_MS_500 0b100 -#define BME280_STANDBY_MS_1000 0b101 - - -typedef struct { - uint16_t dig_T1; // temperature compensation value - int16_t dig_T2; // temperature compensation value - int16_t dig_T3; // temperature compensation value - - uint16_t dig_P1; // pressure compensation value - int16_t dig_P2; // pressure compensation value - int16_t dig_P3; // pressure compensation value - int16_t dig_P4; // pressure compensation value - int16_t dig_P5; // pressure compensation value - int16_t dig_P6; // pressure compensation value - int16_t dig_P7; // pressure compensation value - int16_t dig_P8; // pressure compensation value - int16_t dig_P9; // pressure compensation value - - uint8_t dig_H1; // humidity compensation value - int16_t dig_H2; // humidity compensation value - uint8_t dig_H3; // humidity compensation value - int16_t dig_H4; // humidity compensation value - int16_t dig_H5; // humidity compensation value - int8_t dig_H6; // humidity compensation value -} bme280_calib_data; - -bool bme280_init(uint8_t cs_usrio_pin); -bool bme280_poll(void); - -bool bme280_installed; -bool bme280_ready; -uint8_t bme280_cs_usrio_pin; - -int32_t bme280_temperature_fine_adjust; -int32_t bme280_temperature_fine; - -float bme280_temperature; -float bme280_pressure; -float bme280_humidity; - -bme280_calib_data bme280_calibration; - -#endif \ No newline at end of file diff --git a/hardware/Bluetooth.h b/hardware/Bluetooth.h index a84c467..05841e2 100644 --- a/hardware/Bluetooth.h +++ b/hardware/Bluetooth.h @@ -8,7 +8,7 @@ #include #include "device.h" #include "util/time.h" -#include "hardware/Serial.h" +#include "hardware/serial.h" void bluetooth_init(void); bool bluetooth_enabled(void); diff --git a/hardware/GPS.c b/hardware/GPS.c index e1ca5b3..49f7d51 100644 --- a/hardware/GPS.c +++ b/hardware/GPS.c @@ -39,7 +39,6 @@ void gps_init(Serial *ser) { gps_speed_kmh = 0; gps_bearing = 0; - gps_fix = false; gps_time_set = false; if (gps_detect()) { @@ -47,8 +46,6 @@ void gps_init(Serial *ser) { GPS_DDR |= _BV(GPS_EN_PIN); if (config_gps_mode == CONFIG_GPS_AUTODETECT || config_gps_mode == CONFIG_GPS_REQUIRED) { - gps_powerup(); - serial_setbaudrate_9600(1); delay_ms(100); @@ -62,6 +59,7 @@ void gps_init(Serial *ser) { gps_send_command(PMTK_SET_NMEA_OUTPUT_RMCGGA); gps_power = true; + gps_powerup(); } else { gps_power = false; gps_powerdown(); @@ -73,7 +71,6 @@ void gps_init(Serial *ser) { } } - void gps_update_rtc(void) { struct tm now; @@ -274,7 +271,21 @@ void gps_nmea_parse(uint8_t sentence_length) { gps_t_year = (nmea_date % 100); gps_update_rtc(); } - + + // TODO: Remove this + // printf("GPS fix\r\n"); + // printf("GPS satellites: %d\r\n", gps_sats); + // printf("GPS latitude: %d\" %d' %.2fs %c\r\n", gps_lat_degrees, gps_lat_minutes, gps_lat_seconds, gps_lat_sign); + // printf("GPS longtitude: %d\" %d' %.2fs %c\r\n", gps_lon_degrees, gps_lon_minutes, gps_lon_seconds, gps_lon_sign); + // printf("GPS coords: %.6f,%.6f\r\n", gps_lat, gps_lon); + // printf("GPS speed %.2f Km/h\r\n", gps_speed_kmh); + // printf("GPS speed %.2f knots\r\n", gps_speed_knots); + // printf("GPS bearing %.2f\r\n", gps_bearing); + // printf("GPS height above MSL: %.2f\r\n", gps_height_above_msl); + // printf("GPS altitude: %.2f\r\n", gps_altitude); + // printf("GPS geoid height: %.2f\r\n", gps_geoid_height); + // printf("GPS HDOP: %.2f\r\n", gps_hdop); + // printf("GPS time %d/%d/%d %d:%d:%d UTC\r\n", gps_t_year, gps_t_month, gps_t_day, gps_t_hour, gps_t_minute, gps_t_second); } else { gps_speed_knots = 0; gps_speed_kmh = 0; diff --git a/hardware/GPS.h b/hardware/GPS.h index 6886c93..831d760 100644 --- a/hardware/GPS.h +++ b/hardware/GPS.h @@ -8,7 +8,7 @@ #include #include "device.h" #include "util/time.h" -#include "hardware/Serial.h" +#include "hardware/serial.h" #define NMEA_MAX_LENGTH 128 diff --git a/hardware/Serial.c b/hardware/Serial.c index ac201a5..dadbad0 100755 --- a/hardware/Serial.c +++ b/hardware/Serial.c @@ -84,7 +84,7 @@ ISR(USART0_RX_vect) { char c = uart0_getchar_nowait(); fifo_push(&uart0FIFO, c); } else { - uart0_getchar_nowait(); + //uart0_getchar_nowait(); } } } @@ -95,7 +95,7 @@ ISR(USART1_RX_vect) { char c = uart1_getchar_nowait(); fifo_push(&uart1FIFO, c); } else { - uart1_getchar_nowait(); + //uart1_getchar_nowait(); } } } diff --git a/main.c b/main.c index dcf406a..08147b4 100755 --- a/main.c +++ b/main.c @@ -16,7 +16,6 @@ #include "hardware/SD.h" #include "hardware/Crypto.h" #include "hardware/Bluetooth.h" -#include "hardware/BME280.h" #include "hardware/GPS.h" #include "protocol/AX25.h" #include "protocol/KISS.h" @@ -93,33 +92,7 @@ void init(void) { gps_init(&serial); usrio_init(); - if (config_sensors_enabled) { - if (config_sensor_bme280_enabled) bme280_init(config_sensor_bme280_cs_pin); - } - system_check(); - - if (config_user_jobs_enabled) user_init(); -} - -mtime_t sensor_poll_time = 0; -void sensor_jobs(void) { - if (rtc_milliseconds() > sensor_poll_time+config_sensor_interval_ms) { - if (config_sensor_bme280_enabled && bme280_ready) { - bme280_poll(); - } - - sensor_poll_time = rtc_milliseconds(); - } -} - -void user_init(void) { - // Place user-specified initialisation code here -} - - -void user_jobs(void) { - // Place user-specified tasks and jobs here } @@ -132,9 +105,6 @@ int main (void) { kiss_csma(); sd_jobs(); gps_poll(); - - if (config_sensors_enabled) sensor_jobs(); - if (config_user_jobs_enabled) user_jobs(); } return(0); diff --git a/precompiled/OpenModem_AFSK1200.zip b/precompiled/OpenModem_AFSK1200.zip index 6ae4bb5..5f20426 100644 Binary files a/precompiled/OpenModem_AFSK1200.zip and b/precompiled/OpenModem_AFSK1200.zip differ diff --git a/precompiled/OpenModem_AFSK2400.zip b/precompiled/OpenModem_AFSK2400.zip index ce740ad..2adea83 100644 Binary files a/precompiled/OpenModem_AFSK2400.zip and b/precompiled/OpenModem_AFSK2400.zip differ diff --git a/precompiled/OpenModem_AFSK300.zip b/precompiled/OpenModem_AFSK300.zip index 808e362..65b50bb 100644 Binary files a/precompiled/OpenModem_AFSK300.zip and b/precompiled/OpenModem_AFSK300.zip differ diff --git a/util/Config.c b/util/Config.c index 6bf241b..b6e3cb0 100644 --- a/util/Config.c +++ b/util/Config.c @@ -30,12 +30,7 @@ void config_init(void) { } void config_init_ephemeral(void) { - config_user_jobs_enabled = CONFIG_USER_JOBS_ENABLED; config_gps_nmea_output = CONFIG_GPS_NMEA_NONE; - config_sensors_enabled = CONFIG_SENSORS_ENABLED; - config_sensor_interval_ms = CONFIG_SENSORS_INTERVAL_MS; - config_sensor_bme280_enabled = CONFIG_BME280_ENABLED; - config_sensor_bme280_cs_pin = USR_IO_1; } void config_apply(void) { diff --git a/util/Config.h b/util/Config.h index 69732bd..8833c51 100644 --- a/util/Config.h +++ b/util/Config.h @@ -74,14 +74,8 @@ uint8_t config_gps_nmea_output; uint8_t config_bluetooth_mode; uint8_t config_serial_baudrate; -bool config_user_jobs_enabled; bool config_output_diagnostics; -bool config_sensors_enabled; -int32_t config_sensor_interval_ms; -bool config_sensor_bme280_enabled; -uint8_t config_sensor_bme280_cs_pin; - void config_init(void); void config_init_ephemeral(void); void config_apply(void);