/* armando modem - iz4kll */ #ifdef __XC16 #include #include #endif #include #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; }