Repo unification

This commit is contained in:
2024-03-12 21:22:26 +02:00
parent 7aa7edba33
commit 02cb3a9c70
152 changed files with 14575 additions and 2038 deletions

View File

@@ -0,0 +1,77 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "ain.h"
/**** Private definitions ****/
typedef struct {
uint8_t adc_ch;
uint8_t mul;
uint8_t div;
int16_t offset;
} ainchcfg_t;
/**** Private constants ****/
static const uint8_t MV_MUL = BSP_AIN_DEF_MV_MUL;
static const uint8_t MV_DIV = BSP_AIN_DEF_MV_DIV;
static const int16_t MV_OFFSET = BSP_AIN_DEF_MV_OFFSET;
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t ain_mapping(uint8_t ain_ch, ainchcfg_t* ain_ch_cfg);
/**** Public function definitions ****/
uint16_t bsp_ain_read(uint8_t ch)
{
ainchcfg_t cfg;
// Get analog input config, and check validity
if(ain_mapping(ch, &cfg)) return 0;
//Read ADC
uint16_t raw = mcu_adc_read(cfg.adc_ch);
//Convert to mV
raw = util_convert_muldivoff(raw, cfg.mul, cfg.div, cfg.offset);
// Return result
return raw;
}
/**** Private function definitions ****/
static uint8_t ain_mapping(uint8_t ain_ch, ainchcfg_t* ain_ch_cfg)
{
// Default 10bit ADC with 5V reference to mV conversion
ain_ch_cfg->mul = MV_MUL;
ain_ch_cfg->div = MV_DIV;
ain_ch_cfg->offset = MV_OFFSET;
switch(ain_ch)
{
case BSP_AIN1: // Mode
ain_ch_cfg->adc_ch = MCU_ADC5;
return 0;
case BSP_AIN2: // Pot
ain_ch_cfg->adc_ch = MCU_ADC4;
return 0;;
case BSP_AIN3: // MCU Temp
ain_ch_cfg->adc_ch = MCU_ADC8;
return 0;
case BSP_AIN4: // MCU Internal reference
ain_ch_cfg->adc_ch = MCU_ADC14;
return 0;
case BSP_AIN5: // MCU Ground
ain_ch_cfg->adc_ch = MCU_ADC15;
return 0;
default: // Invalid channel
ain_ch_cfg->adc_ch = MCU_ADC15;
return 1;
}
return 1;
}

View File

@@ -0,0 +1,26 @@
#ifndef AIN_H_
#define AIN_H_
/*
AIN1 MODE
AIN2 POT
*/
/**** Includes ****/
#include <stdint.h>
#include "config.h"
/**** Public definitions ****/
#define BSP_AIN1 1 // Mode
#define BSP_AIN2 2 // Pot
#define BSP_AIN3 3 // MCU Temp
#define BSP_AIN4 4 // MCU Internal reference
#define BSP_AIN5 5 // MCU Ground
/**** Public function declarations ****/
uint16_t bsp_ain_read(uint8_t ch);
#ifdef TESTING
#endif
#endif /* AIN_H_ */

View File

@@ -0,0 +1,32 @@
#ifndef BSP_CONFIG_H_
#define BSP_CONFIG_H_
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
#define BSP_AIN_DEF_MV_MUL 215
#define BSP_AIN_DEF_MV_DIV 44
#define BSP_AIN_DEF_MV_OFFSET 0
#define BSP_HB_MV_MUL BSP_AIN_DEF_MV_MUL
#define BSP_HB_MV_DIV BSP_AIN_DEF_MV_DIV
#define BSP_HB_MV_OFFSET BSP_AIN_DEF_MV_OFFSET
#define BSP_HB_UDIV_MUL 20
#define BSP_HB_UDIV_DIV 1
#define BSP_HB_UDIV_OFFSET 0
#define BSP_HB_ISUP_MUL 235
#define BSP_HB_ISUP_DIV 6
#define BSP_HB_ISUP_OFFSET 0
#define BSP_HB_IOUT_MUL 215
#define BSP_HB_IOUT_DIV 22
#define BSP_HB_IOUT_OFFSET 0
/**** Public function declarations ****/
#ifdef TESTING
#endif
#endif /* BSP_CONFIG_H_ */

View File

@@ -0,0 +1,83 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "din.h"
/**** Private definitions ****/
typedef struct {
uint8_t gpio_ch;
uint8_t invert;
} dinchcfg_t;
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t din_mapping(uint8_t din_ch, dinchcfg_t* din_ch_cfg);
/**** Public function definitions ****/
uint8_t bsp_din_read(uint8_t ch)
{
dinchcfg_t cfg;
// Get digital input config, and check validity
if(din_mapping(ch, &cfg)) return BSP_DIN_LOW;
//Read GPIO
uint8_t raw = mcu_gpio_read(cfg.gpio_ch);
// Check config and invert
if(cfg.invert) raw = util_invert_8b(raw);
// Return result
return raw;
}
/**** Private function definitions ***/
static uint8_t din_mapping(uint8_t din_ch, dinchcfg_t* din_ch_cfg)
{
// By default ch is not inverted
din_ch_cfg->invert = 0;
switch(din_ch)
{
case BSP_DIN1: //Mode
din_ch_cfg->gpio_ch = MCU_GPIO0;
return 0;
case BSP_DIN2: //Pot
din_ch_cfg->gpio_ch = MCU_GPIO1;
return 0;
case BSP_DIN3: //Down
din_ch_cfg->gpio_ch = MCU_GPIO2;
return 0;
case BSP_DIN4: //Up
din_ch_cfg->gpio_ch = MCU_GPIO3;
return 0;
case BSP_DIN5: //Dimm
din_ch_cfg->gpio_ch = MCU_GPIO4;
din_ch_cfg->invert = 1;
return 0;
case BSP_DIN6: //Brakes
din_ch_cfg->gpio_ch = MCU_GPIO5;
din_ch_cfg->invert = 1;
return 0;
case BSP_DIN7: //Handbrake
din_ch_cfg->gpio_ch = MCU_GPIO6;
din_ch_cfg->invert = 1;
return 0;
case BSP_DIN7N: //Handbrake pull
din_ch_cfg->gpio_ch = MCU_GPIO7;
return 0;
default: //Invalid channel
din_ch_cfg->gpio_ch = 0;
return 1;
}
return 1;
}

