2020-08-26 19:57:35 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "log.h"
|
2020-09-10 19:57:41 +00:00
|
|
|
#include "template.h"
|
2020-08-26 19:57:35 +00:00
|
|
|
#include "hal/system.h"
|
2020-08-31 20:07:23 +00:00
|
|
|
#include "hal/delay.h"
|
2020-08-26 19:57:35 +00:00
|
|
|
#include "hal/usart_gps.h"
|
2021-08-12 21:42:50 +00:00
|
|
|
#include "codecs/morse/morse.h"
|
2020-08-26 19:57:35 +00:00
|
|
|
#include "codecs/bell/bell.h"
|
2021-08-11 20:24:30 +00:00
|
|
|
#include "codecs/mfsk/mfsk.h"
|
2020-08-26 19:57:35 +00:00
|
|
|
#include "codecs/jtencode/jtencode.h"
|
2020-09-03 19:12:43 +00:00
|
|
|
#include "drivers/ubxg6010/ubxg6010.h"
|
|
|
|
#include "radio_internal.h"
|
|
|
|
#include "radio_si4032.h"
|
|
|
|
#include "radio_si5351.h"
|
2021-08-12 21:42:50 +00:00
|
|
|
#include "radio_payload_cw.h"
|
2021-11-16 08:11:54 +00:00
|
|
|
#include "radio_payload_aprs_position.h"
|
|
|
|
#include "radio_payload_aprs_weather.h"
|
2021-08-11 20:24:30 +00:00
|
|
|
#include "radio_payload_horus_v1.h"
|
2021-09-14 19:47:39 +00:00
|
|
|
#include "radio_payload_horus_v2.h"
|
2020-09-03 19:12:43 +00:00
|
|
|
#include "radio_payload_wspr.h"
|
2020-09-10 19:57:41 +00:00
|
|
|
#include "radio_payload_jtencode.h"
|
|
|
|
#include "radio_payload_fsq.h"
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
radio_transmit_entry radio_transmit_schedule[] = {
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI4032_TX_HORUS_V1_CONTINUOUS
|
2021-11-10 16:49:29 +00:00
|
|
|
{
|
|
|
|
.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,
|
|
|
|
},
|
2021-11-11 16:15:52 +00:00
|
|
|
#elif RADIO_SI4032_TX_HORUS_V2_CONTINUOUS
|
2021-11-10 16:49:29 +00:00
|
|
|
{
|
|
|
|
.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
|
2022-11-27 21:20:41 +00:00
|
|
|
#if RADIO_SI4032_TX_PIP
|
2022-06-16 07:31:43 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI4032_TX_PIP,
|
|
|
|
.radio_type = RADIO_TYPE_SI4032,
|
|
|
|
.data_mode = RADIO_DATA_MODE_PIP,
|
|
|
|
.transmit_count = RADIO_SI4032_TX_PIP_COUNT,
|
|
|
|
.time_sync_seconds = PIP_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = PIP_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI4032_TX_FREQUENCY_PIP,
|
|
|
|
.tx_power = RADIO_SI4032_TX_POWER,
|
|
|
|
.symbol_rate = MORSE_WPM_TO_SYMBOL_RATE(PIP_SPEED_WPM),
|
|
|
|
.payload_encoder = &radio_cw_payload_encoder,
|
|
|
|
.fsk_encoder_api = &morse_fsk_encoder_api,
|
|
|
|
},
|
2022-11-27 21:20:41 +00:00
|
|
|
#endif
|
|
|
|
#if RADIO_SI4032_TX_CW
|
2021-08-12 21:42:50 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI4032_TX_CW,
|
|
|
|
.radio_type = RADIO_TYPE_SI4032,
|
|
|
|
.data_mode = RADIO_DATA_MODE_CW,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI4032_TX_CW_COUNT,
|
2021-08-12 21:42:50 +00:00
|
|
|
.time_sync_seconds = CW_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = CW_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI4032_TX_FREQUENCY_CW,
|
|
|
|
.tx_power = RADIO_SI4032_TX_POWER,
|
|
|
|
.symbol_rate = MORSE_WPM_TO_SYMBOL_RATE(CW_SPEED_WPM),
|
|
|
|
.payload_encoder = &radio_cw_payload_encoder,
|
|
|
|
.fsk_encoder_api = &morse_fsk_encoder_api,
|
|
|
|
},
|
2022-11-27 21:20:41 +00:00
|
|
|
#endif
|
|
|
|
#if RADIO_SI4032_TX_APRS
|
2020-08-26 19:57:35 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI4032_TX_APRS,
|
2020-08-26 19:57:35 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI4032,
|
2020-09-10 19:57:41 +00:00
|
|
|
.data_mode = RADIO_DATA_MODE_APRS_1200,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI4032_TX_APRS_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = APRS_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = APRS_TIME_SYNC_OFFSET_SECONDS,
|
2020-09-10 19:57:41 +00:00
|
|
|
.frequency = RADIO_SI4032_TX_FREQUENCY_APRS_1200,
|
2020-08-26 19:57:35 +00:00
|
|
|
.tx_power = RADIO_SI4032_TX_POWER,
|
|
|
|
.symbol_rate = 1200,
|
2021-11-16 08:11:54 +00:00
|
|
|
#if APRS_WEATHER_REPORT_ENABLE
|
|
|
|
.payload_encoder = &radio_aprs_weather_report_payload_encoder,
|
|
|
|
#else
|
|
|
|
.payload_encoder = &radio_aprs_position_payload_encoder,
|
|
|
|
#endif
|
2020-08-26 19:57:35 +00:00
|
|
|
.fsk_encoder_api = &bell_fsk_encoder_api,
|
|
|
|
},
|
2022-11-27 21:20:41 +00:00
|
|
|
#endif
|
|
|
|
#if RADIO_SI4032_TX_HORUS_V1
|
2020-09-03 19:12:43 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI4032_TX_HORUS_V1,
|
|
|
|
.radio_type = RADIO_TYPE_SI4032,
|
|
|
|
.data_mode = RADIO_DATA_MODE_HORUS_V1,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI4032_TX_HORUS_V1_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = HORUS_V1_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = HORUS_V1_TIME_SYNC_OFFSET_SECONDS,
|
2021-08-11 20:24:30 +00:00
|
|
|
.frequency = RADIO_SI4032_TX_FREQUENCY_HORUS_V1,
|
|
|
|
.tx_power = RADIO_SI4032_TX_POWER,
|
2021-09-14 19:47:39 +00:00
|
|
|
.symbol_rate = HORUS_V1_BAUD_RATE_SI4032,
|
2021-08-11 20:24:30 +00:00
|
|
|
.payload_encoder = &radio_horus_v1_payload_encoder,
|
|
|
|
.fsk_encoder_api = &mfsk_fsk_encoder_api,
|
|
|
|
},
|
2022-11-27 21:20:41 +00:00
|
|
|
#endif
|
|
|
|
#if RADIO_SI4032_TX_HORUS_V2
|
2021-09-14 19:47:39 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI4032_TX_HORUS_V2,
|
|
|
|
.radio_type = RADIO_TYPE_SI4032,
|
|
|
|
.data_mode = RADIO_DATA_MODE_HORUS_V2,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI4032_TX_HORUS_V2_COUNT,
|
2021-09-14 19:47:39 +00:00
|
|
|
.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,
|
|
|
|
},
|
2022-11-27 21:20:41 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_ENABLE
|
2022-06-16 07:31:43 +00:00
|
|
|
#if RADIO_SI5351_TX_PIP
|
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_PIP,
|
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_PIP,
|
|
|
|
.transmit_count = RADIO_SI5351_TX_PIP_COUNT,
|
|
|
|
.time_sync_seconds = PIP_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = PIP_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI5351_TX_FREQUENCY_PIP,
|
|
|
|
.tx_power = RADIO_SI5351_TX_POWER,
|
|
|
|
.symbol_rate = MORSE_WPM_TO_SYMBOL_RATE(PIP_SPEED_WPM),
|
|
|
|
.payload_encoder = &radio_cw_payload_encoder,
|
|
|
|
.fsk_encoder_api = &morse_fsk_encoder_api,
|
|
|
|
},
|
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_CW
|
2021-09-14 19:47:39 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_CW,
|
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_CW,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_CW_COUNT,
|
2021-09-14 19:47:39 +00:00
|
|
|
.time_sync_seconds = CW_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = CW_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI5351_TX_FREQUENCY_CW,
|
|
|
|
.tx_power = RADIO_SI5351_TX_POWER,
|
|
|
|
.symbol_rate = MORSE_WPM_TO_SYMBOL_RATE(CW_SPEED_WPM),
|
|
|
|
.payload_encoder = &radio_cw_payload_encoder,
|
|
|
|
.fsk_encoder_api = &morse_fsk_encoder_api,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_HORUS_V1
|
2021-09-14 19:47:39 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_HORUS_V1,
|
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_HORUS_V1,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_HORUS_V1_COUNT,
|
2021-09-14 19:47:39 +00:00
|
|
|
.time_sync_seconds = HORUS_V1_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = HORUS_V1_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI5351_TX_FREQUENCY_HORUS_V1,
|
|
|
|
.tx_power = RADIO_SI5351_TX_POWER,
|
|
|
|
.symbol_rate = HORUS_V1_BAUD_RATE_SI5351,
|
|
|
|
.payload_encoder = &radio_horus_v1_payload_encoder,
|
|
|
|
.fsk_encoder_api = &mfsk_fsk_encoder_api,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_HORUS_V2
|
2021-09-14 19:47:39 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_HORUS_V2,
|
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_HORUS_V2,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_HORUS_V2_COUNT,
|
2021-09-14 19:47:39 +00:00
|
|
|
.time_sync_seconds = HORUS_V2_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = HORUS_V2_TIME_SYNC_OFFSET_SECONDS,
|
|
|
|
.frequency = RADIO_SI5351_TX_FREQUENCY_HORUS_V2,
|
|
|
|
.tx_power = RADIO_SI5351_TX_POWER,
|
|
|
|
.symbol_rate = HORUS_V2_BAUD_RATE_SI5351,
|
|
|
|
.payload_encoder = &radio_horus_v2_payload_encoder,
|
|
|
|
.fsk_encoder_api = &mfsk_fsk_encoder_api,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_WSPR
|
2021-08-11 20:24:30 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_WSPR,
|
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
2021-11-30 15:42:51 +00:00
|
|
|
.data_mode = RADIO_DATA_MODE_WSPR,
|
|
|
|
.transmit_count = RADIO_SI5351_TX_WSPR_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = WSPR_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = WSPR_TIME_SYNC_OFFSET_SECONDS,
|
2021-08-11 20:24:30 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_FT8
|
2021-08-11 20:24:30 +00:00
|
|
|
{
|
|
|
|
.enabled = RADIO_SI5351_TX_FT8,
|
2020-08-26 19:57:35 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_FT8,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_FT8_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = FT8_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = FT8_TIME_SYNC_OFFSET_SECONDS,
|
2020-08-26 19:57:35 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_JT9
|
2020-08-26 19:57:35 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI5351_TX_JT9,
|
2020-08-26 19:57:35 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
2020-09-10 19:57:41 +00:00
|
|
|
.data_mode = RADIO_DATA_MODE_JT9,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_JT9_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = JT9_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = JT9_TIME_SYNC_OFFSET_SECONDS,
|
2020-09-10 19:57:41 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_JT4
|
2020-09-10 19:57:41 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI5351_TX_JT4,
|
2020-09-10 19:57:41 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_JT4,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_JT4_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = JT4_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = JT4_TIME_SYNC_OFFSET_SECONDS,
|
2020-09-10 19:57:41 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_JT65
|
2020-09-10 19:57:41 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI5351_TX_JT65,
|
2020-09-10 19:57:41 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
|
|
|
.data_mode = RADIO_DATA_MODE_JT65,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_JT65_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = JT65_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = JT65_TIME_SYNC_OFFSET_SECONDS,
|
2020-09-10 19:57:41 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-11 16:15:52 +00:00
|
|
|
#if RADIO_SI5351_TX_FSQ
|
2020-09-10 19:57:41 +00:00
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
.enabled = RADIO_SI5351_TX_FSQ,
|
2020-09-10 19:57:41 +00:00
|
|
|
.radio_type = RADIO_TYPE_SI5351,
|
2021-08-12 06:48:56 +00:00
|
|
|
.data_mode = FSQ_SUBMODE,
|
2021-11-30 15:42:51 +00:00
|
|
|
.transmit_count = RADIO_SI5351_TX_FSQ_COUNT,
|
2021-08-12 06:48:56 +00:00
|
|
|
.time_sync_seconds = FSQ_TIME_SYNC_SECONDS,
|
|
|
|
.time_sync_seconds_offset = FSQ_TIME_SYNC_OFFSET_SECONDS,
|
2020-09-10 19:57:41 +00:00
|
|
|
.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,
|
|
|
|
},
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2021-11-10 17:04:18 +00:00
|
|
|
#endif
|
2021-11-10 16:49:29 +00:00
|
|
|
#endif
|
2020-09-03 19:12:43 +00:00
|
|
|
{
|
|
|
|
.end = true,
|
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
};
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
static volatile bool radio_module_initialized = false;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
const bool wspr_locator_fixed_enabled = WSPR_LOCATOR_FIXED_ENABLED;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_transmit_entry *radio_current_transmit_entry = NULL;
|
|
|
|
static uint8_t radio_current_transmit_entry_index = 0;
|
|
|
|
static uint8_t radio_transmit_entry_count = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
static volatile uint32_t radio_post_transmit_delay_counter = 0;
|
|
|
|
static volatile uint32_t radio_next_symbol_counter = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
static radio_transmit_entry *radio_start_transmit_entry = NULL;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
static uint32_t radio_previous_time_sync_scheduled = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-10 19:57:41 +00:00
|
|
|
char radio_current_payload_message[RADIO_PAYLOAD_MESSAGE_MAX_LENGTH];
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
uint8_t radio_current_payload[RADIO_PAYLOAD_MAX_LENGTH];
|
|
|
|
uint16_t radio_current_payload_length = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
uint8_t radio_current_symbol_data[RADIO_SYMBOL_DATA_MAX_LENGTH];
|
|
|
|
|
|
|
|
static volatile uint32_t start_tick = 0, end_tick = 0;
|
|
|
|
|
|
|
|
telemetry_data current_telemetry_data;
|
|
|
|
|
|
|
|
radio_module_state radio_shared_state = {
|
|
|
|
.radio_transmission_active = false,
|
|
|
|
.radio_transmission_finished = false,
|
|
|
|
.radio_transmit_next_symbol_flag = false,
|
|
|
|
.radio_symbol_count_interrupt = 0,
|
|
|
|
.radio_symbol_count_loop = 0,
|
|
|
|
.radio_dma_transfer_active = false,
|
|
|
|
.radio_manual_transmit_active = false,
|
2021-08-11 20:24:30 +00:00
|
|
|
.radio_interrupt_transmit_active = false,
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
.radio_current_fsk_tones = NULL,
|
|
|
|
.radio_current_fsk_tone_count = 0,
|
|
|
|
.radio_current_tone_spacing_hz_100 = 0,
|
|
|
|
|
|
|
|
.radio_current_symbol_rate = 0,
|
|
|
|
.radio_current_symbol_delay_ms_100 = 0
|
|
|
|
};
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2021-08-12 06:48:56 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
static inline void radio_reset_next_symbol_counter()
|
|
|
|
{
|
2020-09-03 19:12:43 +00:00
|
|
|
if (radio_shared_state.radio_current_symbol_rate > 0) {
|
2020-08-26 19:57:35 +00:00
|
|
|
radio_next_symbol_counter = (uint32_t) (((float) SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND) /
|
2020-09-03 19:12:43 +00:00
|
|
|
(float) radio_shared_state.radio_current_symbol_rate);
|
2020-08-26 19:57:35 +00:00
|
|
|
} else {
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_next_symbol_counter = (uint32_t) (((float) radio_shared_state.radio_current_symbol_delay_ms_100) *
|
2020-08-26 19:57:35 +00:00
|
|
|
(float) SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND / 100000.0f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool radio_should_transmit_next_symbol()
|
|
|
|
{
|
|
|
|
return radio_next_symbol_counter == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool radio_start_transmit(radio_transmit_entry *entry)
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_symbol_count_interrupt = 0;
|
|
|
|
radio_shared_state.radio_symbol_count_loop = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
telemetry_collect(¤t_telemetry_data);
|
|
|
|
|
2020-09-10 19:57:41 +00:00
|
|
|
if (entry->messages != NULL && entry->message_count > 0) {
|
|
|
|
template_replace(radio_current_payload_message, sizeof(radio_current_payload_message),
|
|
|
|
entry->messages[entry->current_message_index], ¤t_telemetry_data);
|
|
|
|
} else {
|
|
|
|
radio_current_payload_message[0] = '\0';
|
|
|
|
}
|
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
radio_current_payload_length = entry->payload_encoder->encode(
|
2020-09-10 19:57:41 +00:00
|
|
|
radio_current_payload, sizeof(radio_current_payload),
|
|
|
|
¤t_telemetry_data, radio_current_payload_message);
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
log_info("Full payload length: %d\n", radio_current_payload_length);
|
|
|
|
|
2020-09-01 19:56:34 +00:00
|
|
|
#ifdef SEMIHOSTING_ENABLE
|
2020-09-03 19:12:43 +00:00
|
|
|
log_info("Payload: ");
|
2021-08-11 20:24:30 +00:00
|
|
|
log_bytes_hex(radio_current_payload_length, (char *) radio_current_payload);
|
|
|
|
log_info("\n ");
|
|
|
|
log_bytes(radio_current_payload_length, (char *) radio_current_payload);
|
2020-09-03 19:12:43 +00:00
|
|
|
log_info("\n");
|
2020-09-01 19:56:34 +00:00
|
|
|
#endif
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2021-11-11 16:15:52 +00:00
|
|
|
// USART interrupts may interfere with transmission timing
|
|
|
|
bool enable_gps_during_transmit = false;
|
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
switch (entry->data_mode) {
|
|
|
|
case RADIO_DATA_MODE_CW:
|
2022-06-16 07:31:43 +00:00
|
|
|
case RADIO_DATA_MODE_PIP:
|
2021-11-11 16:15:52 +00:00
|
|
|
// CW timing is not as critical
|
|
|
|
enable_gps_during_transmit = true;
|
|
|
|
|
2021-08-12 21:42:50 +00:00
|
|
|
morse_encoder_new(&entry->fsk_encoder, entry->symbol_rate);
|
|
|
|
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);
|
|
|
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
case RADIO_DATA_MODE_RTTY:
|
|
|
|
break;
|
2020-09-10 19:57:41 +00:00
|
|
|
case RADIO_DATA_MODE_APRS_1200:
|
2020-08-26 19:57:35 +00:00
|
|
|
// TODO: make bell tones and flag field count configurable
|
2020-08-31 20:07:23 +00:00
|
|
|
bell_encoder_new(&entry->fsk_encoder, entry->symbol_rate, BELL_FLAG_FIELD_COUNT_1200, bell202_tones);
|
2020-09-03 19:12:43 +00:00
|
|
|
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);
|
2020-08-26 19:57:35 +00:00
|
|
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
|
|
|
break;
|
2021-08-11 20:24:30 +00:00
|
|
|
case RADIO_DATA_MODE_HORUS_V1:
|
2021-11-11 16:15:52 +00:00
|
|
|
// GPS should not disturb the timing of Horus modes
|
|
|
|
enable_gps_during_transmit = true;
|
|
|
|
|
2021-11-10 16:49:29 +00:00
|
|
|
mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V1_TONE_SPACING_HZ_SI5351 * 100);
|
2021-08-11 20:24:30 +00:00
|
|
|
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);
|
2021-09-14 19:47:39 +00:00
|
|
|
radio_shared_state.radio_current_tone_spacing_hz_100 = entry->fsk_encoder_api->get_tone_spacing(
|
|
|
|
&entry->fsk_encoder);
|
|
|
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
|
|
|
break;
|
|
|
|
case RADIO_DATA_MODE_HORUS_V2:
|
2021-11-11 16:15:52 +00:00
|
|
|
// GPS should not disturb the timing of Horus modes
|
|
|
|
enable_gps_during_transmit = true;
|
|
|
|
|
2021-11-10 16:49:29 +00:00
|
|
|
mfsk_encoder_new(&entry->fsk_encoder, MFSK_4, entry->symbol_rate, HORUS_V2_TONE_SPACING_HZ_SI5351 * 100);
|
2021-09-14 19:47:39 +00:00
|
|
|
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);
|
|
|
|
radio_shared_state.radio_current_tone_spacing_hz_100 = entry->fsk_encoder_api->get_tone_spacing(
|
|
|
|
&entry->fsk_encoder);
|
2021-08-11 20:24:30 +00:00
|
|
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
|
|
|
break;
|
2020-08-26 19:57:35 +00:00
|
|
|
case RADIO_DATA_MODE_WSPR:
|
|
|
|
case RADIO_DATA_MODE_FT8:
|
|
|
|
case RADIO_DATA_MODE_JT65:
|
|
|
|
case RADIO_DATA_MODE_JT4:
|
|
|
|
case RADIO_DATA_MODE_JT9:
|
|
|
|
case RADIO_DATA_MODE_FSQ_2:
|
|
|
|
case RADIO_DATA_MODE_FSQ_3:
|
|
|
|
case RADIO_DATA_MODE_FSQ_4_5:
|
2020-09-01 19:56:34 +00:00
|
|
|
case RADIO_DATA_MODE_FSQ_6: {
|
2021-11-11 16:15:52 +00:00
|
|
|
// Timing of these slow modes is not as critical
|
|
|
|
enable_gps_during_transmit = true;
|
|
|
|
|
2020-09-01 19:56:34 +00:00
|
|
|
char locator[5];
|
2021-08-12 06:48:56 +00:00
|
|
|
jtencode_mode_type jtencode_mode = radio_jtencode_mode_type_for(entry->data_mode);
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
if (wspr_locator_fixed_enabled) {
|
|
|
|
strlcpy(locator, WSPR_LOCATOR_FIXED, 4 + 1);
|
|
|
|
} else {
|
|
|
|
strlcpy(locator, current_telemetry_data.locator, 4 + 1);
|
|
|
|
}
|
|
|
|
|
2021-08-11 20:24:30 +00:00
|
|
|
success = jtencode_encoder_new(&entry->fsk_encoder, sizeof(radio_current_symbol_data),
|
2021-08-12 06:48:56 +00:00
|
|
|
radio_current_symbol_data, jtencode_mode, WSPR_CALLSIGN, locator, WSPR_DBM, FSQ_CALLSIGN_FROM);
|
2020-09-03 19:12:43 +00:00
|
|
|
if (!success) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
radio_shared_state.radio_current_symbol_delay_ms_100 = entry->fsk_encoder_api->get_symbol_delay(
|
|
|
|
&entry->fsk_encoder);
|
|
|
|
radio_shared_state.radio_current_tone_spacing_hz_100 = entry->fsk_encoder_api->get_tone_spacing(
|
|
|
|
&entry->fsk_encoder);
|
2020-08-26 19:57:35 +00:00
|
|
|
entry->fsk_encoder_api->set_data(&entry->fsk_encoder, radio_current_payload_length, radio_current_payload);
|
|
|
|
break;
|
2020-09-01 19:56:34 +00:00
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-11-11 16:15:52 +00:00
|
|
|
usart_gps_enable(enable_gps_during_transmit);
|
|
|
|
if (!enable_gps_during_transmit) {
|
|
|
|
ubxg6010_reset_parser();
|
|
|
|
}
|
2020-08-31 20:07:23 +00:00
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
switch (entry->radio_type) {
|
|
|
|
case RADIO_TYPE_SI4032:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_start_transmit_si4032(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
case RADIO_TYPE_SI5351:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_start_transmit_si5351(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-08-31 20:07:23 +00:00
|
|
|
if (!success) {
|
|
|
|
usart_gps_enable(true);
|
|
|
|
// TODO: stop transmit here
|
|
|
|
return false;
|
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
log_info("TX start\n");
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-10 19:57:41 +00:00
|
|
|
if (leds_enabled) {
|
2022-02-27 13:45:10 +00:00
|
|
|
set_red_led(true);
|
2020-09-10 19:57:41 +00:00
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_transmission_active = true;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void radio_reset_transmit_state()
|
|
|
|
{
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_transmission_active = false;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_next_symbol_counter = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
radio_current_payload_length = 0;
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_current_fsk_tones = NULL;
|
|
|
|
radio_shared_state.radio_current_fsk_tone_count = 0;
|
|
|
|
radio_shared_state.radio_current_tone_spacing_hz_100 = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_current_symbol_rate = 0;
|
|
|
|
radio_shared_state.radio_current_symbol_delay_ms_100 = 0;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool radio_stop_transmit(radio_transmit_entry *entry)
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
switch (entry->radio_type) {
|
|
|
|
case RADIO_TYPE_SI4032:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_stop_transmit_si4032(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
case RADIO_TYPE_SI5351:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_stop_transmit_si5351(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-08-31 20:07:23 +00:00
|
|
|
radio_reset_transmit_state();
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_manual_transmit_active = false;
|
2021-08-11 20:24:30 +00:00
|
|
|
radio_shared_state.radio_interrupt_transmit_active = false;
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_dma_transfer_active = false;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
switch (entry->data_mode) {
|
|
|
|
case RADIO_DATA_MODE_CW:
|
2022-06-16 07:31:43 +00:00
|
|
|
case RADIO_DATA_MODE_PIP:
|
2021-08-12 21:42:50 +00:00
|
|
|
morse_encoder_destroy(&entry->fsk_encoder);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
case RADIO_DATA_MODE_RTTY:
|
|
|
|
break;
|
2020-09-10 19:57:41 +00:00
|
|
|
case RADIO_DATA_MODE_APRS_1200:
|
2020-08-26 19:57:35 +00:00
|
|
|
bell_encoder_destroy(&entry->fsk_encoder);
|
|
|
|
break;
|
2021-08-11 20:24:30 +00:00
|
|
|
case RADIO_DATA_MODE_HORUS_V1:
|
2021-09-14 19:47:39 +00:00
|
|
|
case RADIO_DATA_MODE_HORUS_V2:
|
2021-08-11 20:24:30 +00:00
|
|
|
mfsk_encoder_destroy(&entry->fsk_encoder);
|
|
|
|
break;
|
2020-08-26 19:57:35 +00:00
|
|
|
case RADIO_DATA_MODE_WSPR:
|
|
|
|
case RADIO_DATA_MODE_FT8:
|
|
|
|
case RADIO_DATA_MODE_JT65:
|
|
|
|
case RADIO_DATA_MODE_JT4:
|
|
|
|
case RADIO_DATA_MODE_JT9:
|
|
|
|
case RADIO_DATA_MODE_FSQ_2:
|
|
|
|
case RADIO_DATA_MODE_FSQ_3:
|
|
|
|
case RADIO_DATA_MODE_FSQ_4_5:
|
|
|
|
case RADIO_DATA_MODE_FSQ_6:
|
|
|
|
jtencode_encoder_destroy(&entry->fsk_encoder);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
usart_gps_enable(true);
|
2020-09-10 19:57:41 +00:00
|
|
|
if (leds_enabled) {
|
2022-02-27 13:45:10 +00:00
|
|
|
set_red_led(false);
|
2020-09-10 19:57:41 +00:00
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-08-31 20:07:23 +00:00
|
|
|
return success;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool radio_transmit_symbol(radio_transmit_entry *entry)
|
|
|
|
{
|
|
|
|
bool success;
|
|
|
|
|
|
|
|
switch (entry->radio_type) {
|
|
|
|
case RADIO_TYPE_SI4032:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_transmit_symbol_si4032(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
case RADIO_TYPE_SI5351:
|
2020-09-03 19:12:43 +00:00
|
|
|
success = radio_transmit_symbol_si5351(entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (success) {
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_symbol_count_interrupt++;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return success;
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
static void radio_reset_transmit_delay_counter()
|
|
|
|
{
|
|
|
|
radio_post_transmit_delay_counter = RADIO_POST_TRANSMIT_DELAY_MS * SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND / 1000;
|
|
|
|
}
|
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
static void radio_next_transmit_entry()
|
|
|
|
{
|
2020-09-10 19:57:41 +00:00
|
|
|
radio_current_transmit_entry->current_message_index =
|
|
|
|
(radio_current_transmit_entry->current_message_index + 1) % radio_current_transmit_entry->message_count;
|
|
|
|
|
2021-11-30 15:42:51 +00:00
|
|
|
radio_current_transmit_entry->current_transmit_index =
|
|
|
|
(radio_current_transmit_entry->current_transmit_index + 1) % radio_current_transmit_entry->transmit_count;
|
|
|
|
|
|
|
|
// Proceed to next transmit entry when transmit counter wraps
|
|
|
|
if (radio_current_transmit_entry->current_transmit_index == 0) {
|
|
|
|
do {
|
|
|
|
radio_current_transmit_entry_index = (radio_current_transmit_entry_index + 1) % radio_transmit_entry_count;
|
|
|
|
radio_current_transmit_entry = &radio_transmit_schedule[radio_current_transmit_entry_index];
|
|
|
|
} while (!radio_current_transmit_entry->enabled);
|
|
|
|
}
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
radio_reset_transmit_delay_counter();
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void radio_handle_timer_tick()
|
|
|
|
{
|
2021-08-11 20:24:30 +00:00
|
|
|
if (!radio_module_initialized || radio_shared_state.radio_dma_transfer_active
|
|
|
|
|| radio_shared_state.radio_manual_transmit_active || radio_shared_state.radio_interrupt_transmit_active) {
|
2020-08-26 19:57:35 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (radio_shared_state.radio_transmission_active) {
|
|
|
|
if (radio_next_symbol_counter > 0) {
|
|
|
|
radio_next_symbol_counter--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (radio_should_transmit_next_symbol()) {
|
|
|
|
radio_shared_state.radio_transmit_next_symbol_flag = true;
|
|
|
|
radio_reset_next_symbol_counter();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (radio_post_transmit_delay_counter > 0) {
|
|
|
|
// TODO: use power saving
|
|
|
|
radio_post_transmit_delay_counter--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-11 20:24:30 +00:00
|
|
|
void radio_handle_data_timer_tick()
|
|
|
|
{
|
|
|
|
radio_handle_data_timer_si4032();
|
2021-09-14 19:47:39 +00:00
|
|
|
|
|
|
|
radio_handle_data_timer_si5351();
|
2021-08-11 20:24:30 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
bool radio_handle_time_sync()
|
|
|
|
{
|
|
|
|
// TODO: How to poll GPS time?
|
|
|
|
// TODO: Get time at millisecond precision!
|
|
|
|
// ubxg6010_request_gpstime();
|
|
|
|
|
|
|
|
gps_data gps;
|
|
|
|
ubxg6010_get_current_gps_data(&gps);
|
|
|
|
|
|
|
|
if (!gps.updated) {
|
|
|
|
// The GPS data has not been updated yet
|
|
|
|
return false;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (false && gps.fix < 3) {
|
|
|
|
log_info("Skipping transmit entry that requires time sync, no GPS fix");
|
|
|
|
radio_next_transmit_entry();
|
|
|
|
return false;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
uint32_t time_millis = gps.time_of_week_millis;
|
|
|
|
|
|
|
|
if (time_millis == radio_previous_time_sync_scheduled) {
|
|
|
|
// The GPS chip has not provided an updated time yet for some reason
|
|
|
|
return false;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
uint32_t time_sync_offset_millis = radio_current_transmit_entry->time_sync_seconds_offset * 1000;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (time_millis < time_sync_offset_millis) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t time_sync_millis = radio_current_transmit_entry->time_sync_seconds * 1000;
|
|
|
|
|
|
|
|
uint32_t time_with_offset_millis = time_millis - time_sync_offset_millis;
|
|
|
|
uint32_t time_sync_period_millis = time_with_offset_millis % time_sync_millis;
|
|
|
|
|
|
|
|
bool is_scheduled_time = time_sync_period_millis < RADIO_TIME_SYNC_THRESHOLD_MS;
|
|
|
|
|
2021-08-11 20:24:30 +00:00
|
|
|
log_debug("Time with offset: %lu, sync period: %lu, scheduled: %d\n", time_with_offset_millis, time_sync_period_millis, is_scheduled_time);
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
if (!is_scheduled_time) {
|
|
|
|
log_info("Time: %lu, GPS fix: %d - Waiting for time sync at every %d seconds with offset of %d\n", time_millis,
|
|
|
|
gps.fix,
|
|
|
|
radio_current_transmit_entry->time_sync_seconds,
|
|
|
|
radio_current_transmit_entry->time_sync_seconds_offset);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
log_info("Time: %lu, GPS fix: %d, sync period: %lu - Scheduling transmit at %d seconds with offset of %d\n",
|
|
|
|
time_millis, gps.fix,
|
|
|
|
time_sync_period_millis, radio_current_transmit_entry->time_sync_seconds,
|
|
|
|
radio_current_transmit_entry->time_sync_seconds_offset);
|
|
|
|
|
|
|
|
radio_previous_time_sync_scheduled = time_millis;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2020-08-31 20:07:23 +00:00
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
void radio_handle_main_loop()
|
|
|
|
{
|
2020-09-03 19:12:43 +00:00
|
|
|
bool time_sync_required = radio_current_transmit_entry->time_sync_seconds > 0;
|
|
|
|
|
|
|
|
if (time_sync_required && !radio_shared_state.radio_transmission_active &&
|
|
|
|
!radio_shared_state.radio_transmission_finished) {
|
|
|
|
bool schedule_transmit = radio_handle_time_sync();
|
|
|
|
if (!schedule_transmit) {
|
|
|
|
// TODO: use power saving
|
|
|
|
delay_ms(100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
radio_reset_transmit_delay_counter();
|
|
|
|
radio_start_transmit_entry = radio_current_transmit_entry;
|
|
|
|
} else if (!radio_shared_state.radio_transmission_active && radio_post_transmit_delay_counter == 0) {
|
|
|
|
#if defined(SEMIHOSTING_ENABLE) && defined(LOGGING_ENABLE)
|
2020-08-26 19:57:35 +00:00
|
|
|
telemetry_collect(¤t_telemetry_data);
|
|
|
|
log_info("Battery: %d mV\n", current_telemetry_data.battery_voltage_millivolts);
|
2020-09-01 19:56:34 +00:00
|
|
|
log_info("Internal temperature: %ld C\n", current_telemetry_data.internal_temperature_celsius_100 / 100);
|
2020-08-26 19:57:35 +00:00
|
|
|
log_info("Time: %02d:%02d:%02d\n",
|
2020-08-31 20:07:23 +00:00
|
|
|
current_telemetry_data.gps.hours, current_telemetry_data.gps.minutes,
|
|
|
|
current_telemetry_data.gps.seconds);
|
2020-08-26 19:57:35 +00:00
|
|
|
log_info("Fix: %d, Sats: %d, OK packets: %d, Bad packets: %d\n",
|
2020-09-03 19:12:43 +00:00
|
|
|
current_telemetry_data.gps.fix, current_telemetry_data.gps.satellites_visible,
|
2020-08-31 20:07:23 +00:00
|
|
|
current_telemetry_data.gps.ok_packets, current_telemetry_data.gps.bad_packets);
|
2020-08-26 19:57:35 +00:00
|
|
|
log_info("Lat: %ld *1M, Lon: %ld *1M, Alt: %ld m\n",
|
2020-09-03 19:12:43 +00:00
|
|
|
current_telemetry_data.gps.latitude_degrees_1000000 / 10,
|
|
|
|
current_telemetry_data.gps.longitude_degrees_1000000 / 10,
|
|
|
|
(current_telemetry_data.gps.altitude_mm / 1000) * 3280 / 1000);
|
|
|
|
#endif
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_reset_transmit_delay_counter();
|
2020-08-26 19:57:35 +00:00
|
|
|
radio_start_transmit_entry = radio_current_transmit_entry;
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_handle_main_loop_si4032(radio_current_transmit_entry, &radio_shared_state);
|
|
|
|
radio_handle_main_loop_si5351(radio_current_transmit_entry, &radio_shared_state);
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
bool first_symbol = false;
|
|
|
|
if (radio_start_transmit_entry != NULL) {
|
|
|
|
log_info("Start transmit\n");
|
|
|
|
bool success = radio_start_transmit(radio_start_transmit_entry);
|
|
|
|
start_tick = system_get_tick();
|
|
|
|
|
|
|
|
radio_start_transmit_entry = NULL;
|
|
|
|
if (!success) {
|
|
|
|
radio_next_transmit_entry();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (!radio_shared_state.radio_dma_transfer_active) {
|
2020-08-26 19:57:35 +00:00
|
|
|
first_symbol = true;
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_shared_state.radio_transmit_next_symbol_flag = true;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (radio_shared_state.radio_transmission_active && radio_shared_state.radio_transmit_next_symbol_flag) {
|
|
|
|
radio_shared_state.radio_transmit_next_symbol_flag = false;
|
|
|
|
|
2021-08-11 20:24:30 +00:00
|
|
|
if (!radio_shared_state.radio_manual_transmit_active && !radio_shared_state.radio_interrupt_transmit_active) {
|
2020-09-03 19:12:43 +00:00
|
|
|
bool success = radio_transmit_symbol(radio_current_transmit_entry);
|
|
|
|
if (success) {
|
|
|
|
if (first_symbol) {
|
|
|
|
radio_reset_next_symbol_counter();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
radio_shared_state.radio_transmission_finished = true;
|
|
|
|
}
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
if (radio_shared_state.radio_transmission_finished) {
|
2020-08-26 19:57:35 +00:00
|
|
|
end_tick = system_get_tick();
|
2020-09-03 19:12:43 +00:00
|
|
|
radio_stop_transmit(radio_current_transmit_entry);
|
|
|
|
radio_shared_state.radio_transmission_finished = false;
|
2020-08-26 19:57:35 +00:00
|
|
|
|
|
|
|
radio_next_transmit_entry();
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
log_info("TX stop\n");
|
|
|
|
log_info("Symbol count (interrupt): %ld\n", radio_shared_state.radio_symbol_count_interrupt);
|
|
|
|
log_info("Symbol count (loop): %ld\n", radio_shared_state.radio_symbol_count_loop);
|
2020-08-26 19:57:35 +00:00
|
|
|
log_info("Total ticks: %ld\n", end_tick - start_tick);
|
|
|
|
log_info("Next symbol counter: %ld\n", radio_next_symbol_counter);
|
2020-09-03 19:12:43 +00:00
|
|
|
log_info("Symbol rate: %ld\n", radio_shared_state.radio_current_symbol_rate);
|
|
|
|
log_info("Symbol delay: %ld\n", radio_shared_state.radio_current_symbol_delay_ms_100);
|
|
|
|
log_info("Tone spacing: %ld\n", radio_shared_state.radio_current_tone_spacing_hz_100);
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void radio_init()
|
|
|
|
{
|
2020-09-03 19:12:43 +00:00
|
|
|
uint8_t count;
|
|
|
|
for (count = 0; !radio_transmit_schedule[count].end; count++);
|
|
|
|
radio_transmit_entry_count = count;
|
2020-09-01 19:56:34 +00:00
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
memset(¤t_telemetry_data, 0, sizeof(current_telemetry_data));
|
2020-08-26 19:57:35 +00:00
|
|
|
|
2020-09-10 19:57:41 +00:00
|
|
|
for (uint8_t i = 0; i < radio_transmit_entry_count; i++) {
|
|
|
|
radio_transmit_entry *entry = &radio_transmit_schedule[i];
|
|
|
|
switch (entry->data_mode) {
|
2021-08-12 21:42:50 +00:00
|
|
|
case RADIO_DATA_MODE_CW:
|
|
|
|
entry->messages = cw_message_templates;
|
|
|
|
break;
|
2022-06-16 07:31:43 +00:00
|
|
|
case RADIO_DATA_MODE_PIP:
|
|
|
|
entry->messages = pip_message_templates;
|
|
|
|
break;
|
2020-09-10 19:57:41 +00:00
|
|
|
case RADIO_DATA_MODE_APRS_1200:
|
|
|
|
entry->messages = aprs_comment_templates;
|
|
|
|
break;
|
2021-08-11 20:24:30 +00:00
|
|
|
case RADIO_DATA_MODE_HORUS_V1:
|
2021-09-14 19:47:39 +00:00
|
|
|
case RADIO_DATA_MODE_HORUS_V2:
|
2021-08-11 20:24:30 +00:00
|
|
|
// No messages
|
|
|
|
break;
|
2020-09-10 19:57:41 +00:00
|
|
|
case RADIO_DATA_MODE_FT8:
|
|
|
|
case RADIO_DATA_MODE_JT65:
|
|
|
|
case RADIO_DATA_MODE_JT9:
|
|
|
|
case RADIO_DATA_MODE_JT4:
|
|
|
|
entry->messages = ftjt_message_templates;
|
|
|
|
break;
|
|
|
|
case RADIO_DATA_MODE_FSQ_6:
|
|
|
|
case RADIO_DATA_MODE_FSQ_4_5:
|
|
|
|
case RADIO_DATA_MODE_FSQ_3:
|
|
|
|
case RADIO_DATA_MODE_FSQ_2:
|
|
|
|
entry->messages = fsq_comment_templates;
|
|
|
|
break;
|
|
|
|
case RADIO_DATA_MODE_WSPR:
|
|
|
|
// No messages
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-08-11 20:24:30 +00:00
|
|
|
if (entry->messages != NULL) {
|
2020-09-10 19:57:41 +00:00
|
|
|
for (entry->message_count = 0; entry->messages[entry->message_count] != NULL; entry->message_count++);
|
|
|
|
}
|
2021-11-30 15:42:51 +00:00
|
|
|
if (entry->transmit_count == 0) {
|
|
|
|
entry->transmit_count = 1;
|
|
|
|
}
|
2020-09-10 19:57:41 +00:00
|
|
|
}
|
|
|
|
|
2020-08-26 19:57:35 +00:00
|
|
|
radio_current_transmit_entry = &radio_transmit_schedule[radio_current_transmit_entry_index];
|
|
|
|
|
2020-09-03 19:12:43 +00:00
|
|
|
while (!radio_current_transmit_entry->enabled) {
|
|
|
|
radio_current_transmit_entry_index = (radio_current_transmit_entry_index + 1) % radio_transmit_entry_count;
|
|
|
|
radio_current_transmit_entry = &radio_transmit_schedule[radio_current_transmit_entry_index];
|
2020-08-31 20:07:23 +00:00
|
|
|
}
|
2020-09-03 19:12:43 +00:00
|
|
|
|
|
|
|
radio_init_si4032();
|
|
|
|
|
|
|
|
radio_module_initialized = true;
|
2020-08-26 19:57:35 +00:00
|
|
|
}
|