Clean up Si4063 APRS work and make APRS deviation configurable

pull/62/head
Mikael Nousiainen 2023-10-06 17:12:03 +03:00
rodzic bdc3067703
commit 7556ebe9bb
3 zmienionych plików z 96 dodań i 69 usunięć

Wyświetl plik

@ -7,6 +7,7 @@
#include <stdbool.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_tim.h>
#include "hal/hal.h"
#include "hal/delay.h"
@ -53,18 +54,6 @@
#define SI4063_DATA_RATE_APRS 4400
#define RF_DEVIATION_HZ_RTTY 200.0f
#define RF_DEVIATION_HZ_APRS 1300.0f
#define OUTDIV_70CM 8
#define OUTDIV_2M 24
#define OUTDIV_DFM 10
#define FREQUENCY_DEVIATION_RTTY ((((uint32_t)1 << 19) * OUTDIV_2M * RF_DEVIATION_HZ_RTTY)/(2*SI4063_CLOCK))
#define FREQUENCY_DEVIATION_APRS ((((uint32_t)1 << 19) * OUTDIV_2M * RF_DEVIATION_HZ_APRS)/(2*SI4063_CLOCK))
#define FREQUENCY_DEVIATION_APRS_DFM ((((uint32_t)1 << 19) * OUTDIV_DFM * RF_DEVIATION_HZ_APRS)/(2*SI4063_CLOCK))
#define FREQUENCY_DEVIATION_DFM 0x90000
/**
* Filters from uTrak: https://github.com/thasti/utrak
*
@ -97,6 +86,9 @@ uint8_t si4063_filter_lp_4400[9] = {0xd5, 0xe9, 0x03, 0x20, 0x3d, 0x58, 0x6d, 0x
*/
uint8_t si4063_filter_6db_1200_4400[9] = {0x81, 0x9f, 0xc4, 0xee, 0x18, 0x3e, 0x5c, 0x70, 0x76};
uint32_t current_frequency_hz = 434000000UL;
uint32_t current_deviation_hz = 0;
static inline void si4063_set_chip_select(bool select)
{
spi_set_chip_select(GPIO_SI4063_NSEL, GPIO_PIN_SI4063_NSEL, select);
@ -226,6 +218,41 @@ void si4063_disable_tx()
si4063_set_state(SI4063_STATE_SLEEP);
}
static int si4063_get_outdiv(const uint32_t frequency_hz)
{
// Select the output divider according to the recommended ranges in the Si406x datasheet
if (frequency_hz < 177000000UL) {
return 24;
} else if (frequency_hz < 239000000UL) {
return 16;
} else if (frequency_hz < 353000000UL) {
return 12;
} else if (frequency_hz < 525000000UL) {
return 8;
} else if (frequency_hz < 705000000UL) {
return 6;
}
return 4;
}
static int si4063_get_band(const uint32_t frequency_hz)
{
if (frequency_hz < 177000000UL) {
return 5;
} else if (frequency_hz < 239000000UL) {
return 4;
} else if (frequency_hz < 353000000UL) {
return 3;
} else if (frequency_hz < 525000000UL) {
return 2;
} else if (frequency_hz < 705000000UL) {
return 1;
}
return 0;
}
void si4063_set_tx_frequency(const uint32_t frequency_hz)
{
uint8_t outdiv, band;
@ -234,26 +261,8 @@ void si4063_set_tx_frequency(const uint32_t frequency_hz)
log_debug("Si4063: Set frequency %lu\n", frequency_hz);
/* Set the output divider according to the recommended ranges in the si406x datasheet */
if (frequency_hz < 177000000UL) {
outdiv = 24;
band = 5;
} else if (frequency_hz < 239000000UL) {
outdiv = 16;
band = 4;
} else if (frequency_hz < 353000000UL) {
outdiv = 12;
band = 3;
} else if (frequency_hz < 525000000UL) {
outdiv = 8;
band = 2;
} else if (frequency_hz < 705000000UL) {
outdiv = 6;
band = 1;
} else {
outdiv = 4;
band = 0;
}
outdiv = si4063_get_outdiv(frequency_hz);
band = si4063_get_band(frequency_hz);
f_pfd = 2 * SI4063_CLOCK / outdiv;
n = frequency_hz / f_pfd - 1;
@ -291,6 +300,11 @@ void si4063_set_tx_frequency(const uint32_t frequency_hz)
si4063_send_command(SI4063_COMMAND_SET_PROPERTY, sizeof(data), data);
}
current_frequency_hz = frequency_hz;
// Deviation depends on the frequency band
si4063_set_frequency_deviation(current_deviation_hz);
}
void si4063_set_tx_power(uint8_t power)
@ -320,8 +334,18 @@ void si4063_set_frequency_offset(uint16_t offset)
si4063_send_command(SI4063_COMMAND_SET_PROPERTY, sizeof(data), data);
}
void si4063_set_frequency_deviation(uint32_t deviation)
static uint32_t si4063_calculate_deviation(uint32_t deviation_hz)
{
uint8_t outdiv = si4063_get_outdiv(current_frequency_hz);
// SY_SEL = Div-by-2
return (uint32_t) (((double) (1 << 19) * outdiv * deviation_hz) / (2 * SI4063_CLOCK));
}
void si4063_set_frequency_deviation(uint32_t deviation_hz)
{
uint32_t deviation = si4063_calculate_deviation(deviation_hz);
uint8_t data[] = {
0x20, // 0x20 = Group MODEM
0x03, // Set 3 properties (3 bytes)
@ -331,9 +355,11 @@ void si4063_set_frequency_deviation(uint32_t deviation)
deviation & 0xFF
};
log_debug("Si4063: Set freq deviation %lu\n", deviation);
log_info("Si4063: Set frequency deviation to value %lu with %lu Hz\n", deviation, deviation_hz);
si4063_send_command(SI4063_COMMAND_SET_PROPERTY, sizeof(data), data);
current_deviation_hz = deviation_hz;
}
void si4063_set_modulation_type(si4063_modulation_type type)
@ -511,6 +537,7 @@ void si4063_configure()
}
}
// Not used yet, for future use
void si4063_set_filter(const uint8_t *filter)
{
uint8_t data[12] = {
@ -541,11 +568,11 @@ void si4063_configure_data_rate(uint32_t data_rate)
si4063_send_command(SI4063_COMMAND_SET_PROPERTY, sizeof(data), data);
}
// Not used yet, for future use
void si4063_configure_aprs()
{
// For APRS in direct mode with GFSK modulation
si4063_configure_data_rate(4400);
si4063_set_frequency_deviation((uint16_t)(2*FREQUENCY_DEVIATION_APRS));
si4063_configure_data_rate(SI4063_DATA_RATE_APRS);
// Used only for GFSK mode filtering
uint32_t nco_mod = SI4063_CLOCK / 10;
@ -563,6 +590,7 @@ void si4063_configure_aprs()
si4063_send_command(SI4063_COMMAND_SET_PROPERTY, sizeof(data), data);
}
// Not used yet, for future use
void si4063_configure_rtty()
{
// For RTTY:
@ -643,7 +671,9 @@ int si4063_init()
si4063_set_tx_power(0x00);
si4063_set_frequency_offset(0);
si4063_set_frequency_deviation(0x22);
// Set deviation to zero for non-FSK modulations
si4063_set_frequency_deviation(0);
si4063_set_modulation_type(SI4063_MODULATION_TYPE_CW);
@ -651,3 +681,17 @@ int si4063_init()
return HAL_OK;
}
void TIM1_BRK_TIM15_IRQHandler(void)
{
static bool pin_state = false;
if (TIM_GetITStatus(TIM15, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM15, TIM_IT_Update);
#ifdef DFM17
// Restrict the interrupt to DFM17 only just in case this ISR gets called on RS41
pin_state = !pin_state;
si4063_set_direct_mode_pin(pin_state);
#endif
}
}

Wyświetl plik

@ -6,7 +6,6 @@
#include "pwm.h"
#include "log.h"
#include "drivers/si4063/si4063.h"
uint16_t pwm_timer_dma_buffer[PWM_TIMER_DMA_BUFFER_SIZE];
@ -69,7 +68,7 @@ void pwm_timer_init(uint32_t frequency_hz_100)
TIM_DeInit(TIM15);
#ifdef RS41
GPIO_PinRemapConfig(GPIO_Remap_TIM15, DISABLE);
#endif //RS41
#endif
// Not needed: AFIO->MAPR2 |= AFIO_MAPR2_TIM15_REMAP;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE);
@ -110,7 +109,7 @@ void pwm_timer_init(uint32_t frequency_hz_100)
TIM_OC2FastConfig(TIM15, TIM_OCFast_Enable);
TIM_CtrlPWMOutputs(TIM15, DISABLE);
#endif //RS41
#endif
#ifdef DFM17
// For DFM17 we don't have a PWM pin in the right place, so we manually toggle the pin in the ISR
TIM_ClearITPendingBit(TIM15, TIM_IT_Update);
@ -122,7 +121,7 @@ void pwm_timer_init(uint32_t frequency_hz_100)
nvic_init.NVIC_IRQChannelSubPriority = 1;
nvic_init.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_init);
#endif //DFM17
#endif
TIM_Cmd(TIM15, ENABLE);
}
@ -211,7 +210,7 @@ void pwm_timer_pwm_enable(bool enabled)
{
#ifdef RS41
TIM_CtrlPWMOutputs(TIM15, enabled ? ENABLE : DISABLE);
#endif //RS41
#endif
}
void pwm_timer_use(bool use)
@ -220,7 +219,7 @@ void pwm_timer_use(bool use)
// Remapping the TIM15 outputs will allow TIM15 channel 2 can be used to drive pin PB15,
// which is connected to RS41 Si4032 SDI pin for direct modulation
GPIO_PinRemapConfig(GPIO_Remap_TIM15, use ? ENABLE : DISABLE);
#endif //RS41
#endif
}
void pwm_timer_uninit()
@ -232,7 +231,7 @@ void pwm_timer_uninit()
#ifdef RS41
GPIO_PinRemapConfig(GPIO_Remap_TIM15, DISABLE);
#endif //RS41
#endif
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, DISABLE);
}
@ -253,22 +252,3 @@ inline void pwm_timer_set_frequency(uint32_t pwm_period)
// TIM_Cmd(TIM15, ENABLE);
// TIM_CtrlPWMOutputs(TIM15, ENABLE);
}
static uint32_t Tim15Cnt = 0;
volatile bool Tim15On = false;
void TIM1_BRK_TIM15_IRQHandler(void)
{
if (TIM_GetITStatus(TIM15, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM15, TIM_IT_Update);
#ifdef DFM17
// Just in case this ISR gets called on RS41, we restrict this to DFM only
Tim15Cnt++;
Tim15On = !Tim15On;
si4063_set_direct_mode_pin(Tim15On);
}
#endif //DFM17
}