View File

@@ -0,0 +1,37 @@
#ifndef DIN_H_
#define DIN_H_
/*
DIN1 MODE
DIN2 POT
DIN3 DOWN
DIN4 UP
DIN5 HV DIM
DIN6 HV BRAKES
DIN7 HV HANDBRAKE
DIN8 HBRAKE PULL
*/
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
#define BSP_DIN1 1
#define BSP_DIN2 2
#define BSP_DIN3 3
#define BSP_DIN4 4
#define BSP_DIN5 5
#define BSP_DIN6 6
#define BSP_DIN7 7
#define BSP_DIN7N 8
#define BSP_DIN_LOW 0
#define BSP_DIN_HIGH 1
/**** Public function declarations ****/
uint8_t bsp_din_read(uint8_t ch);
#ifdef TESTING
#endif
#endif /* DIN_H_ */

View File

@@ -0,0 +1,58 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "dout.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t dout_mapping(uint8_t dout_ch, uint8_t* gpio_ch);
/**** Public function definitions ****/
void bsp_dout_write(uint8_t ch, int8_t lvl)
{
uint8_t gpio_ch;
// Get digital input config, and check validity
if(dout_mapping(ch, &gpio_ch)) return;
// Write GPIO
mcu_gpio_write(gpio_ch, lvl);
}
/**** Private function definitions ***/
static uint8_t dout_mapping(uint8_t dout_ch, uint8_t* gpio_ch)
{
switch(dout_ch)
{
case BSP_DOUT1: //Mode
*gpio_ch = MCU_GPIO0;
return 0;
case BSP_DOUT2: //Pot
*gpio_ch = MCU_GPIO1;
return 0;
case BSP_DOUT3: //Down
*gpio_ch = MCU_GPIO2;
return 0;
case BSP_DOUT4: //Up
*gpio_ch = MCU_GPIO3;
return 0;
case BSP_DOUT5: //Handbrake pull
*gpio_ch = MCU_GPIO7;
return 0;
case BSP_DOUT6: //Speed pull
*gpio_ch = MCU_GPIO8;
return 0;
default: //Invalid channel
*gpio_ch = 0;
return 1;
}
return 1;
}

View File

@@ -0,0 +1,34 @@
#ifndef DOUT_H_
#define DOUT_H_
/*
DOUT1 MODE
DOUT2 POT
DOUT3 DOWN
DOUT4 UP
DOUT5 HBRAKE PULL
DOUT6 SPEED PULL
*/
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
#define BSP_DOUT1 1
#define BSP_DOUT2 2
#define BSP_DOUT3 3
#define BSP_DOUT4 4
#define BSP_DOUT5 5
#define BSP_DOUT6 6
#define BSP_DOUT_LOW 0
#define BSP_DOUT_HIGH 1
#define BSP_DOUT_HIZ -1
/**** Public function declarations ****/
void bsp_dout_write(uint8_t ch, int8_t lvl);
#ifdef TESTING
#endif
#endif /* DOUT_H_ */

View File

@@ -0,0 +1,179 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "halfbridge.h"
/**** Private definitions ****/
typedef struct {
uint8_t adc_ch;
uint8_t mul;
uint8_t div;
int16_t offset;
} ainchcfg_t;
typedef enum {
AIN_OUT_VOLTAGE,
AIN_OUT_CURRENT,
AIN_SUP_VOLTAGE,
AIN_SUP_CURRENT
} hb_ainch_t;
/**** Private constants ****/
// Analog channels conversion coefficients
static const uint8_t MV_MUL = BSP_HB_MV_MUL;
static const uint8_t MV_DIV = BSP_HB_MV_DIV;
static const int16_t MV_OFFSET = BSP_HB_MV_OFFSET;
static const uint8_t UDIV_MUL = BSP_HB_UDIV_MUL;
static const uint8_t UDIV_DIV = BSP_HB_UDIV_DIV;
static const int16_t UDIV_OFFSET = BSP_HB_UDIV_OFFSET;
static const uint8_t ISUP_MUL = BSP_HB_ISUP_MUL;
static const uint8_t ISUP_DIV = BSP_HB_ISUP_DIV;
static const int16_t ISUP_OFFSET = BSP_HB_ISUP_OFFSET;
static const uint8_t IOUT_MUL = BSP_HB_IOUT_MUL;
static const uint8_t IOUT_DIV = BSP_HB_IOUT_DIV;
static const int16_t IOUT_OFFSET = BSP_HB_IOUT_OFFSET;
/**** Private variables ****/
/**** Mapping function declarations ****/
static uint8_t hb_pwm_mapping(uint8_t* pwm_ch);
static uint8_t hb_low_side_mapping(uint8_t* gpio_ch);
static uint8_t hb_ain_mapping(hb_ainch_t ain_ch, ainchcfg_t* ain_ch_cfg);
/**** Private function declarations ****/
static uint16_t limit_pwm(uint16_t pwm_in);
static uint16_t read_ain(hb_ainch_t ch);
/**** Public function definitions ****/
void bsp_hb_write_low(uint8_t state)
{
uint8_t gpio_ch;
// Get GPIO channel, and check validity
if(hb_low_side_mapping(&gpio_ch)) return;
// Set low side on or off
if(state) mcu_gpio_write(gpio_ch, MCU_GPIO_HIGH);
else mcu_gpio_write(gpio_ch, MCU_GPIO_LOW);
}
void bsp_hb_write_pwm(uint16_t pwm)
{
uint8_t pwm_ch;
// Get PWM channel, and check validity
if(hb_pwm_mapping(&pwm_ch)) return;
// Limit PWM, because of charge pump
pwm = limit_pwm(pwm);
// Set pwm
mcu_pwm_write(pwm_ch, pwm);
}
void bsp_hb_read_meas(hb_meas_t* measurements)
{
// Read analog inputs
measurements->out_voltage = read_ain(AIN_OUT_VOLTAGE);
measurements->out_current = read_ain(AIN_OUT_CURRENT);
measurements->sup_voltage = read_ain(AIN_SUP_VOLTAGE);
measurements->sup_current = read_ain(AIN_SUP_CURRENT);
// Calculate secondary measurements
measurements->out_power = util_sat_mul_kilo(measurements->out_voltage, measurements->out_current);
measurements->sup_power = util_sat_mul_kilo(measurements->sup_voltage, measurements->sup_current);
measurements->out_impedance = util_sat_div_kilo(measurements->out_voltage, measurements->out_current);
uint8_t ch;
//Read low side control GPIO level
if(hb_low_side_mapping(&ch)) measurements->low_side_ctrl = 0;
else measurements->low_side_ctrl = mcu_gpio_read(ch);
//Read PWM duty cycle in 16b format
if(hb_pwm_mapping(&ch)) measurements->pwm = 0;
else measurements->pwm = mcu_pwm_read(ch);
}
/**** Private function declarations ****/
static uint16_t read_ain(hb_ainch_t ch)
{
ainchcfg_t cfg;
// Get analog input config, and check validity
if(hb_ain_mapping(ch, &cfg)) return 0;
//Read ADC
uint16_t raw = mcu_adc_read(cfg.adc_ch);
//Convert to target units
raw = util_convert_muldivoff(raw, cfg.mul, cfg.div, cfg.offset);
// Return result
return raw;
}
static uint16_t limit_pwm(uint16_t pwm_in)
{
// Limit to ~95%
if (pwm_in > 0xFC00) return 0xFC00;
else return pwm_in;
}
/**** Mapping function definitions ****/
static uint8_t hb_pwm_mapping(uint8_t* pwm_ch)
{
*pwm_ch = MCU_PWM0;
return 0;
}
static uint8_t hb_low_side_mapping(uint8_t* gpio_ch)
{
*gpio_ch = MCU_GPIO15;
return 0;
}
static uint8_t hb_ain_mapping(hb_ainch_t ain_ch, ainchcfg_t* ain_ch_cfg)
{
switch(ain_ch)
{
case AIN_OUT_VOLTAGE:
ain_ch_cfg->adc_ch = MCU_ADC1;
ain_ch_cfg->mul = UDIV_MUL;
ain_ch_cfg->div = UDIV_DIV;
ain_ch_cfg->offset = UDIV_OFFSET;
return 0;
case AIN_OUT_CURRENT:
ain_ch_cfg->adc_ch = MCU_ADC0;
ain_ch_cfg->mul = IOUT_MUL;
ain_ch_cfg->div = IOUT_DIV;
ain_ch_cfg->offset = IOUT_OFFSET;
return 0;
case AIN_SUP_VOLTAGE:
ain_ch_cfg->adc_ch = MCU_ADC2;
ain_ch_cfg->mul = UDIV_MUL;
ain_ch_cfg->div = UDIV_DIV;
ain_ch_cfg->offset = UDIV_OFFSET;
return 0;
case AIN_SUP_CURRENT:
ain_ch_cfg->adc_ch = MCU_ADC3;
ain_ch_cfg->mul = ISUP_MUL;
ain_ch_cfg->div = ISUP_DIV;
ain_ch_cfg->offset = ISUP_OFFSET;
return 0;
default: //Invalid channel
ain_ch_cfg->adc_ch = MCU_ADC15;
// Default 10bit ADC with 5V reference to mV conversion
ain_ch_cfg->mul = MV_MUL;
ain_ch_cfg->div = MV_DIV;
ain_ch_cfg->offset = MV_OFFSET;
return 1;
}
return 1;
}

