sforkowany z mirror/RS41ng
70cm APRS working again (WIP). Fix bugs in AX.25 encoding. Generate Bell tones for APRS in a tight loop to avoid issues with inconsistent timing.
rodzic
8f74fa0b34
commit
8a315f5879
|
@ -3,11 +3,11 @@
|
|||
## Direwolf
|
||||
|
||||
```bash
|
||||
rx_fm -f 434250000 -M fm -s 250000 -r 32000 -g 22 -d driver=rtlsdr - | direwolf -n 1 -D 1 -r 32000 -b 16 -
|
||||
rx_fm -f 434250000 -M fm -s 250000 -r 48000 -g 22 -d driver=rtlsdr - | direwolf -n 1 -D 1 -r 48000 -b 16 -
|
||||
```
|
||||
|
||||
```bash
|
||||
rtl_fm -f 434250000 -M fm -s 250k -r 32000 -g 22 - | direwolf -n 1 -D 1 -r 32000 -b 16 -
|
||||
rtl_fm -f 434250000 -M fm -s 250k -r 48000 -g 22 - | direwolf -n 1 -D 1 -r 48000 -b 16 -
|
||||
```
|
||||
|
||||
## SigPlay
|
||||
|
@ -19,5 +19,5 @@ rx_fm -f 434250000 -M fm -s 250000 -r 48000 -g 22 -d driver=rtlsdr - | ./aprs -
|
|||
```
|
||||
|
||||
```bash
|
||||
rtl_fm -f 434250000 -M fm -s 250k -r 32000 -g 22 - | ./aprs -
|
||||
rtl_fm -f 434250000 -M fm -s 250k -r 48000 -g 22 - | ./aprs -
|
||||
```
|
||||
|
|
|
@ -32,9 +32,8 @@ static void convert_degrees_to_dmh(long x, int8_t *degrees, uint8_t *minutes, ui
|
|||
}
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
size_t aprs_generate_position_without_timestamp(uint8_t *payload, size_t length, telemetry_data *data, char symbol, char *comment)
|
||||
size_t aprs_generate_position_without_timestamp(uint8_t *payload, size_t length, telemetry_data *data,
|
||||
char symbol_table, char symbol, char *comment)
|
||||
{
|
||||
int8_t la_degrees, lo_degrees;
|
||||
uint8_t la_minutes, la_h_minutes, lo_minutes, lo_h_minutes;
|
||||
|
@ -48,9 +47,10 @@ size_t aprs_generate_position_without_timestamp(uint8_t *payload, size_t length,
|
|||
|
||||
return snprintf((char *) payload,
|
||||
length,
|
||||
("!%02d%02d.%02u%c/%03d%02u.%02u%c%c/A=%06ld/P%dS%dT%dV%d%s"),
|
||||
("!%02d%02d.%02u%c%c%03d%02u.%02u%c%c/A=%06ld/P%dS%dT%dV%d%s"),
|
||||
abs(la_degrees), la_minutes, la_h_minutes,
|
||||
la_degrees > 0 ? 'N' : 'S',
|
||||
symbol_table,
|
||||
abs(lo_degrees), lo_minutes, lo_h_minutes,
|
||||
lo_degrees > 0 ? 'E' : 'W',
|
||||
symbol,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "gps.h"
|
||||
#include "telemetry.h"
|
||||
|
||||
size_t aprs_generate_position_without_timestamp(uint8_t *payload, size_t length, telemetry_data *data, char symbol, char *comment);
|
||||
size_t aprs_generate_position_without_timestamp(uint8_t *payload, size_t length, telemetry_data *data,
|
||||
char symbol_table, char symbol, char *comment);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -14,7 +14,6 @@ static inline uint16_t ax25_calculate_crc_for_bit(uint16_t crc, bool bit)
|
|||
|
||||
// If XOR result from above has lsb set
|
||||
if (temp & 0x0001U) {
|
||||
// Shift 16-bit CRC one bit to the right
|
||||
result ^= 0x8408U;
|
||||
}
|
||||
|
||||
|
@ -24,7 +23,7 @@ static inline uint16_t ax25_calculate_crc_for_bit(uint16_t crc, bool bit)
|
|||
static inline uint16_t ax25_calculate_crc_for_byte(uint16_t crc, uint8_t byte)
|
||||
{
|
||||
uint8_t temp = byte;
|
||||
for (int i = 0; i < 8; i++, byte >>= 1U) {
|
||||
for (int i = 0; i < 8; i++, temp >>= 1U) {
|
||||
bool bit = ((temp & 1U) == 1U) ? true : false;
|
||||
crc = ax25_calculate_crc_for_bit(crc, bit);
|
||||
}
|
||||
|
@ -109,7 +108,8 @@ size_t ax25_encode_packet_aprs(char *source, uint8_t source_ssid, char *destinat
|
|||
size_t info_length = strlen(information_field);
|
||||
strcpy(header_end->information_field, information_field);
|
||||
|
||||
uint16_t crc = ax25_calculate_crc(14 + digipeater_addresses_length + 2 + info_length, actual_data_start);
|
||||
size_t crc_length = 14 + digipeater_addresses_length + 2 + info_length;
|
||||
uint16_t crc = ax25_calculate_crc(crc_length, actual_data_start);
|
||||
|
||||
ax25_packet_footer *footer = (ax25_packet_footer *) (((uint8_t *) header_end->information_field) + info_length);
|
||||
|
||||
|
|
|
@ -131,25 +131,20 @@ int8_t bell_encoder_next_tone(fsk_encoder *encoder)
|
|||
}
|
||||
|
||||
bool bit = (bell->current_byte >> bell->current_bit_index) & 1U;
|
||||
bool stuff_bit = false;
|
||||
|
||||
if (bit) {
|
||||
bell->bit_stuffing_counter++;
|
||||
if (bell->bit_stuffing_counter == 5) {
|
||||
int8_t previous_tone_index = bell->current_tone_index;
|
||||
bell_encoder_toggle_tone(encoder);
|
||||
bell->bit_stuffing_counter = 0;
|
||||
stuff_bit = true;
|
||||
} else {
|
||||
bell->bit_stuffing_counter++;
|
||||
return previous_tone_index;
|
||||
}
|
||||
} else {
|
||||
bell_encoder_toggle_tone(encoder);
|
||||
bell->bit_stuffing_counter = 0;
|
||||
}
|
||||
|
||||
if (stuff_bit) {
|
||||
return bell->current_tone_index;
|
||||
}
|
||||
|
||||
bell->current_bit_index = (bell->current_bit_index + 1) % 8;
|
||||
|
||||
if (bell->current_bit_index == 0) {
|
||||
|
|
31
src/config.h
31
src/config.h
|
@ -36,13 +36,36 @@
|
|||
#define FSQ_CALLSIGN_TO "N0CALL"
|
||||
#define FSQ_COMMAND ' '
|
||||
|
||||
/**
|
||||
* APRS SSID:
|
||||
*
|
||||
* 0 Your primary station usually fixed and message capable
|
||||
* 1 generic additional station, digi, mobile, wx, etc
|
||||
* 2 generic additional station, digi, mobile, wx, etc
|
||||
* 3 generic additional station, digi, mobile, wx, etc
|
||||
* 4 generic additional station, digi, mobile, wx, etc
|
||||
* 5 Other networks (Dstar, Iphones, Androids, Blackberry's etc)
|
||||
* 6 Special activity, Satellite ops, camping or 6 meters, etc
|
||||
* 7 walkie talkies, HT's or other human portable
|
||||
* 8 boats, sailboats, RV's or second main mobile
|
||||
* 9 Primary Mobile (usually message capable)
|
||||
* A internet, Igates, echolink, winlink, AVRS, APRN, etc
|
||||
* B balloons, aircraft, spacecraft, etc
|
||||
* C APRStt, DTMF, RFID, devices, one-way trackers*, etc
|
||||
* D Weather stations
|
||||
* E Truckers or generally full time drivers
|
||||
* F generic additional station, digi, mobile, wx, etc
|
||||
*/
|
||||
|
||||
#define APRS_CALLSIGN "OH3BHX"
|
||||
#define APRS_SSID 13
|
||||
#define APRS_SYMBOL 'O'
|
||||
#define APRS_COMMENT "Testing 123"
|
||||
#define APRS_SSID 'B'
|
||||
// See APRS symbol table documentation in: http://www.aprs.org/symbols/symbolsX.txt
|
||||
#define APRS_SYMBOL_TABLE '/' // '/' denotes primary and '\\' denotes alternate APRS symbol table
|
||||
#define APRS_SYMBOL '['
|
||||
#define APRS_COMMENT " RS41ng custom radiosonde firmware testing"
|
||||
#define APRS_RELAYS "WIDE1-1,WIDE2-1"
|
||||
#define APRS_DESTINATION "APZ41N"
|
||||
#define APRS_DESTINATION_SSID 0
|
||||
#define APRS_DESTINATION_SSID '0'
|
||||
|
||||
#define PAIR_COUNT 4 // max. 6 (12 characters WWL)
|
||||
#define RTTY_7BIT 1 // if 0 --> 5 bits
|
||||
|
|
|
@ -18,7 +18,7 @@ void delay_init()
|
|||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||||
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE);
|
||||
|
||||
tim_init.TIM_Prescaler = 192 - 1;
|
||||
tim_init.TIM_Prescaler = 24 - 1;
|
||||
tim_init.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
tim_init.TIM_Period = 0;
|
||||
tim_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
|
@ -30,8 +30,8 @@ void delay_init()
|
|||
|
||||
NVIC_InitTypeDef nvic_init;
|
||||
nvic_init.NVIC_IRQChannel = TIM3_IRQn;
|
||||
nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
|
||||
nvic_init.NVIC_IRQChannelSubPriority = 2;
|
||||
nvic_init.NVIC_IRQChannelPreemptionPriority = 0;
|
||||
nvic_init.NVIC_IRQChannelSubPriority = 1;
|
||||
nvic_init.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&nvic_init);
|
||||
|
||||
|
@ -41,7 +41,7 @@ void delay_init()
|
|||
void delay_us(uint16_t us)
|
||||
{
|
||||
TIM_Cmd(TIM3, DISABLE);
|
||||
TIM_SetAutoreload(TIM3, us / 8);
|
||||
TIM_SetAutoreload(TIM3, us);
|
||||
TIM_SetCounter(TIM3, 0);
|
||||
TIM_Cmd(TIM3, ENABLE);
|
||||
done = false;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <misc.h>
|
||||
|
||||
#include "pwm.h"
|
||||
#include "log.h"
|
||||
|
||||
uint16_t pwm_timer_dma_buffer[PWM_TIMER_DMA_BUFFER_SIZE];
|
||||
|
||||
|
@ -28,7 +29,7 @@ void pwm_data_timer_init()
|
|||
|
||||
tim_init.TIM_Prescaler = 2 - 1; // tick every 1/12000000 s
|
||||
tim_init.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
tim_init.TIM_Period = 10000 - 1 - 55; // update every 1/1200 s
|
||||
tim_init.TIM_Period = 10000 - 1; // update every 1/1200 s
|
||||
tim_init.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
tim_init.TIM_RepetitionCounter = 0;
|
||||
|
||||
|
@ -91,7 +92,7 @@ void pwm_timer_init(uint32_t frequency_hz_100)
|
|||
// TIM_SelectOCxM(TIM15, TIM_Channel_2, TIM_OCMode_PWM1);
|
||||
// TIM_CCxCmd(TIM15, TIM_Channel_2, TIM_CCx_Enable);
|
||||
|
||||
// The following make transitions smooth
|
||||
// The following settings make transitions between generated frequencies smooth
|
||||
TIM_ARRPreloadConfig(TIM15, ENABLE);
|
||||
TIM_OC2PreloadConfig(TIM15, TIM_OCPreload_Enable);
|
||||
|
||||
|
@ -146,8 +147,6 @@ void pwm_dma_init()
|
|||
NVIC_Init(&nvic_init);
|
||||
}
|
||||
|
||||
#include "log.h"
|
||||
|
||||
void pwm_dma_start()
|
||||
{
|
||||
//pwm_dma_init_channel();
|
||||
|
@ -177,14 +176,10 @@ void DMA1_Channel2_IRQHandler(void)
|
|||
if (DMA_GetITStatus(DMA1_IT_HT2)) {
|
||||
DMA_ClearITPendingBit(DMA1_IT_HT2);
|
||||
pwm_handle_dma_transfer_half(PWM_TIMER_DMA_BUFFER_SIZE, pwm_timer_dma_buffer);
|
||||
//if (length < PWM_TIMER_DMA_BUFFER_SIZE / 2) {
|
||||
//}
|
||||
}
|
||||
if (DMA_GetITStatus(DMA1_IT_TC2)) {
|
||||
DMA_ClearITPendingBit(DMA1_IT_TC2);
|
||||
pwm_handle_dma_transfer_full(PWM_TIMER_DMA_BUFFER_SIZE, pwm_timer_dma_buffer);
|
||||
//if (length < PWM_TIMER_DMA_BUFFER_SIZE / 2) {
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,15 +210,13 @@ inline uint16_t pwm_calculate_period(uint32_t frequency_hz_100)
|
|||
return (uint16_t) (((100.0f * 1000000.0f) / (frequency_hz_100 * 2.0f))) - 1;
|
||||
}
|
||||
|
||||
inline void pwm_timer_set_frequency(uint32_t frequency_hz_100)
|
||||
inline void pwm_timer_set_frequency(uint32_t pwm_period)
|
||||
{
|
||||
uint16_t period = pwm_calculate_period(frequency_hz_100);
|
||||
|
||||
// TIM_CtrlPWMOutputs(TIM15, DISABLE);
|
||||
// TIM_Cmd(TIM15, DISABLE);
|
||||
|
||||
TIM_SetAutoreload(TIM15, period);
|
||||
// TIM_SetCompare2(TIM15, period / 2);
|
||||
TIM_SetAutoreload(TIM15, pwm_period);
|
||||
// TIM_SetCompare2(TIM15, pwm_period / 2);
|
||||
|
||||
// TIM_Cmd(TIM15, ENABLE);
|
||||
// TIM_CtrlPWMOutputs(TIM15, ENABLE);
|
||||
|
|
|
@ -50,6 +50,8 @@ static void rcc_init()
|
|||
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
|
||||
FLASH_SetLatency(FLASH_Latency_0);
|
||||
|
||||
// TODO: Check what the delay timer TIM3 settings really should be and WTF the clock tick really is!?!?!?
|
||||
|
||||
RCC_HCLKConfig(RCC_SYSCLK_Div1); // Was: RCC_SYSCLK_Div4
|
||||
RCC_PCLK2Config(RCC_HCLK_Div1); // Was: 4
|
||||
RCC_PCLK1Config(RCC_HCLK_Div1); // Was: 2
|
||||
|
@ -221,6 +223,22 @@ void system_scheduler_timer_init()
|
|||
TIM_Cmd(TIM4, ENABLE);
|
||||
}
|
||||
|
||||
void system_disable_tick()
|
||||
{
|
||||
TIM_Cmd(TIM4, DISABLE);
|
||||
NVIC_DisableIRQ(TIM4_IRQn);
|
||||
TIM_ITConfig(TIM4, TIM_IT_Update, DISABLE);
|
||||
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
|
||||
}
|
||||
|
||||
void system_enable_tick()
|
||||
{
|
||||
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
|
||||
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
|
||||
NVIC_EnableIRQ(TIM4_IRQn);
|
||||
TIM_Cmd(TIM4, ENABLE);
|
||||
}
|
||||
|
||||
void system_set_green_led(bool enabled)
|
||||
{
|
||||
if (enabled) {
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
void system_init();
|
||||
uint32_t system_get_tick();
|
||||
void system_disable_tick();
|
||||
void system_enable_tick();
|
||||
void system_disable_irq();
|
||||
void system_enable_irq();
|
||||
void system_set_green_led(bool enabled);
|
||||
|
|
150
src/radio.c
150
src/radio.c
|
@ -5,6 +5,7 @@
|
|||
#include "telemetry.h"
|
||||
#include "log.h"
|
||||
#include "hal/system.h"
|
||||
#include "hal/delay.h"
|
||||
#include "hal/spi.h"
|
||||
#include "hal/pwm.h"
|
||||
#include "hal/usart_gps.h"
|
||||
|
@ -47,11 +48,13 @@ typedef struct _radio_transmit_entry {
|
|||
payload_encoder *payload_encoder;
|
||||
fsk_encoder_api *fsk_encoder_api;
|
||||
|
||||
jtencode_mode_type jtencode_mode_type;
|
||||
jtencode_mode_type jtencode_mode_type;
|
||||
|
||||
fsk_encoder fsk_encoder;
|
||||
} radio_transmit_entry;
|
||||
|
||||
static bool si4032_use_dma = false;
|
||||
|
||||
static volatile bool radio_transmission_active = false;
|
||||
static volatile bool radio_transmission_finished = false;
|
||||
static volatile radio_transmit_entry *radio_current_transmit_entry = NULL;
|
||||
|
@ -75,6 +78,8 @@ static volatile uint32_t radio_symbol_count_loop = 0;
|
|||
static volatile bool radio_dma_transfer_active = false;
|
||||
static volatile int8_t radio_dma_transfer_stop_after_counter = -1;
|
||||
|
||||
static volatile bool radio_manual_transmit_active = false;
|
||||
|
||||
uint8_t radio_current_payload[RADIO_PAYLOAD_MAX_LENGTH];
|
||||
size_t radio_current_payload_length = 0;
|
||||
|
||||
|
@ -90,14 +95,13 @@ telemetry_data current_telemetry_data;
|
|||
uint8_t aprs_packet[RADIO_PAYLOAD_MAX_LENGTH];
|
||||
|
||||
static volatile uint32_t start_tick = 0, end_tick = 0;
|
||||
static volatile bool freq_state = false;
|
||||
|
||||
static size_t radio_fill_pwm_buffer(size_t offset, size_t length, uint16_t *buffer);
|
||||
|
||||
size_t radio_aprs_encode(uint8_t *payload, size_t length, telemetry_data *telemetry_data)
|
||||
{
|
||||
aprs_generate_position_without_timestamp(
|
||||
aprs_packet, sizeof(aprs_packet), telemetry_data, APRS_SYMBOL, APRS_COMMENT);
|
||||
aprs_packet, sizeof(aprs_packet), telemetry_data, APRS_SYMBOL_TABLE, APRS_SYMBOL, APRS_COMMENT);
|
||||
|
||||
log_debug("aprs: %s\n", aprs_packet);
|
||||
|
||||
|
@ -111,6 +115,7 @@ payload_encoder radio_aprs_payload_encoder = {
|
|||
|
||||
size_t radio_ft8_encode(uint8_t *payload, size_t length, telemetry_data *telemetry_data)
|
||||
{
|
||||
// TODO: Encode locator for FT8
|
||||
return snprintf((char *) payload, length, "%s %s", FT8_CALLSIGN, FT8_LOCATOR);
|
||||
}
|
||||
|
||||
|
@ -120,6 +125,7 @@ payload_encoder radio_ft8_payload_encoder = {
|
|||
|
||||
size_t radio_wspr_encode(uint8_t *payload, size_t length, telemetry_data *telemetry_data)
|
||||
{
|
||||
// TODO: Encode locator for WSPR
|
||||
return snprintf((char *) payload, length, "");
|
||||
}
|
||||
|
||||
|
@ -127,7 +133,7 @@ payload_encoder radio_wspr_payload_encoder = {
|
|||
.encode = radio_wspr_encode,
|
||||
};
|
||||
|
||||
#define RADIO_TRANSMIT_ENTRY_COUNT 3
|
||||
#define RADIO_TRANSMIT_ENTRY_COUNT 1
|
||||
|
||||
static radio_transmit_entry radio_transmit_schedule[] = {
|
||||
{
|
||||
|
@ -139,7 +145,7 @@ static radio_transmit_entry radio_transmit_schedule[] = {
|
|||
.payload_encoder = &radio_aprs_payload_encoder,
|
||||
.fsk_encoder_api = &bell_fsk_encoder_api,
|
||||
},
|
||||
{
|
||||
/* {
|
||||
.radio_type = RADIO_TYPE_SI5351,
|
||||
.data_mode = RADIO_DATA_MODE_FT8,
|
||||
.frequency = RADIO_SI5351_TX_FREQUENCY_FT8,
|
||||
|
@ -156,7 +162,7 @@ static radio_transmit_entry radio_transmit_schedule[] = {
|
|||
.payload_encoder = &radio_wspr_payload_encoder,
|
||||
.fsk_encoder_api = &jtencode_fsk_encoder_api,
|
||||
.jtencode_mode_type = JTENCODE_MODE_WSPR,
|
||||
},
|
||||
},*/
|
||||
};
|
||||
|
||||
static bool radio_start_transmit_si4032(radio_transmit_entry *entry)
|
||||
|
@ -180,7 +186,9 @@ static bool radio_start_transmit_si4032(radio_transmit_entry *entry)
|
|||
frequency_offset = 0;
|
||||
modulation_type = SI4032_MODULATION_TYPE_FSK;
|
||||
use_direct_mode = true;
|
||||
radio_fill_pwm_buffer(0, PWM_TIMER_DMA_BUFFER_SIZE, pwm_timer_dma_buffer);
|
||||
if (si4032_use_dma) {
|
||||
radio_fill_pwm_buffer(0, PWM_TIMER_DMA_BUFFER_SIZE, pwm_timer_dma_buffer);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -203,10 +211,17 @@ static bool radio_start_transmit_si4032(radio_transmit_entry *entry)
|
|||
|
||||
switch (entry->data_mode) {
|
||||
case RADIO_DATA_MODE_APRS:
|
||||
// TODO: Set up DMA for APRS
|
||||
radio_dma_transfer_active = true;
|
||||
radio_dma_transfer_stop_after_counter = -1;
|
||||
pwm_dma_start();
|
||||
if (si4032_use_dma) {
|
||||
radio_dma_transfer_active = true;
|
||||
radio_dma_transfer_stop_after_counter = -1;
|
||||
system_disable_tick();
|
||||
pwm_dma_start();
|
||||
} else {
|
||||
log_info("Si4032 manual TX\n");
|
||||
radio_manual_transmit_active = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -269,7 +284,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
|
|||
break;
|
||||
case RADIO_DATA_MODE_APRS:
|
||||
// TODO: make bell tones and flag field count configurable
|
||||
bell_encoder_new(&entry->fsk_encoder, entry->symbol_rate, 20, bell202_tones);
|
||||
bell_encoder_new(&entry->fsk_encoder, entry->symbol_rate, BELL_FLAG_FIELD_COUNT_1200, bell202_tones);
|
||||
radio_current_symbol_rate = entry->fsk_encoder_api->get_symbol_rate(&entry->fsk_encoder);
|
||||
entry->fsk_encoder_api->get_tones(&entry->fsk_encoder, &radio_current_fsk_tone_count,
|
||||
&radio_current_fsk_tones);
|
||||
|
@ -284,6 +299,7 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
|
|||
case RADIO_DATA_MODE_FSQ_3:
|
||||
case RADIO_DATA_MODE_FSQ_4_5:
|
||||
case RADIO_DATA_MODE_FSQ_6:
|
||||
// TODO: Encode WSPR locator
|
||||
jtencode_encoder_new(&entry->fsk_encoder, entry->jtencode_mode_type, WSPR_CALLSIGN, WSPR_LOCATOR, WSPR_DBM,
|
||||
FSQ_CALLSIGN_FROM, FSQ_CALLSIGN_TO, FSQ_COMMAND);
|
||||
radio_current_symbol_delay_ms_100 = entry->fsk_encoder_api->get_symbol_delay(&entry->fsk_encoder);
|
||||
|
@ -294,27 +310,27 @@ static bool radio_start_transmit(radio_transmit_entry *entry)
|
|||
return false;
|
||||
}
|
||||
|
||||
// USART interrupts may interfere with transmission timing
|
||||
usart_gps_enable(false);
|
||||
|
||||
switch (entry->radio_type) {
|
||||
case RADIO_TYPE_SI4032:
|
||||
success = radio_start_transmit_si4032(entry);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case RADIO_TYPE_SI5351:
|
||||
success = radio_start_transmit_si5351(entry);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
log_info("TX enabled\n");
|
||||
if (!success) {
|
||||
usart_gps_enable(true);
|
||||
// TODO: stop transmit here
|
||||
return false;
|
||||
}
|
||||
|
||||
// USART interrupts may interfere with transmission timing
|
||||
usart_gps_enable(false);
|
||||
log_info("TX enabled\n");
|
||||
|
||||
system_set_red_led(true);
|
||||
|
||||
|
@ -336,9 +352,12 @@ static bool radio_stop_transmit_si4032(radio_transmit_entry *entry)
|
|||
break;
|
||||
case RADIO_DATA_MODE_APRS:
|
||||
use_direct_mode = true;
|
||||
if (si4032_use_dma) {
|
||||
system_enable_tick();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_direct_mode) {
|
||||
|
@ -353,6 +372,16 @@ static bool radio_stop_transmit_si4032(radio_transmit_entry *entry)
|
|||
|
||||
si4032_inhibit_tx();
|
||||
|
||||
switch (entry->data_mode) {
|
||||
case RADIO_DATA_MODE_APRS:
|
||||
if (si4032_use_dma) {
|
||||
system_enable_tick();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -384,20 +413,17 @@ static bool radio_stop_transmit(radio_transmit_entry *entry)
|
|||
switch (entry->radio_type) {
|
||||
case RADIO_TYPE_SI4032:
|
||||
success = radio_stop_transmit_si4032(entry);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case RADIO_TYPE_SI5351:
|
||||
success = radio_stop_transmit_si5351(entry);
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
radio_reset_transmit_state();
|
||||
|
||||
radio_manual_transmit_active = false;
|
||||
radio_dma_transfer_active = false;
|
||||
|
||||
switch (entry->data_mode) {
|
||||
|
@ -423,12 +449,10 @@ static bool radio_stop_transmit(radio_transmit_entry *entry)
|
|||
return false;
|
||||
}
|
||||
|
||||
radio_reset_transmit_state();
|
||||
|
||||
usart_gps_enable(true);
|
||||
system_set_red_led(false);
|
||||
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
static uint32_t radio_next_symbol_si4032(radio_transmit_entry *entry)
|
||||
|
@ -444,8 +468,7 @@ static uint32_t radio_next_symbol_si4032(radio_transmit_entry *entry)
|
|||
return 0;
|
||||
}
|
||||
|
||||
fsk_tone *tone = &radio_current_fsk_tones[next_tone_index];
|
||||
return tone->frequency_hz_100;
|
||||
return radio_current_fsk_tones[next_tone_index].frequency_hz_100;
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
|
@ -479,7 +502,8 @@ static bool radio_transmit_symbol_si5351(radio_transmit_entry *entry)
|
|||
|
||||
log_trace("Tone: %d\n", next_tone_index);
|
||||
|
||||
uint64_t frequency = ((uint64_t) entry->frequency) * 100UL + (next_tone_index * radio_current_tone_spacing_hz_100);
|
||||
uint64_t frequency =
|
||||
((uint64_t) entry->frequency) * 100UL + (next_tone_index * radio_current_tone_spacing_hz_100);
|
||||
radio_si5351_freq = frequency;
|
||||
radio_si5351_state_change = true;
|
||||
break;
|
||||
|
@ -520,7 +544,7 @@ static void radio_next_transmit_entry()
|
|||
|
||||
void radio_handle_timer_tick()
|
||||
{
|
||||
if (radio_dma_transfer_active) {
|
||||
if (radio_dma_transfer_active || radio_manual_transmit_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -541,6 +565,8 @@ void radio_handle_timer_tick()
|
|||
// TODO: implement time sync
|
||||
}
|
||||
|
||||
uint16_t symbol_delay = 823; // -> good around ~823 for a tight loop
|
||||
|
||||
void radio_handle_main_loop()
|
||||
{
|
||||
if (radio_post_transmit_delay_counter == 0) {
|
||||
|
@ -548,21 +574,54 @@ void radio_handle_main_loop()
|
|||
log_info("Battery: %d mV\n", current_telemetry_data.battery_voltage_millivolts);
|
||||
log_info("Internal temperature: %ld C*100\n", current_telemetry_data.internal_temperature_celsius_100);
|
||||
log_info("Time: %02d:%02d:%02d\n",
|
||||
current_telemetry_data.gps.hours, current_telemetry_data.gps.minutes, current_telemetry_data.gps.seconds);
|
||||
current_telemetry_data.gps.hours, current_telemetry_data.gps.minutes,
|
||||
current_telemetry_data.gps.seconds);
|
||||
log_info("Fix: %d, Sats: %d, OK packets: %d, Bad packets: %d\n",
|
||||
current_telemetry_data.gps.fix, current_telemetry_data.gps.sats_raw, current_telemetry_data.gps.ok_packets, current_telemetry_data.gps.bad_packets);
|
||||
current_telemetry_data.gps.fix, current_telemetry_data.gps.sats_raw,
|
||||
current_telemetry_data.gps.ok_packets, current_telemetry_data.gps.bad_packets);
|
||||
log_info("Lat: %ld *1M, Lon: %ld *1M, Alt: %ld m\n",
|
||||
current_telemetry_data.gps.lat_raw / 10, current_telemetry_data.gps.lon_raw / 10, (current_telemetry_data.gps.alt_raw / 1000) * 3280 / 1000);
|
||||
current_telemetry_data.gps.lat_raw / 10, current_telemetry_data.gps.lon_raw / 10,
|
||||
(current_telemetry_data.gps.alt_raw / 1000) * 3280 / 1000);
|
||||
|
||||
radio_post_transmit_delay_counter = RADIO_POST_TRANSMIT_DELAY * SYSTEM_SCHEDULER_TIMER_TICKS_PER_SECOND / 1000;
|
||||
radio_start_transmit_entry = radio_current_transmit_entry;
|
||||
}
|
||||
|
||||
if (radio_si4032_state_change) {
|
||||
radio_si4032_state_change = false;
|
||||
pwm_timer_set_frequency(radio_si4032_freq);
|
||||
radio_symbol_count_loop++;
|
||||
freq_state = !freq_state;
|
||||
if (radio_manual_transmit_active) {
|
||||
// TODO: Refactor this code for proper handling of APRS
|
||||
fsk_encoder_api *fsk_encoder_api = radio_current_transmit_entry->fsk_encoder_api;
|
||||
fsk_encoder *fsk_enc = &radio_current_transmit_entry->fsk_encoder;
|
||||
log_info("Si4032 manual TX start: %d\n", symbol_delay);
|
||||
system_disable_tick();
|
||||
int8_t tone_index = 0;
|
||||
uint32_t pwm_periods[2];
|
||||
pwm_periods[0] = pwm_calculate_period(radio_current_fsk_tones[0].frequency_hz_100);
|
||||
pwm_periods[1] = pwm_calculate_period(radio_current_fsk_tones[1].frequency_hz_100);
|
||||
switch (radio_current_transmit_entry->data_mode) {
|
||||
case RADIO_DATA_MODE_APRS:
|
||||
do {
|
||||
// radio_si4032_state_change = false;
|
||||
pwm_timer_set_frequency(pwm_periods[tone_index]);
|
||||
// radio_symbol_count_loop++;
|
||||
delay_us(symbol_delay);
|
||||
tone_index = fsk_encoder_api->next_tone(fsk_enc);
|
||||
} while (tone_index >= 0);
|
||||
//} while (radio_transmit_symbol(radio_current_transmit_entry));
|
||||
|
||||
radio_si4032_state_change = false;
|
||||
radio_transmission_finished = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
system_enable_tick();
|
||||
//symbol_delay += 1;
|
||||
} else {
|
||||
radio_si4032_state_change = false;
|
||||
pwm_timer_set_frequency(radio_si4032_freq);
|
||||
radio_symbol_count_loop++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -696,7 +755,10 @@ void radio_init()
|
|||
|
||||
radio_current_transmit_entry = &radio_transmit_schedule[radio_current_transmit_entry_index];
|
||||
|
||||
pwm_data_timer_init();
|
||||
pwm_timer_init(100 * 100);
|
||||
pwm_dma_init();
|
||||
|
||||
if (si4032_use_dma) {
|
||||
pwm_data_timer_init();
|
||||
pwm_dma_init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include "codecs/bell/bell.h"
|
||||
#include "codecs/aprs/aprs.h"
|
||||
#include "codecs/ax25/ax25.h"
|
||||
#include "telemetry.h"
|
||||
#include "config.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
@ -9,10 +13,29 @@ int main(void)
|
|||
|
||||
bell_encoder_new(&fsk_encoder, 1200, 0, bell202_tones);
|
||||
|
||||
// aprs_generate_position_without_timestamp(
|
||||
// aprs_packet, sizeof(aprs_packet), telemetry_data, APRS_SYMBOL, APRS_COMMENT);
|
||||
// ax25_encode_packet_aprs(APRS_CALLSIGN, APRS_SSID, "APZ41N", 0, "",
|
||||
// (char *) aprs_packet, length, payload);
|
||||
telemetry_data telemetry;
|
||||
memset(&telemetry, 0, sizeof(telemetry_data));
|
||||
|
||||
uint8_t aprs_packet[256];
|
||||
size_t aprs_length = aprs_generate_position_without_timestamp(
|
||||
aprs_packet, sizeof(aprs_packet), &telemetry, APRS_SYMBOL_TABLE, APRS_SYMBOL, APRS_COMMENT);
|
||||
|
||||
uint8_t payload[256];
|
||||
size_t payload_length = ax25_encode_packet_aprs(APRS_CALLSIGN, APRS_SSID, APRS_DESTINATION, APRS_DESTINATION_SSID, APRS_RELAYS,
|
||||
(char *) aprs_packet, aprs_length, payload);
|
||||
|
||||
printf("Full payload length: %d\n", payload_length);
|
||||
|
||||
for (int i = 0; i < payload_length; i++) {
|
||||
uint8_t c = payload[i];
|
||||
if (c >= 0x20 && c <= 0x7e) {
|
||||
printf("%c", c);
|
||||
} else {
|
||||
printf(" [%02X] ", c);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
//uint8_t payload[] = { 0x7e, 0x82, 0xa0, 0xb4, 'h', 'b', 0x9c, 0x00, 0x7e};
|
||||
// 0x7e: 0 1 1 1 1 1 1 0
|
||||
|
@ -20,7 +43,7 @@ int main(void)
|
|||
// 0xa0: 0 0 0 0 0 1 0 1
|
||||
// 0xb4: 0 0 1 0 1 1 0 1
|
||||
|
||||
uint8_t payload[] = { 0x7e, 0x3f, 0x7f };
|
||||
//uint8_t payload[] = { 0x7e, 0x3f, 0x7f };
|
||||
// 1 1 1 1 1 1 0 0
|
||||
// N N N N N S N C C
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue