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

92 wiersze
4.0 KiB
C

/*
* fsk4.c
* By SQ2DK
*/
#include "fsk4.h"
#include "adf.h"
#include "main.h"
#include "config.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;
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
//TIM2->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN)); // Disable the TIM Counter
//TIM2->ARR = timer1StartValue; //set timer counter max value to pre-set value for baudrate (auto-reload register)
//TIM2->CNT = 0; //reset timer
//TIM2->CR1 |= TIM_CR1_CEN; //enable timer again
}
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, PA_FSK4); //turn on radio TX
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
}