View File

@@ -0,0 +1,34 @@
#ifndef HALFBRIDGE_H_
#define HALFBRIDGE_H_
/*
*/
/**** Includes ****/
#include <stdint.h>
#include "config.h"
/**** Public definitions ****/
typedef struct {
uint16_t out_voltage;
uint16_t out_current;
uint16_t sup_voltage;
uint16_t sup_current;
uint16_t out_power;
uint16_t sup_power;
uint16_t out_impedance;
uint8_t low_side_ctrl;
uint16_t pwm;
} hb_meas_t;
/**** Public function declarations ****/
void bsp_hb_write_low(uint8_t state);
void bsp_hb_write_pwm(uint16_t pwm);
// Feedback functions
void bsp_hb_read_meas(hb_meas_t* measurements);
#ifdef TESTING
#endif
#endif /* HALFBRIDGE_H_ */

View File

@@ -0,0 +1,120 @@
#ifndef MCU_HAL_H_
#define MCU_HAL_H_
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
/*
GPIO0 Down
GPIO1 Up
GPIO2 Mode
GPIO3 Handbrake
GPIO4 Brakes
GPIO5 Dimm
GPIO6 LED0
GPIO7 LED1
GPIO8 LED2
GPIO9 LED3
GPIO10 LED4
GPIO11 LED5
GPIO12 DCCD Enable
GPIO13 Handbrake pull
GPIO14 Speed pull
GPIO15 DCCD PWM
GPIO16 LED PWM
ADC0 Output current
ADC1 Output voltage
ADC2 Battery current
ADC3 Battery voltage
ADC4 Potentiometer
ADC5 Mode
ADC8 MCU temperature
ADC14 MCU internal reference
ADC15 MCU ground
*/
#define MCU_GPIO0 0 //Mode
#define MCU_GPIO1 1 //Pot
#define MCU_GPIO2 2 //Down
#define MCU_GPIO3 3 //Up
#define MCU_GPIO4 4 //Dimm
#define MCU_GPIO5 5 //Brakes
#define MCU_GPIO6 6 //Handbrake
#define MCU_GPIO7 7 //Handbrake pull
#define MCU_GPIO8 8 //Speed pull
#define MCU_GPIO9 9 //LED0
#define MCU_GPIO10 10 //LED1
#define MCU_GPIO11 11 //LED2
#define MCU_GPIO12 12 //LED3
#define MCU_GPIO13 13 //LED4
#define MCU_GPIO14 14 //LED5
#define MCU_GPIO15 15 //DCCD Enable
#define MCU_GPIO16 16 //DCCD PWM
#define MCU_GPIO17 17 //LED PWM
#define MCU_GPIO_LOW 0
#define MCU_GPIO_HIGH 1
#define MCU_GPIO_HIZ -1
#define MCU_ADC0 0 //Output current
#define MCU_ADC1 1 //Output voltage
#define MCU_ADC2 2 //Battery voltage
#define MCU_ADC3 3 //Battery current
#define MCU_ADC4 4 //Potentiometer
#define MCU_ADC5 5 //Mode
#define MCU_ADC8 8 //MCU temperature
#define MCU_ADC14 14 //MCU internal reference
#define MCU_ADC15 15 //MCU ground
#define MCU_PWM0 0 //DCCD
#define MCU_PWM1 1 //LED
//ADC definitions
typedef enum {
MCU_ADC_DIV2 = 0x01,
MCU_ADC_DIV4 = 0x02,
MCU_ADC_DIV8 = 0x03,
MCU_ADC_DIV16 = 0x04,
MCU_ADC_DIV32 = 0x05,
MCU_ADC_DIV64 = 0x06,
MCU_ADC_DIV128 = 0x07
} adcClkDiv_t;
//Timer definitions
typedef enum {
MCU_TIM_DIV1 = 0x01,
MCU_TIM_DIV8 = 0x02,
MCU_TIM_DIV64 = 0x03,
MCU_TIM_DIV256 = 0x04,
MCU_TIM_DIV1024 = 0x05
} timerClkDiv_t;
typedef struct {
adcClkDiv_t adc_clk;
timerClkDiv_t pwm_clk;
uint16_t pwm_top;
uint8_t pwm_chb_en;
} startupCfg_t;
/**** Public function declarations ****/
void mcu_startup(startupCfg_t* hwCfg);
uint8_t mcu_gpio_read(uint8_t ch);
void mcu_gpio_write(uint8_t ch, int8_t lvl);
uint16_t mcu_adc_read(uint8_t ch);
void mcu_pwm_write(uint8_t ch, uint16_t dc);
uint16_t mcu_pwm_read(uint8_t ch);
uint8_t mcu_ee_read8b(uint16_t address);
uint16_t mcu_ee_read16b(uint16_t address);
uint32_t mcu_ee_read32b(uint16_t address);
void mcu_ee_write8b(uint16_t address, uint8_t value);
void mcu_ee_write16b(uint16_t address, uint16_t value);
void mcu_ee_write32b(uint16_t address, uint32_t value);
#endif /* MCU_HAL_H_ */

