/* * File: main.c * Author: Carlo Alessandro Nicolau @ INFN * * Created on May 28, 2021, 4:29 PM * * Firmware for BPD-V01 board. * Main. * */ #include <pic18.h> #include "irqs.h" #include "communication.h" #include "errorcodes.h" #include "errors.h" #include "hardware.h" #include "adcreader.h" #include "timing.h" #include "rescue.h" void init_mcu(void); void init_comm(void); void init_adcreader(void); void start_irqs(void); void sensors_acquire_offsets(void); void alarms_enable(void); void manage_incoming_data(void); void _delay_seconds(uint8_t _seconds); void main(void) { return; } void init_mcu(void) { // initializations (generated by MCC): IRQ Manager, PINs, Oscillator, Peripherals SYSTEM_Initialize(); // set the timer 0 and 2 interrupt service routine // assuming interrupts are not currently enabled TMR0_SetInterruptHandler(irq_timer_slow); // "slow" timer (208us period) TMR2_SetInterruptHandler(irq_timer_fast); // "fast" timer (20us period) // safety measure: 10ms delay __delay_ms(10); } void init_comm(void) { // initialize the communication parser communication_parser_reset(); } void init_adcreader(void) { adcreader_reset(); adcreader_start(); } void start_irqs(void){ // activate interrupts INTERRUPT_GlobalInterruptEnable(); INTERRUPT_PeripheralInterruptEnable(); // clean the serial port input buffer while(serialport_dataready) serialport_read; // start timer0 TMR0_StartTimer(); // start timer2 TMR2_StartTimer(); // at this point: // - The TMR0 interrupt is constantly firing // - The serial port receive buffer is clean } void sensors_acquire_offsets(void) { // ADC reader must have already started. // We only need to read acquired values and wait properly. // Note that the ADC is 10 bit, but data are left aligned to 16 bit, we thus // have an headroom of 6 bits = 32 counts. // Note also that stored offset values are initialized to zero. userpin_SWITCH_LED_D10_set_high(); userpin_SWITCH_LED_D9_set_high(); _delay_seconds(5); // wait 5 seconds to make signals steady userpin_SWITCH_LED_D9_set_low(); for(uint8_t k = 0; k < 32; k++) { __delay_ms(30); // 2.2 * 30 millis are (much) more than sufficient for ADC reader to acquire from all ADC channels for(uint8_t varidx = 0; varidx < ANALOG_VARIABLES_COUNT; varidx++) { analog_variables[varidx].offset += analog_variables[varidx].value/32; } } userpin_SWITCH_LED_D10_set_low(); } void alarms_enable(void) { // not necessary since the alarms are already enabled by // initializing the variables analog_variables and digital_variables // (see variables.h in generated/sources) } void manage_incoming_data(void) { // check if a new byte is present in serial port receive buffer if(serialport_dataready) { // a byte is present, read it and parse it communication_parser_appendbyte(serialport_read()); } // check if a complete command was received if(communication_parser_commandready()) { // a new complete command was received // execute the received command and verify result err_t retval = communication_parser_executecommand(); if(NOERR == retval){ // command correctly executed // reset second counter since last received command // (this function is called after the command was executed to be able to read its value) timing_reset_seconds_since_last_command(); // send the response to the host // (it was created by the [...]_executecommand function) communication_transmitter_sendresponse(); }else{ // do nothing error_notify(retval); } // reset the parser communication_parser_reset(); } } void _delay_seconds(uint8_t _seconds) { while(_seconds--) { __delay_ms(447); // value trimmed, takes into account the time used under irq } }