m20-custom-firmware/m20/Core/Src/fsk4.c

101 wiersze
3.8 KiB
C

/*
* fsk4.c
* By SQ2DK
*/
#include "fsk4.h"
#include "adf.h"
#include "config.h"
#include "main.h"
/*
* In this file i will try to prepare procedure for transmitting earlier
* prepared message using 4fsk We will be using adf.c - library for handling
* ADF7012 chip. Frequency setting and initialization of chip will be done
* outside of this library idea is to use frequency correction register for
* shifting base frequency, which should produce 244Hz steps in frequency. This
* will limit minimum baud rate to 100bd and its multipliers. As experience
* showed, 244Hz tone-spacing is not sufficient for efficient decoding of
* packets using standard 270Hz shift Thus generation of 9MHz signal for radio
* chip was required via STM32 PLL to achieve spacing close to 270Hz. Baud rate
* will be generated by microcontroler's timer. we will use timer2 for this,
* setting prescaler to (cpu_freuency/100000)-1, so, for 100bd single pulse we
* should set counter to 1000-1
*/
static uint16_t current_2_bit = 0;
static bool FSK_Active = false;
static char *buffer;
static uint8_t buffer_len;
static uint8_t QRGCounter = 0;
void FSK4_stop_TX() {
TIM2->DIER &= ~(TIM_DIER_UIE); // Disable the interrupt
adf_RF_off(); // turn TX off
FSK_Active = false;
}
static void FSK4_send_2bit(uint8_t bits_to_send) { // sends 2 bit value
bits_to_send =
(bits_to_send & 3); // make sure to take only 2 last bites of value - we
// cannot send more than 2 bits at the same time
adf_4fsk_fone(bits_to_send * FSK4_SPACE_MULTIPLIER);
}
bool FSK4_is_active() { // returns 1 if transmitter is active for 4FSK
return FSK_Active;
}
static void FSK4_write(char *buff, uint16_t address_2bit) {
int full_bytes = address_2bit / 4; // number of full bytes of address
int fraction_part =
address_2bit -
(full_bytes * 4); // fraction part of address (number of 2bytes offset)
uint8_t byte_to_send = (buff[full_bytes] >> (6 - (fraction_part * 2)) &
3); // returns 2 bytes of buffer at address
FSK4_send_2bit(byte_to_send); // sends those 2 bytes
}
void FSK4_timer_handler() { // called out by interrupt handling procedure in
// main
TIM2->CNT = 0; // reset timer - make sure to have it at the beginning of
// procedure, otherwise there will be some delays.
if (current_2_bit < (FSK4_HEADER_LENGTH * 4)) { // we are still in header
uint8_t tmp_offset = ((0xD8 >> current_2_bit % 4) & 3);
FSK4_send_2bit(tmp_offset);
} else {
FSK4_write(buffer,
(current_2_bit -
(FSK4_HEADER_LENGTH *
4))); // send 2 bits of data from address of current_2_bit * 2
}
current_2_bit++;
if (current_2_bit > ((buffer_len + FSK4_HEADER_LENGTH) * 4)) {
FSK4_stop_TX();
} // if we got to the end of data - finish transmitting
}
void FSK4_start_TX(char *buff, uint8_t len) {
buffer = buff;
buffer_len = len;
// adf_setup();
current_2_bit = 0; // reset counter of current position of bit address
adf_RF_on(QRG_FSK4[QRGCounter++], PA_FSK4); // turn on radio TX
if (QRGCounter >= sizeof(QRG_FSK4) / sizeof(QRG_FSK4[0]))
QRGCounter = 0;
FSK_Active = true; // change status
TIM2->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN)); // Disable the TIM Counter
uint16_t timer2StartValue =
(100000 / FSK4_BAUD) -
1; // timer value calculated according to baud rate 999 for 100bd
TIM2->ARR = timer2StartValue; // set timer counter max value to pre-set value
// for baudrate (auto-reload register)
TIM2->CR1 |= TIM_CR1_CEN; // enable timer again
TIM2->DIER |= TIM_DIER_UIE; // Enable the interrupt
FSK4_timer_handler(); // force execution of procedure responsible for
// interrupt handling
}