View File

@@ -0,0 +1,418 @@
/**** Includes ****/
#include <avr/io.h>
#include <avr/eeprom.h>
#include "mcu_hal.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t gpio_read(uint8_t pin_reg, uint8_t mask);
static void pwm_write_ocx(uint8_t ch, uint16_t value);
static uint16_t pwm_read_ocx(uint8_t ch);
/**** Public function definitions ****/
void mcu_startup(startupCfg_t* hwCfg)
{
// Fail-safe GPIO init
PORTB = 0xF8; // Set PORTB pull-ups
DDRB = 0x00; // Set all as inputs
PORTC = 0x40; // Set PORTC pull-ups
DDRC = 0x00; // Set all as inputs
PORTD = 0x80; // Set PORTD pull-ups
DDRD = 0x00; // Set all as inputs
PORTE = 0x0A; // Set PORTE pull-ups
DDRE = 0x00; // Set all as inputs
// Half-bridge related pins
PORTB &= ~0x03; //Set low
DDRB |= 0x03; //Set as output
// Common OD PWM pin
if(hwCfg->pwm_chb_en) PORTB &= ~0x04; //Set low
else PORTB |= 0x04; //Set high
DDRB |= 0x04; //Set as output
// OD control pins
PORTD &= ~0x3F; //Set low (off)
DDRD |= 0x3F; //Set as outputs
// Handbrake pull-up pin
PORTB |= 0x20; //Set high
DDRB |= 0x20; //Set as output
// Handbrake and brakes pins
PORTB |= 0xC0; //Set pull-up on
DDRB &= ~0xC0; //Set as inputs
// Dimm
PORTD |= 0x80; //Set pull-up on
DDRD &= ~0x80; //Set as input
// Up and Down
PORTE |= 0x0A; //Set pull-up on
DDRE &= ~0x0A; //Set as inputs
// Internal ADC inputs
PORTC &= ~0x0F; //Pull-up off
DDRC &= ~0x0F; //Set as inputs
// Potentiometer & Mode
PORTC &= ~0x30; //Pull-up off
DDRC &= ~0x30; //Set as inputs
//ADC configuration
PRR0 &= ~0x01; //Enable ADC power
DIDR0 |= 0x0F; //Disable digital inputs, ADC0-ADC3
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
//DCCD and LED PWM configuration
PRR0 &= ~0x80; //Enable Timer1 power
TCCR1A = 0xC2; //Connect OC1A, inverted mode
if(hwCfg->pwm_chb_en) TCCR1A |= 0x30; //Connect OC1B, inverted mode
TCCR1B = 0x18; //PWM, Phase & Frequency Correct ICR1 top, no clock, WGM:0xE
TCCR1C = 0x00;
TCNT1 = 0x0000;
OCR1A = 0xFFFF;
OCR1B = 0xFFFF;
ICR1 = hwCfg->pwm_top;
TIMSK1 = 0x00; //No interrupts
TIFR1 = 0x00; //Clear all flags
uint8_t tim1_prescaler = (uint8_t)hwCfg->pwm_clk;
TCCR1B |= tim1_prescaler; //Enable timer
}
// 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;
}
// PWM Timer Interface functions
void mcu_pwm_write(uint8_t ch, uint16_t dc)
{
dc = 0xFFFF - dc;
// Calculate value as % of TOP
uint32_t top = (uint32_t)ICR1;
uint32_t temp = (uint32_t)dc * top;
temp = temp/0x0000FFFF;
//Limit temp
if(temp>0x0000FFFF) temp = 0x0000FFFF;
uint16_t ocrx = (uint16_t)temp;
// Write register
pwm_write_ocx(ch, ocrx);
}
uint16_t mcu_pwm_read(uint8_t ch)
{
uint16_t ocrx = pwm_read_ocx(ch);
// Check easy answers
if(ocrx == 0) return 0;
if(ocrx >= ICR1) return 0xFFFF;
// Calculate
uint32_t top = (uint32_t)ICR1;
uint32_t temp = (uint32_t)ocrx * 0xFFFF;
temp = temp/top;
//Limit temp
if(temp>0x0000FFFF) return 0xFFFF;
return (uint16_t)temp;
}
uint8_t mcu_gpio_read(uint8_t ch)
{
switch(ch)
{
case MCU_GPIO0: // Mode DIN1
return gpio_read(PINC,0x20);
case MCU_GPIO1: // Pot DIN2
return gpio_read(PINC,0x10);
case MCU_GPIO2: // Down DIN3
return gpio_read(PINE,0x02);
case MCU_GPIO3: // Up DIN4
return gpio_read(PINE,0x08);
case MCU_GPIO4: // Dimm DIN5
return gpio_read(PIND,0x80);
case MCU_GPIO5: // Brakes DIN6
return gpio_read(PINB,0x80);
case MCU_GPIO6: // Handbrake DIN7
return gpio_read(PINB,0x40);
case MCU_GPIO7: // Handbrake pull DIN8
return gpio_read(PINB,0x20);
case MCU_GPIO8: // Speed-pull
return gpio_read(PIND,0x40);
case MCU_GPIO9: // LED 0
return gpio_read(PIND,0x01);
case MCU_GPIO10: // LED 1
return gpio_read(PIND,0x02);
case MCU_GPIO11: // LED 2
return gpio_read(PIND,0x04);
case MCU_GPIO12: // LED 3
return gpio_read(PIND,0x08);
case MCU_GPIO13: // LED 4
return gpio_read(PIND,0x10);
case MCU_GPIO14: // LED 5
return gpio_read(PIND,0x20);
case MCU_GPIO15: // DCCD Enable
return gpio_read(PINB,0x01);
case MCU_GPIO16: // DCCD PWM
return gpio_read(PINB,0x02);
case MCU_GPIO17: // LED PWM
return gpio_read(PINB,0x04);
default:
return 0;
}
}
void mcu_gpio_write(uint8_t ch, int8_t lvl)
{
switch(ch)
{
case MCU_GPIO0: // Mode DIN1
if(lvl>0)
{
PORTC |= 0x20;
DDRC |= 0x20;
}
else if(lvl<0)
{
DDRC &= ~0x20;
PORTC &= ~0x20;
}
else
{
PORTC &= ~0x20;
DDRC |= 0x20;
}
return;
case MCU_GPIO1: // Pot DIN2
if(lvl>0)
{
PORTC |= 0x10;
DDRC |= 0x10;
}
else if(lvl<0)
{
DDRC &= ~0x10;
PORTC &= ~0x10;
}
else
{
PORTC &= ~0x10;
DDRC |= 0x10;
}
return;
case MCU_GPIO2: // Down DIN3
if(lvl>0)
{
PORTE |= 0x02;
DDRE |= 0x02;
}
else if(lvl<0)
{
DDRE &= ~0x02;
PORTE &= ~0x02;
}
else
{
PORTE &= ~0x02;
DDRE |= 0x02;
}
return;
case MCU_GPIO3: // Up DIN4
if(lvl>0)
{
PORTE |= 0x08;
DDRE |= 0x08;
}
else if(lvl<0)
{
DDRE &= ~0x08;
PORTE &= ~0x08;
}
else
{
PORTE &= ~0x08;
DDRE |= 0x08;
}
return;
case MCU_GPIO7: // Handbrake pull DIN
if(lvl>0)
{
PORTB |= 0x20;
DDRB |= 0x20;
}
else if(lvl<0)
{
DDRB &= ~0x20;
PORTB &= ~0x20;
}
else
{
PORTB &= ~0x20;
DDRB |= 0x20;
}
return;
case MCU_GPIO8: // Speed-pull
if(lvl>0) PORTD |= 0x40;
else PORTD &= ~0x40;
return;
case MCU_GPIO9: // LED 0
if(lvl>0) PORTD |= 0x01;
else PORTD &= ~0x01;
return;
case MCU_GPIO10: // LED 1
if(lvl>0) PORTD |= 0x02;
else PORTD &= ~0x02;
return;
case MCU_GPIO11: // LED 2
if(lvl>0) PORTD |= 0x04;
else PORTD &= ~0x04;
return;
case MCU_GPIO12: // LED 3
if(lvl>0) PORTD |= 0x08;
else PORTD &= ~0x08;
return;
case MCU_GPIO13: // LED 4
if(lvl>0) PORTD |= 0x10;
else PORTD &= ~0x10;
return;
case MCU_GPIO14: // LED 5
if(lvl>0) PORTD |= 0x20;
else PORTD &= ~0x20;
return;
case MCU_GPIO15: // DCCD Enable
if(lvl>0) PORTB |= 0x01;
else PORTB &= ~0x01;
return;
default:
return;
}
}
uint8_t mcu_ee_read8b(uint16_t address)
{
return eeprom_read_byte((uint8_t*)address);
}
uint16_t mcu_ee_read16b(uint16_t address)
{
return eeprom_read_word((uint16_t*)address);
}
uint32_t mcu_ee_read32b(uint16_t address)
{
return eeprom_read_dword((uint32_t*)address);
}
void mcu_ee_write8b(uint16_t address, uint8_t value)
{
eeprom_write_byte((uint8_t*)address, value);
}
void mcu_ee_write16b(uint16_t address, uint16_t value)
{
eeprom_write_word((uint16_t*)address, value);
}
void mcu_ee_write32b(uint16_t address, uint32_t value)
{
eeprom_write_dword((uint32_t*)address, value);
}
/**** Private function definitions ****/
static uint8_t gpio_read(uint8_t pin_reg, uint8_t mask)
{
if(pin_reg&mask) return MCU_GPIO_HIGH;
else return MCU_GPIO_LOW;
}
static void pwm_write_ocx(uint8_t ch, uint16_t value)
{
switch(ch)
{
case MCU_PWM0:
OCR1A = value;
return;
case MCU_PWM1:
OCR1B = value;
return;
default:
return;
}
}
static uint16_t pwm_read_ocx(uint8_t ch)
{
switch(ch)
{
case MCU_PWM0:
return OCR1A;
case MCU_PWM1:
return OCR1B ;
default:
return 0x0000;
}
}