Wyświetl plik

@ -12,6 +12,9 @@
#include "radio_si4063.h"
#include "codecs/mfsk/mfsk.h"
#define SI4063_DEVIATION_HZ_RTTY 200.0
#define SI4063_DEVIATION_HZ_APRS 2600.0
#define CW_SYMBOL_RATE_MULTIPLIER 4
// TODO: Add support for multiple APRS baud rates
@ -19,9 +22,7 @@
#define symbol_delay_bell_202_1200bps_us 823
#elif defined(DFM17)
#define symbol_delay_bell_202_1200bps_us 820
#else
Improper definitions
#endif // Sonde Type
#endif
static volatile bool radio_si4063_state_change = false;
static volatile uint32_t radio_si4063_freq = 0;
@ -29,6 +30,7 @@ static volatile uint32_t radio_si4063_freq = 0;
bool radio_start_transmit_si4063(radio_transmit_entry *entry, radio_module_state *shared_state)
{
uint16_t frequency_offset;
uint32_t frequency_deviation = 0;
si4063_modulation_type modulation_type;
bool use_direct_mode;
@ -43,11 +45,13 @@ bool radio_start_transmit_si4063(radio_transmit_entry *entry, radio_module_state
break;
case RADIO_DATA_MODE_RTTY:
frequency_offset = 0;
frequency_deviation = SI4063_DEVIATION_HZ_RTTY;
modulation_type = SI4063_MODULATION_TYPE_CW;
use_direct_mode = false;
break;
case RADIO_DATA_MODE_APRS_1200:
frequency_offset = 0;
frequency_deviation = SI4063_DEVIATION_HZ_APRS;
modulation_type = SI4063_MODULATION_TYPE_FSK;
use_direct_mode = true;
break;
@ -69,6 +73,7 @@ bool radio_start_transmit_si4063(radio_transmit_entry *entry, radio_module_state
si4063_set_tx_power(entry->tx_power);
si4063_set_frequency_offset(frequency_offset);
si4063_set_modulation_type(modulation_type);
si4063_set_frequency_deviation(frequency_deviation);
si4063_enable_tx();
@ -151,7 +156,6 @@ static void radio_handle_main_loop_manual_si4063(radio_transmit_entry *entry, ra
case RADIO_DATA_MODE_APRS_1200: {
int8_t tone_index;
log_info("APRS TX starts\n");
while ((tone_index = fsk_encoder_api->next_tone(fsk_enc)) >= 0) {
pwm_timer_set_frequency(precalculated_pwm_periods[tone_index]);
shared_state->radio_symbol_count_loop++;
@ -160,7 +164,6 @@ static void radio_handle_main_loop_manual_si4063(radio_transmit_entry *entry, ra
radio_si4063_state_change = false;
shared_state->radio_transmission_finished = true;
log_info("APRS TX ends\n");
break;
}
default:
@ -304,4 +307,4 @@ bool radio_stop_transmit_si4063(radio_transmit_entry *entry, radio_module_state
void radio_init_si4063()
{
}
#endif //DFM17
#endif