-
Carlo Alessandro Nicolau authoredCarlo Alessandro Nicolau authored
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
}
}