View File

@@ -0,0 +1,80 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "odout.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
static uint8_t odout_pwm_mapping(uint8_t* pwm_ch);
static uint8_t odout_mapping(uint8_t od_ch, uint8_t* gpio_ch);
/**** Public function definitions ****/
void bsp_odout_write(uint8_t ch, int8_t lvl)
{
uint8_t gpio_ch;
// Get GPIO channel config, and check validity
if(odout_mapping(ch, &gpio_ch)) return;
// Set output level
if(lvl==0) mcu_gpio_write(gpio_ch, 1); // Output active
else mcu_gpio_write(gpio_ch, 0); // Output off
}
void bsp_odout_write_common(uint8_t percent)
{
uint8_t pwm_ch;
// Get PWM channel config, and check validity
if(odout_pwm_mapping(&pwm_ch)) return;
// Convert percent to 16b duty cycle
uint16_t dc = util_percent_to_16b(percent);
// Set PWM
mcu_pwm_write(pwm_ch, dc);
}
/**** Private function definitions ****/
static uint8_t odout_pwm_mapping(uint8_t* pwm_ch)
{
*pwm_ch = MCU_PWM1;
return 0;
}
static uint8_t odout_mapping(uint8_t od_ch, uint8_t* gpio_ch)
{
switch(od_ch)
{
case BSP_OD1: // LED0
*gpio_ch = MCU_GPIO9;
return 0;
case BSP_OD2: // LED1
*gpio_ch = MCU_GPIO10;
return 0;
case BSP_OD3: // LED2
*gpio_ch = MCU_GPIO11;
return 0;
case BSP_OD4: // LED3
*gpio_ch = MCU_GPIO12;
return 0;
case BSP_OD5: // LED4
*gpio_ch = MCU_GPIO13;
return 0;
case BSP_OD6: // LED5
*gpio_ch = MCU_GPIO14;
return 0;
default: //Invalid channel
*gpio_ch = 0;
return 1;
}
return 1;
}

