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.

main
Mikael Nousiainen 2020-08-31 23:07:23 +03:00
rodzic 8f74fa0b34
commit 8a315f5879
12 zmienionych plików z 206 dodań i 89 usunięć

Wyświetl plik

@ -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 -
```

Wyświetl plik

@ -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,

Wyświetl plik

@ -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

Wyświetl plik

@ -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);

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);

Wyświetl plik

@ -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) {

Wyświetl plik

@ -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);

Wyświetl plik

@ -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();
}
}

Wyświetl plik

@ -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