diff --git a/firmware/src/logic-controller/bsp/mcu/mcu_hal.cpp b/firmware/src/logic-controller/bsp/mcu/mcu_hal.cpp new file mode 100644 index 0000000..12ab833 --- /dev/null +++ b/firmware/src/logic-controller/bsp/mcu/mcu_hal.cpp @@ -0,0 +1,435 @@ +/**** Includes ****/ +#include +#include +#include "mcu_hal.h" + +using namespace mcu; + +/**** Private definitions ****/ +/**** Private constants ****/ +/**** Private variables ****/ +/**** Private function declarations ****/ +static uint8_t gpio_read_level(uint8_t pin_reg, uint8_t mask); + +/**** Public function definitions ****/ +void mcu::startup(startupCfg_t* hwCfg) +{ + // Fail-safe GPIO init + PORTB = 0x00; // Reset PORTB pull-ups + DDRB = 0x00; // Set all as inputs + + PORTC = 0x40; // Reset PORTC pull-ups, except reset + DDRC = 0x00; // Set all as inputs + + PORTD = 0x00; // Reset PORTD pull-ups + DDRD = 0x00; // Set all as inputs + + PORTE = 0x00; // Reset PORTE pull-ups + DDRE = 0x00; // Set all as inputs + + // Pull-x set all HiZ + PORTB &= ~0xFF; // Reset pull-ups + DDRB &= ~0xFF; // Set all as inputs + + // Inputs set all as HiZ inputs + PORTC &= ~0x3F; // Reset pull-ups + DDRC &= ~0x3F; // Set all as inputs + + PORTE &= ~0x0C; // Reset pull-ups + DDRE &= ~0x0C; // Set all as inputs + + // Outputs set all low + PORTD &= ~0xFF; // Reset all low + DDRD |= 0xFF; // Set all as outputs + + // Ignition input + PORTE |= 0x01; // Set pull-up + DDRE &= ~0x01; // Set all as input + + // 5V switched control + PORTE &= ~0x02; // Set low + DDRE |= 0x02; // Set all as output + + //ADC configuration + PRR0 &= ~0x01; //Enable ADC power + DIDR0 &= ~0x00; //Enable digital inputs + + ADMUX = 0x40; //Set AVCC reference, Right adjust + ADCSRA = 0x00; //ADC Disabled, Single conversion, no IT + ADCSRA |= (uint8_t)hwCfg->adc_clk; + ADCSRB = 0x00; //no trigger input + + ADCSRA |= 0x80; //Enable ADC +} + +// ADC Interface functions +uint16_t mcu::adc_read(uint8_t ch) +{ + //check if ADC is enabled + if(!(ADCSRA&0x80)) return 0xFFFF; + + //Safe guard mux + if(ch > 15) return 0xFFFF; + // Not available channels + if((ch > 8) && (ch<14)) return 0xFFFF; + + ADMUX &= ~0x0F; + ADMUX |= ch; + ADCSRA |= 0x40; + while(ADCSRA&0x40); //wait to finish + return ADC; +} + +// GPIO functions +uint8_t mcu::gpio_read(uint8_t ch) +{ + switch(ch) + { + case PIN_PB0: + return gpio_read_level(PINB,0x01); + + case PIN_PB1: + return gpio_read_level(PINB,0x02); + + case PIN_PB2: + return gpio_read_level(PINB,0x04); + + case PIN_PB3: + return gpio_read_level(PINB,0x08); + + case PIN_PB4: + return gpio_read_level(PINB,0x10); + + case PIN_PB5: + return gpio_read_level(PINB,0x20); + + case PIN_PB6: + return gpio_read_level(PINB,0x40); + + case PIN_PB7: + return gpio_read_level(PINB,0x80); + + case PIN_PC0: + return gpio_read_level(PINC,0x01); + + case PIN_PC1: + return gpio_read_level(PINC,0x02); + + case PIN_PC2: + return gpio_read_level(PINC,0x04); + + case PIN_PC3: + return gpio_read_level(PINC,0x08); + + case PIN_PC4: + return gpio_read_level(PINC,0x10); + + case PIN_PC5: + return gpio_read_level(PINC,0x20); + + case PIN_PD0: + return gpio_read_level(PIND,0x01); + + case PIN_PD1: + return gpio_read_level(PIND,0x02); + + case PIN_PD2: + return gpio_read_level(PIND,0x04); + + case PIN_PD3: + return gpio_read_level(PIND,0x08); + + case PIN_PD4: + return gpio_read_level(PIND,0x10); + + case PIN_PD5: + return gpio_read_level(PIND,0x20); + + case PIN_PD6: + return gpio_read_level(PIND,0x40); + + case PIN_PD7: + return gpio_read_level(PIND,0x80); + + case PIN_PE0: + return gpio_read_level(PINE,0x01); + + case PIN_PE1: + return gpio_read_level(PINE,0x02); + + case PIN_PE2: + return gpio_read_level(PINE,0x04); + + case PIN_PE3: + return gpio_read_level(PINE,0x08); + + default: + return LEVEL_LOW; + } +} + +void mcu::gpio_write(uint8_t ch, int8_t lvl) +{ + switch(ch) + { + case PIN_PB0: + if(lvl>0){ + PORTB |= 0x01; + DDRB |= 0x01; + } + else if(lvl<0){ + DDRB &= ~0x01; + PORTB &= ~0x01; + } + else{ + PORTB &= ~0x01; + DDRB |= 0x01; + } + return; + + case PIN_PB1: + if(lvl>0){ + PORTB |= 0x02; + DDRB |= 0x02; + } + else if(lvl<0){ + DDRB &= ~0x02; + PORTB &= ~0x02; + } + else{ + PORTB &= ~0x02; + DDRB |= 0x02; + } + return; + + case PIN_PB2: + if(lvl>0){ + PORTB |= 0x04; + DDRB |= 0x04; + } + else if(lvl<0){ + DDRB &= ~0x04; + PORTB &= ~0x04; + } + else{ + PORTB &= ~0x04; + DDRB |= 0x04; + } + return; + + case PIN_PB3: + if(lvl>0){ + PORTB |= 0x08; + DDRB |= 0x08; + } + else if(lvl<0){ + DDRB &= ~0x08; + PORTB &= ~0x08; + } + else{ + PORTB &= ~0x08; + DDRB |= 0x08; + } + return; + + case PIN_PB4: + if(lvl>0){ + PORTB |= 0x10; + DDRB |= 0x10; + } + else if(lvl<0){ + DDRB &= ~0x10; + PORTB &= ~0x10; + } + else{ + PORTB &= ~0x10; + DDRB |= 0x10; + } + return; + + case PIN_PB5: + if(lvl>0){ + PORTB |= 0x20; + DDRB |= 0x20; + } + else if(lvl<0){ + DDRB &= ~0x20; + PORTB &= ~0x20; + } + else{ + PORTB &= ~0x20; + DDRB |= 0x20; + } + return; + + case PIN_PB6: + if(lvl>0){ + PORTB |= 0x40; + DDRB |= 0x40; + } + else if(lvl<0){ + DDRB &= ~0x40; + PORTB &= ~0x40; + } + else{ + PORTB &= ~0x40; + DDRB |= 0x40; + } + return; + + case PIN_PB7: + if(lvl>0){ + PORTB |= 0x80; + DDRB |= 0x80; + } + else if(lvl<0){ + DDRB &= ~0x80; + PORTB &= ~0x80; + } + else{ + PORTB &= ~0x80; + DDRB |= 0x80; + } + return; + + case PIN_PD0: + if(lvl>0){ + PORTD |= 0x01; + DDRD |= 0x01; + } + else{ + PORTD &= ~0x01; + DDRD |= 0x01; + } + return; + + case PIN_PD1: + if(lvl>0){ + PORTD |= 0x02; + DDRD |= 0x02; + } + else{ + PORTD &= ~0x02; + DDRD |= 0x02; + } + return; + + case PIN_PD2: + if(lvl>0){ + PORTD |= 0x04; + DDRD |= 0x04; + } + else{ + PORTD &= ~0x04; + DDRD |= 0x04; + } + return; + + case PIN_PD3: + if(lvl>0){ + PORTD |= 0x08; + DDRD |= 0x08; + } + else{ + PORTD &= ~0x08; + DDRD |= 0x08; + } + return; + + case PIN_PD4: + if(lvl>0){ + PORTD |= 0x10; + DDRD |= 0x10; + } + else{ + PORTD &= ~0x10; + DDRD |= 0x10; + } + return; + + case PIN_PD5: + if(lvl>0){ + PORTD |= 0x20; + DDRD |= 0x20; + } + else{ + PORTD &= ~0x20; + DDRD |= 0x20; + } + return; + + case PIN_PD6: + if(lvl>0){ + PORTD |= 0x40; + DDRD |= 0x40; + } + else{ + PORTD &= ~0x40; + DDRD |= 0x40; + } + return; + + case PIN_PD7: + if(lvl>0){ + PORTD |= 0x80; + DDRD |= 0x80; + } + else{ + PORTD &= ~0x80; + DDRD |= 0x80; + } + return; + + case PIN_PE1: + if(lvl>0){ + PORTE |= 0x02; + DDRE |= 0x02; + } + else{ + PORTE &= ~0x02; + DDRE |= 0x02; + } + return; + + default: + return; + } +} + +uint8_t mcu::eeprom_read8b(uint16_t address) +{ + return eeprom_read_byte((uint8_t*)address); +} + +uint16_t mcu::eeprom_read16b(uint16_t address) +{ + return eeprom_read_word((uint16_t*)address); +} + +uint32_t mcu::eeprom_read32b(uint16_t address) +{ + return eeprom_read_dword((uint32_t*)address); +} + +void mcu::eeprom_write8b(uint16_t address, uint8_t value) +{ + eeprom_write_byte((uint8_t*)address, value); +} + +void mcu::eeprom_write16b(uint16_t address, uint16_t value) +{ + eeprom_write_word((uint16_t*)address, value); +} + +void mcu::eeprom_write32b(uint16_t address, uint32_t value) +{ + eeprom_write_dword((uint32_t*)address, value); +} + +/**** Private function definitions ****/ +static uint8_t gpio_read_level(uint8_t pin_reg, uint8_t mask) +{ + if(pin_reg&mask) return LEVEL_HIGH; + else return LEVEL_LOW; +} + diff --git a/firmware/src/logic-controller/bsp/mcu/mcu_hal.h b/firmware/src/logic-controller/bsp/mcu/mcu_hal.h new file mode 100644 index 0000000..2312413 --- /dev/null +++ b/firmware/src/logic-controller/bsp/mcu/mcu_hal.h @@ -0,0 +1,101 @@ +#ifndef MCU_HAL_H_ +#define MCU_HAL_H_ + +/**** Includes ****/ +#include + +namespace mcu { + +/**** Public definitions ****/ +/* +*/ + +const uint8_t PIN_PB0 = 1; // Pull-x 2 +const uint8_t PIN_PB1 = 2; // Pull-x 7 +const uint8_t PIN_PB2 = 3; // Pull-x 3 +const uint8_t PIN_PB3 = 4; // Pull-x 8 +const uint8_t PIN_PB4 = 5; // Pull-x 4 +const uint8_t PIN_PB5 = 6; // Pull-x 5 +const uint8_t PIN_PB6 = 7; // Pull-x 1 +const uint8_t PIN_PB7 = 8; // Pull-x 6 + +const uint8_t PIN_PC0 = 9; // Input 2 +const uint8_t PIN_PC1 = 10; // Input 7 +const uint8_t PIN_PC2 = 11; // Input 3 +const uint8_t PIN_PC3 = 12; // Input 8 +const uint8_t PIN_PC4 = 13; // Input 4 +const uint8_t PIN_PC5 = 14; // Input 5 + +const uint8_t PIN_PD0 = 15; // Output 5 +const uint8_t PIN_PD1 = 16; // Output 4 +const uint8_t PIN_PD2 = 17; // Output 6 +const uint8_t PIN_PD3 = 18; // Output 1 +const uint8_t PIN_PD4 = 19; // Output 7 +const uint8_t PIN_PD5 = 20; // Output 2 +const uint8_t PIN_PD6 = 21; // Output 8 +const uint8_t PIN_PD7 = 22; // Output 3 + +const uint8_t PIN_PE0 = 23; // Ignition input +const uint8_t PIN_PE1 = 24; // 5V control +const uint8_t PIN_PE2 = 25; // Input 1 +const uint8_t PIN_PE3 = 26; // Input 6 + +const uint8_t LEVEL_LOW = 0; +const uint8_t LEVEL_HIGH = 1; +const int8_t LEVEL_HIZ = -1; + +const uint8_t ADC0 = 0; // Input 1 +const uint8_t ADC1 = 1; // Input 2 +const uint8_t ADC2 = 2; // Input 3 +const uint8_t ADC3 = 3; // Input 4 +const uint8_t ADC4 = 4; // Input 5 +const uint8_t ADC5 = 5; // Input 6 +const uint8_t ADC6 = 6; // Input 7 +const uint8_t ADC7 = 7; // Input 8 +const uint8_t ADC8 = 8; // MCU temperature +const uint8_t ADC14 = 14; // MCU internal reference +const uint8_t ADC15 = 15; // MCU ground + +//ADC definitions +typedef enum { + ADC_DIV2 = 0x01, + ADC_DIV4 = 0x02, + ADC_DIV8 = 0x03, + ADC_DIV16 = 0x04, + ADC_DIV32 = 0x05, + ADC_DIV64 = 0x06, + ADC_DIV128 = 0x07 +} adcClkDiv_t; + +//Timer definitions +typedef enum { + TIM_DIV1 = 0x01, + TIM_DIV8 = 0x02, + TIM_DIV64 = 0x03, + TIM_DIV256 = 0x04, + TIM_DIV1024 = 0x05 +} timerClkDiv_t; + +typedef struct { + adcClkDiv_t adc_clk; +} startupCfg_t; + +/**** Public function declarations ****/ +void startup(startupCfg_t* hwCfg); + +uint8_t gpio_read(uint8_t ch); +void gpio_write(uint8_t ch, int8_t lvl); + +uint16_t adc_read(uint8_t ch); + +uint8_t eeprom_read8b(uint16_t address); +uint16_t eeprom_read16b(uint16_t address); +uint32_t eeprom_read32b(uint16_t address); + +void eeprom_write8b(uint16_t address, uint8_t value); +void eeprom_write16b(uint16_t address, uint16_t value); +void eeprom_write32b(uint16_t address, uint32_t value); + +} //namespace + +#endif /* MCU_HAL_H_ */