View File

@@ -0,0 +1,37 @@
#ifndef ODOUT_H_
#define ODOUT_H_
/*
OD1 LED 0
OD2 LED 1
OD3 LED 2
OD4 LED 3
OD5 LED 4
OD6 LED 5
COMMON LED PWM
*/
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
#define BSP_OD1 1
#define BSP_OD2 2
#define BSP_OD3 3
#define BSP_OD4 4
#define BSP_OD5 5
#define BSP_OD6 6
#define BSP_ODOUT_LOW 0
#define BSP_ODOUT_HIGH 1
#define BSP_ODOUT_HIZ -1
/**** Public function declarations ****/
void bsp_odout_write(uint8_t ch, int8_t lvl);
void bsp_odout_write_common(uint8_t percent);
#ifdef TESTING
#endif
#endif /* ODOUT_H_ */

View File

@@ -0,0 +1,23 @@
/**** Includes ****/
#include "utils/utils.h"
#include "mcu/mcu_hal.h"
#include "setup.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
/**** Public function definitions ****/
/**** Private function definitions ****/
void bsp_startup(void)
{
startupCfg_t mcu_cfg;
mcu_cfg.adc_clk = MCU_ADC_DIV2;
mcu_cfg.pwm_clk = MCU_TIM_DIV1;
mcu_cfg.pwm_top = 511;
mcu_cfg.pwm_chb_en = 1;
mcu_startup(&mcu_cfg);
}

View File

@@ -0,0 +1,14 @@
#ifndef BSP_SETUP_H_
#define BSP_SETUP_H_
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
/**** Public function declarations ****/
void bsp_startup(void);
#ifdef TESTING
#endif
#endif /* BSP_SETUP_H_ */

View File

@@ -0,0 +1,67 @@
/**** Includes ****/
#include "faults.h"
#include "utils.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Mapping function declarations ****/
/**** Private function declarations ****/
/**** Public function definitions ****/
#ifdef TESTING
#endif
uint8_t fault_process(fault_t* fault, uint8_t w_trig, uint8_t f_trig, fault_cfg_t* cfg)
{
// Override warning trigger in case of fault trigger
if(f_trig) w_trig = 1;
// Increase warning time, if reoccurring
if((w_trig)&&(fault->severity != FAULT_LVL_OK)) fault->w_time = util_sat_add_16b(fault->w_time, 1);
else fault->w_time = 0;
// Check if waring can be considered fault
if((cfg->wtof > 0)&&(fault->w_time > cfg->wtof)) f_trig = 1;
// Increase fault time, if reoccurring
if((f_trig)&&(fault->severity != FAULT_LVL_OK)) fault->f_time = util_sat_add_16b(fault->f_time, 1);
else fault->f_time = 0;
// Modify fault trigger
if((cfg->delay)&&(fault->f_time < cfg->delay)) f_trig = 0;
// Process fault level
if(f_trig)
{
fault->severity = FAULT_LVL_FAULT;
return 1;
}
else
{
if(w_trig) fault->severity = FAULT_LVL_WARNING;
else fault->severity = FAULT_LVL_OK;
}
return 0;
}
uint8_t fault_is_active(fault_t* fault)
{
if(fault->severity == FAULT_LVL_FAULT) return 1;
else return 0;
}
uint8_t fault_is_warning(fault_t* fault)
{
if(fault->severity != FAULT_LVL_OK) return 1;
else return 0;
}
void fault_reset(fault_t* fault)
{
fault->severity = FAULT_LVL_OK;
fault->w_time = 0;
fault->f_time = 0;
}
/**** Private function definitions ****/

View File

@@ -0,0 +1,37 @@
#ifndef FAULTS_H_
#define FAULTS_H_
/*
*/
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
typedef enum {
FAULT_LVL_OK,
FAULT_LVL_WARNING,
FAULT_LVL_FAULT
} fault_lvl_t;
typedef struct {
fault_lvl_t severity;
uint16_t w_time;
uint16_t f_time;
} fault_t;
typedef struct {
uint16_t delay;
uint16_t wtof;
} fault_cfg_t;
/**** Public function declarations ****/
uint8_t fault_process(fault_t* fault, uint8_t w_trig, uint8_t f_trig, fault_cfg_t* cfg);
uint8_t fault_is_active(fault_t* fault);
uint8_t fault_is_warning(fault_t* fault);
void fault_reset(fault_t* fault);
#ifdef TESTING
#endif
#endif /* FAULTS_H_ */

View File

