diff --git a/src/codecs/horus/horus_packet_v2.c b/src/codecs/horus/horus_packet_v2.c index 842b6a2..9e05fcb 100644 --- a/src/codecs/horus/horus_packet_v2.c +++ b/src/codecs/horus/horus_packet_v2.c @@ -44,14 +44,27 @@ size_t horus_packet_v2_create(uint8_t *payload, size_t length, telemetry_data *d horus_packet.Sats += 200; } + uint8_t *custom_data_pointer = horus_packet.CustomData; + + uint16_t cus_packet_counter = horus_v2_packet_counter; + memcpy(custom_data_pointer, &cus_packet_counter, sizeof(cus_packet_counter)); + custom_data_pointer += sizeof(cus_packet_counter); + + int16_t cus_temp_celsius_10 = (int16_t) (data->internal_temperature_celsius_100 / 10.0f); + memcpy(custom_data_pointer, &cus_temp_celsius_10, sizeof(cus_temp_celsius_10)); + custom_data_pointer += sizeof(cus_temp_celsius_10); + int16_t ext_temp_celsius_10 = (int16_t) (data->temperature_celsius_100 / 10.0f); - memcpy(horus_packet.CustomData, &ext_temp_celsius_10, sizeof(ext_temp_celsius_10)); + memcpy(custom_data_pointer, &ext_temp_celsius_10, sizeof(ext_temp_celsius_10)); + custom_data_pointer += sizeof(ext_temp_celsius_10); uint8_t ext_humidity_percentage = (uint8_t) (data->humidity_percentage_100 / 100.0f); - memcpy(horus_packet.CustomData + sizeof(ext_temp_celsius_10), &ext_humidity_percentage, sizeof(ext_humidity_percentage)); + memcpy(custom_data_pointer, &ext_humidity_percentage, sizeof(ext_humidity_percentage)); + custom_data_pointer += sizeof(ext_humidity_percentage); uint16_t ext_pressure_mbar = (uint8_t) (data->pressure_mbar_100 / 100.0f); - memcpy(horus_packet.CustomData + sizeof(ext_temp_celsius_10) + sizeof(ext_humidity_percentage), &ext_pressure_mbar, sizeof(ext_pressure_mbar)); + memcpy(custom_data_pointer, &ext_pressure_mbar, sizeof(ext_pressure_mbar)); + // custom_data_pointer += sizeof(ext_pressure_mbar); horus_packet.Checksum = (uint16_t) calculate_crc16_checksum((char *) &horus_packet, sizeof(horus_packet) - 2); diff --git a/src/config.h b/src/config.h index 22f049e..6e8165b 100644 --- a/src/config.h +++ b/src/config.h @@ -30,8 +30,8 @@ // 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 1000 +// Delay after transmission for modes that do not use time synchronization. Zero delay allows continuous transmit mode for Horus V1 and V2. +#define RADIO_POST_TRANSMIT_DELAY_MS 0 // Threshold for time-synchronized modes regarding how far from scheduled transmission time the transmission is still allowed #define RADIO_TIME_SYNC_THRESHOLD_MS 2000 @@ -50,8 +50,12 @@ #define RADIO_SI4032_TX_HORUS_V1 true #define RADIO_SI4032_TX_HORUS_V2 true +// Continuous transmit mode can be enabled for *either* Horus V1 or V2, but not both. This disables all other transmission modes. +#define RADIO_SI4032_TX_HORUS_V1_CONTINUOUS false +#define RADIO_SI4032_TX_HORUS_V2_CONTINUOUS false + // Transmit frequencies for the Si4032 transmitter modes -#define RADIO_SI4032_TX_FREQUENCY_CW 432500000 +#define RADIO_SI4032_TX_FREQUENCY_CW 432500000 #define RADIO_SI4032_TX_FREQUENCY_APRS_1200 432500000 // Use a frequency offset to place FSK tones slightly above the defined frequency for SSB reception #define RADIO_SI4032_TX_FREQUENCY_HORUS_V1 432501000 @@ -125,6 +129,12 @@ // Delay transmission for an N second offset after the scheduled time. #define APRS_TIME_SYNC_OFFSET_SECONDS 0 +/** + * Common Horus 4FSK mode settings + */ + +#define HORUS_FREQUENCY_OFFSET_SI4032 0 + /** * Horus V1 4FSK mode settings */ @@ -134,8 +144,8 @@ #define HORUS_V1_BAUD_RATE_SI4032 100 #define HORUS_V1_BAUD_RATE_SI5351 50 #define HORUS_V1_PREAMBLE_LENGTH 16 -#define HORUS_V1_FREQUENCY_OFFSET_SI4032 0 -#define HORUS_V1_TONE_SPACING_HZ 270 +#define HORUS_V1_IDLE_PREAMBLE_LENGTH 32 +#define HORUS_V1_TONE_SPACING_HZ_SI5351 270 // 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 0 @@ -151,8 +161,8 @@ #define HORUS_V2_BAUD_RATE_SI4032 100 #define HORUS_V2_BAUD_RATE_SI5351 50 #define HORUS_V2_PREAMBLE_LENGTH 16 -#define HORUS_V2_FREQUENCY_OFFSET_SI4032 0 -#define HORUS_V2_TONE_SPACING_HZ 270 +#define HORUS_V2_IDLE_PREAMBLE_LENGTH 32 +#define HORUS_V2_TONE_SPACING_HZ_SI5351 270 // Schedule transmission every N seconds, counting from beginning of an hour (based on GPS time). Set to zero to disable time sync. #define HORUS_V2_TIME_SYNC_SECONDS 0 diff --git a/src/hal/i2c.c b/src/hal/i2c.c index 5f68f44..dc3a4da 100644 --- a/src/hal/i2c.c +++ b/src/hal/i2c.c @@ -5,6 +5,7 @@ #include "hal.h" #include "i2c.h" #include "delay.h" +#include "log.h" struct _i2c_port { I2C_TypeDef *i2c; @@ -59,6 +60,9 @@ void i2c_init() while (I2C_GetFlagStatus(I2C_PORT, I2C_FLAG_BUSY) && count--) { delay_ms(1); } + if (count == 0) { + log_error("ERROR: I²C bus busy during initialization"); + } I2C_Cmd(I2C_PORT, ENABLE); } @@ -70,38 +74,110 @@ void i2c_uninit() RCC_APB1PeriphClockCmd(I2C_PORT_RCC_PERIPH, DISABLE); } +static void i2c_reset_bus(i2c_port *port) +{ + for (int i = 0; i < 10; i++) { + I2C_GenerateSTOP(port->i2c, ENABLE); + delay_us(100); + I2C_GenerateSTOP(port->i2c, DISABLE); + delay_us(100); + } + + I2C_GetFlagStatus(port->i2c, I2C_FLAG_BUSY); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_BERR); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_SMBALERT); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_TIMEOUT); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_PECERR); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_OVR); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_AF); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_ARLO); + I2C_GetFlagStatus(port->i2c, I2C_FLAG_BERR); + I2C_ClearFlag(port->i2c, I2C_FLAG_SMBALERT | I2C_FLAG_TIMEOUT | I2C_FLAG_PECERR | I2C_FLAG_OVR | I2C_FLAG_AF | I2C_FLAG_ARLO | I2C_FLAG_BERR); +} + +static int i2c_wait_until_not_busy(i2c_port *port) +{ + __IO uint32_t timeout = 0xFFFFFF; + + while (I2C_GetFlagStatus(I2C_PORT, I2C_FLAG_BUSY)) { + if (--timeout == 0) { + log_error("ERROR: Timeout - I2C bus busy"); + i2c_reset_bus(port); + return HAL_ERROR_TIMEOUT; + } + } + + return HAL_OK; +} + +static bool i2c_wait_event(i2c_port *port, uint32_t flag) +{ + __IO uint32_t timeout = 0xFFFFFF; + + while (I2C_CheckEvent(port->i2c, flag) != SUCCESS) { + if (--timeout == 0) { + log_error("ERROR: WE event timeout: 0x%08lx", flag); + i2c_reset_bus(port); + return false; + } + } + + return true; +} + static int i2c_prepare_op(i2c_port *port, uint8_t address) { I2C_AcknowledgeConfig(port->i2c, ENABLE); I2C_GenerateSTART(port->i2c, ENABLE); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_MODE_SELECT)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) { + log_error("ERROR: PO MMS timeout: 0x%02x", address); + return HAL_ERROR_TIMEOUT; + } I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Transmitter); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) { + log_error("ERROR: PO MTMS timeout: 0x%02x", address); + return HAL_ERROR_TIMEOUT; + } return HAL_OK; } static int i2c_prepare_op_with_register(i2c_port *port, uint8_t address, uint8_t reg) { - i2c_prepare_op(port, address); + int result = i2c_prepare_op(port, address); + if (result != HAL_OK) { + return result; + } I2C_SendData(port->i2c, reg); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { + log_error("ERROR: POWR MBT timeout: 0x%02x 0x%02x", address, reg); + return HAL_ERROR_TIMEOUT; + } return HAL_OK; } static int i2c_prepare_read(i2c_port *port, uint8_t address, uint8_t reg) { - i2c_prepare_op_with_register(port, address, reg); + int result = i2c_prepare_op_with_register(port, address, reg); + if (result != HAL_OK) { + return result; + } I2C_GenerateSTART(port->i2c, ENABLE); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_MODE_SELECT)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_MODE_SELECT)) { + log_error("ERROR: PR MMS timeout: 0x%02x 0x%02x", address, reg); + return HAL_ERROR_TIMEOUT; + } I2C_Send7bitAddress(port->i2c, address, I2C_Direction_Receiver); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)) { + log_error("ERROR: PR MRMS timeout: 0x%02x 0x%02x", address, reg); + return HAL_ERROR_TIMEOUT; + } return HAL_OK; } @@ -111,7 +187,10 @@ static int i2c_finish_read(i2c_port *port) I2C_GenerateSTOP(port->i2c, ENABLE); I2C_AcknowledgeConfig(port->i2c, DISABLE); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_BYTE_RECEIVED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) { + log_error("ERROR: FR MBR timeout"); + return HAL_ERROR_TIMEOUT; + } I2C_ReceiveData(port->i2c); return HAL_OK; @@ -126,17 +205,31 @@ static int i2c_finish_write(i2c_port *port) { I2C_GenerateSTOP(port->i2c, ENABLE); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { + log_error("ERROR: FW MBT timeout"); + return HAL_ERROR_TIMEOUT; + } return HAL_OK; } int i2c_read_bytes(i2c_port *port, uint8_t address, uint8_t reg, uint8_t size, uint8_t *data) { - i2c_prepare_read(port, address, reg); + int result = i2c_wait_until_not_busy(port); + if (result != HAL_OK) { + return result; + } + + result = i2c_prepare_read(port, address, reg); + if (result != HAL_OK) { + return result; + } for (uint8_t i = 0; i < size; i++) { - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_BYTE_RECEIVED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) { + log_error("ERROR: MBR timeout: 0x%02x 0x%02x", address, reg); + return HAL_ERROR_TIMEOUT; + } data[i] = I2C_ReceiveData(port->i2c); } @@ -152,11 +245,22 @@ int i2c_read_byte(i2c_port *port, uint8_t address, uint8_t reg, uint8_t *data) int i2c_write_bytes(i2c_port *port, uint8_t address, uint8_t reg, uint8_t size, uint8_t *data) { - i2c_prepare_write(port, address, reg); + int result = i2c_wait_until_not_busy(port); + if (result != HAL_OK) { + return result; + } + + result = i2c_prepare_write(port, address, reg); + if (result != HAL_OK) { + return result; + } for (uint8_t i = 0; i < size; i++) { I2C_SendData(port->i2c, data[i]); - while (!I2C_CheckEvent(port->i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); + if (!i2c_wait_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED)) { + log_error("ERROR: MBF timeout: 0x%02x 0x%02x", address, reg); + return HAL_ERROR_TIMEOUT; + } } i2c_finish_write(port); diff --git a/src/radio.c b/src/radio.c index add3ef8..8b3629e 100644 --- a/src/radio.c +++ b/src/radio.c @@ -23,6 +23,58 @@ #include "radio_payload_fsq.h" radio_transmit_entry radio_transmit_schedule[] = { +#if RADIO_SI4032_TX_HORUS_V1_CONTINUOUS == true + { + .enabled = RADIO_SI4032_TX_HORUS_V1, + .radio_type = RADIO_TYPE_SI4032, + .data_mode = RADIO_DATA_MODE_HORUS_V1, + .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_SI4032, + .payload_encoder = &radio_horus_v1_payload_encoder, + .fsk_encoder_api = &mfsk_fsk_encoder_api, + }, + { + .enabled = RADIO_SI4032_TX_HORUS_V1, + .radio_type = RADIO_TYPE_SI4032, + .data_mode = RADIO_DATA_MODE_HORUS_V1, + .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_SI4032, + .payload_encoder = &radio_horus_v1_idle_encoder, + .fsk_encoder_api = &mfsk_fsk_encoder_api, + }, +#elif RADIO_SI4032_TX_HORUS_V2_CONTINUOUS == true + { + .enabled = RADIO_SI4032_TX_HORUS_V2, + .radio_type = RADIO_TYPE_SI4032, + .data_mode = RADIO_DATA_MODE_HORUS_V2, + .time_sync_seconds = HORUS_V2_TIME_SYNC_SECONDS, + .time_sync_seconds_offset = HORUS_V2_TIME_SYNC_OFFSET_SECONDS, + .frequency = RADIO_SI4032_TX_FREQUENCY_HORUS_V2, + .tx_power = RADIO_SI4032_TX_POWER, + .symbol_rate = HORUS_V2_BAUD_RATE_SI4032, + .payload_encoder = &radio_horus_v2_payload_encoder, + .fsk_encoder_api = &mfsk_fsk_encoder_api, + }, + { + .enabled = RADIO_SI4032_TX_HORUS_V2, + .radio_type = RADIO_TYPE_SI4032, + .data_mode = RADIO_DATA_MODE_HORUS_V2, + .time_sync_seconds = HORUS_V2_TIME_SYNC_SECONDS, + .time_sync_seconds_offset = HORUS_V2_TIME_SYNC_OFFSET_SECONDS, + .frequency = RADIO_SI4032_TX_FREQUENCY_HORUS_V2, + .tx_power = RADIO_SI4032_TX_POWER, + .symbol_rate = HORUS_V2_BAUD_RATE_SI4032, + .payload_encoder = &radio_horus_v2_idle_encoder, + .fsk_encoder_api = &mfsk_fsk_encoder_api, + }, +#else +#endif { .enabled = RADIO_SI4032_TX_CW, .radio_type = RADIO_TYPE_SI4032, @@ -71,6 +123,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_horus_v2_payload_encoder, .fsk_encoder_api = &mfsk_fsk_encoder_api, }, +#if RADIO_SI5351_ENABLE == true +#if RADIO_SI5351_TX_CW == true { .enabled = RADIO_SI5351_TX_CW, .radio_type = RADIO_TYPE_SI5351, @@ -83,6 +137,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_cw_payload_encoder, .fsk_encoder_api = &morse_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_HORUS_V1 == true { .enabled = RADIO_SI5351_TX_HORUS_V1, .radio_type = RADIO_TYPE_SI5351, @@ -95,6 +151,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_horus_v1_payload_encoder, .fsk_encoder_api = &mfsk_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_HORUS_V2 == true { .enabled = RADIO_SI5351_TX_HORUS_V2, .radio_type = RADIO_TYPE_SI5351, @@ -107,7 +165,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_horus_v2_payload_encoder, .fsk_encoder_api = &mfsk_fsk_encoder_api, }, -/* +#endif +#if RADIO_SI5351_TX_WSPR == true { .enabled = RADIO_SI5351_TX_WSPR, .radio_type = RADIO_TYPE_SI5351, @@ -119,6 +178,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_wspr_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_FT8 == true { .enabled = RADIO_SI5351_TX_FT8, .radio_type = RADIO_TYPE_SI5351, @@ -130,6 +191,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_ft8_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_JT9 == true { .enabled = RADIO_SI5351_TX_JT9, .radio_type = RADIO_TYPE_SI5351, @@ -141,6 +204,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_jt9_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_JT4 == true { .enabled = RADIO_SI5351_TX_JT4, .radio_type = RADIO_TYPE_SI5351, @@ -152,6 +217,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_jt4_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, +#endif +#if RADIO_SI5351_TX_JT65 == true { .enabled = RADIO_SI5351_TX_JT65, .radio_type = RADIO_TYPE_SI5351, @@ -163,7 +230,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_jt65_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, -*/ +#endif +#if RADIO_SI5351_TX_FSQ == true { .enabled = RADIO_SI5351_TX_FSQ, .radio_type = RADIO_TYPE_SI5351, @@ -175,6 +243,8 @@ radio_transmit_entry radio_transmit_schedule[] = { .payload_encoder = &radio_fsq_payload_encoder, .fsk_encoder_api = &jtencode_fsk_encoder_api, }, +#endif +#endif { .end = true, } @@ -315,7 +385,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry) entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload); break; case RADIO_DATA_MODE_HORUS_V1: - mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V1_TONE_SPACING_HZ * 100); + mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V1_TONE_SPACING_HZ_SI5351 * 100); radio_shared_state.radio_current_symbol_rate = entry->fsk_encoder_api->get_symbol_rate(&entry->fsk_encoder); entry->fsk_encoder_api->get_tones(&entry->fsk_encoder, &radio_shared_state.radio_current_fsk_tone_count, &radio_shared_state.radio_current_fsk_tones); @@ -324,7 +394,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry) entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload); break; case RADIO_DATA_MODE_HORUS_V2: - mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V2_TONE_SPACING_HZ * 100); + mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V2_TONE_SPACING_HZ_SI5351 * 100); radio_shared_state.radio_current_symbol_rate = entry->fsk_encoder_api->get_symbol_rate(&entry->fsk_encoder); entry->fsk_encoder_api->get_tones(&entry->fsk_encoder, &radio_shared_state.radio_current_fsk_tone_count, &radio_shared_state.radio_current_fsk_tones); diff --git a/src/radio_payload_horus_v1.c b/src/radio_payload_horus_v1.c index a2261c0..f637864 100644 --- a/src/radio_payload_horus_v1.c +++ b/src/radio_payload_horus_v1.c @@ -6,7 +6,11 @@ #include "telemetry.h" #include "radio_payload_horus_v1.h" +#ifdef SEMIHOSTING_ENABLE #include "log.h" +#endif + +#define HORUS_V1_PREAMBLE_BYTE 0x1B uint16_t radio_horus_v1_encode(uint8_t *payload, uint16_t length, telemetry_data *telemetry_data, char *message) { @@ -23,7 +27,7 @@ uint16_t radio_horus_v1_encode(uint8_t *payload, uint16_t length, telemetry_data // Preamble to help the decoder lock-on after a quiet period. for (int i = 0; i < HORUS_V1_PREAMBLE_LENGTH; i++) { - payload[i] = 0x1b; + payload[i] = HORUS_V1_PREAMBLE_BYTE; } // Encode the packet, and write into the mfsk buffer. @@ -34,6 +38,20 @@ uint16_t radio_horus_v1_encode(uint8_t *payload, uint16_t length, telemetry_data return encoded_length + HORUS_V1_PREAMBLE_LENGTH; } +uint16_t radio_horus_v1_idle_encode(uint8_t *payload, uint16_t length, telemetry_data *telemetry_data, char *message) +{ + // Use the preamble for idle tones during continuous transmit mode + for (int i = 0; i < HORUS_V1_IDLE_PREAMBLE_LENGTH; i++) { + payload[i] = HORUS_V1_PREAMBLE_BYTE; + } + + return HORUS_V1_IDLE_PREAMBLE_LENGTH; +} + payload_encoder radio_horus_v1_payload_encoder = { .encode = radio_horus_v1_encode, }; + +payload_encoder radio_horus_v1_idle_encoder = { + .encode = radio_horus_v1_idle_encode, +}; diff --git a/src/radio_payload_horus_v1.h b/src/radio_payload_horus_v1.h index 0ac589e..29b1169 100644 --- a/src/radio_payload_horus_v1.h +++ b/src/radio_payload_horus_v1.h @@ -4,5 +4,6 @@ #include "payload.h" extern payload_encoder radio_horus_v1_payload_encoder; +extern payload_encoder radio_horus_v1_idle_encoder; #endif diff --git a/src/radio_payload_horus_v2.c b/src/radio_payload_horus_v2.c index a1a2888..549bca7 100644 --- a/src/radio_payload_horus_v2.c +++ b/src/radio_payload_horus_v2.c @@ -6,7 +6,11 @@ #include "telemetry.h" #include "radio_payload_horus_v2.h" +#ifdef SEMIHOSTING_ENABLE #include "log.h" +#endif + +#define HORUS_V2_PREAMBLE_BYTE 0xE4 uint16_t radio_horus_v2_encode(uint8_t *payload, uint16_t length, telemetry_data *telemetry_data, char *message) { @@ -23,7 +27,7 @@ uint16_t radio_horus_v2_encode(uint8_t *payload, uint16_t length, telemetry_data // Preamble to help the decoder lock-on after a quiet period. for (int i = 0; i < HORUS_V2_PREAMBLE_LENGTH; i++) { - payload[i] = 0x1b; + payload[i] = HORUS_V2_PREAMBLE_BYTE; } // Encode the packet, and write into the mfsk buffer. @@ -34,6 +38,20 @@ uint16_t radio_horus_v2_encode(uint8_t *payload, uint16_t length, telemetry_data return encoded_length + HORUS_V2_PREAMBLE_LENGTH; } +uint16_t radio_horus_v2_idle_encode(uint8_t *payload, uint16_t length, telemetry_data *telemetry_data, char *message) +{ + // Use the preamble for idle tones during continuous transmit mode + for (int i = 0; i < HORUS_V2_IDLE_PREAMBLE_LENGTH; i++) { + payload[i] = HORUS_V2_PREAMBLE_BYTE; + } + + return HORUS_V2_IDLE_PREAMBLE_LENGTH; +} + payload_encoder radio_horus_v2_payload_encoder = { .encode = radio_horus_v2_encode, }; + +payload_encoder radio_horus_v2_idle_encoder = { + .encode = radio_horus_v2_idle_encode, +}; diff --git a/src/radio_payload_horus_v2.h b/src/radio_payload_horus_v2.h index 3087fd5..aff5828 100644 --- a/src/radio_payload_horus_v2.h +++ b/src/radio_payload_horus_v2.h @@ -4,5 +4,6 @@ #include "payload.h" extern payload_encoder radio_horus_v2_payload_encoder; +extern payload_encoder radio_horus_v2_idle_encoder; #endif diff --git a/src/radio_si4032.c b/src/radio_si4032.c index 4d7d765..b50e531 100644 --- a/src/radio_si4032.c +++ b/src/radio_si4032.c @@ -68,7 +68,7 @@ bool radio_start_transmit_si4032(radio_transmit_entry *entry, radio_module_state case RADIO_DATA_MODE_HORUS_V1: case RADIO_DATA_MODE_HORUS_V2: { fsk_tone *idle_tone = mfsk_get_idle_tone(&entry->fsk_encoder); - frequency_offset = (uint16_t) idle_tone->index + HORUS_V1_FREQUENCY_OFFSET_SI4032; + frequency_offset = (uint16_t) idle_tone->index + HORUS_FREQUENCY_OFFSET_SI4032; modulation_type = SI4032_MODULATION_TYPE_OOK; use_direct_mode = false; @@ -258,7 +258,7 @@ inline void radio_handle_data_timer_si4032() break; } - si4032_set_frequency_offset_small(tone_index + HORUS_V1_FREQUENCY_OFFSET_SI4032); + si4032_set_frequency_offset_small(tone_index + HORUS_FREQUENCY_OFFSET_SI4032); radio_shared_state.radio_symbol_count_interrupt++; break;