Files
armod/modem.c
2022-10-24 19:41:38 +02:00

162 lines
4.9 KiB
C

/* armando modem - iz4kll */
#ifdef __XC16
#include <libq.h>
#include <dsp.h>
#endif
#include <stdint.h>
#include "modem.h"
#include "../peripheral/gpio.h"
#include "../peripheral/adc.h"
#include "../peripheral/dac.h"
#if defined(__DEBUG) && ! defined(__MPLAB_DEBUGGER_PK3)
extern fractional debug_value1, debug_value2, debug_value3;
#endif
// parametri della modulazione
modulation mod;
uint8_t modem_tx_state, modem_rx_state;
// predelay
uint16_t modem_predelay_mstime, modem_predelay_buffer_size, modem_predelay_buffer_index;
// non trasmettere quando stai ricevendo payload phy
uint8_t modem_avoid_overlap;
// payload
uint16_t modem_payload_max_symbols, modem_payload_symbols_index;
// solo al boot
void modem_init(void) {
FIR_init();
/// Initialize the A/D converter
adc_init();
adc_init_dma();
/// Initialize the Timer to generate sampling event for ADC
adc_init_tmr();
modem_preamble_waiting = 0;
#ifndef __DEBUG
// PENDING
InitDACDMA(); // prima di initdac!!
initDac(); // Initialize the D/A converter
#endif
}
// ad ogni cambio modulazione
void modem_set_up(void) {
/// imposta dimensione alfabeto
mod.alphabet_size = (1 << mod.bits_per_symbol);
/// calcola numero di buffer per simbolo
mod.buffers_per_symbol = BUFFER_RATE / mod.symbol_rate;
/// setup modulatore
modulator_setup();
/// setup demodulatore
demodulator_setup();
modem_set_up_predelay();
// va a valle del popolamento della costellazione di detect
modem_set_up_preamble();
}
// loopback per test
void DAC_ADC_loopback(void){
#ifdef __DSP_LIB__
/// Travaso DAC-> ADC per test
VectorCopy(SAMPLES_PER_BUFFER, ADCBuffer[dac_buffer_toggle], Q_DACBuffer[dac_buffer_toggle]);
#endif
}
void modem_process_sample_buffer(fractional *buffer) {
static detector_symbol detector_modulation_averages;
// demodula un buffer di campioni e torna le medie di freq, ph e amp
demodulator_sample_buffer_demodulate(buffer, &detector_modulation_averages);
// spia OverLoad
#ifdef USE_GPIO
if ((gpio_mode == GPIO_INFO) && (detector_modulation_averages.amplitude > ADC_MAX_AMPLITUDE)) GPIO_ADC_OL = 1;
else {
GPIO_ADC_OL = 0;
}
#endif
#if ! defined(__DEBUG)
// viene riasserito dall'interrupt DMA2, meglio azzerare presto per non perdere eventi
process_input_sample_buffer = 0; // TEST quando in debug ci pensa chi ?
#endif
#if defined(__DEBUG) && ! defined(__MPLAB_DEBUGGER_PK3)
// stampa frequenza vista dal demodulatore
debug_value2 = detector_modulation_averages.frequency;
#endif
// aspetta un preambolo
if (modem_preamble_waiting) {
if (modem_detect_preamble(detector_modulation_averages.frequency)) {
// preambolo trovato
modem_preamble_waiting = 0;
modem_post_preamble_timer = modem_post_preamble_delay;
#ifdef USE_GPIO
if (gpio_mode == GPIO_INFO) GPIO_PHY_PAYLOAD = 1;
#endif
}
} else if (modem_post_preamble_timer > 0) {
modem_post_preamble_timer--; // aspetta
} else {
// comincia a ricevere i dati
// aspetta header o dati
if (rx_sample_buffer_index < mod.buffers_per_symbol) {
// confronta le medie con la costellazione e torna il simbolo piu vicino
rx_sample_buffers_buffer[rx_sample_buffer_index] = demodulator_find_nearest_symbol(&detector_modulation_averages, detector_constellation, &symbol_error);
#ifdef USE_GPIO
// qualita' TODO
GPIO_SYM_OK = 0;
if (symbol_error.frequency < (min_symbol_distance.frequency / 4)) GPIO_SYM_OK = 1;
else {
GPIO_SYM_OK = 0;
}
#endif
// sarebbe preferibile avere uno storico dei valori, invece che dei simboli, ma sarebbe MAX_BUFFERS_PER_SYMBOL * detector_symbol
// anche accumulare una media sembra critico
}
rx_sample_buffer_index++;
#if defined(__DEBUG) && ! defined(__MPLAB_DEBUGGER_PK3)
// value3 = rx_sample_buffer_index;
debug_value3 = symbol_error.frequency;
#endif
// numero di buffer per simbolo raggiunto
if (rx_sample_buffer_index >= mod.buffers_per_symbol) {
// valore piu ricorrente
rx_symbol_buffer[rx_symbol_buffer_index] = demodulator_most_frequent_value(&rx_sample_buffers_buffer[rx_symbol_detected_part_offset], mod.alphabet_size, rx_symbol_detected_part_length);
// deviazione TODO
// find_symbol_deviation(&rx_sample_buffers_buffer[rx_symbol_detected_part_offset], rx_symbol_buffer[rx_symbol_buffer_index], rx_symbol_detected_part_length);
// simbolo fatto, avanza al successivo
rx_symbol_buffer_index++;
rx_sample_buffer_index = 0;
// stava qua
}
}
}
void modem_set_up_predelay(void) {
silence = (rotor_symbol){0, 0, 0};
modem_predelay_buffer_size = (modem_predelay_mstime * BUFFER_RATE) / 1000;
}