@@ -0,0 +1,81 @@
/**** Includes ****/
#include "fuses.h"
#include "utils.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Mapping function declarations ****/
/**** Private function declarations ****/
/**** Public function definitions ****/
#ifdef TESTING
#endif
void fuse_reset(fuse_t* fuse)
{
fuse->state = FUSE_OFF;
fuse->timer = 0;
fuse->count = 0;
}
uint8_t fuse_process(fuse_t* fuse, uint8_t fault, fuse_cfg_t* cfg)
{
// Active fault condition
if(fault)
{
// Note fuse time count
if((fuse->state == FUSE_OFF)||(fuse->state == FUSE_RETRY)) fuse->count++;
// Go to fused state in any case
fuse->state = FUSE_ACTIVE;
fuse->timer = 0;
return 1;
};
// No active fault condition
if(fuse->state==FUSE_ACTIVE)
{
// Go to cooldown
fuse->state = FUSE_COOLDOWN;
fuse->timer = cfg->cooldown_time;
};
// Wait for timeout
if(fuse->timer)
{
fuse->timer--;
if(fuse->state == FUSE_RETRY) return 0;
else return 1;
};
// Timeout end, transition logic
switch(fuse->state)
{
case FUSE_COOLDOWN:
// Cooldown end
if(cfg->retry_time)
{
fuse->state = FUSE_RETRY;
fuse->timer = cfg->retry_time;
}
else
{
fuse->state = FUSE_OFF;
fuse->timer = 0;
}
break;
case FUSE_RETRY:
// Go back to normal
fuse->state = FUSE_OFF;
break;
default:
// Nothing to do
break;
}
return 0;
}
/**** Private function definitions ****/

View File

@@ -0,0 +1,36 @@
#ifndef FUSES_H_
#define FUSES_H_
/*
*/
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
typedef enum {
FUSE_OFF,
FUSE_ACTIVE,
FUSE_COOLDOWN,
FUSE_RETRY
} fuse_state_t;
typedef struct {
fuse_state_t state;
uint8_t count;
uint16_t timer;
} fuse_t;
typedef struct {
uint16_t cooldown_time;
uint16_t retry_time;
} fuse_cfg_t;
/**** Public function declarations ****/
void fuse_reset(fuse_t* fuse);
uint8_t fuse_process(fuse_t* fuse, uint8_t fault, fuse_cfg_t* cfg);
#ifdef TESTING
#endif
#endif /* FUSES_H_ */

View File

