Skip to content
Snippets Groups Projects
main.c 4.03 KiB
/*
 * 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
    }
}