@@ -0,0 +1,272 @@
/**** Includes ****/
#include "utils.h"
/**** Private definitions ****/
/**** Private constants ****/
/**** Private variables ****/
/**** Private function declarations ****/
#ifndef TESTING
static uint8_t find_interval_end_index(uint16_t val, uint16_t* axis_values, uint8_t len_axis);
static uint16_t interpolate_u16b(uint16_t x, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1);
static uint16_t index2d_to_index1d(uint8_t ix, uint8_t iy, uint8_t len_x);
#endif
/**** Public function definitions ****/
uint8_t util_invert_8b(uint8_t x)
{
if(x!=0) return 0;
else return 1;
}
uint8_t util_sat_add_8b(uint8_t x, uint8_t y)
{
uint8_t z = x + y;
// Check for overflow
if((z < x)||(z < y)) return 0xFF;
else return z;
}
uint8_t util_sat_subtract_8b(uint8_t x, uint8_t y)
{
uint8_t z = x - y;
// Check for underflow
if(z > x) return 0;
else return z;
}
uint16_t util_sat_add_16b(uint16_t x, uint16_t y)
{
uint16_t z = x + y;
// Check for overflow
if((z < x)||(z < y)) return 0xFFFF;
else return z;
}
uint16_t util_sat_subtract_16b(uint16_t x, uint16_t y)
{
uint16_t z = x - y;
// Check for underflow
if(z > x) return 0;
else return z;
}
uint16_t util_limit_u32b_to_u16b(uint32_t in)
{
if(in == 0) return 0;
else if(in >= 0x0000FFFF) return 0xFFFF;
else return (uint16_t)in;
}
uint16_t util_limit_s32b_to_u16b(int32_t in)
{
if(in <= 0) return 0;
else if(in >= 0x0000FFFF) return 0xFFFF;
else return (uint16_t)in;
}
uint16_t util_convert_muldivoff(uint16_t raw, uint8_t mul, uint8_t div, int16_t offset)
{
int32_t temp = (int32_t)raw;
temp = temp * mul;
if(div>1) temp /= div;
temp += offset;
return util_limit_s32b_to_u16b(temp);
}
uint16_t util_sat_mul_kilo(uint16_t xk, uint16_t yk)
{
uint32_t temp = (uint32_t)xk * (uint32_t)yk;
temp /= 1000;
return util_limit_u32b_to_u16b(temp);
}
uint16_t util_sat_div_kilo(uint16_t top, uint16_t bot)
{
//Sanity check bot
if(bot==0) return 0xFFFF; //aka infinity
uint32_t temp = (uint32_t)top * 1000;
temp /= (uint32_t)bot;
return util_limit_u32b_to_u16b(temp);
}
uint16_t util_sat_ratio_16b(uint16_t top, uint16_t bot)
{
//Sanity check bot
if(bot==0) return 0xFFFF; //aka infinity
//Easy option
if(top>=bot) return 0xFFFF;
uint32_t temp = (uint32_t)top * 0x0000FFFF;
temp /= (uint32_t)bot;
return util_limit_u32b_to_u16b(temp);
}
uint16_t util_percent_to_16b(uint8_t percent)
{
uint32_t temp = (uint32_t)percent * 0x0000FFFF;
temp /= 100;
// Limit to 16 bits
uint16_t pwm = util_limit_u32b_to_u16b(temp);
return pwm;
}
uint16_t util_interpolate_1d_u16b(uint16_t x, uint16_t* x_axis, uint16_t* y_values, uint8_t len_axis)
{
// validate axis length
if(len_axis==0) return 0; // Empty data set
if(len_axis==1) return y_values[0]; // Only one data point
uint16_t y;
uint8_t i = find_interval_end_index(x, x_axis, len_axis);
if(i==0)
{
//Less then start
y = y_values[0];
}
else if(i==len_axis)
{
//More than end
y = y_values[len_axis-1];
}
else
{
// Do interpolate
y = interpolate_u16b(x, x_axis[i-1], x_axis[i], y_values[i-1], y_values[i]);
}
return y;
}
uint16_t util_interpolate_2d_u16b(uint16_t x, uint16_t y, uint16_t* x_axis, uint8_t len_x_axis, uint16_t* y_axis, uint8_t len_y_axis, uint16_t* z_values)
{
// validate axis length
if((len_x_axis==0)&&(len_y_axis==0)) return 0; // Empty data set
if((len_x_axis==1)&&(len_y_axis==1)) return z_values[0]; // Only one data point
uint8_t ix = find_interval_end_index(x, x_axis, len_x_axis);
uint8_t iy = find_interval_end_index(y, y_axis, len_y_axis);
// Check corners - easy answers
if((ix==0)&&(iy==0))
{
return z_values[0]; //[0][0] [Y][X]
}
else if((ix==len_x_axis)&&(iy==0))
{
return z_values[len_x_axis-1]; //[0][end]
}
else if((ix==0)&&(iy==len_y_axis))
{
uint16_t i = index2d_to_index1d(0, len_y_axis-1, len_x_axis);
return z_values[i]; //[end][0]
}
else if((ix==len_x_axis)&&(iy==len_y_axis))
{
uint16_t i = index2d_to_index1d(len_x_axis-1, len_y_axis-1, len_x_axis);
return z_values[i]; //[end][end]
};
// Check boundaries - 1D interpolation
if(ix==0)
{
// On ix=0 line
uint16_t i = 0;
uint16_t z0 = z_values[i];
i = index2d_to_index1d(0, len_y_axis-1, len_x_axis);
uint16_t z1 = z_values[i];
return interpolate_u16b(y, y_axis[0], y_axis[len_y_axis-1], z0, z1);
}
else if(ix==len_x_axis)
{
// On ix=END line
uint16_t i = len_x_axis-1;
uint16_t z0 = z_values[i];
i = index2d_to_index1d(len_x_axis-1, len_y_axis-1, len_x_axis);
uint16_t z1 = z_values[i];
return interpolate_u16b(y, y_axis[0], y_axis[len_y_axis-1], z0, z1);
}
else if(iy==0)
{
// On iy=0 line
uint16_t i = 0;
uint16_t z0 = z_values[i];
i = len_x_axis-1;
uint16_t z1 = z_values[i];
return interpolate_u16b(x, x_axis[0], x_axis[len_x_axis-1], z0, z1);
}
else if(iy==len_y_axis)
{
// On iy=END line
uint16_t i = index2d_to_index1d(0, len_y_axis-1, len_x_axis);
uint16_t z0 = z_values[i];
i = index2d_to_index1d(len_x_axis-1, len_y_axis-1, len_x_axis);
uint16_t z1 = z_values[i];
return interpolate_u16b(x, x_axis[0], x_axis[len_x_axis-1], z0, z1);
}
// Do interpolation
// Get axis values
uint16_t x0 = x_axis[ix-1];
uint16_t x1 = x_axis[ix];
uint16_t y0 = y_axis[iy-1];
uint16_t y1 = y_axis[iy];
// Do y0 line calculation
// Get z values at x0 and x1 points on y0 line
uint16_t i = index2d_to_index1d(ix-1, iy-1, len_x_axis);
uint16_t z0 = z_values[i];
uint16_t z1 = z_values[i+1];
// Interpolate z value on y0 line
uint16_t zy0 = interpolate_u16b(x, x0, x1, z0, z1);
// Do y1 line calculation
// Get z values at x0 and x1 points on y1 line
i = index2d_to_index1d(ix-1, iy, len_x_axis);
z0 = z_values[i];
z1 = z_values[i+1];
// Interpolate z value on y0 line
uint16_t zy1 = interpolate_u16b(x, x0, x1, z0, z1);
// Do calculation in y axis on xz line
return interpolate_u16b(y, y0, y1, zy0, zy1);
}
/**** Private function definitions ****/
static uint16_t interpolate_u16b(uint16_t x, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1)
{
int32_t dy = (int32_t)y1 - (int32_t)y0;
int32_t dx = (int32_t)x1 - (int32_t)x0;
int32_t d = (int32_t)x - (int32_t)x0;
int32_t y = dy * d;
y /= dx;
y += y0;
return util_limit_s32b_to_u16b(y);
}
static uint8_t find_interval_end_index(uint16_t val, uint16_t* axis_values, uint8_t len_axis)
{
for(uint8_t i=0; i<len_axis; i++)
{
if(val < axis_values[i]) return i;
continue;
}
return len_axis;
}
static uint16_t index2d_to_index1d(uint8_t ix, uint8_t iy, uint8_t len_x)
{
return ((uint16_t)len_x * iy) + ix;
}

View File

@@ -0,0 +1,37 @@
#ifndef UTILS_H_
#define UTILS_H_
/**** Includes ****/
#include <stdint.h>
/**** Public definitions ****/
/**** Public function declarations ****/
uint8_t util_invert_8b(uint8_t x);
uint16_t util_limit_u32b_to_u16b(uint32_t in);
uint16_t util_limit_s32b_to_u16b(int32_t in);
uint16_t util_convert_muldivoff(uint16_t raw, uint8_t mul, uint8_t div, int16_t offset);
uint16_t util_sat_mul_kilo(uint16_t xk, uint16_t yk);
uint16_t util_sat_div_kilo(uint16_t top, uint16_t bot);
uint16_t util_sat_ratio_16b(uint16_t top, uint16_t bot);
uint16_t util_percent_to_16b(uint8_t percent);
uint8_t util_sat_add_8b(uint8_t x, uint8_t y);
uint8_t util_sat_subtract_8b(uint8_t x, uint8_t y);
uint16_t util_sat_add_16b(uint16_t x, uint16_t y);
uint16_t util_sat_subtract_16b(uint16_t x, uint16_t y);
uint16_t util_interpolate_1d_u16b(uint16_t x, uint16_t* x_axis, uint16_t* y_values, uint8_t len_axis);
uint16_t util_interpolate_2d_u16b(uint16_t x, uint16_t y, uint16_t* x_axis, uint8_t len_x_axis, uint16_t* y_axis, uint8_t len_y_axis, uint16_t* z_values);
#ifdef TESTING
// Access to private functions for unit testing
static uint8_t find_interval_end_index(uint16_t val, uint16_t* axis_values, uint8_t len_axis);
static uint16_t interpolate_u16b(uint16_t x, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1);
static uint16_t index2d_to_index1d(uint8_t ix, uint8_t iy, uint8_t len_x);
#endif
#endif /* UTILS_H_ */