Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c2033f8547 | ||
| 4a84afcf7a | |||
| 68f0f52566 | |||
| 9a7f4933b3 | |||
| 6ba884f51f |
BIN
docs/uDCCD_Controller_R9V1_Schematic.PDF
Normal file
BIN
docs/uDCCD_Controller_R9V1_Schematic.PDF
Normal file
Binary file not shown.
@@ -1,120 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "hal/udccd_hal.h"
|
|
||||||
#include "analog.h"
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static const uint8_t ICOIL_MUL = 215;
|
|
||||||
static const uint8_t ICOIL_DIV = 22;
|
|
||||||
static const int16_t ICOIL_OFF = 0;
|
|
||||||
static const uint8_t ICOIL_CNT = 1;
|
|
||||||
|
|
||||||
static const uint8_t UCOIL_MUL = 20;
|
|
||||||
static const uint8_t UCOIL_DIV = 1;
|
|
||||||
static const int16_t UCOIL_OFF = 0;
|
|
||||||
static const uint8_t UCOIL_CNT = 1;
|
|
||||||
|
|
||||||
static const uint8_t UBAT_MUL = 20;
|
|
||||||
static const uint8_t UBAT_DIV = 1;
|
|
||||||
static const int16_t UBAT_OFF = 0;
|
|
||||||
static const uint8_t UBAT_CNT = 1;
|
|
||||||
|
|
||||||
static const uint8_t IBAT_MUL = 235;
|
|
||||||
static const uint8_t IBAT_DIV = 6;
|
|
||||||
static const int16_t IBAT_OFF = 0;
|
|
||||||
static const uint8_t IBAT_CNT = 1;
|
|
||||||
|
|
||||||
static const uint8_t POT_MUL = 215;
|
|
||||||
static const uint8_t POT_DIV = 44;
|
|
||||||
static const int16_t POT_OFF = 0;
|
|
||||||
static const uint8_t POT_CNT = 1;
|
|
||||||
|
|
||||||
static const uint8_t MODE_MUL = 215;
|
|
||||||
static const uint8_t MODE_DIV = 44;
|
|
||||||
static const int16_t MODE_OFF = 0;
|
|
||||||
static const uint8_t MODE_CNT = 1;
|
|
||||||
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static uint16_t ConvertSIntShort(int32_t in);
|
|
||||||
static uint16_t ConvertUintShort(uint32_t in);
|
|
||||||
static uint16_t read_ch(adcCh_t ch, uint16_t gnd_raw, uint8_t mul, uint8_t div, int16_t offset, uint8_t samples);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Analog_UpdateAll(analog_t* meas)
|
|
||||||
{
|
|
||||||
uint16_t gnd_lvl = HAL_ADC_Read(ADC_GND);
|
|
||||||
|
|
||||||
meas->hb_currnet = read_ch(ADC_ICOIL, 0, ICOIL_MUL, ICOIL_DIV, ICOIL_OFF, ICOIL_CNT ); //mA
|
|
||||||
meas->hb_voltage = read_ch(ADC_UCOIL, 0, UCOIL_MUL, UCOIL_DIV, UCOIL_OFF, UCOIL_CNT ); //mV
|
|
||||||
meas->supply_current = read_ch(ADC_IBAT , 0, IBAT_MUL , IBAT_DIV , IBAT_OFF , IBAT_CNT ); //mA
|
|
||||||
meas->supply_voltage = read_ch(ADC_UBAT , 0, UBAT_MUL , UBAT_DIV , UBAT_OFF , UBAT_CNT ); //mV
|
|
||||||
meas->pot_voltage = read_ch(ADC_POT , 0, POT_MUL , POT_DIV , POT_OFF , POT_CNT ); //mV
|
|
||||||
meas->mode_voltage = read_ch(ADC_MODE , 0, MODE_MUL , MODE_DIV , MODE_OFF , MODE_CNT ); //mV
|
|
||||||
|
|
||||||
// Calculate derived measurements
|
|
||||||
// Halfbridge output power
|
|
||||||
uint32_t temp = (uint32_t)meas->hb_currnet * (uint32_t)meas->hb_voltage;
|
|
||||||
temp /= 1000;
|
|
||||||
meas->hb_power = ConvertUintShort(temp);
|
|
||||||
|
|
||||||
// Halfbridge output resistance
|
|
||||||
if(meas->hb_currnet == 0) meas->hb_resistance = 0xFFFF;
|
|
||||||
else if(meas->hb_voltage == 0) meas->hb_resistance = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
temp = (uint32_t)meas->hb_voltage * 1000;
|
|
||||||
temp /= (uint32_t)meas->hb_currnet;
|
|
||||||
meas->hb_resistance = ConvertUintShort(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supply power
|
|
||||||
temp = (uint32_t)meas->supply_current * (uint32_t)meas->supply_voltage;
|
|
||||||
temp /= 1000;
|
|
||||||
meas->supply_power = ConvertUintShort(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t read_ch(adcCh_t ch, uint16_t gnd_raw, uint8_t mul, uint8_t div, int16_t offset, uint8_t samples)
|
|
||||||
{
|
|
||||||
//Sanity check
|
|
||||||
if(div==0) return 0xFFFF;
|
|
||||||
|
|
||||||
// Do at least one sample
|
|
||||||
if(samples<1) samples = 1;
|
|
||||||
|
|
||||||
// Read ADC value
|
|
||||||
int32_t raw = 0;
|
|
||||||
for(uint8_t i=0; i<samples; i++)
|
|
||||||
{
|
|
||||||
raw += (int32_t)HAL_ADC_Read(ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do average
|
|
||||||
if(samples != 1)
|
|
||||||
{
|
|
||||||
raw /= samples;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove GND level
|
|
||||||
if(gnd_raw) raw = raw - (int32_t)gnd_raw;
|
|
||||||
|
|
||||||
// Convert to target units
|
|
||||||
raw = raw * mul;
|
|
||||||
if(div!=1) raw /= div;
|
|
||||||
raw += offset;
|
|
||||||
|
|
||||||
return ConvertSIntShort(raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t ConvertSIntShort(int32_t in)
|
|
||||||
{
|
|
||||||
if(in <= 0) return 0;
|
|
||||||
else if(in >= 0x0000FFFF) return 0xFFFF;
|
|
||||||
else return (uint16_t)in;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t ConvertUintShort(uint32_t in)
|
|
||||||
{
|
|
||||||
if(in == 0) return 0;
|
|
||||||
else if(in >= 0x0000FFFF) return 0xFFFF;
|
|
||||||
else return (uint16_t)in;
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#ifndef ANALOG_H_
|
|
||||||
#define ANALOG_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef struct {
|
|
||||||
uint16_t hb_currnet;
|
|
||||||
uint16_t hb_voltage;
|
|
||||||
uint16_t hb_power;
|
|
||||||
uint16_t hb_resistance;
|
|
||||||
uint16_t supply_current;
|
|
||||||
uint16_t supply_voltage;
|
|
||||||
uint16_t supply_power;
|
|
||||||
uint16_t pot_voltage;
|
|
||||||
uint16_t mode_voltage;
|
|
||||||
} analog_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Analog_UpdateAll(analog_t* meas);
|
|
||||||
|
|
||||||
#endif /* ANALOG_H_ */
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#ifndef LEVEL_T_H_
|
|
||||||
#define LEVEL_T_H_
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef enum {
|
|
||||||
HIZ = -1,
|
|
||||||
LOW = 0,
|
|
||||||
HIGH = 1
|
|
||||||
} level_t;
|
|
||||||
|
|
||||||
#endif /* LEVEL_T_H_ */
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "hal/udccd_hal.h"
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Init_HW(void)
|
|
||||||
{
|
|
||||||
hwConfig_t hwCfg;
|
|
||||||
hwCfg.adc_clk_prescaler = ADC_DIV2;
|
|
||||||
hwCfg.adc_auto_wake = 1;
|
|
||||||
// 64kHz PWM
|
|
||||||
hwCfg.pwm_timer_prescaler = TIM_DIV1;
|
|
||||||
hwCfg.pwm_timer_top = 0x01FF;
|
|
||||||
// 1.9Hz..62.5kHz Speed input
|
|
||||||
hwCfg.freq_timer_prescaler = TIM_DIV64;
|
|
||||||
// 1kHz systick
|
|
||||||
hwCfg.systick_timer_top = 125;
|
|
||||||
hwCfg.systick_timer_prescaler = TIM_DIV64;
|
|
||||||
// No extra features
|
|
||||||
hwCfg.uart_prescaler = 0;
|
|
||||||
hwCfg.disable_unused = 0;
|
|
||||||
hwCfg.en_watchdog = 0;
|
|
||||||
HAL_Init_Min(&hwCfg);
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef CONFIG_H_
|
|
||||||
#define CONFIG_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Init_HW(void);
|
|
||||||
|
|
||||||
#endif /* CONFIG_H_ */
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "filter_iir_lpf.h"
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
uint16_t LPF_Update(uint16_t new, uint16_t last, uint8_t strength)
|
|
||||||
{
|
|
||||||
if(strength==0) return new;
|
|
||||||
else if(strength==255) return last;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t temp = (uint32_t)last * strength;
|
|
||||||
temp += new * (255-strength);
|
|
||||||
temp /= 255;
|
|
||||||
|
|
||||||
//Limit to 16bits
|
|
||||||
if(temp > 0x0000FFFF) return 0xFFFF;
|
|
||||||
else return (uint16_t) temp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#ifndef FILTER_IIR_LPF_H_
|
|
||||||
#define FILTER_IIR_LPF_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
uint16_t LPF_Update(uint16_t new, uint16_t last, uint8_t strength);
|
|
||||||
|
|
||||||
#endif /* FILTER_IIR_LPF_H_ */
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#ifndef UDCCD_R8_BSP_H_
|
|
||||||
#define UDCCD_R8_BSP_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../common/level.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
//ADC definitions
|
|
||||||
typedef enum {
|
|
||||||
ADC_ICOIL = 0x00,
|
|
||||||
ADC_UCOIL = 0x01,
|
|
||||||
ADC_UBAT = 0x02,
|
|
||||||
ADC_IBAT = 0x03,
|
|
||||||
ADC_POT = 0x04,
|
|
||||||
ADC_MODE = 0x05,
|
|
||||||
ADC_TEMP = 0x08,
|
|
||||||
ADC_INTREF = 0x0E,
|
|
||||||
ADC_GND = 0x0F
|
|
||||||
} adcCh_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ADC_DIV2 = 0x01,
|
|
||||||
ADC_DIV4 = 0x02,
|
|
||||||
ADC_DIV8 = 0x03,
|
|
||||||
ADC_DIV16 = 0x04,
|
|
||||||
ADC_DIV32 = 0x05,
|
|
||||||
ADC_DIV64 = 0x06,
|
|
||||||
ADC_DIV128 = 0x07
|
|
||||||
} adcDiv_t;
|
|
||||||
|
|
||||||
//Timer definitions
|
|
||||||
typedef enum {
|
|
||||||
TIM_DIV1 = 0x01,
|
|
||||||
TIM_DIV8 = 0x02,
|
|
||||||
TIM_DIV64 = 0x03,
|
|
||||||
TIM_DIV256 = 0x04,
|
|
||||||
TIM_DIV1024 = 0x05
|
|
||||||
} timerDiv_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PWM_COIL = 'A',
|
|
||||||
PWM_LED = 'B'
|
|
||||||
} pwmCh_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SPEED_1 = 3,
|
|
||||||
SPEED_0 = 4
|
|
||||||
} speedCh_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
adcDiv_t adc_clk_prescaler;
|
|
||||||
uint8_t adc_auto_wake;
|
|
||||||
timerDiv_t pwm_timer_prescaler;
|
|
||||||
uint16_t pwm_timer_top;
|
|
||||||
timerDiv_t freq_timer_prescaler;
|
|
||||||
uint16_t uart_prescaler;
|
|
||||||
uint8_t systick_timer_top;
|
|
||||||
timerDiv_t systick_timer_prescaler;
|
|
||||||
uint8_t disable_unused;
|
|
||||||
uint8_t en_watchdog;
|
|
||||||
} hwConfig_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void HAL_Init_Min(hwConfig_t* hwCfg);
|
|
||||||
void HAL_Init_Extra(hwConfig_t* hwCfg);
|
|
||||||
|
|
||||||
level_t HAL_ReadLvl_Handbrake(void);
|
|
||||||
level_t HAL_ReadLvl_Brake(void);
|
|
||||||
level_t HAL_ReadLvl_Dimm(void);
|
|
||||||
level_t HAL_ReadLvl_BtnUp(void);
|
|
||||||
level_t HAL_ReadLvl_BtnDown(void);
|
|
||||||
level_t HAL_ReadLvl_BtnMode(void);
|
|
||||||
level_t HAL_ReadLvl_HandbrakePull(void);
|
|
||||||
level_t HAL_ReadLvl_CoilLow(void);
|
|
||||||
level_t HAL_ReadLvl_CoilHigh(void);
|
|
||||||
level_t HAL_ReadLvl_LedsPwm(void);
|
|
||||||
level_t HAL_ReadLvl_Speed0(void);
|
|
||||||
level_t HAL_ReadLvl_Speed1(void);
|
|
||||||
level_t HAL_ReadLvl_SpeedPull(void);
|
|
||||||
|
|
||||||
void HAL_SetPull_Handbrake(level_t lvl);
|
|
||||||
void HAL_SetPull_Speed(level_t lvl);
|
|
||||||
|
|
||||||
void HAL_ADC_Wake(void);
|
|
||||||
void HAL_ADC_Sleep(void);
|
|
||||||
uint16_t HAL_ADC_Read(adcCh_t ch);
|
|
||||||
|
|
||||||
void HAL_Coil_SetLowSide(uint8_t on);
|
|
||||||
void HAL_Coil_SetPWM(uint8_t percent);
|
|
||||||
void HAL_Coil_SetPWM16b(uint16_t value);
|
|
||||||
|
|
||||||
void HAL_LEDS_Set(uint8_t image);
|
|
||||||
uint8_t HAL_LEDS_Get(void);
|
|
||||||
void HAL_LEDS_SetPWM(uint8_t percent);
|
|
||||||
|
|
||||||
void HAL_PWM_Wake(void);
|
|
||||||
void HAL_PWM_Sleep(void);
|
|
||||||
void HAL_PWM_SetDuty16b(pwmCh_t ch, uint16_t value);
|
|
||||||
void HAL_PWM_SetDuty100(pwmCh_t ch, uint8_t percent);
|
|
||||||
|
|
||||||
#endif /* UDCCD_R8_BSP_H_ */
|
|
||||||
@@ -1,463 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include "udccd_hal.h"
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static uint8_t tim0_prescaler = 0x00;
|
|
||||||
static uint8_t tim1_prescaler = 0x00;
|
|
||||||
static uint8_t tim3_prescaler = 0x00;
|
|
||||||
static uint8_t tim4_prescaler = 0x00;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static void PWM_SetOCx(pwmCh_t ch, uint16_t value);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void HAL_Init_Min(hwConfig_t* hwCfg)
|
|
||||||
{
|
|
||||||
// PIN Configuration
|
|
||||||
//DCCD Enable and PWM
|
|
||||||
PORTB &= ~0x03; //Set low
|
|
||||||
DDRB |= 0x03; //Set as outputs
|
|
||||||
|
|
||||||
//LED PWM
|
|
||||||
PORTB &= ~0x04; //Set low
|
|
||||||
DDRB |= 0x04; //Set as output
|
|
||||||
|
|
||||||
//UART TX
|
|
||||||
PORTB |= 0x18; //Set high / pull-up on
|
|
||||||
DDRB |= 0x08; //Set as output
|
|
||||||
DDRB &= ~0x10; //Set as input
|
|
||||||
|
|
||||||
//Handbrake pull-up
|
|
||||||
PORTB |= 0x20; //Set high
|
|
||||||
DDRB |= 0x20; //Set as output
|
|
||||||
|
|
||||||
//Handbrake and Brake inputs
|
|
||||||
PORTB |= 0xC0; //Pull-up on
|
|
||||||
DDRB &= ~0xC0; //Set as input
|
|
||||||
|
|
||||||
// ADC inputs
|
|
||||||
PORTC &= ~0x3F; //Pull-up off
|
|
||||||
DDRC &= ~0x3F; //Set as inputs
|
|
||||||
|
|
||||||
// Reset
|
|
||||||
PORTC |= 0x40; //Pull-up on
|
|
||||||
DDRC &= ~0x40; //Set as input
|
|
||||||
|
|
||||||
// LED control
|
|
||||||
PORTD &= ~0x3F; //Set low
|
|
||||||
DDRD |= 0x3F; //Set as outputs
|
|
||||||
|
|
||||||
// Speed pull
|
|
||||||
PORTD &= ~0x40; //Set low
|
|
||||||
DDRD |= 0x40; //Set as outputs
|
|
||||||
|
|
||||||
// Dim input
|
|
||||||
PORTD |= 0x80; //Set pull-up on
|
|
||||||
DDRD &= ~0x80; //Set as input
|
|
||||||
|
|
||||||
// Speed inputs
|
|
||||||
PORTE &= ~0x05; //Set pull-down
|
|
||||||
DDRE |= 0x05; //Set as output
|
|
||||||
|
|
||||||
// Up/Down inputs
|
|
||||||
PORTE |= 0x0A; //Set pull-up on
|
|
||||||
DDRE &= ~0x0A; //Set as input
|
|
||||||
|
|
||||||
|
|
||||||
//ADC configuration
|
|
||||||
PRR0 &= ~0x01; //Enable ADC power
|
|
||||||
DIDR0 |= 0x1F; //Disable digital inputs, ADC0-ADC4
|
|
||||||
|
|
||||||
ADMUX = 0x40; //Set AVCC reference, Right adjust
|
|
||||||
ADCSRA = 0x00; //ADC Disabled, Single conversion, no IT
|
|
||||||
ADCSRA |= (uint8_t)hwCfg->adc_clk_prescaler;
|
|
||||||
ADCSRB = 0x00; //no trigger input
|
|
||||||
|
|
||||||
if(hwCfg->adc_auto_wake) ADCSRA |= 0x80; //Enable ADC
|
|
||||||
else PRR0 |= 0x01;
|
|
||||||
|
|
||||||
|
|
||||||
//DCCD and LED PWM configuration
|
|
||||||
PRR0 &= ~0x80; //Enable Timer1 power
|
|
||||||
TCCR1A = 0xF2; //Connect OC1A and OC1B, normal logic
|
|
||||||
TCCR1B = 0x18; //PWM, Phase & Frequency Correct ICR1 top, no clock, WGM:0xE
|
|
||||||
TCCR1C = 0x00;
|
|
||||||
TCNT1 = 0x0000;
|
|
||||||
OCR1A = 0x0000;
|
|
||||||
OCR1B = 0x0000;
|
|
||||||
ICR1 = (hwCfg->pwm_timer_top);
|
|
||||||
TIMSK1 = 0x00; //No interrupts
|
|
||||||
TIFR1 = 0x00; //Clear all flags
|
|
||||||
|
|
||||||
tim1_prescaler = (uint8_t)hwCfg->pwm_timer_prescaler;
|
|
||||||
TCCR1B |= tim1_prescaler; //Enable timer
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_Init_Extra(hwConfig_t* hwCfg)
|
|
||||||
{
|
|
||||||
//Speed 1 input timer configuration
|
|
||||||
PRR1 &= ~0x01; //Enable Timer3 power
|
|
||||||
TCCR3A = 0x00; //OCx disconnected, WGM:0x0
|
|
||||||
TCCR3B = 0x80; //ICP Noise filter, Falling edge, no clock
|
|
||||||
TCCR3C = 0x00;
|
|
||||||
TCNT3 = 0x0000;
|
|
||||||
OCR3A = 0x0000;
|
|
||||||
OCR3B = 0x0000;
|
|
||||||
ICR3 = 0x0000;
|
|
||||||
TIMSK3 = 0x00;
|
|
||||||
//TIMSK3 |= 0x21; //ICP and OVF interrupts
|
|
||||||
TIFR3 = 0x00; //Clear all flags
|
|
||||||
|
|
||||||
tim3_prescaler = (uint8_t)hwCfg->freq_timer_prescaler;
|
|
||||||
TCCR3B |= tim3_prescaler; //Enable timer
|
|
||||||
|
|
||||||
|
|
||||||
//Speed 0 input timer configuration
|
|
||||||
PRR1 &= ~0x08; //Enable Timer4 power
|
|
||||||
TCCR4A = 0x00; //OCx disconnected, WGM:0x0
|
|
||||||
TCCR4B = 0x80; //ICP Noise filter, Falling edge, no clock
|
|
||||||
TCCR4C = 0x00;
|
|
||||||
TCNT4 = 0x0000;
|
|
||||||
OCR4A = 0x0000;
|
|
||||||
OCR4B = 0x0000;
|
|
||||||
ICR4 = 0x0000;
|
|
||||||
TIMSK4 = 0x00;
|
|
||||||
//TIMSK4 |= 0x21; //ICP and OVF interrupts
|
|
||||||
TIFR4 = 0x00; //Clear all flags
|
|
||||||
|
|
||||||
tim4_prescaler = (uint8_t)hwCfg->freq_timer_prescaler;
|
|
||||||
TCCR4B |= tim4_prescaler; //Enable timer
|
|
||||||
|
|
||||||
|
|
||||||
//UART1 configuration
|
|
||||||
PRR0 &= 0x10; //Enable UART1 power
|
|
||||||
UCSR1A = 0x00; //Clear flags, Single UART speed, Single processor mode
|
|
||||||
UCSR1B = 0x18; //Enable RX/TX hardware, 8bit char
|
|
||||||
//UCSR1B |= 0xC0; //Enable RX/TX interrupt,
|
|
||||||
UCSR1C = 0x06; ; //async, No parity, 1 stop bit, 8bit char,
|
|
||||||
UBRR1 = hwCfg->uart_prescaler; //UART baud rate select
|
|
||||||
|
|
||||||
|
|
||||||
//"Systick" timer configuration
|
|
||||||
PRR0 &= ~0x20; //Enable Timer0 power
|
|
||||||
TCCR0A = 0x02 ;//OC0x not connected, WGM 0x01-CTC OC0A TOP
|
|
||||||
TCCR0B = 0x00; //WGM 0x01-CTC, No clock
|
|
||||||
TIMSK0 = 0x00;
|
|
||||||
//TIMSK0 |= 0x01; //OVF interrupt enabled
|
|
||||||
TCNT0 = 0x00;
|
|
||||||
OCR0A = hwCfg->systick_timer_top;
|
|
||||||
OCR0B= 0x00;
|
|
||||||
TIFR0 = 0x00; //Reset all flags
|
|
||||||
|
|
||||||
tim0_prescaler = (uint8_t)hwCfg->systick_timer_prescaler;
|
|
||||||
TCCR0B |= tim0_prescaler;
|
|
||||||
|
|
||||||
|
|
||||||
//Disabled not used power configuration
|
|
||||||
if(hwCfg->disable_unused)
|
|
||||||
{
|
|
||||||
//Disable power to not used peripherals
|
|
||||||
PRR0 |= 0xC6; //Disable TWI0, TIM2, SPI0, UART0
|
|
||||||
PRR1 |= 0x34; //Disable TWI1, PRTC, SPI1
|
|
||||||
}
|
|
||||||
|
|
||||||
//Watchdog configuration
|
|
||||||
if(hwCfg->en_watchdog)
|
|
||||||
{
|
|
||||||
//watchdog timer setup
|
|
||||||
WDTCSR |= 0x10; //Change enable
|
|
||||||
WDTCSR |= 0x0D; //System reset mode, 0.5s period.
|
|
||||||
//use special instruction to reset watchdog timer
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Handbrake input
|
|
||||||
level_t HAL_ReadLvl_Handbrake(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x40) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Brakes input
|
|
||||||
level_t HAL_ReadLvl_Brake(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x80) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dimm input
|
|
||||||
level_t HAL_ReadLvl_Dimm(void)
|
|
||||||
{
|
|
||||||
if(PIND & 0x80) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// UP button
|
|
||||||
level_t HAL_ReadLvl_BtnUp(void)
|
|
||||||
{
|
|
||||||
if(PINE & 0x08) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Down button
|
|
||||||
level_t HAL_ReadLvl_BtnDown(void)
|
|
||||||
{
|
|
||||||
if(PINE & 0x02) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode button
|
|
||||||
level_t HAL_ReadLvl_BtnMode(void)
|
|
||||||
{
|
|
||||||
if(PINC & 0x20) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handbrake pull
|
|
||||||
level_t HAL_ReadLvl_HandbrakePull(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x20) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coil driver control low
|
|
||||||
level_t HAL_ReadLvl_CoilLow(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x01) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Coil driver control high
|
|
||||||
level_t HAL_ReadLvl_CoilHigh(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x02) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// LED PWM control
|
|
||||||
level_t HAL_ReadLvl_LedsPwm(void)
|
|
||||||
{
|
|
||||||
if(PINB & 0x04) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Speed 0 input pin
|
|
||||||
level_t HAL_ReadLvl_Speed0(void)
|
|
||||||
{
|
|
||||||
if(PINE & 0x04) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Speed 1 input pin
|
|
||||||
level_t HAL_ReadLvl_Speed1(void)
|
|
||||||
{
|
|
||||||
if(PINE & 0x01) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Speed common pull pin
|
|
||||||
level_t HAL_ReadLvl_SpeedPull(void)
|
|
||||||
{
|
|
||||||
if(PIND & 0x40) return HIGH;
|
|
||||||
else return LOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Set handbrake pull-up
|
|
||||||
void HAL_SetPull_Handbrake(level_t lvl)
|
|
||||||
{
|
|
||||||
switch(lvl)
|
|
||||||
{
|
|
||||||
case HIGH:
|
|
||||||
PORTB |= 0x20; //Set high
|
|
||||||
DDRB |= 0x20; //Set as output
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LOW:
|
|
||||||
PORTB &= ~0x20; //Set low
|
|
||||||
DDRB |= 0x20; //Set as output
|
|
||||||
|
|
||||||
default:
|
|
||||||
DDRB &= ~0x20; //Set as input
|
|
||||||
PORTB |= 0x20; //Set high
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set speed inputs common pull
|
|
||||||
void HAL_SetPull_Speed(level_t lvl)
|
|
||||||
{
|
|
||||||
switch(lvl)
|
|
||||||
{
|
|
||||||
case HIGH:
|
|
||||||
PORTD |= 0x40; //Set high
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
PORTD &= ~0x40; //Set low
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ADC Wake
|
|
||||||
void HAL_ADC_Wake(void)
|
|
||||||
{
|
|
||||||
//Enable ADC power
|
|
||||||
PRR0 &= ~0x01;
|
|
||||||
//Enable ADC
|
|
||||||
ADCSRA |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ADC Sleep
|
|
||||||
void HAL_ADC_Sleep(void)
|
|
||||||
{
|
|
||||||
//wait to finish
|
|
||||||
while(ADCSRA&0x40);
|
|
||||||
//Disable ADC
|
|
||||||
ADCSRA &= ~0x80;
|
|
||||||
//Disable ADC power
|
|
||||||
PRR0 |= 0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ADC Read
|
|
||||||
uint16_t HAL_ADC_Read(adcCh_t ch)
|
|
||||||
{
|
|
||||||
//check if ADC is enabled
|
|
||||||
if(!(ADCSRA&0x80)) return 0xFFFF;
|
|
||||||
|
|
||||||
uint8_t mux = (uint8_t)ch;
|
|
||||||
//Safe guard mux
|
|
||||||
if(mux > 15) return 0xFFFF;
|
|
||||||
// Not available channels
|
|
||||||
if((mux > 8) && (mux<14)) return 0xFFFF;
|
|
||||||
|
|
||||||
ADMUX &= ~0x0F;
|
|
||||||
ADMUX |= mux;
|
|
||||||
ADCSRA |= 0x40;
|
|
||||||
while(ADCSRA&0x40); //wait to finish
|
|
||||||
return ADC;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Coil Driver Low Side control
|
|
||||||
void HAL_Coil_SetLowSide(uint8_t on)
|
|
||||||
{
|
|
||||||
if(on) PORTB |= 0x01;
|
|
||||||
else PORTB &= ~0x01;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_Coil_SetPWM(uint8_t percent)
|
|
||||||
{
|
|
||||||
HAL_PWM_SetDuty100(PWM_COIL, percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_Coil_SetPWM16b(uint16_t value)
|
|
||||||
{
|
|
||||||
HAL_PWM_SetDuty16b(PWM_COIL, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// LED Display
|
|
||||||
void HAL_LEDS_Set(uint8_t image)
|
|
||||||
{
|
|
||||||
//Read current PORTD pin6, pin7
|
|
||||||
uint8_t keep = PORTD & 0xC0;
|
|
||||||
|
|
||||||
//Safe guard display
|
|
||||||
image &= 0x3F;
|
|
||||||
|
|
||||||
//Calculate new PORTD
|
|
||||||
keep |= image;
|
|
||||||
|
|
||||||
//Set PORTD
|
|
||||||
PORTD = keep;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t HAL_LEDS_Get(void)
|
|
||||||
{
|
|
||||||
return (PIND & 0x3F);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_LEDS_SetPWM(uint8_t percent)
|
|
||||||
{
|
|
||||||
HAL_PWM_SetDuty100(PWM_LED, percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// PWM Direct functions
|
|
||||||
void HAL_PWM_Wake(void)
|
|
||||||
{
|
|
||||||
//Enable Timer1 power
|
|
||||||
PRR0 &= ~0x80;
|
|
||||||
//Prepare Timer1 settings
|
|
||||||
TCNT1 = 0x0000;
|
|
||||||
OCR1A = 0x0000;
|
|
||||||
OCR1B = 0x0000;
|
|
||||||
//Enable clock
|
|
||||||
TCCR1B |= tim1_prescaler; //Enable timer
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_PWM_Sleep(void)
|
|
||||||
{
|
|
||||||
// Turn off outputs
|
|
||||||
OCR1A = 0x0000;
|
|
||||||
OCR1B = 0x0000;
|
|
||||||
// Force timer to bottom
|
|
||||||
TCNT1 = (ICR1-1);
|
|
||||||
// Wait for outputs to be off
|
|
||||||
while((PINB&0x06)!=0x00) continue;
|
|
||||||
// Disable clock
|
|
||||||
TCCR1B &= ~0x07;
|
|
||||||
// Disable Timer1 power
|
|
||||||
PRR0 |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_PWM_SetDuty16b(pwmCh_t ch, uint16_t value)
|
|
||||||
{
|
|
||||||
value = 0xFFFF - value;
|
|
||||||
|
|
||||||
uint32_t top = (uint32_t)ICR1;
|
|
||||||
uint32_t temp = (uint32_t)value * top;
|
|
||||||
temp = temp/0x0000FFFF;
|
|
||||||
//Limit temp
|
|
||||||
if(temp>0x0000FFFF) temp = 0x0000FFFF;
|
|
||||||
uint16_t ocrx = (uint16_t) temp;
|
|
||||||
|
|
||||||
PWM_SetOCx(ch, ocrx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HAL_PWM_SetDuty100(pwmCh_t ch, uint8_t percent)
|
|
||||||
{
|
|
||||||
if(percent > 100) percent = 100;
|
|
||||||
percent = 100 - percent;
|
|
||||||
|
|
||||||
uint32_t top = (uint32_t)ICR1;
|
|
||||||
uint32_t temp = (uint32_t)percent * top;
|
|
||||||
temp = temp/100;
|
|
||||||
//Limit temp
|
|
||||||
if(temp>0x0000FFFF) temp = 0x0000FFFF;
|
|
||||||
uint16_t ocrx = (uint16_t) temp;
|
|
||||||
|
|
||||||
PWM_SetOCx(ch, ocrx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static void PWM_SetOCx(pwmCh_t ch, uint16_t value)
|
|
||||||
{
|
|
||||||
switch(ch)
|
|
||||||
{
|
|
||||||
case PWM_COIL:
|
|
||||||
OCR1A = value;
|
|
||||||
return;
|
|
||||||
|
|
||||||
case PWM_LED:
|
|
||||||
OCR1B = value;
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "hal/udccd_hal.h"
|
|
||||||
#include "halfbridge.h"
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static const uint16_t min_dc = 3277; //5%
|
|
||||||
static const uint16_t max_dc = 62258; //95%
|
|
||||||
|
|
||||||
static uint16_t target = 0;
|
|
||||||
static uint8_t low_side_on = 1;
|
|
||||||
|
|
||||||
static uint16_t active_dc = 0;
|
|
||||||
|
|
||||||
static uint8_t is_en = 0;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static uint16_t CalculateDuty16b(uint16_t target, uint16_t supply);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void HB_SetTarget(uint16_t voltage)
|
|
||||||
{
|
|
||||||
target = voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HB_SetLowSide(uint8_t on)
|
|
||||||
{
|
|
||||||
low_side_on = on;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t HB_GetTarget(void)
|
|
||||||
{
|
|
||||||
return target;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HB_UpdateOutput(uint16_t supply)
|
|
||||||
{
|
|
||||||
uint16_t temp_dc = CalculateDuty16b(target, supply);
|
|
||||||
|
|
||||||
HB_SetDirect(temp_dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HB_SetDirect(uint16_t duty)
|
|
||||||
{
|
|
||||||
/// Limit duty cycle
|
|
||||||
if(duty > max_dc) active_dc = max_dc;
|
|
||||||
else if(duty < min_dc) active_dc = 0;
|
|
||||||
else active_dc = duty;
|
|
||||||
|
|
||||||
// Set duty cycle
|
|
||||||
if(!is_en) return;
|
|
||||||
HAL_Coil_SetLowSide(low_side_on);
|
|
||||||
HAL_Coil_SetPWM16b(active_dc);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t HB_IsLowOn(void)
|
|
||||||
{
|
|
||||||
if(HAL_ReadLvl_CoilLow() == HIGH) return 1;
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HB_Enable(void)
|
|
||||||
{
|
|
||||||
// Restore low side
|
|
||||||
if(low_side_on) HAL_Coil_SetLowSide(1);
|
|
||||||
// Restore duty cycle
|
|
||||||
HAL_Coil_SetPWM(active_dc);
|
|
||||||
is_en = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HB_Disable(void)
|
|
||||||
{
|
|
||||||
// Set 0 DC
|
|
||||||
HAL_Coil_SetPWM(0);
|
|
||||||
// Disable low side
|
|
||||||
HAL_Coil_SetLowSide(0);
|
|
||||||
is_en = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t HB_IsEnabled(void)
|
|
||||||
{
|
|
||||||
if(is_en) return 1;
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int8_t HB_IsOutputMatch(uint16_t fb_output_voltage, uint16_t limit)
|
|
||||||
{
|
|
||||||
// No fault if output not enabled
|
|
||||||
if(!is_en) return -1;
|
|
||||||
|
|
||||||
// Can't check voltage if low side is off
|
|
||||||
if(!low_side_on) return -1;
|
|
||||||
|
|
||||||
if(target==0)
|
|
||||||
{
|
|
||||||
// Output can be only 0
|
|
||||||
if(fb_output_voltage != 0) return 0;
|
|
||||||
else return 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Calculate upper and lower bounds
|
|
||||||
uint16_t max = target + limit;
|
|
||||||
uint16_t min = target - limit;
|
|
||||||
|
|
||||||
//Sanity check
|
|
||||||
if(max < target) max = 0xFFFF;
|
|
||||||
if(min > target) min = 0;
|
|
||||||
|
|
||||||
//Do check
|
|
||||||
if((fb_output_voltage < min)||(fb_output_voltage > max)) return 0;
|
|
||||||
else return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static uint16_t CalculateDuty16b(uint16_t target, uint16_t supply)
|
|
||||||
{
|
|
||||||
if(target==0) return 0;
|
|
||||||
if(supply==0) return 0;
|
|
||||||
if(target > supply) return 0xFFFF;
|
|
||||||
|
|
||||||
// Calculate Duty cycle, in 16bit format
|
|
||||||
uint32_t temp = (uint32_t)target * 0x0000FFFF;
|
|
||||||
temp = temp / supply;
|
|
||||||
|
|
||||||
//Limit output to 16 bits
|
|
||||||
if(temp > 0x0000FFFF) return 0xFFFF;
|
|
||||||
else return (uint16_t)temp;
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#ifndef HALFBRIDGE_H_
|
|
||||||
#define HALFBRIDGE_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void HB_UpdateOutput(uint16_t supply);
|
|
||||||
|
|
||||||
void HB_SetTarget(uint16_t voltage);
|
|
||||||
void HB_SetLowSide(uint8_t on);
|
|
||||||
|
|
||||||
void HB_SetDirect(uint16_t duty);
|
|
||||||
|
|
||||||
void HB_Enable(void);
|
|
||||||
void HB_Disable(void);
|
|
||||||
|
|
||||||
uint16_t HB_GetTarget(void);
|
|
||||||
|
|
||||||
uint8_t HB_IsLowOn(void);
|
|
||||||
uint8_t HB_IsEnabled(void);
|
|
||||||
int8_t HB_IsOutputMatch(uint16_t fb_output_voltage, uint16_t limit);
|
|
||||||
|
|
||||||
#endif /* HALFBRIDGE_H_ */
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "hal/udccd_hal.h"
|
|
||||||
#include "inputs.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static const uint8_t def_debounce_lim = 10;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static void InitDefaultInput(inCh_t* inp);
|
|
||||||
static void ProcessInput(uint8_t read_lvl, inCh_t* inp);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Inputs_DefInit(inputs_t* inputs)
|
|
||||||
{
|
|
||||||
InitDefaultInput(&inputs->handbrake);
|
|
||||||
InitDefaultInput(&inputs->brakes);
|
|
||||||
InitDefaultInput(&inputs->dimm);
|
|
||||||
InitDefaultInput(&inputs->up);
|
|
||||||
InitDefaultInput(&inputs->down);
|
|
||||||
InitDefaultInput(&inputs->mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Inputs_UpdateAll(inputs_t* inputs)
|
|
||||||
{
|
|
||||||
// Chassis inputs
|
|
||||||
ProcessInput(HAL_ReadLvl_Handbrake(), &inputs->handbrake);
|
|
||||||
ProcessInput(HAL_ReadLvl_Brake(), &inputs->brakes);
|
|
||||||
ProcessInput(HAL_ReadLvl_Dimm(), &inputs->dimm);
|
|
||||||
|
|
||||||
// User inputs
|
|
||||||
ProcessInput(HAL_ReadLvl_BtnUp(), &inputs->up);
|
|
||||||
ProcessInput(HAL_ReadLvl_BtnDown(), &inputs->down);
|
|
||||||
ProcessInput(HAL_ReadLvl_BtnMode(), &inputs->mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Inputs_SetHanbrakePullUp(uint8_t on)
|
|
||||||
{
|
|
||||||
if(on) HAL_SetPull_Handbrake(HIGH);
|
|
||||||
else HAL_SetPull_Handbrake(HIZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static void InitDefaultInput(inCh_t* inp)
|
|
||||||
{
|
|
||||||
inp->is_active = 0;
|
|
||||||
inp->is_new = 0;
|
|
||||||
inp->state_timer = 0;
|
|
||||||
inp->cfg.act_level = LOW;
|
|
||||||
inp->cfg.dbnc_treshold = def_debounce_lim;
|
|
||||||
inp->proc.level = LOW;
|
|
||||||
inp->proc.dbnc_counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ProcessInput(uint8_t read_lvl, inCh_t* inp)
|
|
||||||
{
|
|
||||||
if(inp->state_timer < 0xFFFF) inp->state_timer++;
|
|
||||||
|
|
||||||
if(read_lvl != inp->proc.level)
|
|
||||||
{
|
|
||||||
//Debounce ongoing
|
|
||||||
inp->proc.dbnc_counter++;
|
|
||||||
if(inp->proc.dbnc_counter < inp->cfg.dbnc_treshold) return;
|
|
||||||
|
|
||||||
//Save level
|
|
||||||
inp->proc.level = read_lvl;
|
|
||||||
//Change state
|
|
||||||
if(inp->proc.level == inp->cfg.act_level) inp->is_active = 1;
|
|
||||||
else inp->is_active = 0;
|
|
||||||
// Update new flag
|
|
||||||
inp->is_new = 1;
|
|
||||||
// Reset state timer
|
|
||||||
inp->state_timer = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Debounce failed
|
|
||||||
if(inp->proc.dbnc_counter) inp->proc.dbnc_counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#ifndef INPUTS_H_
|
|
||||||
#define INPUTS_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "common/level.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef struct {
|
|
||||||
level_t act_level;
|
|
||||||
uint8_t dbnc_treshold;
|
|
||||||
} inChCfg_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
level_t level;
|
|
||||||
uint8_t dbnc_counter;
|
|
||||||
} inChRaw_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t is_active;
|
|
||||||
uint8_t is_new;
|
|
||||||
uint16_t state_timer;
|
|
||||||
inChRaw_t proc;
|
|
||||||
inChCfg_t cfg;
|
|
||||||
} inCh_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
inCh_t handbrake;
|
|
||||||
inCh_t brakes;
|
|
||||||
inCh_t dimm;
|
|
||||||
inCh_t up;
|
|
||||||
inCh_t down;
|
|
||||||
inCh_t mode;
|
|
||||||
} inputs_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Inputs_DefInit(inputs_t* inputs);
|
|
||||||
|
|
||||||
void Inputs_UpdateAll(inputs_t* inputs);
|
|
||||||
|
|
||||||
void Inputs_SetHanbrakePullUp(uint8_t on);
|
|
||||||
|
|
||||||
#endif /* INPUTS_H_ */
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "hal/udccd_hal.h"
|
|
||||||
#include "led_display.h"
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void LED_DSP_ShowImage(uint8_t image)
|
|
||||||
{
|
|
||||||
HAL_LEDS_Set(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LED_DSP_SetBrightness(uint8_t percent)
|
|
||||||
{
|
|
||||||
HAL_LEDS_SetPWM(percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#ifndef LED_DISPLAY_H_
|
|
||||||
#define LED_DISPLAY_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void LED_DSP_ShowImage(uint8_t image);
|
|
||||||
void LED_DSP_SetBrightness(uint8_t percent);
|
|
||||||
|
|
||||||
#endif /* LED_DISPLAY_H_ */
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include <avr/eeprom.h>
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
uint8_t MEM_Read8b(uint8_t address)
|
|
||||||
{
|
|
||||||
return eeprom_read_byte((uint8_t*)address);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t MEM_Read16b(uint8_t address)
|
|
||||||
{
|
|
||||||
return eeprom_read_word((uint8_t*)address);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MEM_Read32b(uint8_t address)
|
|
||||||
{
|
|
||||||
return eeprom_read_dword((uint8_t*)address);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MEM_Write8b(uint8_t address, uint8_t value)
|
|
||||||
{
|
|
||||||
return eeprom_write_byte((uint8_t*)address, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MEM_Write16b(uint8_t address, uint16_t value)
|
|
||||||
{
|
|
||||||
return eeprom_write_word((uint8_t*)address, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MEM_Write32b(uint8_t address, uint32_t value)
|
|
||||||
{
|
|
||||||
return eeprom_write_dword((uint8_t*)address, value);
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#ifndef MEMORY_H_
|
|
||||||
#define MEMORY_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
uint8_t MEM_Read8b(uint8_t address);
|
|
||||||
uint16_t MEM_Read16b(uint8_t address);
|
|
||||||
uint32_t MEM_Read32b(uint8_t address);
|
|
||||||
|
|
||||||
void MEM_Write8b(uint8_t address, uint8_t value);
|
|
||||||
void MEM_Write16b(uint8_t address, uint16_t value);
|
|
||||||
void MEM_Write32b(uint8_t address, uint32_t value);
|
|
||||||
|
|
||||||
#endif /* MEMORY_H_ */
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "display.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static uint8_t PWM_DIMM = 50;
|
|
||||||
static uint8_t PWM_BRIGTH = 100;
|
|
||||||
|
|
||||||
static uint8_t set_image = 0x00;
|
|
||||||
|
|
||||||
static uint16_t lock_timer = 0;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static uint8_t ImageGen_Dot10(uint8_t percent);
|
|
||||||
static uint8_t ImageGen_Dot20(uint8_t percent);
|
|
||||||
static uint8_t ImageGen_Bar(uint8_t percent);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Display_CfgBacklight(uint8_t brigth, uint8_t dimm)
|
|
||||||
{
|
|
||||||
//Limit values
|
|
||||||
if(brigth>100) brigth = 100;
|
|
||||||
else if(brigth==0) brigth = 1;
|
|
||||||
|
|
||||||
if(dimm>100) dimm = 100;
|
|
||||||
else if(dimm==0) dimm = 1;
|
|
||||||
|
|
||||||
//Save values
|
|
||||||
PWM_BRIGTH = brigth;
|
|
||||||
PWM_DIMM = dimm;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display_SetImage(uint8_t image)
|
|
||||||
{
|
|
||||||
if(lock_timer) return;
|
|
||||||
|
|
||||||
set_image = image & 0x3F;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display_SetPercent(uint8_t value, dspStyle_t style)
|
|
||||||
{
|
|
||||||
switch(style)
|
|
||||||
{
|
|
||||||
case BAR:
|
|
||||||
Display_SetImage(ImageGen_Bar(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DOT10:
|
|
||||||
Display_SetImage(ImageGen_Dot10(value));
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Display_SetImage(ImageGen_Dot20(value));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display_SetScale(uint16_t value, uint16_t max_value ,dspStyle_t style)
|
|
||||||
{
|
|
||||||
//Convert value to percent
|
|
||||||
uint32_t temp = (uint32_t)value *100;
|
|
||||||
temp /= max_value;
|
|
||||||
|
|
||||||
//Limit value to 100 percent
|
|
||||||
uint8_t percent = 0;
|
|
||||||
if(temp >= 100) percent = 100;
|
|
||||||
else if(temp == 0) percent = 0;
|
|
||||||
else percent = (uint8_t)temp;
|
|
||||||
|
|
||||||
Display_SetPercent(percent, style);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display_SetLock(uint16_t time)
|
|
||||||
{
|
|
||||||
lock_timer = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Display_Update(inputs_t* inputs)
|
|
||||||
{
|
|
||||||
// Brightness control
|
|
||||||
if(inputs->dimm.is_active) LED_DSP_SetBrightness(PWM_DIMM);
|
|
||||||
else LED_DSP_SetBrightness(PWM_BRIGTH);
|
|
||||||
|
|
||||||
if(lock_timer) lock_timer--;
|
|
||||||
|
|
||||||
// Set image
|
|
||||||
LED_DSP_ShowImage(set_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static uint8_t ImageGen_Dot10(uint8_t percent)
|
|
||||||
{
|
|
||||||
if(percent<6) return 0x01;
|
|
||||||
else if(percent<16) return 0x03;
|
|
||||||
else if(percent<26) return 0x02;
|
|
||||||
else if(percent<36) return 0x06;
|
|
||||||
else if(percent<46) return 0x04;
|
|
||||||
else if(percent<56) return 0x0C;
|
|
||||||
else if(percent<66) return 0x08;
|
|
||||||
else if(percent<76) return 0x18;
|
|
||||||
else if(percent<86) return 0x10;
|
|
||||||
else if(percent<96) return 0x30;
|
|
||||||
else return 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t ImageGen_Dot20(uint8_t percent)
|
|
||||||
{
|
|
||||||
if(percent<11) return 0x01;
|
|
||||||
else if(percent<31) return 0x02;
|
|
||||||
else if(percent<51) return 0x04;
|
|
||||||
else if(percent<71) return 0x08;
|
|
||||||
else if(percent<91) return 0x10;
|
|
||||||
else return 0x20;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t ImageGen_Bar(uint8_t percent)
|
|
||||||
{
|
|
||||||
if(percent<11) return 0x01;
|
|
||||||
else if(percent<31) return 0x03;
|
|
||||||
else if(percent<51) return 0x07;
|
|
||||||
else if(percent<71) return 0x0F;
|
|
||||||
else if(percent<91) return 0x1F;
|
|
||||||
else return 0x3F;
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#ifndef DISPLAY_DRV_H_
|
|
||||||
#define DISPLAY_DRV_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include "../devices/led_display.h"
|
|
||||||
#include "../devices/inputs.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef enum {
|
|
||||||
DOT20,
|
|
||||||
DOT10,
|
|
||||||
BAR
|
|
||||||
} dspStyle_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Display_SetImage(uint8_t image);
|
|
||||||
void Display_SetPercent(uint8_t value, dspStyle_t style);
|
|
||||||
void Display_SetScale(uint16_t value, uint16_t max_value ,dspStyle_t style);
|
|
||||||
|
|
||||||
void Display_SetLock(uint16_t time);
|
|
||||||
|
|
||||||
void Display_Update(inputs_t* inputs);
|
|
||||||
|
|
||||||
void Display_CfgBacklight(uint8_t brigth, uint8_t dimm);
|
|
||||||
|
|
||||||
#endif /* DISPLAY_DRV_H_ */
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "output.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
typedef struct {
|
|
||||||
uint8_t active;
|
|
||||||
uint8_t time;
|
|
||||||
} warn_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
warn_t supply_voltage;
|
|
||||||
warn_t supply_current;
|
|
||||||
warn_t supply_power;
|
|
||||||
warn_t output_voltage;
|
|
||||||
warn_t output_current;
|
|
||||||
warn_t output_power;
|
|
||||||
warn_t output_open;
|
|
||||||
warn_t output_short;
|
|
||||||
warn_t output_mismatch;
|
|
||||||
} warnings_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t supply_uvlo;
|
|
||||||
uint8_t supply_ovp;
|
|
||||||
uint8_t supply_ocp;
|
|
||||||
uint8_t supply_opp;
|
|
||||||
uint8_t output_ovp;
|
|
||||||
uint8_t output_ocp;
|
|
||||||
uint8_t output_opp;
|
|
||||||
uint8_t output_open;
|
|
||||||
uint8_t output_short;
|
|
||||||
} faults_t;
|
|
||||||
|
|
||||||
/**** Private constants ****/
|
|
||||||
static const uint16_t LIM_SUPPLY_UVLO = 8000; //mV
|
|
||||||
static const uint16_t LIM_SUPPLY_OVP = 18000; //mV
|
|
||||||
static const uint16_t LIM_SUPPLY_OCP = 7000; //mA
|
|
||||||
static const uint16_t LIM_SUPPLY_OPP = 40000; //mW
|
|
||||||
|
|
||||||
static const uint16_t LIM_OUTPUT_OVP = 12000; //mV
|
|
||||||
static const uint16_t LIM_OUTPUT_OCP = 7000; //mA
|
|
||||||
static const uint16_t LIM_OUTPUT_OPP = 40000; //mW
|
|
||||||
|
|
||||||
static const uint16_t LIM_OUTPUT_OPEN = 40000; //mR
|
|
||||||
static const uint16_t LIM_OUTPUT_SHORT = 750; //mR
|
|
||||||
|
|
||||||
static const uint16_t LIM_OUTPUT_MATCH = 100; //mV
|
|
||||||
|
|
||||||
static const uint8_t OCP_WARNING_LIMIT = 10; //cycles
|
|
||||||
static const uint8_t SHORT_WARNING_LIMIT = 50; //cycles
|
|
||||||
|
|
||||||
static const uint16_t MAX_OUTPUT_VOLTAGE = 10000; //mV
|
|
||||||
static const uint16_t MIN_OUTPUT_VOLTAGE = 100; //mV
|
|
||||||
|
|
||||||
static const uint16_t COOLDOWN_TIME = 5000;
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static warnings_t warnings;
|
|
||||||
static faults_t faults;
|
|
||||||
|
|
||||||
static uint16_t target_output = 0;
|
|
||||||
static uint16_t adj_target = 0;
|
|
||||||
|
|
||||||
static int32_t hb_volt_sum = 0;
|
|
||||||
|
|
||||||
static uint8_t new_target = 1;
|
|
||||||
|
|
||||||
static uint8_t steady_state = 0;
|
|
||||||
|
|
||||||
static faultState_t fault_state = F_NONE;
|
|
||||||
|
|
||||||
static uint16_t cooldown_timer = 0;
|
|
||||||
|
|
||||||
static outState_t out_state = O_OFF;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static void Process_Warnings(analog_t* meas);
|
|
||||||
static uint8_t Process_Faults(void);
|
|
||||||
|
|
||||||
static void ProcessWarningTime(warn_t* w);
|
|
||||||
static uint8_t isAnyFaultActive(faults_t* f);
|
|
||||||
static uint8_t isFaultWarningActive(warnings_t* w, faults_t* f);
|
|
||||||
static void ResetFaults(faults_t* f);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Output_Enable(void)
|
|
||||||
{
|
|
||||||
ResetFaults(&faults);
|
|
||||||
target_output = 0;
|
|
||||||
out_state = O_ACTIVE;
|
|
||||||
HB_SetTarget(0) ;
|
|
||||||
HB_SetLowSide(1);
|
|
||||||
HB_Enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Output_Update(analog_t* meas)
|
|
||||||
{
|
|
||||||
Process_Warnings(meas);
|
|
||||||
|
|
||||||
// Convert Warnings to Faults
|
|
||||||
uint8_t active_fault = Process_Faults();
|
|
||||||
|
|
||||||
/// Ignore faults
|
|
||||||
active_fault = 0;
|
|
||||||
|
|
||||||
// Determine coil state
|
|
||||||
switch(out_state)
|
|
||||||
{
|
|
||||||
case O_ACTIVE:
|
|
||||||
if(active_fault)
|
|
||||||
{
|
|
||||||
// Disable output
|
|
||||||
HB_Disable();
|
|
||||||
out_state = O_FAULTED;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Do target adjustment logic
|
|
||||||
if(steady_state >= 10)
|
|
||||||
{
|
|
||||||
//Calculate average HB voltage
|
|
||||||
hb_volt_sum /= 11;
|
|
||||||
|
|
||||||
// Calculate feedback adjusted HB output
|
|
||||||
int32_t error = hb_volt_sum - (int32_t)target_output;
|
|
||||||
int32_t temp = (int32_t)adj_target - error;
|
|
||||||
// Limit to 16bits
|
|
||||||
if(temp<=0) adj_target = 0;
|
|
||||||
else if(temp >= 0x0000FFFF) adj_target = 0xFFFF;
|
|
||||||
else adj_target = (uint16_t)temp;
|
|
||||||
steady_state = 0;
|
|
||||||
hb_volt_sum = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hb_volt_sum += meas->hb_voltage;
|
|
||||||
steady_state++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Closed loop or open loop target set
|
|
||||||
if(new_target)
|
|
||||||
{
|
|
||||||
// Set open-loop HB output
|
|
||||||
HB_SetTarget(target_output);
|
|
||||||
adj_target = target_output;
|
|
||||||
steady_state = 0;
|
|
||||||
new_target = 0;
|
|
||||||
hb_volt_sum = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HB_SetTarget(adj_target);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update output
|
|
||||||
HB_UpdateOutput(meas->supply_voltage);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case O_FAULTED:
|
|
||||||
if(!active_fault)
|
|
||||||
{
|
|
||||||
//Return to normal state
|
|
||||||
HB_Enable();
|
|
||||||
out_state = O_ACTIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: //OFF
|
|
||||||
if(HB_IsEnabled()) HB_Disable();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Output_SetTarget(uint16_t voltage)
|
|
||||||
{
|
|
||||||
if(voltage > MAX_OUTPUT_VOLTAGE) voltage = MAX_OUTPUT_VOLTAGE;
|
|
||||||
else if((voltage > 0)&&(voltage < MIN_OUTPUT_VOLTAGE)) voltage = MIN_OUTPUT_VOLTAGE;
|
|
||||||
|
|
||||||
if(voltage != target_output) new_target = 1;
|
|
||||||
target_output = voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
outState_t Output_GetOutputState(void)
|
|
||||||
{
|
|
||||||
return out_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static void Process_Warnings(analog_t* meas)
|
|
||||||
{
|
|
||||||
// Supply UVLO and OVP
|
|
||||||
if((meas->supply_voltage > LIM_SUPPLY_OVP)||(meas->supply_voltage < LIM_SUPPLY_UVLO)) warnings.supply_voltage.active = 1;
|
|
||||||
else warnings.supply_voltage.active = 0;
|
|
||||||
|
|
||||||
// Supply OCP
|
|
||||||
if(meas->supply_current > LIM_SUPPLY_OCP) warnings.supply_current.active = 1;
|
|
||||||
else warnings.supply_current.active = 0;
|
|
||||||
|
|
||||||
// Supply OPP
|
|
||||||
if(meas->supply_power > LIM_SUPPLY_OPP) warnings.supply_power.active = 1;
|
|
||||||
else warnings.supply_power.active = 0;
|
|
||||||
|
|
||||||
// Halfbridge output conditions
|
|
||||||
// Output Target mismatch
|
|
||||||
if(HB_IsOutputMatch(meas->hb_voltage, LIM_OUTPUT_MATCH) == 0) warnings.output_mismatch.active = 1;
|
|
||||||
else warnings.output_mismatch.active = 0;
|
|
||||||
|
|
||||||
// Output OCP
|
|
||||||
if((HB_IsLowOn())&&(meas->hb_currnet > LIM_OUTPUT_OCP)) warnings.output_current.active = 1;
|
|
||||||
else warnings.output_current.active = 0;
|
|
||||||
|
|
||||||
// Output OVP
|
|
||||||
if((HB_IsLowOn())&&(meas->hb_voltage > LIM_OUTPUT_OVP)) warnings.output_voltage.active = 1;
|
|
||||||
else warnings.output_voltage.active = 0;
|
|
||||||
|
|
||||||
// Output OPP
|
|
||||||
if((HB_IsEnabled())&&(meas->hb_power > LIM_OUTPUT_OPP)) warnings.output_power.active = 1;
|
|
||||||
else warnings.output_power.active = 0;
|
|
||||||
|
|
||||||
// Output Short
|
|
||||||
if((HB_IsEnabled())&&(meas->hb_resistance < LIM_OUTPUT_SHORT)) warnings.output_short.active = 1;
|
|
||||||
else warnings.output_short.active = 0;
|
|
||||||
|
|
||||||
// Output Open - Load loss
|
|
||||||
if((HB_IsEnabled())&&(meas->hb_resistance > LIM_OUTPUT_OPEN)) warnings.output_open.active = 1;
|
|
||||||
else warnings.output_open.active = 0;
|
|
||||||
|
|
||||||
ProcessWarningTime(&warnings.supply_voltage);
|
|
||||||
ProcessWarningTime(&warnings.supply_current);
|
|
||||||
ProcessWarningTime(&warnings.supply_power);
|
|
||||||
ProcessWarningTime(&warnings.output_mismatch);
|
|
||||||
ProcessWarningTime(&warnings.output_voltage);
|
|
||||||
ProcessWarningTime(&warnings.output_current);
|
|
||||||
ProcessWarningTime(&warnings.output_power);
|
|
||||||
ProcessWarningTime(&warnings.output_open);
|
|
||||||
ProcessWarningTime(&warnings.output_short);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t Process_Faults(void)
|
|
||||||
{
|
|
||||||
// Check warnings to escalate to fault
|
|
||||||
// Supply OCP
|
|
||||||
if(warnings.supply_current.time > OCP_WARNING_LIMIT) faults.supply_ocp = 1;
|
|
||||||
|
|
||||||
// Output OCP
|
|
||||||
if(warnings.output_current.time > OCP_WARNING_LIMIT) faults.output_ocp = 1;
|
|
||||||
|
|
||||||
// Output short
|
|
||||||
if(warnings.output_short.time > SHORT_WARNING_LIMIT) faults.output_short = 1;
|
|
||||||
|
|
||||||
switch(fault_state)
|
|
||||||
{
|
|
||||||
case F_ACTIVE:
|
|
||||||
// Check if fault still active
|
|
||||||
if(!isFaultWarningActive(&warnings, &faults))
|
|
||||||
{
|
|
||||||
// Fault cause ended, go to cooldown
|
|
||||||
cooldown_timer = COOLDOWN_TIME;
|
|
||||||
fault_state = F_COOLDOWN;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
case F_COOLDOWN:
|
|
||||||
// Check if fault reoccurs
|
|
||||||
if(isFaultWarningActive(&warnings, &faults))
|
|
||||||
{
|
|
||||||
fault_state = F_ACTIVE;
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Wait for cooldown timer, reset fault flags
|
|
||||||
if(cooldown_timer) cooldown_timer--;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ResetFaults(&faults);
|
|
||||||
fault_state = F_NONE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: //NONE
|
|
||||||
// Check for new faults
|
|
||||||
if(isAnyFaultActive(&faults))
|
|
||||||
{
|
|
||||||
// Start fault process
|
|
||||||
fault_state = F_ACTIVE;
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fault_state != F_NONE) return 1;
|
|
||||||
else return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ProcessWarningTime(warn_t* w)
|
|
||||||
{
|
|
||||||
if((w->active)&&(w->time < 0xFF)) w->time++;
|
|
||||||
else if(w->active == 0) w->time = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t isAnyFaultActive(faults_t* f)
|
|
||||||
{
|
|
||||||
if(f->supply_uvlo) return 1;
|
|
||||||
if(f->supply_ovp) return 1;
|
|
||||||
if(f->supply_ocp) return 1;
|
|
||||||
if(f->supply_opp) return 1;
|
|
||||||
if(f->output_ovp) return 1;
|
|
||||||
if(f->output_ocp) return 1;
|
|
||||||
if(f->output_opp) return 1;
|
|
||||||
if(f->output_open) return 1;
|
|
||||||
if(f->output_short) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t isFaultWarningActive(warnings_t* w, faults_t* f)
|
|
||||||
{
|
|
||||||
if((f->supply_uvlo) && (w->supply_voltage.active)) return 1;
|
|
||||||
if((f->supply_ovp) && (w->supply_voltage.active)) return 1;
|
|
||||||
if((f->supply_ocp) && (w->supply_current.active)) return 1;
|
|
||||||
if((f->supply_opp) && (w->supply_power.active) ) return 1;
|
|
||||||
if((f->output_ovp) && (w->output_voltage.active)) return 1;
|
|
||||||
if((f->output_ocp) && (w->output_current.active)) return 1;
|
|
||||||
if((f->output_opp) && (w->output_power.active) ) return 1;
|
|
||||||
if((f->output_open) && (w->output_open.active) ) return 1;
|
|
||||||
if((f->output_short) && (w->output_short.active) ) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ResetFaults(faults_t* f)
|
|
||||||
{
|
|
||||||
f->supply_uvlo = 0;
|
|
||||||
f->supply_ovp = 0;
|
|
||||||
f->supply_ocp = 0;
|
|
||||||
f->supply_opp = 0;
|
|
||||||
f->output_ovp = 0;
|
|
||||||
f->output_ocp = 0;
|
|
||||||
f->output_opp = 0;
|
|
||||||
f->output_open = 0;
|
|
||||||
f->output_short = 0;
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#ifndef OUTPUT_DRV_H_
|
|
||||||
#define OUTPUT_DRV_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <avr/io.h>
|
|
||||||
#include "../devices/analog.h"
|
|
||||||
#include "../devices/halfbridge.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef enum {
|
|
||||||
F_NONE,
|
|
||||||
F_ACTIVE,
|
|
||||||
F_COOLDOWN
|
|
||||||
} faultState_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
O_OFF,
|
|
||||||
O_ACTIVE,
|
|
||||||
O_FAULTED
|
|
||||||
} outState_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Output_Enable(void);
|
|
||||||
void Output_Update(analog_t* meas);
|
|
||||||
|
|
||||||
void Output_SetTarget(uint16_t voltage);
|
|
||||||
|
|
||||||
outState_t Output_GetOutputState(void);
|
|
||||||
|
|
||||||
#endif /* OUTPUT_DRV_H_ */
|
|
||||||
@@ -1,127 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "coil.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private constants ****/
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static uint16_t lock_current = 4500; //mA
|
|
||||||
static uint16_t min_current = 100; //mA
|
|
||||||
static uint16_t target_current = 0; //mA
|
|
||||||
static uint8_t new_target = 1;
|
|
||||||
|
|
||||||
static uint16_t adj_target_current = 0; //mA
|
|
||||||
static uint16_t target_voltage = 0; //mV
|
|
||||||
|
|
||||||
static uint8_t act_force = 0;
|
|
||||||
|
|
||||||
static uint16_t nominal_resitance = 1500; //mR
|
|
||||||
|
|
||||||
static int32_t sum_current = 0;
|
|
||||||
static uint8_t sum_cnt = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static uint16_t UpdateVoltage(uint16_t cur, uint16_t res);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Coil_SetLockCurrent(uint16_t lock_i)
|
|
||||||
{
|
|
||||||
lock_current = lock_i;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Coil_SetTarget_Force(uint8_t force)
|
|
||||||
{
|
|
||||||
// Check if worth doing
|
|
||||||
if(force == act_force) return;
|
|
||||||
|
|
||||||
// Calculate new target current
|
|
||||||
act_force = force;
|
|
||||||
|
|
||||||
// Check simple answer
|
|
||||||
uint16_t new_current = 0;
|
|
||||||
if(force==0) new_current = 0;
|
|
||||||
else if(force >= 100) new_current = lock_current;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t temp = (uint32_t)force * lock_current;
|
|
||||||
temp /= 100;
|
|
||||||
|
|
||||||
if(temp > 0x0000FFFF) new_current = lock_current;
|
|
||||||
else new_current = (uint16_t) temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update new target
|
|
||||||
Coil_SetTarget_Current(new_current);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Coil_SetTarget_Current(uint16_t current)
|
|
||||||
{
|
|
||||||
if(current >= lock_current) current = lock_current;
|
|
||||||
else if((current > 0)&&(current <= min_current)) current = min_current;
|
|
||||||
|
|
||||||
if(current != target_current) new_target = 1;
|
|
||||||
target_current = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t Coil_GetTargetVolatge(void)
|
|
||||||
{
|
|
||||||
return target_voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t Coil_Update(analog_t* meas)
|
|
||||||
{
|
|
||||||
// Collect average current
|
|
||||||
sum_current += meas->hb_currnet;
|
|
||||||
sum_cnt++;
|
|
||||||
|
|
||||||
// Update measurement
|
|
||||||
if(sum_cnt >= 10)
|
|
||||||
{
|
|
||||||
// Calculate average
|
|
||||||
sum_current /= sum_cnt;
|
|
||||||
|
|
||||||
// Calculate error
|
|
||||||
int32_t error = sum_current - (int32_t)target_current;
|
|
||||||
int32_t temp = (int32_t)adj_target_current - error;
|
|
||||||
|
|
||||||
// Limit to 16bits
|
|
||||||
if(temp<0) adj_target_current = 0;
|
|
||||||
else if(temp > 0x0000FFFF) adj_target_current = 0xFFFF;
|
|
||||||
else adj_target_current = (uint16_t)temp;
|
|
||||||
sum_cnt = 0;
|
|
||||||
sum_current = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Closed loop or open loop target set
|
|
||||||
if(new_target)
|
|
||||||
{
|
|
||||||
// Set open-loop HB output
|
|
||||||
target_voltage = UpdateVoltage(target_current, nominal_resitance);
|
|
||||||
adj_target_current = target_current;
|
|
||||||
new_target = 0;
|
|
||||||
sum_cnt = 0;
|
|
||||||
sum_current = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
target_voltage = UpdateVoltage(adj_target_current, nominal_resitance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return target_voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static uint16_t UpdateVoltage(uint16_t cur, uint16_t res)
|
|
||||||
{
|
|
||||||
// Update settable voltage
|
|
||||||
if(cur==0) return 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t volt = (uint32_t)cur * res;
|
|
||||||
volt /= 1000;
|
|
||||||
if(volt > 0x0000FFFF) return 0xFFFF;
|
|
||||||
else return (uint16_t)volt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#ifndef COIL_LOGIC_H_
|
|
||||||
#define COIL_LOGIC_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../devices/analog.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Coil_SetTarget_Force(uint8_t force);
|
|
||||||
void Coil_SetTarget_Current(uint16_t current);
|
|
||||||
uint16_t Coil_GetTargetVolatge(void);
|
|
||||||
|
|
||||||
uint16_t Coil_Update(analog_t* meas);
|
|
||||||
|
|
||||||
void Coil_SetLockCurrent(uint16_t lock_i);
|
|
||||||
|
|
||||||
#endif /* COIL_LOGIC_H_ */
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "force.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private constants ****/
|
|
||||||
static const int8_t BUTTONS_STEP = 10;
|
|
||||||
static const uint16_t BUTTON_HOLD_TIME = 250;
|
|
||||||
static const uint16_t MODE_HOLD_TIME = 500;
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static inputMode_t input_mode = IM_BUTTONS;
|
|
||||||
|
|
||||||
static uint8_t user_force = 0;
|
|
||||||
static uint8_t new_user_force = 0;
|
|
||||||
|
|
||||||
static brakeMode_t brake_mode = BM_OPEN;
|
|
||||||
static uint8_t new_brake_mode = 1;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
static uint8_t SaturatedAdd(uint8_t base, int8_t delta);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
inputMode_t Force_GetInputMode(void)
|
|
||||||
{
|
|
||||||
return input_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Force_CfgInputMode(inputMode_t in_mode)
|
|
||||||
{
|
|
||||||
input_mode = in_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Force_SetUserForce(uint8_t force)
|
|
||||||
{
|
|
||||||
if(force > 100) force = 100;
|
|
||||||
user_force = force;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Force_SetBrakeMode(uint8_t bmode)
|
|
||||||
{
|
|
||||||
brake_mode = bmode;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Force_Update(inputs_t* inputs, analog_t* meas)
|
|
||||||
{
|
|
||||||
// Process user inputs
|
|
||||||
if(input_mode==IM_POT)
|
|
||||||
{
|
|
||||||
// Process potentiometer
|
|
||||||
if(meas->pot_voltage <= 500) user_force = 0;
|
|
||||||
else if(meas->pot_voltage >= 4500 ) user_force = 100;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint16_t pot_u = meas->pot_voltage;
|
|
||||||
pot_u /= 50;
|
|
||||||
|
|
||||||
//Limit to 100
|
|
||||||
if(pot_u > 100) user_force = 100;
|
|
||||||
else if(pot_u < 10) user_force = 10;
|
|
||||||
else user_force = (uint8_t)pot_u;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Process +/- timer
|
|
||||||
if((inputs->down.is_active)&&(inputs->down.state_timer > BUTTON_HOLD_TIME))
|
|
||||||
{
|
|
||||||
inputs->down.is_new = 1;
|
|
||||||
inputs->down.state_timer = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
if((inputs->up.is_active)&&(inputs->up.state_timer > BUTTON_HOLD_TIME))
|
|
||||||
{
|
|
||||||
inputs->up.is_new = 1;
|
|
||||||
inputs->up.state_timer = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Process +/- logic
|
|
||||||
if((inputs->down.is_new)&&(inputs->down.is_active))
|
|
||||||
{
|
|
||||||
user_force = SaturatedAdd(user_force, -1 * BUTTONS_STEP);
|
|
||||||
new_user_force = 1;
|
|
||||||
}
|
|
||||||
else if((inputs->up.is_new)&&(inputs->up.is_active))
|
|
||||||
{
|
|
||||||
user_force = SaturatedAdd(user_force, BUTTONS_STEP);
|
|
||||||
new_user_force = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
inputs->down.is_new = 0;
|
|
||||||
inputs->up.is_new = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process mode timer
|
|
||||||
if((inputs->mode.is_active)&&(inputs->mode.state_timer > MODE_HOLD_TIME))
|
|
||||||
{
|
|
||||||
inputs->mode.is_new = 1;
|
|
||||||
inputs->mode.state_timer = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Process mode logic
|
|
||||||
if((inputs->mode.is_new)&&(inputs->mode.is_active))
|
|
||||||
{
|
|
||||||
//Cycle mode
|
|
||||||
switch(brake_mode)
|
|
||||||
{
|
|
||||||
case BM_OPEN:
|
|
||||||
brake_mode = BM_KEEP;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BM_KEEP:
|
|
||||||
brake_mode = BM_LOCK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BM_LOCK:
|
|
||||||
brake_mode = BM_OPEN;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
brake_mode = BM_OPEN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
new_brake_mode = 1;
|
|
||||||
};
|
|
||||||
inputs->mode.is_new = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Determine next target force from inputs
|
|
||||||
if(inputs->handbrake.is_active)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if(inputs->brakes.is_active)
|
|
||||||
{
|
|
||||||
switch(brake_mode)
|
|
||||||
{
|
|
||||||
case BM_LOCK:
|
|
||||||
return 100;
|
|
||||||
|
|
||||||
case BM_KEEP:
|
|
||||||
return user_force;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return user_force;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Force_IsNewUserForce(void)
|
|
||||||
{
|
|
||||||
return new_user_force;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Force_ResetNewUserForce(void)
|
|
||||||
{
|
|
||||||
new_user_force = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
brakeMode_t Force_GetBrakeMode(void)
|
|
||||||
{
|
|
||||||
return brake_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Force_IsNewBrakeMode(void)
|
|
||||||
{
|
|
||||||
return new_brake_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Force_ResetNewBrakeMode(void)
|
|
||||||
{
|
|
||||||
new_brake_mode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
static uint8_t SaturatedAdd(uint8_t base, int8_t delta)
|
|
||||||
{
|
|
||||||
int16_t temp = (int16_t)base + delta;
|
|
||||||
if(temp < 0) return 0;
|
|
||||||
else if(temp >= 100) return 100;
|
|
||||||
else return (uint8_t)temp;
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#ifndef FORCE_LOGIC_H_
|
|
||||||
#define FORCE_LOGIC_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../devices/analog.h"
|
|
||||||
#include "../devices/inputs.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
typedef enum {
|
|
||||||
BM_OPEN,
|
|
||||||
BM_KEEP,
|
|
||||||
BM_LOCK
|
|
||||||
} brakeMode_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
IM_BUTTONS,
|
|
||||||
IM_POT
|
|
||||||
} inputMode_t;
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Force_CfgInputMode(inputMode_t in_mode);
|
|
||||||
inputMode_t Force_GetInputMode(void);
|
|
||||||
|
|
||||||
uint8_t Force_Update(inputs_t* inputs, analog_t* meas);
|
|
||||||
|
|
||||||
void Force_SetBrakeMode(uint8_t bmode);
|
|
||||||
brakeMode_t Force_GetBrakeMode(void);
|
|
||||||
uint8_t Force_IsNewBrakeMode(void);
|
|
||||||
void Force_ResetNewBrakeMode(void);
|
|
||||||
|
|
||||||
void Force_SetUserForce(uint8_t force);
|
|
||||||
uint8_t Force_IsNewUserForce(void);
|
|
||||||
void Force_ResetNewUserForce(void);
|
|
||||||
|
|
||||||
#endif /* FORCE_LOGIC_H_ */
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include "settings.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private constants ****/
|
|
||||||
static const uint8_t addr_force = 0x01;
|
|
||||||
static const uint8_t addr_bmode = 0x02;
|
|
||||||
static const uint8_t addr_inmode = 0x03;
|
|
||||||
|
|
||||||
static const uint8_t addr_dsp_bright = 0x04;
|
|
||||||
static const uint8_t addr_dsp_dimm = 0x05;
|
|
||||||
|
|
||||||
static const uint8_t addr_lock_amps = 0x06;
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
static uint16_t save_force_timer = 0;
|
|
||||||
static uint16_t save_bmode_timer = 0;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
void Setings_Update(uint8_t is_new_force, uint8_t force, uint8_t is_new_bmode, brakeMode_t bmode)
|
|
||||||
{
|
|
||||||
if(is_new_force) save_force_timer = 5000;
|
|
||||||
|
|
||||||
if(is_new_bmode) save_bmode_timer = 5000;
|
|
||||||
|
|
||||||
if(save_force_timer)
|
|
||||||
{
|
|
||||||
save_force_timer--;
|
|
||||||
if(!save_force_timer)
|
|
||||||
{
|
|
||||||
// Save force setting
|
|
||||||
Setings_SaveForce(force);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if(save_bmode_timer)
|
|
||||||
{
|
|
||||||
save_bmode_timer--;
|
|
||||||
if(!save_bmode_timer)
|
|
||||||
{
|
|
||||||
// Save mode setting
|
|
||||||
Setings_SaveBrakeMode(bmode);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveForce(uint8_t value)
|
|
||||||
{
|
|
||||||
MEM_Write8b(addr_force, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Setings_GetForce(void)
|
|
||||||
{
|
|
||||||
uint8_t val = MEM_Read8b(addr_force);
|
|
||||||
if(val > 100) return 0;
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveBrakeMode(brakeMode_t bmode)
|
|
||||||
{
|
|
||||||
// Convert and save input mode setting
|
|
||||||
// Convert and save mode setting
|
|
||||||
uint8_t val = 0x00;
|
|
||||||
switch(bmode)
|
|
||||||
{
|
|
||||||
case BM_LOCK:
|
|
||||||
val = 'L';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BM_KEEP:
|
|
||||||
val = 'K';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
val = 'O';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MEM_Write8b(addr_bmode, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
brakeMode_t Setings_GetBrakeMode(void)
|
|
||||||
{
|
|
||||||
// Convert and return mode setting
|
|
||||||
uint8_t val = MEM_Read8b(addr_bmode);
|
|
||||||
switch(val)
|
|
||||||
{
|
|
||||||
case 'L':
|
|
||||||
return BM_LOCK;
|
|
||||||
|
|
||||||
case 'K':
|
|
||||||
return BM_KEEP;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return BM_OPEN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveInputMode(inputMode_t inmode)
|
|
||||||
{
|
|
||||||
// Convert and save input mode setting
|
|
||||||
uint8_t val = 0x00;
|
|
||||||
switch(inmode)
|
|
||||||
{
|
|
||||||
case IM_POT:
|
|
||||||
val = 'P';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
val = 'B';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
MEM_Write8b(addr_inmode, val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inputMode_t Setings_GetInputMode(void)
|
|
||||||
{
|
|
||||||
// Convert and return input mode setting
|
|
||||||
uint8_t val = MEM_Read8b(addr_inmode);
|
|
||||||
switch(val)
|
|
||||||
{
|
|
||||||
case 'P':
|
|
||||||
return IM_POT;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return IM_BUTTONS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveDisplayBrigthLvl(uint8_t value)
|
|
||||||
{
|
|
||||||
MEM_Write8b(addr_dsp_bright, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Setings_GetDisplayBrigthLvl(void)
|
|
||||||
{
|
|
||||||
uint8_t val = MEM_Read8b(addr_dsp_bright);
|
|
||||||
if(val > 100) return 100;
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveDisplayDimmLvl(uint8_t value)
|
|
||||||
{
|
|
||||||
MEM_Write8b(addr_dsp_dimm, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t Setings_GetDisplayDimmLvl(void)
|
|
||||||
{
|
|
||||||
uint8_t val = MEM_Read8b(addr_dsp_dimm);
|
|
||||||
if(val > 100) return 50;
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Setings_SaveLockCurrent(uint16_t value)
|
|
||||||
{
|
|
||||||
MEM_Write16b(addr_lock_amps, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t Setings_GetLockCurrent(void)
|
|
||||||
{
|
|
||||||
uint16_t val = MEM_Read16b(addr_lock_amps);
|
|
||||||
if(val > 6000) return 4500;
|
|
||||||
else return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Setings_SaveDefault(void)
|
|
||||||
{
|
|
||||||
Setings_SaveForce(0);
|
|
||||||
Setings_SaveBrakeMode(BM_OPEN);
|
|
||||||
Setings_SaveInputMode(IM_BUTTONS);
|
|
||||||
Setings_SaveDisplayBrigthLvl(100);
|
|
||||||
Setings_SaveDisplayDimmLvl(50);
|
|
||||||
Setings_SaveLockCurrent(4500);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
#ifndef SETTINGS_LOGIC_H_
|
|
||||||
#define SETTINGS_LOGIC_H_
|
|
||||||
|
|
||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "../devices/memory.h"
|
|
||||||
#include "force.h"
|
|
||||||
|
|
||||||
/**** Public definitions ****/
|
|
||||||
|
|
||||||
/**** Public function declarations ****/
|
|
||||||
void Setings_Update(uint8_t is_new_force, uint8_t force, uint8_t is_new_bmode, brakeMode_t bmode);
|
|
||||||
|
|
||||||
void Setings_SaveForce(uint8_t value);
|
|
||||||
uint8_t Setings_GetForce(void);
|
|
||||||
|
|
||||||
void Setings_SaveBrakeMode(brakeMode_t bmode);
|
|
||||||
brakeMode_t Setings_GetBrakeMode(void);
|
|
||||||
|
|
||||||
void Setings_SaveInputMode(inputMode_t inmode);
|
|
||||||
inputMode_t Setings_GetInputMode(void);
|
|
||||||
|
|
||||||
void Setings_SaveDisplayBrigthLvl(uint8_t value);
|
|
||||||
uint8_t Setings_GetDisplayBrigthLvl(void);
|
|
||||||
|
|
||||||
void Setings_SaveDisplayDimmLvl(uint8_t value);
|
|
||||||
uint8_t Setings_GetDisplayDimmLvl(void);
|
|
||||||
|
|
||||||
void Setings_SaveLockCurrent(uint16_t value);
|
|
||||||
uint16_t Setings_GetLockCurrent(void);
|
|
||||||
|
|
||||||
void Setings_SaveDefault(void);
|
|
||||||
|
|
||||||
#endif /* SETTINGS_LOGIC_H_ */
|
|
||||||
170
firmware/main.c
170
firmware/main.c
@@ -1,170 +0,0 @@
|
|||||||
/**** Includes ****/
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "devices/config.h"
|
|
||||||
#include "devices/analog.h"
|
|
||||||
#include "devices/inputs.h"
|
|
||||||
#include "devices/memory.h"
|
|
||||||
|
|
||||||
#include "drivers/output.h"
|
|
||||||
#include "drivers/display.h"
|
|
||||||
|
|
||||||
#include "logic/force.h"
|
|
||||||
#include "logic/coil.h"
|
|
||||||
#include "logic/settings.h"
|
|
||||||
|
|
||||||
/**** Private definitions ****/
|
|
||||||
|
|
||||||
/**** Private constants ****/
|
|
||||||
|
|
||||||
/**** Private variables ****/
|
|
||||||
inputs_t inputs;
|
|
||||||
analog_t analog;
|
|
||||||
|
|
||||||
/**** Private function declarations ****/
|
|
||||||
void Setup(void);
|
|
||||||
void GatherData(uint8_t times);
|
|
||||||
|
|
||||||
/**** Public function definitions ****/
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
Setup();
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
{
|
|
||||||
// Read all inputs
|
|
||||||
GatherData(1);
|
|
||||||
|
|
||||||
// Process force logic
|
|
||||||
uint8_t force = Force_Update(&inputs, &analog);
|
|
||||||
|
|
||||||
// Save values
|
|
||||||
uint8_t new_bmode = Force_IsNewBrakeMode();
|
|
||||||
uint8_t new_force = Force_IsNewUserForce();
|
|
||||||
if(Force_GetInputMode()==IM_POT) new_force = 0;
|
|
||||||
Setings_Update(new_force, force, new_bmode, Force_GetBrakeMode());
|
|
||||||
|
|
||||||
// Set coil current target
|
|
||||||
Coil_SetTarget_Force(force);
|
|
||||||
|
|
||||||
// Calculate next target voltage
|
|
||||||
uint16_t next_u = Coil_Update(&analog);
|
|
||||||
|
|
||||||
// Set next output voltage
|
|
||||||
Output_SetTarget(next_u);
|
|
||||||
|
|
||||||
// Update output
|
|
||||||
Output_Update(&analog);
|
|
||||||
|
|
||||||
|
|
||||||
// Display logic
|
|
||||||
if(Output_GetOutputState()==O_FAULTED)
|
|
||||||
{
|
|
||||||
// Show fault code
|
|
||||||
Display_SetLock(0);
|
|
||||||
Display_SetImage(0x33);
|
|
||||||
}
|
|
||||||
else if(Force_IsNewBrakeMode())
|
|
||||||
{
|
|
||||||
Display_SetLock(0);
|
|
||||||
switch(Force_GetBrakeMode())
|
|
||||||
{
|
|
||||||
case BM_LOCK:
|
|
||||||
Display_SetImage(0x38);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BM_KEEP:
|
|
||||||
Display_SetImage(0x1E);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Display_SetImage(0x07);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Display_SetLock(1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Display_SetPercent(force, DOT10);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update display
|
|
||||||
Display_Update(&inputs);
|
|
||||||
|
|
||||||
// Reset new flags
|
|
||||||
Force_ResetNewBrakeMode();
|
|
||||||
Force_ResetNewUserForce();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**** Private function definitions ****/
|
|
||||||
void Setup(void)
|
|
||||||
{
|
|
||||||
// Initialize low level hardware
|
|
||||||
Init_HW();
|
|
||||||
|
|
||||||
// Prime EEPROM
|
|
||||||
//Setings_SaveDefault();
|
|
||||||
|
|
||||||
// Configure inputs
|
|
||||||
Inputs_DefInit(&inputs);
|
|
||||||
|
|
||||||
inputs.handbrake.cfg.act_level = HIGH;
|
|
||||||
inputs.handbrake.cfg.dbnc_treshold = 10;
|
|
||||||
|
|
||||||
inputs.brakes.cfg.act_level = LOW;
|
|
||||||
inputs.brakes.cfg.dbnc_treshold = 20;
|
|
||||||
|
|
||||||
inputs.dimm.cfg.act_level = LOW;
|
|
||||||
inputs.dimm.cfg.dbnc_treshold = 20;
|
|
||||||
|
|
||||||
inputs.up.cfg.act_level = LOW;
|
|
||||||
inputs.up.cfg.dbnc_treshold = 20;
|
|
||||||
|
|
||||||
inputs.down.cfg.act_level = LOW;
|
|
||||||
inputs.down.cfg.dbnc_treshold = 20;
|
|
||||||
|
|
||||||
inputs.mode.cfg.act_level = LOW;
|
|
||||||
inputs.mode.cfg.dbnc_treshold = 20;
|
|
||||||
|
|
||||||
Inputs_SetHanbrakePullUp(0);
|
|
||||||
|
|
||||||
// Configure display
|
|
||||||
Display_CfgBacklight(100,50);
|
|
||||||
// Show startup display
|
|
||||||
Display_SetImage(0xFF);
|
|
||||||
Display_Update(&inputs);
|
|
||||||
|
|
||||||
// Configure force logic
|
|
||||||
Force_CfgInputMode(IM_POT); //IM_BUTTONS IM_POT
|
|
||||||
|
|
||||||
// Restore saved force
|
|
||||||
Force_SetUserForce(Setings_GetForce());
|
|
||||||
|
|
||||||
// Restore saved brake mode
|
|
||||||
Force_SetBrakeMode(Setings_GetBrakeMode());
|
|
||||||
|
|
||||||
// Prime analog channels
|
|
||||||
GatherData(100);
|
|
||||||
|
|
||||||
// Show default display
|
|
||||||
Display_SetImage(0x01);
|
|
||||||
Display_Update(&inputs);
|
|
||||||
|
|
||||||
// Enable output
|
|
||||||
Output_Enable();
|
|
||||||
Output_SetTarget(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GatherData(uint8_t times)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
Analog_UpdateAll(&analog);
|
|
||||||
Inputs_UpdateAll(&inputs);
|
|
||||||
if(times) times--;
|
|
||||||
}
|
|
||||||
while(times);
|
|
||||||
}
|
|
||||||
45
firmware/src/bsp/ain.cpp
Normal file
45
firmware/src/bsp/ain.cpp
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "ain.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::AnalogIn::AnalogIn(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::AnalogIn::~AnalogIn(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::AnalogIn::init(uint8_t adc_ch)
|
||||||
|
{
|
||||||
|
this->adc_ch = adc_ch;
|
||||||
|
this->mul = DEF_AIN_MUL;
|
||||||
|
this->div = DEF_AIN_DIV;
|
||||||
|
this->offset = DEF_AIN_OFFSET;
|
||||||
|
this->last_read = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t bsp::AnalogIn::read(void)
|
||||||
|
{
|
||||||
|
//Read ADC
|
||||||
|
uint16_t raw = mcu::adc_read(this->adc_ch);
|
||||||
|
|
||||||
|
//Convert to mV
|
||||||
|
this->last_read = util::convert_muldivoff(raw, this->mul, this->div, this->offset);
|
||||||
|
|
||||||
|
return this->last_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
42
firmware/src/bsp/ain.h
Normal file
42
firmware/src/bsp/ain.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#ifndef ANALOG_IN_H_
|
||||||
|
#define ANALOG_IN_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
static const uint8_t DEF_AIN_MUL = 215;
|
||||||
|
static const uint8_t DEF_AIN_DIV = 44;
|
||||||
|
static const int16_t DEF_AIN_OFFSET = 0;
|
||||||
|
|
||||||
|
class AnalogIn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnalogIn(void);
|
||||||
|
~AnalogIn(void);
|
||||||
|
|
||||||
|
void init(uint8_t adc_ch);
|
||||||
|
|
||||||
|
uint8_t mul;
|
||||||
|
uint8_t div;
|
||||||
|
int16_t offset;
|
||||||
|
uint16_t last_read;
|
||||||
|
|
||||||
|
uint16_t read(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
uint8_t adc_ch;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* ANALOG_IN_H_ */
|
||||||
52
firmware/src/bsp/ain_lpf.cpp
Normal file
52
firmware/src/bsp/ain_lpf.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "ain_lpf.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::AnalogInLfp::AnalogInLfp(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::AnalogInLfp::~AnalogInLfp(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::AnalogInLfp::init(uint8_t adc_ch)
|
||||||
|
{
|
||||||
|
this->adc_ch = adc_ch;
|
||||||
|
this->mul = DEF_AIN_MUL;
|
||||||
|
this->div = DEF_AIN_DIV;
|
||||||
|
this->offset = DEF_AIN_OFFSET;
|
||||||
|
this->strength = 0;
|
||||||
|
this->last_read = 0;
|
||||||
|
this->last_read_direct = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bsp::AnalogInLfp::read(void)
|
||||||
|
{
|
||||||
|
//Read ADC
|
||||||
|
uint16_t raw = mcu::adc_read(this->adc_ch);
|
||||||
|
|
||||||
|
//Convert to mV
|
||||||
|
this->last_read_direct = util::convert_muldivoff(raw, this->mul, this->div, this->offset);
|
||||||
|
|
||||||
|
// Do filtering
|
||||||
|
uint32_t td0 = ((uint32_t)(255 - this->strength) * this->last_read_direct);
|
||||||
|
uint32_t td1 = ((uint32_t)(this->strength) * this->last_read);
|
||||||
|
uint32_t out = (td0 + td1)/255;
|
||||||
|
|
||||||
|
this->last_read = util::sat_cast(out);
|
||||||
|
|
||||||
|
return this->last_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
36
firmware/src/bsp/ain_lpf.h
Normal file
36
firmware/src/bsp/ain_lpf.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef ANALOG_IN_LPF_H_
|
||||||
|
#define ANALOG_IN_LPF_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "ain.h"
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class AnalogInLfp : public AnalogIn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// New stuff
|
||||||
|
AnalogInLfp(void);
|
||||||
|
~AnalogInLfp(void);
|
||||||
|
|
||||||
|
void init(uint8_t adc_ch);
|
||||||
|
uint16_t read(void);
|
||||||
|
|
||||||
|
uint8_t strength;
|
||||||
|
uint16_t last_read_direct;
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* ANALOG_IN_LPF_H_ */
|
||||||
108
firmware/src/bsp/board.cpp
Normal file
108
firmware/src/bsp/board.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::Board::Board(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::Board::~Board(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::Board::init(boardCfg_t* cfg)
|
||||||
|
{
|
||||||
|
// Calculate settings
|
||||||
|
|
||||||
|
// Controller setup
|
||||||
|
mcu::startupCfg_t mcu_cfg;
|
||||||
|
|
||||||
|
mcu_cfg.adc_clk = mcu::ADC_DIV64; // 8MHz/64=125kHz
|
||||||
|
mcu_cfg.pwm_clk = mcu::TIM_DIV1; // 8MHz/1 = 8MHz
|
||||||
|
mcu_cfg.pwm_top = 4000/(uint16_t)cfg->pwm_f_khz;
|
||||||
|
mcu_cfg.od_common_is_pwm = cfg->od_common_is_pwm;
|
||||||
|
|
||||||
|
mcu::startup(&mcu_cfg);
|
||||||
|
|
||||||
|
// Analog inputs
|
||||||
|
this->out_voltage.init(mcu::ADC_VOUT);
|
||||||
|
this->out_voltage.mul = 20;
|
||||||
|
this->out_voltage.div = 1;
|
||||||
|
this->out_voltage.offset = 0;
|
||||||
|
|
||||||
|
this->out_current.init(mcu::ADC_IOUT);
|
||||||
|
this->out_current.mul = 215;
|
||||||
|
this->out_current.div = 22;
|
||||||
|
this->out_current.offset = 0;
|
||||||
|
|
||||||
|
this->battery_voltage.init(mcu::ADC_VBAT);
|
||||||
|
this->battery_voltage.mul = 20;
|
||||||
|
this->battery_voltage.div = 1;
|
||||||
|
this->battery_voltage.offset = 0;
|
||||||
|
|
||||||
|
this->battery_current.init(mcu::ADC_IBAT);
|
||||||
|
this->battery_current.mul = 235;
|
||||||
|
this->battery_current.div = 6;
|
||||||
|
this->battery_current.offset = 0;
|
||||||
|
|
||||||
|
this->ain1.init(mcu::ADC_AIN1);
|
||||||
|
this->ain2.init(mcu::ADC_AIN2);
|
||||||
|
|
||||||
|
// Digital inputs
|
||||||
|
this->din1.init(mcu::GPIO_DIN1, 0);
|
||||||
|
this->din2.init(mcu::GPIO_DIN2, 0);
|
||||||
|
this->din3.init(mcu::GPIO_DIN3, 0);
|
||||||
|
this->din4.init(mcu::GPIO_DIN4, 0);
|
||||||
|
this->hvdin1.init(mcu::GPIO_HVDIN1, 1);
|
||||||
|
this->hvdin2.init(mcu::GPIO_HVDIN2, 1);
|
||||||
|
this->hvdin3.init(mcu::GPIO_HVDIN3, 1);
|
||||||
|
|
||||||
|
this->hvdin3_pull.init(mcu::GPIO_HVDIN3_PULL, 0);
|
||||||
|
this->freq_pull.init(mcu::GPIO_FREQ_PULL, 0);
|
||||||
|
|
||||||
|
// Open-drain outputs
|
||||||
|
this->od1.init(mcu::GPIO_OD1, 1);
|
||||||
|
this->od2.init(mcu::GPIO_OD2, 1);
|
||||||
|
this->od3.init(mcu::GPIO_OD3, 1);
|
||||||
|
this->od4.init(mcu::GPIO_OD4, 1);
|
||||||
|
this->od5.init(mcu::GPIO_OD5, 1);
|
||||||
|
this->od6.init(mcu::GPIO_OD6, 1);
|
||||||
|
this->od_pwm.init(mcu::PWM_OD, 100);
|
||||||
|
|
||||||
|
// PWM driver output
|
||||||
|
this->out_pwm.init(mcu::PWM_OUT, 95);
|
||||||
|
this->out_low.init(mcu::GPIO_OUT_LOW, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::Board::read(void)
|
||||||
|
{
|
||||||
|
// Update all analog inputs
|
||||||
|
this->out_voltage.read();
|
||||||
|
this->out_current.read();
|
||||||
|
this->battery_voltage.read();
|
||||||
|
this->battery_current.read();
|
||||||
|
this->ain1.read();
|
||||||
|
this->ain2.read();
|
||||||
|
|
||||||
|
// Update all digital inputs
|
||||||
|
this->din1.read();
|
||||||
|
this->din2.read();
|
||||||
|
this->din3.read();
|
||||||
|
this->din4.read();
|
||||||
|
this->hvdin1.read();
|
||||||
|
this->hvdin2.read();
|
||||||
|
this->hvdin3.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
75
firmware/src/bsp/board.h
Normal file
75
firmware/src/bsp/board.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#ifndef UDCCD_BOARD_H_
|
||||||
|
#define UDCCD_BOARD_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "ain.h"
|
||||||
|
#include "ain_lpf.h"
|
||||||
|
#include "din.h"
|
||||||
|
#include "dout.h"
|
||||||
|
#include "pwm_out.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class Board
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
uint8_t pwm_f_khz;
|
||||||
|
uint8_t od_common_is_pwm;
|
||||||
|
} boardCfg_t;
|
||||||
|
|
||||||
|
Board(void);
|
||||||
|
~Board(void);
|
||||||
|
|
||||||
|
void init(boardCfg_t* cfg);
|
||||||
|
|
||||||
|
AnalogIn out_voltage;
|
||||||
|
AnalogIn out_current;
|
||||||
|
AnalogIn battery_voltage;
|
||||||
|
AnalogIn battery_current;
|
||||||
|
AnalogIn ain1;
|
||||||
|
AnalogIn ain2;
|
||||||
|
|
||||||
|
DigitalIn din1;
|
||||||
|
DigitalIn din2;
|
||||||
|
DigitalIn din3;
|
||||||
|
DigitalIn din4;
|
||||||
|
DigitalIn hvdin1;
|
||||||
|
DigitalIn hvdin2;
|
||||||
|
DigitalIn hvdin3;
|
||||||
|
|
||||||
|
DigitalOut hvdin3_pull;
|
||||||
|
DigitalOut freq_pull;
|
||||||
|
|
||||||
|
DigitalOut od1;
|
||||||
|
DigitalOut od2;
|
||||||
|
DigitalOut od3;
|
||||||
|
DigitalOut od4;
|
||||||
|
DigitalOut od5;
|
||||||
|
DigitalOut od6;
|
||||||
|
PwmOut od_pwm;
|
||||||
|
|
||||||
|
PwmOut out_pwm;
|
||||||
|
DigitalOut out_low;
|
||||||
|
|
||||||
|
Memory nvmem;
|
||||||
|
|
||||||
|
void read(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* UDCCD_BOARD_H_ */
|
||||||
48
firmware/src/bsp/din.cpp
Normal file
48
firmware/src/bsp/din.cpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "din.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::DigitalIn::DigitalIn(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::DigitalIn::~DigitalIn(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::DigitalIn::init(uint8_t gpio_ch, uint8_t inverted)
|
||||||
|
{
|
||||||
|
this->gpio_ch = gpio_ch;
|
||||||
|
if(inverted == 0) this->is_inverted = 0;
|
||||||
|
else this->is_inverted = 1;
|
||||||
|
this->last_read = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t bsp::DigitalIn::read(void)
|
||||||
|
{
|
||||||
|
// Read ADC
|
||||||
|
this->last_read = mcu::gpio_read(this->gpio_ch);
|
||||||
|
|
||||||
|
// Invert if necessary
|
||||||
|
if(this->is_inverted)
|
||||||
|
{
|
||||||
|
if(this->last_read==0) this->last_read = 1;
|
||||||
|
else this->last_read = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->last_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
36
firmware/src/bsp/din.h
Normal file
36
firmware/src/bsp/din.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef DIGITAL_IN_H_
|
||||||
|
#define DIGITAL_IN_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class DigitalIn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DigitalIn(void);
|
||||||
|
~DigitalIn(void);
|
||||||
|
|
||||||
|
void init(uint8_t gpio_ch, uint8_t inverted);
|
||||||
|
|
||||||
|
uint8_t last_read;
|
||||||
|
|
||||||
|
uint8_t read(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
uint8_t gpio_ch;
|
||||||
|
uint8_t is_inverted;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* DIGITAL_IN_H_ */
|
||||||
37
firmware/src/bsp/dout.cpp
Normal file
37
firmware/src/bsp/dout.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "dout.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::DigitalOut::DigitalOut(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::DigitalOut::~DigitalOut(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::DigitalOut::write(int8_t level)
|
||||||
|
{
|
||||||
|
if(this->is_inverted)
|
||||||
|
{
|
||||||
|
if(level==0) level = 1;
|
||||||
|
else if (level > 0) level = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
mcu::gpio_write(this->gpio_ch, level);
|
||||||
|
|
||||||
|
this->last_writen = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
34
firmware/src/bsp/dout.h
Normal file
34
firmware/src/bsp/dout.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef DIGITAL_OUT_H_
|
||||||
|
#define DIGITAL_OUT_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "din.h"
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class DigitalOut : public DigitalIn
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// New or redefined stuff
|
||||||
|
DigitalOut(void);
|
||||||
|
~DigitalOut(void);
|
||||||
|
|
||||||
|
int8_t last_writen;
|
||||||
|
|
||||||
|
void write(int8_t level);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* DIGITAL_OUT_H_ */
|
||||||
114
firmware/src/bsp/mcu/mcu_hal.h
Normal file
114
firmware/src/bsp/mcu/mcu_hal.h
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#ifndef MCU_HAL_H_
|
||||||
|
#define MCU_HAL_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace mcu {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
const uint8_t LEVEL_LOW = 0;
|
||||||
|
const uint8_t LEVEL_HIGH = 1;
|
||||||
|
const int8_t LEVEL_HIZ = -1;
|
||||||
|
|
||||||
|
const uint8_t GPIO_DIN1 = 0;
|
||||||
|
const uint8_t GPIO_DIN2 = 1;
|
||||||
|
const uint8_t GPIO_DIN3 = 2;
|
||||||
|
const uint8_t GPIO_DIN4 = 3;
|
||||||
|
const uint8_t GPIO_HVDIN1 = 4;
|
||||||
|
const uint8_t GPIO_HVDIN2 = 5;
|
||||||
|
const uint8_t GPIO_HVDIN3 = 6;
|
||||||
|
const uint8_t GPIO_HVDIN3_PULL = 7;
|
||||||
|
const uint8_t GPIO_OD1 = 8;
|
||||||
|
const uint8_t GPIO_OD2 = 9;
|
||||||
|
const uint8_t GPIO_OD3 = 10;
|
||||||
|
const uint8_t GPIO_OD4 = 11;
|
||||||
|
const uint8_t GPIO_OD5 = 12;
|
||||||
|
const uint8_t GPIO_OD6 = 13;
|
||||||
|
const uint8_t GPIO_OUT_LOW = 14;
|
||||||
|
const uint8_t GPIO_OUT_HIGH = 15;
|
||||||
|
const uint8_t GPIO_OD_PWM = 16;
|
||||||
|
const uint8_t GPIO_FREQ1 = 17;
|
||||||
|
const uint8_t GPIO_FREQ2 = 18;
|
||||||
|
const uint8_t GPIO_FREQ_PULL = 19;
|
||||||
|
const uint8_t GPIO_TX = 20;
|
||||||
|
const uint8_t GPIO_RX = 21;
|
||||||
|
|
||||||
|
const uint8_t ADC_IOUT = 0; //Output current
|
||||||
|
const uint8_t ADC_VOUT = 1; //Output voltage
|
||||||
|
const uint8_t ADC_VBAT = 2; //Battery voltage
|
||||||
|
const uint8_t ADC_IBAT = 3; //Battery current
|
||||||
|
const uint8_t ADC_AIN2 = 4; //Potentiometer
|
||||||
|
const uint8_t ADC_AIN1 = 5; //Mode
|
||||||
|
const uint8_t ADC_TEMP = 8; //MCU temperature
|
||||||
|
const uint8_t ADC_IVREF = 14; //MCU internal reference
|
||||||
|
const uint8_t ADC_GND = 15; //MCU ground
|
||||||
|
|
||||||
|
const uint8_t PWM_OUT = 0; //DCCD
|
||||||
|
const uint8_t PWM_OD = 1; //LED
|
||||||
|
|
||||||
|
//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;
|
||||||
|
timerClkDiv_t pwm_clk;
|
||||||
|
uint16_t pwm_top;
|
||||||
|
uint8_t od_common_is_pwm;
|
||||||
|
} startupCfg_t;
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
void startup(startupCfg_t* hwCfg);
|
||||||
|
|
||||||
|
void rtc_set_calibration(uint16_t coef);
|
||||||
|
|
||||||
|
uint8_t gpio_read(uint8_t ch);
|
||||||
|
void gpio_write(uint8_t ch, int8_t lvl);
|
||||||
|
void gpio_write_pull(uint8_t ch, int8_t lvl);
|
||||||
|
|
||||||
|
void adc_start(uint8_t ch);
|
||||||
|
uint8_t adc_is_running(void);
|
||||||
|
uint8_t adc_is_new(void);
|
||||||
|
uint16_t adc_read(void);
|
||||||
|
uint16_t adc_read(uint8_t ch);
|
||||||
|
|
||||||
|
void pwm_write(uint8_t ch, uint16_t dc);
|
||||||
|
uint16_t pwm_read(uint8_t ch);
|
||||||
|
|
||||||
|
void timer_reset(uint8_t ch);
|
||||||
|
uint16_t timer_read(uint8_t ch);
|
||||||
|
uint16_t timer_read_top(uint8_t ch);
|
||||||
|
|
||||||
|
uint32_t timer_convert_us(uint8_t ch, uint16_t raw);
|
||||||
|
uint32_t timer_convert_ms(uint8_t ch, uint16_t raw);
|
||||||
|
|
||||||
|
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_ */
|
||||||
533
firmware/src/bsp/mcu/mcu_hal_r8.cpp
Normal file
533
firmware/src/bsp/mcu/mcu_hal_r8.cpp
Normal file
@@ -0,0 +1,533 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/eeprom.h>
|
||||||
|
#include "mcu_hal.h"
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#define F_CPU 8000000UL
|
||||||
|
|
||||||
|
using namespace mcu;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
static volatile uint16_t rtc_ms = 1000;
|
||||||
|
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
static uint8_t gpio_read_level(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->od_common_is_pwm) 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
|
||||||
|
|
||||||
|
// Freq-pull control pins
|
||||||
|
PORTD &= ~0x40; //Set low
|
||||||
|
DDRD |= 0x40; //Set as output
|
||||||
|
|
||||||
|
//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->od_common_is_pwm) 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
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcu::rtc_set_calibration(uint16_t coef)
|
||||||
|
{
|
||||||
|
rtc_ms = coef;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GPIO interface functions
|
||||||
|
uint8_t mcu::gpio_read(uint8_t ch)
|
||||||
|
{
|
||||||
|
switch(ch)
|
||||||
|
{
|
||||||
|
case GPIO_DIN1: // Mode DIN1
|
||||||
|
return gpio_read_level(PINC,0x20);
|
||||||
|
|
||||||
|
case GPIO_DIN2: // Pot DIN2
|
||||||
|
return gpio_read_level(PINC,0x10);
|
||||||
|
|
||||||
|
case GPIO_DIN3: // Down DIN3
|
||||||
|
return gpio_read_level(PINE,0x02);
|
||||||
|
|
||||||
|
case GPIO_DIN4: // Up DIN4
|
||||||
|
return gpio_read_level(PINE,0x08);
|
||||||
|
|
||||||
|
case GPIO_HVDIN1: // Dimm DIN5
|
||||||
|
return gpio_read_level(PIND,0x80);
|
||||||
|
|
||||||
|
case GPIO_HVDIN2: // Brakes DIN6
|
||||||
|
return gpio_read_level(PINB,0x80);
|
||||||
|
|
||||||
|
case GPIO_HVDIN3: // Handbrake DIN7
|
||||||
|
return gpio_read_level(PINB,0x40);
|
||||||
|
|
||||||
|
case GPIO_HVDIN3_PULL: // Handbrake pull DIN8
|
||||||
|
return gpio_read_level(PINB,0x20);
|
||||||
|
|
||||||
|
case GPIO_OD1: // LED 0
|
||||||
|
return gpio_read_level(PIND,0x01);
|
||||||
|
|
||||||
|
case GPIO_OD2: // LED 1
|
||||||
|
return gpio_read_level(PIND,0x02);
|
||||||
|
|
||||||
|
case GPIO_OD3: // LED 2
|
||||||
|
return gpio_read_level(PIND,0x04);
|
||||||
|
|
||||||
|
case GPIO_OD4: // LED 3
|
||||||
|
return gpio_read_level(PIND,0x08);
|
||||||
|
|
||||||
|
case GPIO_OD5: // LED 4
|
||||||
|
return gpio_read_level(PIND,0x10);
|
||||||
|
|
||||||
|
case GPIO_OD6: // LED 5
|
||||||
|
return gpio_read_level(PIND,0x20);
|
||||||
|
|
||||||
|
case GPIO_OUT_LOW: // DCCD Enable
|
||||||
|
return gpio_read_level(PINB,0x01);
|
||||||
|
|
||||||
|
case GPIO_OUT_HIGH: // DCCD PWM
|
||||||
|
return gpio_read_level(PINB,0x02);
|
||||||
|
|
||||||
|
case GPIO_OD_PWM: // LED PWM
|
||||||
|
return gpio_read_level(PINB,0x04);
|
||||||
|
|
||||||
|
case GPIO_FREQ1: // Speed 1
|
||||||
|
return gpio_read_level(PINE,0x04);
|
||||||
|
|
||||||
|
case GPIO_FREQ2: // Speed 2
|
||||||
|
return gpio_read_level(PINE,0x01);
|
||||||
|
|
||||||
|
case GPIO_FREQ_PULL: // Speed-pull
|
||||||
|
return gpio_read_level(PIND,0x40);
|
||||||
|
|
||||||
|
case GPIO_TX: //
|
||||||
|
return gpio_read_level(PINB,0x08);
|
||||||
|
|
||||||
|
case GPIO_RX: //
|
||||||
|
return gpio_read_level(PINB,0x10);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcu::gpio_write(uint8_t ch, int8_t lvl)
|
||||||
|
{
|
||||||
|
switch(ch)
|
||||||
|
{
|
||||||
|
case GPIO_DIN1: // Mode DIN1
|
||||||
|
if(lvl>0)
|
||||||
|
{
|
||||||
|
PORTC |= 0x20;
|
||||||
|
DDRC |= 0x20;
|
||||||
|
}
|
||||||
|
else if(lvl<0)
|
||||||
|
{
|
||||||
|
DDRC &= ~0x20;
|
||||||
|
PORTC &= ~0x20;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PORTC &= ~0x20;
|
||||||
|
DDRC |= 0x20;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN2: // Pot DIN2
|
||||||
|
if(lvl>0)
|
||||||
|
{
|
||||||
|
PORTC |= 0x10;
|
||||||
|
DDRC |= 0x10;
|
||||||
|
}
|
||||||
|
else if(lvl<0)
|
||||||
|
{
|
||||||
|
DDRC &= ~0x10;
|
||||||
|
PORTC &= ~0x10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PORTC &= ~0x10;
|
||||||
|
DDRC |= 0x10;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN3: // Down DIN3
|
||||||
|
if(lvl>0)
|
||||||
|
{
|
||||||
|
PORTE |= 0x02;
|
||||||
|
DDRE |= 0x02;
|
||||||
|
}
|
||||||
|
else if(lvl<0)
|
||||||
|
{
|
||||||
|
DDRE &= ~0x02;
|
||||||
|
PORTE &= ~0x02;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PORTE &= ~0x02;
|
||||||
|
DDRE |= 0x02;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN4: // Up DIN4
|
||||||
|
if(lvl>0)
|
||||||
|
{
|
||||||
|
PORTE |= 0x08;
|
||||||
|
DDRE |= 0x08;
|
||||||
|
}
|
||||||
|
else if(lvl<0)
|
||||||
|
{
|
||||||
|
DDRE &= ~0x08;
|
||||||
|
PORTE &= ~0x08;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PORTE &= ~0x08;
|
||||||
|
DDRE |= 0x08;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_HVDIN3_PULL: // 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 GPIO_OD1: // LED 0
|
||||||
|
if(lvl>0) PORTD |= 0x01;
|
||||||
|
else PORTD &= ~0x01;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OD2: // LED 1
|
||||||
|
if(lvl>0) PORTD |= 0x02;
|
||||||
|
else PORTD &= ~0x02;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OD3: // LED 2
|
||||||
|
if(lvl>0) PORTD |= 0x04;
|
||||||
|
else PORTD &= ~0x04;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OD4: // LED 3
|
||||||
|
if(lvl>0) PORTD |= 0x08;
|
||||||
|
else PORTD &= ~0x08;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OD5: // LED 4
|
||||||
|
if(lvl>0) PORTD |= 0x10;
|
||||||
|
else PORTD &= ~0x10;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OD6: // LED 5
|
||||||
|
if(lvl>0) PORTD |= 0x20;
|
||||||
|
else PORTD &= ~0x20;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_OUT_LOW: // DCCD Enable
|
||||||
|
if(lvl>0) PORTB |= 0x01;
|
||||||
|
else PORTB &= ~0x01;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_FREQ_PULL: // Speed-pull
|
||||||
|
if(lvl>0) PORTD |= 0x40;
|
||||||
|
else PORTD &= ~0x40;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcu::gpio_write_pull(uint8_t ch, int8_t lvl)
|
||||||
|
{
|
||||||
|
switch(ch)
|
||||||
|
{
|
||||||
|
case GPIO_DIN1: // Mode DIN1
|
||||||
|
if(lvl>0) PORTC |= 0x20;
|
||||||
|
else PORTC &= ~0x20;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN2: // Pot DIN2
|
||||||
|
if(lvl>0) PORTC |= 0x10;
|
||||||
|
else PORTC &= ~0x10;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN3: // Down DIN3
|
||||||
|
if(lvl>0) PORTE |= 0x02;
|
||||||
|
else PORTE &= ~0x02;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_DIN4: // Up DIN4
|
||||||
|
if(lvl>0) PORTE |= 0x08;
|
||||||
|
else PORTE &= ~0x08;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_HVDIN1: // Dimm
|
||||||
|
if(lvl>0) PORTD |= 0x80;
|
||||||
|
else PORTD &= ~0x80;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_HVDIN2: // Brakes
|
||||||
|
if(lvl>0) PORTB |= 0x80;
|
||||||
|
else PORTB &= ~0x80;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case GPIO_HVDIN3: // Handbrake
|
||||||
|
if(lvl>0) PORTB |= 0x40;
|
||||||
|
else PORTB &= ~0x40;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ADC interface functions
|
||||||
|
void mcu::adc_start(uint8_t ch)
|
||||||
|
{
|
||||||
|
// check if already running
|
||||||
|
if(ADCSRA&0x40) return;
|
||||||
|
|
||||||
|
//check if ADC is enabled
|
||||||
|
if(!(ADCSRA&0x80)) return;
|
||||||
|
|
||||||
|
//Safe guard mux
|
||||||
|
if(ch > 15) return;
|
||||||
|
// Not available channels
|
||||||
|
if((ch > 8) && (ch<14)) return;
|
||||||
|
|
||||||
|
ADMUX &= ~0x0F;
|
||||||
|
ADMUX |= ch;
|
||||||
|
ADCSRA |= 0x10; // Reset int. flag
|
||||||
|
ADCSRA |= 0x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t mcu::adc_is_running(void)
|
||||||
|
{
|
||||||
|
if(ADCSRA&0x40) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t mcu::adc_is_new(void)
|
||||||
|
{
|
||||||
|
if(ADCSRA&0x10) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t mcu::adc_read(void)
|
||||||
|
{
|
||||||
|
ADCSRA |= 0x10; // Reset int. flag
|
||||||
|
return ADC;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EEPROM interface functions
|
||||||
|
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);
|
||||||
|
_delay_ms(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcu::eeprom_write16b(uint16_t address, uint16_t value)
|
||||||
|
{
|
||||||
|
eeprom_write_word((uint16_t*)address, value);
|
||||||
|
_delay_ms(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mcu::eeprom_write32b(uint16_t address, uint32_t value)
|
||||||
|
{
|
||||||
|
eeprom_write_dword((uint32_t*)address, value);
|
||||||
|
_delay_ms(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pwm_write_ocx(uint8_t ch, uint16_t value)
|
||||||
|
{
|
||||||
|
switch(ch)
|
||||||
|
{
|
||||||
|
case PWM_OUT:
|
||||||
|
OCR1A = value;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case PWM_OD:
|
||||||
|
OCR1B = value;
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t pwm_read_ocx(uint8_t ch)
|
||||||
|
{
|
||||||
|
switch(ch)
|
||||||
|
{
|
||||||
|
case PWM_OUT:
|
||||||
|
return OCR1A;
|
||||||
|
|
||||||
|
case PWM_OD:
|
||||||
|
return OCR1B ;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0x0000;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
firmware/src/bsp/memory.cpp
Normal file
55
firmware/src/bsp/memory.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::Memory::Memory(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::Memory::~Memory(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t bsp::Memory::read_8b(uint16_t address)
|
||||||
|
{
|
||||||
|
return mcu::eeprom_read8b(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t bsp::Memory::read_16b(uint16_t address)
|
||||||
|
{
|
||||||
|
return mcu::eeprom_read16b(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bsp::Memory::read_32b(uint16_t address)
|
||||||
|
{
|
||||||
|
return mcu::eeprom_read32b(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::Memory::write_8b(uint16_t address, uint8_t value)
|
||||||
|
{
|
||||||
|
mcu::eeprom_write8b(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void bsp::Memory::write_16b(uint16_t address, uint16_t value)
|
||||||
|
{
|
||||||
|
mcu::eeprom_write16b(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::Memory::write_32b(uint16_t address, uint32_t value)
|
||||||
|
{
|
||||||
|
mcu::eeprom_write32b(address, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
36
firmware/src/bsp/memory.h
Normal file
36
firmware/src/bsp/memory.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef MEMORY_IN_H_
|
||||||
|
#define MEMORY_IN_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class Memory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Memory(void);
|
||||||
|
~Memory(void);
|
||||||
|
|
||||||
|
uint8_t read_8b(uint16_t address);
|
||||||
|
uint16_t read_16b(uint16_t address);
|
||||||
|
uint32_t read_32b(uint16_t address);
|
||||||
|
|
||||||
|
void write_8b(uint16_t address, uint8_t value);
|
||||||
|
void write_16b(uint16_t address, uint16_t value);
|
||||||
|
void write_32b(uint16_t address, uint32_t value);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* MEMORY_IN_H_ */
|
||||||
56
firmware/src/bsp/pwm_out.cpp
Normal file
56
firmware/src/bsp/pwm_out.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "mcu/mcu_hal.h"
|
||||||
|
#include "pwm_out.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
bsp::PwmOut::PwmOut(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bsp::PwmOut::~PwmOut(void)
|
||||||
|
{
|
||||||
|
this->last_duty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::PwmOut::init(uint8_t pwm_ch, uint8_t max_dc)
|
||||||
|
{
|
||||||
|
this->pwm_ch = pwm_ch;
|
||||||
|
|
||||||
|
this->last_duty = 0;
|
||||||
|
|
||||||
|
if(max_dc>100) max_dc = 100;
|
||||||
|
|
||||||
|
this->max_dc = util::percent_to_16b(max_dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::PwmOut::write(uint16_t numerator)
|
||||||
|
{
|
||||||
|
// Update target
|
||||||
|
if(numerator > this->max_dc) numerator = this->max_dc;
|
||||||
|
this->last_duty = numerator;
|
||||||
|
|
||||||
|
// Set PWM
|
||||||
|
mcu::pwm_write(this->pwm_ch, numerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bsp::PwmOut::write(uint8_t percent)
|
||||||
|
{
|
||||||
|
// Convert to numerator/0xFFFF
|
||||||
|
this->write(util::percent_to_16b(percent));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t bsp::PwmOut::get_set_duty(void)
|
||||||
|
{
|
||||||
|
return this->last_duty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
37
firmware/src/bsp/pwm_out.h
Normal file
37
firmware/src/bsp/pwm_out.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef PWM_OUT_H_
|
||||||
|
#define PWM_OUT_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace bsp {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class PwmOut
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PwmOut(void);
|
||||||
|
~PwmOut(void);
|
||||||
|
|
||||||
|
void init(uint8_t pwm_ch, uint8_t max_dc);
|
||||||
|
|
||||||
|
void write(uint16_t numerator);
|
||||||
|
void write(uint8_t percent);
|
||||||
|
uint16_t get_set_duty(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
uint8_t pwm_ch;
|
||||||
|
uint16_t last_duty;
|
||||||
|
uint16_t max_dc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* PWM_OUT_H_ */
|
||||||
432
firmware/src/dccd/dccd.cpp
Normal file
432
firmware/src/dccd/dccd.cpp
Normal file
@@ -0,0 +1,432 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "dccd.h"
|
||||||
|
|
||||||
|
using namespace dccd;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
static const uint16_t def_lock_current = 4500;
|
||||||
|
static const uint16_t def_max_hbrake_time = 0;
|
||||||
|
static const uint16_t def_btn_force_repeat_time = 300;
|
||||||
|
static const uint16_t def_btn_mode_repeat_time = 700;
|
||||||
|
static const uint8_t def_button_inputs = 1;
|
||||||
|
|
||||||
|
static const uint8_t def_display_brigth = 100;
|
||||||
|
static const uint8_t def_display_dimm = 50;
|
||||||
|
|
||||||
|
static const uint16_t cv_ref_resistance = 1500;
|
||||||
|
static const uint16_t cc_ref_resistance = 2000;
|
||||||
|
static const uint16_t cc_min_resistance = 1000;
|
||||||
|
|
||||||
|
static const uint8_t bmode_image_open = 0x07;
|
||||||
|
static const uint8_t bmode_image_user = 0x1E;
|
||||||
|
static const uint8_t bmode_image_lock = 0x38;
|
||||||
|
|
||||||
|
static const uint16_t display_keep_bmode = 2000;
|
||||||
|
static const uint16_t display_keep_userf = 1000;
|
||||||
|
|
||||||
|
static const uint8_t user_force_step = 10;
|
||||||
|
|
||||||
|
static const uint8_t def_btn_force = 0;
|
||||||
|
static const uint8_t def_brake_mode = 0;
|
||||||
|
|
||||||
|
static const uint16_t def_chasis_inp_debounce = 100;
|
||||||
|
static const uint16_t def_user_inp_debounce = 20;
|
||||||
|
|
||||||
|
static const uint16_t mem_addr_inp_mode = 0;
|
||||||
|
static const uint16_t mem_addr_force = 1;
|
||||||
|
static const uint16_t mem_addr_bmode = 2;
|
||||||
|
static const uint16_t mem_addr_dsp_brigth = 3;
|
||||||
|
static const uint16_t mem_addr_dsp_dimm = 4;
|
||||||
|
static const uint16_t mem_addr_lock_current = 5;
|
||||||
|
static const uint16_t mem_addr_hbrake_time = 7;
|
||||||
|
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
static uint8_t img_gen_dot10(uint8_t percent);
|
||||||
|
static uint8_t img_gen_dot20(uint8_t percent);
|
||||||
|
static uint8_t img_gen_bar(uint8_t percent);
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
dccd::DccdApp::DccdApp(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dccd::DccdApp::~DccdApp(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdApp::init(DccdHw* dccd_hw)
|
||||||
|
{
|
||||||
|
this->hardware = dccd_hw;
|
||||||
|
|
||||||
|
#define OVERRIDEDEDBNC
|
||||||
|
#ifdef OVERRIDEDEDBNC
|
||||||
|
this->hardware->btn_mode.dbnc_lim = def_user_inp_debounce;
|
||||||
|
this->hardware->btn_up.dbnc_lim = def_user_inp_debounce;
|
||||||
|
this->hardware->btn_down.dbnc_lim = def_user_inp_debounce;
|
||||||
|
this->hardware->handbrake.dbnc_lim = def_chasis_inp_debounce;
|
||||||
|
this->hardware->brakes.dbnc_lim = def_chasis_inp_debounce;
|
||||||
|
this->hardware->dimm.dbnc_lim = def_chasis_inp_debounce;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Load saved config from memory
|
||||||
|
this->loadMemCfg();
|
||||||
|
|
||||||
|
this->btn_force_repeat_time = def_btn_force_repeat_time;
|
||||||
|
this->btn_mode_repeat_time = def_btn_mode_repeat_time;
|
||||||
|
this->pot_force = 0;
|
||||||
|
|
||||||
|
this->hardware->read();
|
||||||
|
this->hardware->dimm.force_read();
|
||||||
|
|
||||||
|
this->hardware->outreg.write_voltage(0);
|
||||||
|
this->hardware->outreg.write_current(0);
|
||||||
|
this->hardware->outreg.write_on(1);
|
||||||
|
|
||||||
|
this->hardware->display.write(0x01);
|
||||||
|
if(this->hardware->dimm.state) this->hardware->display.write_backlight(this->display_dimm);
|
||||||
|
else this->hardware->display.write_backlight(this->display_brigth);
|
||||||
|
|
||||||
|
this->hardware->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdApp::process(void)
|
||||||
|
{
|
||||||
|
// Update all inputs
|
||||||
|
this->hardware->read();
|
||||||
|
|
||||||
|
uint8_t is_new_mode = 0;
|
||||||
|
uint8_t is_new_btn_force = 0;
|
||||||
|
|
||||||
|
// Process mode button
|
||||||
|
if((this->hardware->btn_mode.state==1)&&((this->hardware->btn_mode.is_new)||(this->hardware->btn_mode.time_read() >= this->btn_mode_repeat_time)))
|
||||||
|
{
|
||||||
|
this->hardware->btn_mode.time_reset();
|
||||||
|
this->hardware->btn_mode.is_new = 0;
|
||||||
|
// Change mode
|
||||||
|
switch(this->brake_mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
this->brake_mode = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
this->brake_mode = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this->brake_mode = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
is_new_mode = 1;
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_bmode, this->brake_mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Process user force inputs
|
||||||
|
if((this->hardware->btn_up.state==1)&&((this->hardware->btn_up.is_new)||(this->hardware->btn_up.time_read() >= this->btn_force_repeat_time)))
|
||||||
|
{
|
||||||
|
this->hardware->btn_up.time_reset();
|
||||||
|
this->hardware->btn_up.is_new = 0;
|
||||||
|
// Increase user force
|
||||||
|
this->btn_force += user_force_step;
|
||||||
|
if(this->btn_force > 100) this->btn_force = 100;
|
||||||
|
is_new_btn_force = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
if((this->hardware->btn_down.state==1)&&((this->hardware->btn_down.is_new)||(this->hardware->btn_down.time_read() >= this->btn_force_repeat_time)))
|
||||||
|
{
|
||||||
|
this->hardware->btn_down.time_reset();
|
||||||
|
this->hardware->btn_down.is_new = 0;
|
||||||
|
// Decrease user force
|
||||||
|
this->btn_force -= user_force_step;
|
||||||
|
if(this->btn_force > 100) this->btn_force = 0;
|
||||||
|
is_new_btn_force = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
if(is_new_btn_force)
|
||||||
|
{
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_force, this->btn_force);
|
||||||
|
};
|
||||||
|
|
||||||
|
this->pot_force = this->hardware->pot.last_percent;
|
||||||
|
|
||||||
|
// Determine user force
|
||||||
|
int8_t user_force;
|
||||||
|
if(this->button_inputs) user_force = (int8_t)this->btn_force;
|
||||||
|
else user_force = (int8_t)this->pot_force;
|
||||||
|
|
||||||
|
// Determine next settable force
|
||||||
|
int8_t next_force;
|
||||||
|
|
||||||
|
uint8_t hbrake_timeout = 0;
|
||||||
|
if((this->max_hbrake_time!=0)&&(this->hardware->handbrake.time_read() >= this->max_hbrake_time))
|
||||||
|
{
|
||||||
|
hbrake_timeout = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
if((this->hardware->handbrake.state == 1)&&(hbrake_timeout==0))
|
||||||
|
{
|
||||||
|
// Handbrake override
|
||||||
|
next_force = -1;
|
||||||
|
}
|
||||||
|
else if(this->hardware->brakes.state == 1)
|
||||||
|
{
|
||||||
|
// Brakes override
|
||||||
|
switch(this->brake_mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
next_force = -1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
next_force = user_force;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
next_force = 100;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
next_force = -1;
|
||||||
|
this->brake_mode = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User force
|
||||||
|
next_force = user_force;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply next force
|
||||||
|
if(next_force < 0)
|
||||||
|
{
|
||||||
|
// HiZ
|
||||||
|
this->hardware->outreg.write_voltage(0);
|
||||||
|
this->hardware->outreg.write_current(0);
|
||||||
|
this->hardware->outreg.write_on(0);
|
||||||
|
// For display
|
||||||
|
next_force = 0;
|
||||||
|
}
|
||||||
|
else if(next_force == 0)
|
||||||
|
{
|
||||||
|
// Open
|
||||||
|
this->hardware->outreg.write_voltage(0);
|
||||||
|
this->hardware->outreg.write_current(0);
|
||||||
|
this->hardware->outreg.write_on(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate current and voltage settings
|
||||||
|
this->hardware->outreg.write_current(util::percent_of((uint8_t)next_force, this->lock_current));
|
||||||
|
uint16_t ref_resistance = cv_ref_resistance;
|
||||||
|
if(this->hardware->outreg.cc_mode_en) ref_resistance = cc_ref_resistance;
|
||||||
|
this->hardware->outreg.write_voltage(util::sat_mul_kilo(this->hardware->outreg.read_current(), ref_resistance));
|
||||||
|
this->hardware->outreg.write_on(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display image
|
||||||
|
if(is_new_mode)
|
||||||
|
{
|
||||||
|
uint8_t bmode_image;
|
||||||
|
switch(this->brake_mode)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
bmode_image = bmode_image_open;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
bmode_image = bmode_image_user;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
bmode_image = bmode_image_lock;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
bmode_image = bmode_image_open;
|
||||||
|
this->brake_mode = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this->hardware->display.write(bmode_image, display_keep_bmode, display_keep_bmode, 1);
|
||||||
|
is_new_mode = 0;
|
||||||
|
}
|
||||||
|
else if((is_new_btn_force)&&(this->button_inputs))
|
||||||
|
{
|
||||||
|
this->hardware->display.write(img_gen_dot10(this->btn_force), display_keep_userf, display_keep_userf, 1);
|
||||||
|
is_new_btn_force = 0;
|
||||||
|
}
|
||||||
|
else if(this->hardware->display.is_cycle_end())
|
||||||
|
{
|
||||||
|
this->hardware->display.write(img_gen_dot10((uint8_t)next_force));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Display backlight
|
||||||
|
if(this->hardware->dimm.is_new)
|
||||||
|
{
|
||||||
|
this->hardware->dimm.is_new = 0;
|
||||||
|
if(this->hardware->dimm.state) this->hardware->display.write_backlight(this->display_dimm);
|
||||||
|
else this->hardware->display.write_backlight(this->display_brigth);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Execute outputs
|
||||||
|
this->hardware->write();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t dccd::DccdApp::loadMemCfg(void)
|
||||||
|
{
|
||||||
|
// Load saved config from memory
|
||||||
|
uint8_t t1;
|
||||||
|
uint16_t t2;
|
||||||
|
uint8_t def_applied = 0;
|
||||||
|
|
||||||
|
t1 = this->hardware->board_hw.nvmem.read_8b(mem_addr_inp_mode);
|
||||||
|
if(t1 > 1){this->button_inputs = def_button_inputs; def_applied=1; }
|
||||||
|
else this->button_inputs = t1;
|
||||||
|
|
||||||
|
t1 = this->hardware->board_hw.nvmem.read_8b(mem_addr_force);
|
||||||
|
if(t1 > 100){this->btn_force = def_btn_force; def_applied=1; }
|
||||||
|
else this->btn_force = t1;
|
||||||
|
|
||||||
|
t1 = this->hardware->board_hw.nvmem.read_8b(mem_addr_bmode);
|
||||||
|
if(t1 > 2){this->brake_mode = def_brake_mode; def_applied=1; }
|
||||||
|
else this->brake_mode = t1;
|
||||||
|
|
||||||
|
t1 = this->hardware->board_hw.nvmem.read_8b(mem_addr_dsp_brigth);
|
||||||
|
if((t1 > 100)||(t1 == 0)){this->display_brigth = def_brake_mode; def_applied=1; }
|
||||||
|
else this->display_brigth = t1;
|
||||||
|
|
||||||
|
t1 = this->hardware->board_hw.nvmem.read_8b(mem_addr_dsp_dimm);
|
||||||
|
if((t1 > 100)||(t1 == 0)){this->display_dimm = def_brake_mode; def_applied=1; }
|
||||||
|
else this->display_dimm = t1;
|
||||||
|
|
||||||
|
t2 = this->hardware->board_hw.nvmem.read_16b(mem_addr_lock_current);
|
||||||
|
if((t2 > 5000)||(t2 < 1000)){this->lock_current = def_lock_current; def_applied=1; }
|
||||||
|
else this->lock_current = t2;
|
||||||
|
|
||||||
|
t2 = this->hardware->board_hw.nvmem.read_16b(mem_addr_hbrake_time);
|
||||||
|
if((t2 > 30000)||(t2 == 0)){this->max_hbrake_time = def_max_hbrake_time; def_applied=1; }
|
||||||
|
else this->max_hbrake_time = t2;
|
||||||
|
|
||||||
|
return def_applied;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdApp::saveMemCfg(void)
|
||||||
|
{
|
||||||
|
// Save config to memory
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_inp_mode, this->button_inputs);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_force, this->btn_force);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_bmode, this->brake_mode);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_dsp_brigth, this->display_brigth);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_8b(mem_addr_dsp_dimm, this->display_dimm);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_16b(mem_addr_lock_current, this->lock_current);
|
||||||
|
|
||||||
|
this->hardware->board_hw.nvmem.write_16b(mem_addr_hbrake_time, this->max_hbrake_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ***/
|
||||||
|
static uint8_t img_gen_dot10(uint8_t percent)
|
||||||
|
{
|
||||||
|
switch(percent)
|
||||||
|
{
|
||||||
|
case 0 ... 5:
|
||||||
|
return 0x01;
|
||||||
|
|
||||||
|
case 6 ... 15:
|
||||||
|
return 0x03;
|
||||||
|
|
||||||
|
case 16 ... 25:
|
||||||
|
return 0x02;
|
||||||
|
|
||||||
|
case 26 ... 35:
|
||||||
|
return 0x06;
|
||||||
|
|
||||||
|
case 36 ... 45:
|
||||||
|
return 0x04;
|
||||||
|
|
||||||
|
case 46 ... 55:
|
||||||
|
return 0x0C;
|
||||||
|
|
||||||
|
case 56 ... 65:
|
||||||
|
return 0x08;
|
||||||
|
|
||||||
|
case 66 ... 75:
|
||||||
|
return 0x18;
|
||||||
|
|
||||||
|
case 76 ... 85:
|
||||||
|
return 0x10;
|
||||||
|
|
||||||
|
case 86 ... 95:
|
||||||
|
return 0x30;
|
||||||
|
|
||||||
|
case 96 ... 100:
|
||||||
|
return 0x20;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t img_gen_dot20(uint8_t percent)
|
||||||
|
{
|
||||||
|
switch(percent)
|
||||||
|
{
|
||||||
|
case 0 ... 10:
|
||||||
|
return 0x01;
|
||||||
|
|
||||||
|
case 11 ... 30:
|
||||||
|
return 0x02;
|
||||||
|
|
||||||
|
case 31 ... 50:
|
||||||
|
return 0x04;
|
||||||
|
|
||||||
|
case 51 ... 70:
|
||||||
|
return 0x08;
|
||||||
|
|
||||||
|
case 71 ... 90:
|
||||||
|
return 0x10;
|
||||||
|
|
||||||
|
case 91 ... 100:
|
||||||
|
return 0x20;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0x20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t img_gen_bar(uint8_t percent)
|
||||||
|
{
|
||||||
|
switch(percent)
|
||||||
|
{
|
||||||
|
case 0 ... 10:
|
||||||
|
return 0x01;
|
||||||
|
|
||||||
|
case 11 ... 30:
|
||||||
|
return 0x03;
|
||||||
|
|
||||||
|
case 31 ... 50:
|
||||||
|
return 0x07;
|
||||||
|
|
||||||
|
case 51 ... 70:
|
||||||
|
return 0x0F;
|
||||||
|
|
||||||
|
case 71 ... 90:
|
||||||
|
return 0x1F;
|
||||||
|
|
||||||
|
case 91 ... 100:
|
||||||
|
return 0x3F;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0x3F;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
firmware/src/dccd/dccd.h
Normal file
48
firmware/src/dccd/dccd.h
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef DCCD_APP_H_
|
||||||
|
#define DCCD_APP_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "dccd_hw.h"
|
||||||
|
|
||||||
|
namespace dccd {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class DccdApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DccdApp(void);
|
||||||
|
~DccdApp(void);
|
||||||
|
|
||||||
|
void init(DccdHw* dccd_hw);
|
||||||
|
void process(void);
|
||||||
|
|
||||||
|
uint16_t lock_current;
|
||||||
|
uint16_t max_hbrake_time;
|
||||||
|
uint16_t btn_force_repeat_time;
|
||||||
|
uint16_t btn_mode_repeat_time;
|
||||||
|
uint8_t button_inputs;
|
||||||
|
uint8_t display_brigth;
|
||||||
|
uint8_t display_dimm;
|
||||||
|
|
||||||
|
uint8_t btn_force;
|
||||||
|
uint8_t pot_force;
|
||||||
|
uint8_t brake_mode;
|
||||||
|
|
||||||
|
uint8_t loadMemCfg(void);
|
||||||
|
void saveMemCfg(void);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
DccdHw* hardware;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* DCCD_APP_H_ */
|
||||||
190
firmware/src/dccd/dccd_hw.cpp
Normal file
190
firmware/src/dccd/dccd_hw.cpp
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "dccd_hw.h"
|
||||||
|
|
||||||
|
using namespace dccd;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
static const uint8_t def_dbnc_time = 10;
|
||||||
|
|
||||||
|
static const uint16_t def_pot_dead_bot = 500;
|
||||||
|
static const uint16_t def_pot_dead_top = 4500;
|
||||||
|
|
||||||
|
static const uint8_t def_cc_mode_en = 1;
|
||||||
|
|
||||||
|
static const uint16_t def_cnter_us = 900;
|
||||||
|
|
||||||
|
static const uint16_t def_out_voltage_under_treshold = 0;
|
||||||
|
static const uint16_t def_out_voltage_over_treshold = 9000;
|
||||||
|
static const uint16_t def_out_voltage_hold_time = 1000;
|
||||||
|
static const uint16_t def_out_voltage_cooldown_time = 0;
|
||||||
|
|
||||||
|
static const uint16_t def_out_current_under_treshold = 0;
|
||||||
|
static const uint16_t def_out_current_over_treshold = 6000;
|
||||||
|
static const uint16_t def_out_current_hold_time = 200;
|
||||||
|
static const uint16_t def_out_current_cooldown_time = 1000;
|
||||||
|
|
||||||
|
static const uint16_t def_battery_voltage_under_treshold = 9000;
|
||||||
|
static const uint16_t def_battery_voltage_over_treshold = 18000;
|
||||||
|
static const uint16_t def_battery_voltage_hold_time = 1000;
|
||||||
|
static const uint16_t def_battery_voltage_cooldown_time = 0;
|
||||||
|
|
||||||
|
static const uint16_t def_battery_current_under_treshold = 0;
|
||||||
|
static const uint16_t def_battery_current_over_treshold = 8000;
|
||||||
|
static const uint16_t def_battery_current_hold_time = 200;
|
||||||
|
static const uint16_t def_battery_current_cooldown_time = 1000;
|
||||||
|
|
||||||
|
static const uint16_t def_inital_bat_voltage = 12000;
|
||||||
|
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
dccd::DccdHw::DccdHw(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dccd::DccdHw::~DccdHw(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdHw::init(dccdHwCfg_t* cfg)
|
||||||
|
{
|
||||||
|
// Apply config
|
||||||
|
bsp::Board::boardCfg_t board_cfg;
|
||||||
|
board_cfg.pwm_f_khz = cfg->pwm_f_khz;
|
||||||
|
board_cfg.od_common_is_pwm = 1;
|
||||||
|
this->board_hw.init(&board_cfg);
|
||||||
|
|
||||||
|
this->counter.init(0xFFFF, cfg->counter_step_us);
|
||||||
|
this->counter.disabled = 0;
|
||||||
|
|
||||||
|
this->out_voltage.init(&(this->board_hw.out_voltage), &(this->counter));
|
||||||
|
this->out_voltage.under_treshold = def_out_voltage_under_treshold;
|
||||||
|
this->out_voltage.over_treshold = def_out_voltage_over_treshold;
|
||||||
|
this->out_voltage.hold_time = def_out_voltage_hold_time;
|
||||||
|
this->out_voltage.cooldown_time = def_out_voltage_cooldown_time;
|
||||||
|
this->out_voltage.update_ain = 0;
|
||||||
|
this->out_voltage.auto_reset = 1;
|
||||||
|
|
||||||
|
this->out_current.init(&(this->board_hw.out_current), &(this->counter));
|
||||||
|
this->out_current.under_treshold = def_out_current_under_treshold;
|
||||||
|
this->out_current.over_treshold = def_out_current_over_treshold;
|
||||||
|
this->out_current.hold_time = def_out_current_hold_time;
|
||||||
|
this->out_current.cooldown_time = def_out_current_cooldown_time;
|
||||||
|
this->out_current.update_ain = 0;
|
||||||
|
this->out_current.auto_reset = 1;
|
||||||
|
|
||||||
|
this->battery_voltage.init(&(this->board_hw.battery_voltage), &(this->counter));
|
||||||
|
this->battery_voltage.under_treshold = def_battery_voltage_under_treshold;
|
||||||
|
this->battery_voltage.over_treshold = def_battery_voltage_over_treshold;
|
||||||
|
this->battery_voltage.hold_time = def_battery_voltage_hold_time;
|
||||||
|
this->battery_voltage.cooldown_time = def_battery_voltage_cooldown_time;
|
||||||
|
this->battery_voltage.update_ain = 0;
|
||||||
|
this->battery_voltage.auto_reset = 1;
|
||||||
|
this->battery_voltage.last_read = def_inital_bat_voltage;
|
||||||
|
|
||||||
|
this->battery_current.init(&(this->board_hw.battery_current), &(this->counter));
|
||||||
|
this->battery_current.under_treshold = def_battery_current_under_treshold;
|
||||||
|
this->battery_current.over_treshold = def_battery_current_over_treshold;
|
||||||
|
this->battery_current.hold_time = def_battery_current_hold_time;
|
||||||
|
this->battery_current.cooldown_time = def_battery_current_cooldown_time;
|
||||||
|
this->battery_current.update_ain = 0;
|
||||||
|
this->battery_current.auto_reset = 1;
|
||||||
|
|
||||||
|
this->btn_up.init(&(this->board_hw.din4), 0, &(this->counter), def_dbnc_time);
|
||||||
|
this->btn_up.update_din = 0;
|
||||||
|
|
||||||
|
this->btn_down.init(&(this->board_hw.din3), 0, &(this->counter), def_dbnc_time);
|
||||||
|
this->btn_down.update_din = 0;
|
||||||
|
|
||||||
|
this->btn_mode.init(&(this->board_hw.din1), 0, &(this->counter), def_dbnc_time);
|
||||||
|
this->btn_mode.update_din = 0;
|
||||||
|
|
||||||
|
this->handbrake.init(&(this->board_hw.hvdin3), 0, &(this->counter), def_dbnc_time);
|
||||||
|
this->handbrake.update_din = 0;
|
||||||
|
|
||||||
|
this->brakes.init(&(this->board_hw.hvdin2), 1, &(this->counter), def_dbnc_time);
|
||||||
|
this->brakes.update_din = 0;
|
||||||
|
|
||||||
|
this->dimm.init(&(this->board_hw.hvdin1), 1, &(this->counter), def_dbnc_time);
|
||||||
|
this->dimm.update_din = 0;
|
||||||
|
|
||||||
|
this->pot.init(&(this->board_hw.ain2), def_pot_dead_bot, def_pot_dead_top);
|
||||||
|
this->pot.update_ain = 0;
|
||||||
|
|
||||||
|
hw::OutReg::outRegCfg_t outreg_cfg;
|
||||||
|
outreg_cfg.pwm_high = &this->board_hw.out_pwm;
|
||||||
|
outreg_cfg.dout_low = &this->board_hw.out_low;
|
||||||
|
outreg_cfg.ubat = &this->board_hw.battery_voltage;
|
||||||
|
outreg_cfg.uout = &this->board_hw.out_voltage;
|
||||||
|
outreg_cfg.iout = &this->board_hw.out_current;
|
||||||
|
this->outreg.init(&outreg_cfg);
|
||||||
|
this->outreg.cc_mode_en = def_cc_mode_en;
|
||||||
|
this->outreg.update_ain = 0;
|
||||||
|
|
||||||
|
hw::LedDisplay::doutCfg_t dsp_cfg;
|
||||||
|
dsp_cfg.led0_dout_ch = &(this->board_hw.od1);
|
||||||
|
dsp_cfg.led1_dout_ch = &(this->board_hw.od2);
|
||||||
|
dsp_cfg.led2_dout_ch = &(this->board_hw.od3);
|
||||||
|
dsp_cfg.led3_dout_ch = &(this->board_hw.od4);
|
||||||
|
dsp_cfg.led4_dout_ch = &(this->board_hw.od5);
|
||||||
|
dsp_cfg.led5_dout_ch = &(this->board_hw.od6);
|
||||||
|
|
||||||
|
this->display.init(&dsp_cfg, 0, &(this->counter), &(this->board_hw.od_pwm));
|
||||||
|
|
||||||
|
// Apply configuration
|
||||||
|
if(cfg->handbrake_pull_up)
|
||||||
|
{
|
||||||
|
this->board_hw.hvdin3_pull.write(1);
|
||||||
|
}
|
||||||
|
else this->board_hw.hvdin3_pull.write(0);
|
||||||
|
|
||||||
|
if(cfg->speed_hall)
|
||||||
|
{
|
||||||
|
this->board_hw.freq_pull.write(1);
|
||||||
|
}
|
||||||
|
else this->board_hw.freq_pull.write(0);
|
||||||
|
|
||||||
|
// Set initial output states
|
||||||
|
this->outreg.write_voltage(0);
|
||||||
|
this->outreg.write_current(0);
|
||||||
|
this->outreg.write_on(0);
|
||||||
|
this->outreg.write_lock(0);
|
||||||
|
this->outreg.process();
|
||||||
|
|
||||||
|
this->display.write_backlight(100);
|
||||||
|
this->display.write(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdHw::read(void)
|
||||||
|
{
|
||||||
|
// Update low level inputs
|
||||||
|
this->board_hw.read();
|
||||||
|
|
||||||
|
this->counter.increment();
|
||||||
|
|
||||||
|
this->out_voltage.process();
|
||||||
|
this->out_current.process();
|
||||||
|
this->battery_voltage.process();
|
||||||
|
this->battery_current.process();
|
||||||
|
|
||||||
|
this->btn_up.process();
|
||||||
|
this->btn_down.process();
|
||||||
|
this->btn_mode.process();
|
||||||
|
this->handbrake.process();
|
||||||
|
this->brakes.process();
|
||||||
|
this->dimm.process();
|
||||||
|
|
||||||
|
this->pot.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void dccd::DccdHw::write(void)
|
||||||
|
{
|
||||||
|
this->display.process();
|
||||||
|
this->outreg.process();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ***/
|
||||||
69
firmware/src/dccd/dccd_hw.h
Normal file
69
firmware/src/dccd/dccd_hw.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#ifndef DCCD_HW_H_
|
||||||
|
#define DCCD_HW_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
#include "../utils/vcounter.h"
|
||||||
|
#include "../hw/button.h"
|
||||||
|
#include "../hw/led_display.h"
|
||||||
|
#include "../hw/potentiometer.h"
|
||||||
|
#include "../hw/out_driver.h"
|
||||||
|
#include "../hw/safe_ain.h"
|
||||||
|
#include "../hw/out_reg.h"
|
||||||
|
|
||||||
|
namespace dccd {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class DccdHw
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
uint8_t pwm_f_khz;
|
||||||
|
uint8_t handbrake_pull_up;
|
||||||
|
uint8_t speed_hall;
|
||||||
|
uint16_t counter_step_us;
|
||||||
|
} dccdHwCfg_t;
|
||||||
|
|
||||||
|
DccdHw(void);
|
||||||
|
~DccdHw(void);
|
||||||
|
|
||||||
|
void init(dccdHwCfg_t* cfg);
|
||||||
|
|
||||||
|
// Inputs
|
||||||
|
hw::SafeAin out_voltage;
|
||||||
|
hw::SafeAin out_current;
|
||||||
|
hw::SafeAin battery_voltage;
|
||||||
|
hw::SafeAin battery_current;
|
||||||
|
|
||||||
|
hw::Button btn_up;
|
||||||
|
hw::Button btn_down;
|
||||||
|
hw::Button btn_mode;
|
||||||
|
hw::Button handbrake;
|
||||||
|
hw::Button brakes;
|
||||||
|
hw::Button dimm;
|
||||||
|
|
||||||
|
hw::Potentiometer pot;
|
||||||
|
|
||||||
|
// Outputs
|
||||||
|
hw::LedDisplay display;
|
||||||
|
hw::OutReg outreg;
|
||||||
|
|
||||||
|
void read(void);
|
||||||
|
void write(void);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::Board board_hw;
|
||||||
|
util::VCounter counter;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* DCCD_HW_H_ */
|
||||||
116
firmware/src/hw/button.cpp
Normal file
116
firmware/src/hw/button.cpp
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "button.h"
|
||||||
|
|
||||||
|
using namespace hw;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::Button::Button(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::Button::~Button(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::Button::init(bsp::DigitalIn* din_ch, uint8_t act_lvl, util::VCounter* timer, uint16_t dbnc_lim)
|
||||||
|
{
|
||||||
|
this->din_ch = din_ch;
|
||||||
|
this->timer = timer;
|
||||||
|
|
||||||
|
if(act_lvl) this->act_lvl = 1;
|
||||||
|
else this->act_lvl = 0;
|
||||||
|
|
||||||
|
this->state_start_ts = 0;
|
||||||
|
this->dbnc_ts = 0;
|
||||||
|
this->dbnc_lim = dbnc_lim;
|
||||||
|
|
||||||
|
this->state = BUTTON_OFF;
|
||||||
|
this->is_new = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hw::Button::process(void)
|
||||||
|
{
|
||||||
|
// Read din
|
||||||
|
if(this->update_din) this->din_ch->read();
|
||||||
|
|
||||||
|
// Get last read level
|
||||||
|
uint8_t lvl = this->din_ch->last_read;
|
||||||
|
|
||||||
|
// Determine next state
|
||||||
|
uint8_t next_state = BUTTON_OFF;
|
||||||
|
if(lvl==this->act_lvl) next_state = BUTTON_ON;
|
||||||
|
|
||||||
|
// Advance debounce sample counter
|
||||||
|
uint16_t ts_now = this->timer->read();
|
||||||
|
|
||||||
|
if(next_state != this->state)
|
||||||
|
{
|
||||||
|
if(this->dbnc_ts == 0) this->dbnc_ts = ts_now;
|
||||||
|
uint16_t td = util::time_delta(this->dbnc_ts, ts_now);
|
||||||
|
uint32_t td_ms = this->timer->convert_ms(td);
|
||||||
|
// Check for debounce end
|
||||||
|
if(td_ms >= this->dbnc_lim)
|
||||||
|
{
|
||||||
|
// Debounce end. Apply new state.
|
||||||
|
this->dbnc_ts = 0;
|
||||||
|
this->state = next_state;
|
||||||
|
this->state_start_ts = ts_now;
|
||||||
|
this->is_new = 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else this->dbnc_ts = 0;
|
||||||
|
|
||||||
|
return this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hw::Button::force_read(void)
|
||||||
|
{
|
||||||
|
// Read din
|
||||||
|
if(this->update_din) this->din_ch->read();
|
||||||
|
|
||||||
|
// Get last read level
|
||||||
|
uint8_t lvl = this->din_ch->last_read;
|
||||||
|
|
||||||
|
// Cancels active debounce
|
||||||
|
this->dbnc_ts = 0;
|
||||||
|
|
||||||
|
// Determine next state
|
||||||
|
uint8_t next_state = BUTTON_OFF;
|
||||||
|
if(lvl==this->act_lvl) next_state = BUTTON_ON;
|
||||||
|
|
||||||
|
if(next_state != this->state)
|
||||||
|
{
|
||||||
|
this->state_start_ts = this->timer->read();
|
||||||
|
this->state = next_state;
|
||||||
|
this->is_new = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
return this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hw::Button::time_read(void)
|
||||||
|
{
|
||||||
|
uint16_t ts_now = this->timer->read();
|
||||||
|
uint16_t td = util::time_delta(this->state_start_ts, ts_now);
|
||||||
|
return this->timer->convert_ms(td);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::Button::time_reset(void)
|
||||||
|
{
|
||||||
|
this->state_start_ts = this->timer->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t hw::Button::time_read_max(void)
|
||||||
|
{
|
||||||
|
uint16_t ts_max = this->timer->read_top();
|
||||||
|
return this->timer->convert_ms(ts_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
49
firmware/src/hw/button.h
Normal file
49
firmware/src/hw/button.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#ifndef BUTTONS_H_
|
||||||
|
#define BUTTONS_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../utils/vcounter.h"
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
const uint8_t BUTTON_OFF = 0;
|
||||||
|
const uint8_t BUTTON_ON = 1;
|
||||||
|
|
||||||
|
class Button
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Button(void);
|
||||||
|
~Button(void);
|
||||||
|
|
||||||
|
uint8_t state;
|
||||||
|
uint16_t dbnc_lim;
|
||||||
|
uint8_t is_new;
|
||||||
|
uint8_t update_din;
|
||||||
|
|
||||||
|
void init(bsp::DigitalIn* din_ch, uint8_t act_lvl, util::VCounter* timer, uint16_t dbnc_lim);
|
||||||
|
uint8_t process(void);
|
||||||
|
uint8_t force_read(void);
|
||||||
|
uint32_t time_read(void);
|
||||||
|
void time_reset(void);
|
||||||
|
uint32_t time_read_max(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::DigitalIn* din_ch;
|
||||||
|
util::VCounter* timer;
|
||||||
|
uint8_t act_lvl;
|
||||||
|
uint16_t state_start_ts;
|
||||||
|
uint16_t dbnc_ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* BUTTONS_H_ */
|
||||||
160
firmware/src/hw/led_display.cpp
Normal file
160
firmware/src/hw/led_display.cpp
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "led_display.h"
|
||||||
|
|
||||||
|
using namespace hw;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::LedDisplay::LedDisplay(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::LedDisplay::~LedDisplay(void)
|
||||||
|
{
|
||||||
|
this->force(0x00);
|
||||||
|
this->write_backlight(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::init(doutCfg_t* dout_chs, uint8_t act_lvl, util::VCounter* timer, bsp::PwmOut* pwm_ch)
|
||||||
|
{
|
||||||
|
this->led0_dout_ch = dout_chs->led0_dout_ch;
|
||||||
|
this->led1_dout_ch = dout_chs->led1_dout_ch;
|
||||||
|
this->led2_dout_ch = dout_chs->led2_dout_ch;
|
||||||
|
this->led3_dout_ch = dout_chs->led3_dout_ch;
|
||||||
|
this->led4_dout_ch = dout_chs->led4_dout_ch;
|
||||||
|
this->led5_dout_ch = dout_chs->led5_dout_ch;
|
||||||
|
|
||||||
|
if(act_lvl) this->act_lvl = 1;
|
||||||
|
else this->act_lvl = 0;
|
||||||
|
|
||||||
|
this->timer = timer;
|
||||||
|
|
||||||
|
this->pwm_ch = pwm_ch;
|
||||||
|
|
||||||
|
this->on_time = 0;
|
||||||
|
this->period = 0;
|
||||||
|
this->cycle_cnt = 0;
|
||||||
|
this->cycle_limit = 0;
|
||||||
|
this->timestamp_start = 0;
|
||||||
|
this->image = 0x00;
|
||||||
|
|
||||||
|
this->force(0x00);
|
||||||
|
this->write_backlight(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::force(uint8_t image)
|
||||||
|
{
|
||||||
|
uint8_t led_state;
|
||||||
|
|
||||||
|
if(image&0x01) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led0_dout_ch);
|
||||||
|
|
||||||
|
if(image&0x02) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led1_dout_ch);
|
||||||
|
|
||||||
|
if(image&0x04) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led2_dout_ch);
|
||||||
|
|
||||||
|
if(image&0x08) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led3_dout_ch);
|
||||||
|
|
||||||
|
if(image&0x10) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led4_dout_ch);
|
||||||
|
|
||||||
|
if(image&0x20) led_state = 1;
|
||||||
|
else led_state = 0;
|
||||||
|
this->set_single_led(led_state, this->led5_dout_ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::write(uint8_t image)
|
||||||
|
{
|
||||||
|
// Static mode
|
||||||
|
this->on_time = 1;
|
||||||
|
this->period = 0;
|
||||||
|
this->cycle_cnt = 0;
|
||||||
|
this->cycle_limit = 0;
|
||||||
|
this->timestamp_start = 0;
|
||||||
|
this->image = image;
|
||||||
|
|
||||||
|
// Set initial state
|
||||||
|
this->force(this->image);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::write(uint8_t image, uint16_t on_time, uint16_t period, uint8_t cycle_limit)
|
||||||
|
{
|
||||||
|
// "PWM" mode
|
||||||
|
this->on_time = on_time;
|
||||||
|
this->period = period;
|
||||||
|
this->cycle_cnt = 0;
|
||||||
|
this->cycle_limit = cycle_limit;
|
||||||
|
this->image = image;
|
||||||
|
|
||||||
|
// Set initial state
|
||||||
|
if(this->on_time > 0) this->force(this->image);
|
||||||
|
else this->force(0x00);
|
||||||
|
|
||||||
|
// Cycle start time
|
||||||
|
this->timestamp_start = this->timer->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::process(void)
|
||||||
|
{
|
||||||
|
if(this->period == 0) return; // Nothing to do
|
||||||
|
|
||||||
|
// Update cycle timing
|
||||||
|
uint16_t ts_now = this->timer->read();
|
||||||
|
uint16_t td = util::time_delta(this->timestamp_start, ts_now);
|
||||||
|
uint32_t td_ms = this->timer->convert_ms(td);
|
||||||
|
|
||||||
|
if(td_ms >= this->period)
|
||||||
|
{
|
||||||
|
this->timestamp_start = ts_now;
|
||||||
|
this->cycle_cnt++;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check cycle limit
|
||||||
|
if((this->cycle_cnt >= this->cycle_limit)&&(this->cycle_limit))
|
||||||
|
{
|
||||||
|
this->on_time = 0;
|
||||||
|
this->period = 0;
|
||||||
|
this->timestamp_start = 0;
|
||||||
|
this->force(0x00);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Do output compare
|
||||||
|
if(td_ms < this->on_time) this->force(this->image);
|
||||||
|
else this->force(0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hw::LedDisplay::is_cycle_end(void)
|
||||||
|
{
|
||||||
|
if(this->cycle_cnt >= this->cycle_limit) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::write_backlight(uint8_t percent)
|
||||||
|
{
|
||||||
|
this->pwm_ch->write(percent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::LedDisplay::set_single_led(uint8_t state, bsp::DigitalOut* led_ch)
|
||||||
|
{
|
||||||
|
uint8_t lvl = 0;
|
||||||
|
|
||||||
|
if(((state==0)&&(this->act_lvl==0))||((state!=0)&&(this->act_lvl==1))) lvl = 1;
|
||||||
|
|
||||||
|
led_ch->write(lvl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ***/
|
||||||
66
firmware/src/hw/led_display.h
Normal file
66
firmware/src/hw/led_display.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef LED_DISPLAY_H_
|
||||||
|
#define LED_DISPLAY_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../utils/vcounter.h"
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class LedDisplay
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
bsp::DigitalOut* led0_dout_ch;
|
||||||
|
bsp::DigitalOut* led1_dout_ch;
|
||||||
|
bsp::DigitalOut* led2_dout_ch;
|
||||||
|
bsp::DigitalOut* led3_dout_ch;
|
||||||
|
bsp::DigitalOut* led4_dout_ch;
|
||||||
|
bsp::DigitalOut* led5_dout_ch;
|
||||||
|
} doutCfg_t;
|
||||||
|
|
||||||
|
LedDisplay(void);
|
||||||
|
~LedDisplay(void);
|
||||||
|
|
||||||
|
uint16_t on_time;
|
||||||
|
uint16_t period;
|
||||||
|
uint8_t cycle_cnt;
|
||||||
|
uint8_t cycle_limit;
|
||||||
|
|
||||||
|
void init(doutCfg_t* dout_chs, uint8_t act_lvl, util::VCounter* timer, bsp::PwmOut* pwm_ch);
|
||||||
|
void write(uint8_t image);
|
||||||
|
void write(uint8_t image, uint16_t on_time, uint16_t period, uint8_t cycle_limit);
|
||||||
|
void process(void);
|
||||||
|
uint8_t is_cycle_end(void);
|
||||||
|
void force(uint8_t image);
|
||||||
|
|
||||||
|
void write_backlight(uint8_t percent);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::DigitalOut* led0_dout_ch;
|
||||||
|
bsp::DigitalOut* led1_dout_ch;
|
||||||
|
bsp::DigitalOut* led2_dout_ch;
|
||||||
|
bsp::DigitalOut* led3_dout_ch;
|
||||||
|
bsp::DigitalOut* led4_dout_ch;
|
||||||
|
bsp::DigitalOut* led5_dout_ch;
|
||||||
|
uint8_t act_lvl;
|
||||||
|
util::VCounter* timer;
|
||||||
|
bsp::PwmOut* pwm_ch;
|
||||||
|
uint16_t timestamp_start;
|
||||||
|
uint8_t image;
|
||||||
|
|
||||||
|
void set_single_led(uint8_t state, bsp::DigitalOut* led_ch);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* LED_DISPLAY_H_ */
|
||||||
105
firmware/src/hw/out_driver.cpp
Normal file
105
firmware/src/hw/out_driver.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "out_driver.h"
|
||||||
|
|
||||||
|
using namespace hw;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::OutDriver::OutDriver(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::OutDriver::~OutDriver(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::init(bsp::PwmOut* pwm_high, bsp::DigitalOut* dout_low)
|
||||||
|
{
|
||||||
|
this->pwm_high = pwm_high;
|
||||||
|
this->dout_low = dout_low;
|
||||||
|
|
||||||
|
this->target_duty = 0;
|
||||||
|
this->target_low = 0;
|
||||||
|
this->disabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::write(uint16_t numerator)
|
||||||
|
{
|
||||||
|
this->target_duty = numerator;
|
||||||
|
this->target_low = 1;
|
||||||
|
|
||||||
|
// Check if enabled
|
||||||
|
if(this->disabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set low side
|
||||||
|
if(this->dout_low->last_writen == 0)
|
||||||
|
{
|
||||||
|
this->dout_low->write(this->target_low);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set PWM
|
||||||
|
this->pwm_high->write(this->target_duty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::write(uint8_t percent)
|
||||||
|
{
|
||||||
|
// Convert to numerator/0xFFFF
|
||||||
|
this->write(util::percent_to_16b(percent));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::write_hiz(void)
|
||||||
|
{
|
||||||
|
this->target_duty = 0;
|
||||||
|
this->target_low = 0;
|
||||||
|
|
||||||
|
// Check if enabled
|
||||||
|
if(this->disabled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set PWM
|
||||||
|
this->pwm_high->write((uint16_t)0);
|
||||||
|
|
||||||
|
// Set low side
|
||||||
|
this->dout_low->write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::enable(void)
|
||||||
|
{
|
||||||
|
if(this->disabled==0) return;
|
||||||
|
this->disabled = 0;
|
||||||
|
|
||||||
|
if(this->target_low==0) this->write_hiz();
|
||||||
|
else this->write(this->target_duty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutDriver::disable(void)
|
||||||
|
{
|
||||||
|
if(this->disabled!=0) return;
|
||||||
|
|
||||||
|
// Set PWM
|
||||||
|
this->pwm_high->write((uint16_t)0);
|
||||||
|
|
||||||
|
// Set low side
|
||||||
|
this->dout_low->write(0);
|
||||||
|
|
||||||
|
this->disabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hw::OutDriver::is_disabled(void)
|
||||||
|
{
|
||||||
|
return this->disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
45
firmware/src/hw/out_driver.h
Normal file
45
firmware/src/hw/out_driver.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef OUT_DRIVER_H_
|
||||||
|
#define OUT_DRIVER_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
|
||||||
|
class OutDriver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OutDriver(void);
|
||||||
|
~OutDriver(void);
|
||||||
|
|
||||||
|
void init(bsp::PwmOut* pwm_high, bsp::DigitalOut* dout_low);
|
||||||
|
|
||||||
|
uint16_t target_duty;
|
||||||
|
uint8_t target_low;
|
||||||
|
|
||||||
|
void write(uint16_t numerator);
|
||||||
|
void write(uint8_t percent);
|
||||||
|
void write_hiz(void);
|
||||||
|
void enable(void);
|
||||||
|
void disable(void);
|
||||||
|
uint8_t is_disabled(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::PwmOut* pwm_high;
|
||||||
|
bsp::DigitalOut* dout_low;
|
||||||
|
uint8_t disabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* OUT_DRIVER_H_ */
|
||||||
139
firmware/src/hw/out_reg.cpp
Normal file
139
firmware/src/hw/out_reg.cpp
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "out_reg.h"
|
||||||
|
|
||||||
|
using namespace bsp;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::OutReg::OutReg(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::OutReg::~OutReg(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::init(outRegCfg_t* cfg)
|
||||||
|
{
|
||||||
|
this->pwm_high = cfg->pwm_high;
|
||||||
|
this->dout_low = cfg->dout_low;
|
||||||
|
this->ubat = cfg->ubat;
|
||||||
|
this->uout = cfg->uout;
|
||||||
|
this->iout = cfg->iout;
|
||||||
|
|
||||||
|
this->voltage = 0;
|
||||||
|
this->current = 0;
|
||||||
|
this->out_on = 0;
|
||||||
|
this->lock = 0;
|
||||||
|
|
||||||
|
this->cc_mode_en = 0;
|
||||||
|
this->update_ain = 0;
|
||||||
|
this->cc_tolerance = 75;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::write_voltage(uint16_t voltage)
|
||||||
|
{
|
||||||
|
this->voltage = voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::write_current(uint16_t current)
|
||||||
|
{
|
||||||
|
this->current = current;
|
||||||
|
this->current_bot = util::sat_subtract(current, this->cc_tolerance);
|
||||||
|
this->current_top = util::sat_add(current, this->cc_tolerance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::write_on(uint8_t state)
|
||||||
|
{
|
||||||
|
this->out_on = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::write_lock(uint8_t state)
|
||||||
|
{
|
||||||
|
this->lock = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t hw::OutReg::read_voltage(void)
|
||||||
|
{
|
||||||
|
return this->voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t hw::OutReg::read_current(void)
|
||||||
|
{
|
||||||
|
return this->current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::process(void)
|
||||||
|
{
|
||||||
|
// Update analog input
|
||||||
|
if(this->update_ain)
|
||||||
|
{
|
||||||
|
this->ubat->read();
|
||||||
|
this->uout->read();
|
||||||
|
this->iout->read();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if turned off
|
||||||
|
if((out_on == 0)||(this->lock != 0))
|
||||||
|
{
|
||||||
|
|
||||||
|
this->pwm_high->write((uint16_t)0);
|
||||||
|
this->dout_low->write(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(this->dout_low->last_writen == 0)
|
||||||
|
{
|
||||||
|
this->dout_low->write(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate next duty cycle setting
|
||||||
|
uint16_t next_duty = this->pwm_high->get_set_duty();
|
||||||
|
|
||||||
|
if((this->voltage==0)||(this->current==0))
|
||||||
|
{
|
||||||
|
// Off but not HiZ
|
||||||
|
next_duty = 0;
|
||||||
|
}
|
||||||
|
else if((this->cc_mode_en)&&(this->iout->last_read > this->current_bot))
|
||||||
|
{
|
||||||
|
// Constant current mode - Change voltage to be within current limit
|
||||||
|
if(util::is_in_range(this->iout->last_read, this->current_bot, this->current_top)==0)
|
||||||
|
{
|
||||||
|
// Current outside of tolerance. Recalculate duty cycle.
|
||||||
|
uint32_t temp = (uint32_t)this->pwm_high->get_set_duty() * (uint32_t)this->current;
|
||||||
|
temp /= this->iout->last_read;
|
||||||
|
next_duty = util::sat_cast(temp);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Constant voltage mode
|
||||||
|
next_duty = util::sat_ratio(this->voltage, this->ubat->last_read);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->pwm_high->write(next_duty);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::OutReg::force_off(void)
|
||||||
|
{
|
||||||
|
// Turn off output - HiZ
|
||||||
|
this->pwm_high->write((uint16_t)0);
|
||||||
|
this->dout_low->write(0);
|
||||||
|
|
||||||
|
// Update targets
|
||||||
|
this->voltage = 0;
|
||||||
|
this->current = 0;
|
||||||
|
this->out_on = 0;
|
||||||
|
this->lock = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
66
firmware/src/hw/out_reg.h
Normal file
66
firmware/src/hw/out_reg.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
#ifndef OUTPUT_REGULATOR_H_
|
||||||
|
#define OUTPUT_REGULATOR_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
|
||||||
|
class OutReg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef struct {
|
||||||
|
bsp::PwmOut* pwm_high;
|
||||||
|
bsp::DigitalOut* dout_low;
|
||||||
|
bsp::AnalogIn* ubat;
|
||||||
|
bsp::AnalogIn* uout;
|
||||||
|
bsp::AnalogIn* iout;
|
||||||
|
} outRegCfg_t;
|
||||||
|
|
||||||
|
OutReg(void);
|
||||||
|
~OutReg(void);
|
||||||
|
|
||||||
|
void init(outRegCfg_t* cfg);
|
||||||
|
|
||||||
|
uint8_t cc_mode_en;
|
||||||
|
uint8_t update_ain;
|
||||||
|
uint16_t cc_tolerance;
|
||||||
|
|
||||||
|
void write_voltage(uint16_t voltage);
|
||||||
|
void write_current(uint16_t current);
|
||||||
|
void write_on(uint8_t state);
|
||||||
|
void write_lock(uint8_t state);
|
||||||
|
|
||||||
|
uint16_t read_voltage(void);
|
||||||
|
uint16_t read_current(void);
|
||||||
|
|
||||||
|
void process(void);
|
||||||
|
void force_off(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::PwmOut* pwm_high;
|
||||||
|
bsp::DigitalOut* dout_low;
|
||||||
|
bsp::AnalogIn* ubat;
|
||||||
|
bsp::AnalogIn* uout;
|
||||||
|
bsp::AnalogIn* iout;
|
||||||
|
uint16_t voltage;
|
||||||
|
uint16_t current;
|
||||||
|
uint16_t current_top;
|
||||||
|
uint16_t current_bot;
|
||||||
|
uint8_t out_on;
|
||||||
|
uint8_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* OUTPUT_REGULATOR_H_ */
|
||||||
46
firmware/src/hw/potentiometer.cpp
Normal file
46
firmware/src/hw/potentiometer.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "../utils/interpolate.h"
|
||||||
|
#include "potentiometer.h"
|
||||||
|
|
||||||
|
using namespace hw;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::Potentiometer::Potentiometer(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::Potentiometer::~Potentiometer(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::Potentiometer::init(bsp::AnalogIn* ain_ch, uint16_t low_deadzone, uint16_t high_deadzone)
|
||||||
|
{
|
||||||
|
this->ain_ch = ain_ch;
|
||||||
|
this->low_deadzone = low_deadzone;
|
||||||
|
this->high_deadzone = high_deadzone;
|
||||||
|
this->last_percent = 0;
|
||||||
|
this->update_ain = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t hw::Potentiometer::read(void)
|
||||||
|
{
|
||||||
|
// Update analog input
|
||||||
|
if(this->update_ain) this->ain_ch->read();
|
||||||
|
|
||||||
|
// Calculate percent
|
||||||
|
if(this->ain_ch->last_read <= this->low_deadzone) this->last_percent = 0;
|
||||||
|
else if(this->ain_ch->last_read >= this->high_deadzone ) this->last_percent = 100;
|
||||||
|
else this->last_percent = util::interpolate(this->ain_ch->last_read, this->low_deadzone, this->high_deadzone, 0, 100);
|
||||||
|
|
||||||
|
return this->last_percent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
40
firmware/src/hw/potentiometer.h
Normal file
40
firmware/src/hw/potentiometer.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef POTENTIOMETER_H_
|
||||||
|
#define POTENTIOMETER_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
|
||||||
|
class Potentiometer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Potentiometer(void);
|
||||||
|
~Potentiometer(void);
|
||||||
|
|
||||||
|
void init(bsp::AnalogIn* ain_ch, uint16_t low_deadzone, uint16_t high_deadzone);
|
||||||
|
|
||||||
|
uint16_t low_deadzone;
|
||||||
|
uint16_t high_deadzone;
|
||||||
|
uint8_t last_percent;
|
||||||
|
uint8_t update_ain;
|
||||||
|
|
||||||
|
uint8_t read(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::AnalogIn* ain_ch;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* POTENTIOMETER_H_ */
|
||||||
87
firmware/src/hw/safe_ain.cpp
Normal file
87
firmware/src/hw/safe_ain.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "../utils/utils.h"
|
||||||
|
#include "safe_ain.h"
|
||||||
|
|
||||||
|
using namespace hw;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
hw::SafeAin::SafeAin(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hw::SafeAin::~SafeAin(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::SafeAin::init(bsp::AnalogIn* ain_ch, util::VCounter* timer)
|
||||||
|
{
|
||||||
|
this->ain_ch = ain_ch;
|
||||||
|
this->timer = timer;
|
||||||
|
|
||||||
|
this->under_treshold = 0;
|
||||||
|
this->over_treshold = 0xFFFF;
|
||||||
|
this->hold_time = 0;
|
||||||
|
this->cooldown_time = 0;
|
||||||
|
|
||||||
|
this->update_ain = 0;
|
||||||
|
this->auto_reset = 0;
|
||||||
|
|
||||||
|
this->warning = 0;
|
||||||
|
this->fault = 0;
|
||||||
|
|
||||||
|
this->last_read = 0;
|
||||||
|
|
||||||
|
this->ts_state_chnage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void hw::SafeAin::process(void)
|
||||||
|
{
|
||||||
|
// Update analog input
|
||||||
|
if(this->update_ain) this->ain_ch->read();
|
||||||
|
|
||||||
|
this->last_read = this->ain_ch->last_read;
|
||||||
|
|
||||||
|
// Get current time
|
||||||
|
uint16_t ts_now = this->timer->read();
|
||||||
|
|
||||||
|
// Update over current and warning condition
|
||||||
|
uint8_t is_outside = 0;
|
||||||
|
if(this->last_read < this->under_treshold) is_outside = 1;
|
||||||
|
if(this->last_read > this->over_treshold) is_outside = 1;
|
||||||
|
|
||||||
|
// Note start time if new OC condition
|
||||||
|
if(is_outside != this->warning) this->ts_state_chnage = ts_now;
|
||||||
|
|
||||||
|
// Update warning
|
||||||
|
this->warning = is_outside;
|
||||||
|
|
||||||
|
// Calculate warning condition time
|
||||||
|
uint16_t td = util::time_delta(this->ts_state_chnage, ts_now);
|
||||||
|
uint32_t time_ms = this->timer->convert_ms(td);
|
||||||
|
|
||||||
|
// Check for fault set
|
||||||
|
if((this->fault==0)&&(time_ms > (uint32_t)this->hold_time))
|
||||||
|
{
|
||||||
|
this->fault = 1;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if allowed auto reset
|
||||||
|
if(this->auto_reset==0) return;
|
||||||
|
|
||||||
|
// Check for fault reset
|
||||||
|
if((this->fault!=0)&&(time_ms > (uint32_t)this->cooldown_time))
|
||||||
|
{
|
||||||
|
this->fault = 0;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
50
firmware/src/hw/safe_ain.h
Normal file
50
firmware/src/hw/safe_ain.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef SAFE_AIN_H_
|
||||||
|
#define SAFE_AIN_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "../utils/vcounter.h"
|
||||||
|
#include "../bsp/board.h"
|
||||||
|
|
||||||
|
namespace hw {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
|
||||||
|
class SafeAin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SafeAin(void);
|
||||||
|
~SafeAin(void);
|
||||||
|
|
||||||
|
void init(bsp::AnalogIn* ain_ch, util::VCounter* timer);
|
||||||
|
|
||||||
|
uint8_t warning;
|
||||||
|
uint8_t fault;
|
||||||
|
uint16_t last_read;
|
||||||
|
|
||||||
|
uint16_t under_treshold;
|
||||||
|
uint16_t over_treshold;
|
||||||
|
uint16_t hold_time;
|
||||||
|
uint16_t cooldown_time;
|
||||||
|
|
||||||
|
uint8_t update_ain;
|
||||||
|
uint8_t auto_reset;
|
||||||
|
|
||||||
|
void process(void);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
bsp::AnalogIn* ain_ch;
|
||||||
|
util::VCounter* timer;
|
||||||
|
uint16_t ts_state_chnage;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* SAFE_AIN_H_ */
|
||||||
60
firmware/src/main.cpp
Normal file
60
firmware/src/main.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "utils/utils.h"
|
||||||
|
|
||||||
|
#include "dccd/dccd_hw.h"
|
||||||
|
#include "dccd/dccd.h"
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
static dccd::DccdHw dccd_hw;
|
||||||
|
static dccd::DccdApp app;
|
||||||
|
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// Setup
|
||||||
|
dccd::DccdHw::dccdHwCfg_t cfg;
|
||||||
|
cfg.handbrake_pull_up = 1;
|
||||||
|
cfg.pwm_f_khz = 16;
|
||||||
|
cfg.speed_hall = 0;
|
||||||
|
cfg.counter_step_us = 2000;
|
||||||
|
dccd_hw.init(&cfg);
|
||||||
|
|
||||||
|
app.init(&dccd_hw);
|
||||||
|
|
||||||
|
//#define OVERRIDECFG
|
||||||
|
#ifdef OVERRIDECFG
|
||||||
|
// Configuration
|
||||||
|
app.lock_current = 4500;
|
||||||
|
app.max_hbrake_time = 2000;
|
||||||
|
app.button_inputs = 1;
|
||||||
|
app.display_brigth = 100;
|
||||||
|
app.display_dimm = 25;
|
||||||
|
|
||||||
|
// Initial values
|
||||||
|
app.btn_force = 0;
|
||||||
|
app.brake_mode = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Save config to memory
|
||||||
|
//#define SAVECFG
|
||||||
|
#ifdef SAVECFG
|
||||||
|
app.saveMemCfg();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Super loop
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Do stuff
|
||||||
|
app.process();
|
||||||
|
// End of super loop
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape the matrix
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ***/
|
||||||
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Atmel Studio Solution File, Format Version 11.00
|
# Atmel Studio Solution File, Format Version 11.00
|
||||||
VisualStudioVersion = 14.0.23107.0
|
VisualStudioVersion = 14.0.23107.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "uDCCD_Controller", "uDCCD_Controller.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
|
Project("{E66E83B9-2572-4076-B26E-6BE79FF3018A}") = "uDCCD", "uDCCD.cppproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<Attribute>template</Attribute>
|
<Attribute>template</Attribute>
|
||||||
<Category>source</Category>
|
<Category>source</Category>
|
||||||
<Condition>C Exe</Condition>
|
<Condition>C Exe</Condition>
|
||||||
<FileContentHash>YLr2MkKo6ZooP7MhARWYNA==</FileContentHash>
|
<FileContentHash>KjvOcFWd++tbnsEMfVPd/w==</FileContentHash>
|
||||||
<FileVersion></FileVersion>
|
<FileVersion></FileVersion>
|
||||||
<Name>templates/main.c</Name>
|
<Name>templates/main.c</Name>
|
||||||
<SelectString>Main file (.c)</SelectString>
|
<SelectString>Main file (.c)</SelectString>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
<Attribute>template</Attribute>
|
<Attribute>template</Attribute>
|
||||||
<Category>source</Category>
|
<Category>source</Category>
|
||||||
<Condition>C Exe</Condition>
|
<Condition>C Exe</Condition>
|
||||||
<FileContentHash>mkKaE95TOoATsuBGv6jmxg==</FileContentHash>
|
<FileContentHash>w5aB/d0+DbxGZ7yY0aMMjw==</FileContentHash>
|
||||||
<FileVersion></FileVersion>
|
<FileVersion></FileVersion>
|
||||||
<Name>templates/main.cpp</Name>
|
<Name>templates/main.cpp</Name>
|
||||||
<SelectString>Main file (.cpp)</SelectString>
|
<SelectString>Main file (.cpp)</SelectString>
|
||||||
262
firmware/src/uDCCD.cppproj
Normal file
262
firmware/src/uDCCD.cppproj
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectVersion>7.0</ProjectVersion>
|
||||||
|
<ToolchainName>com.Atmel.AVRGCC8.CPP</ToolchainName>
|
||||||
|
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
|
||||||
|
<avrdevice>ATmega328PB</avrdevice>
|
||||||
|
<avrdeviceseries>none</avrdeviceseries>
|
||||||
|
<OutputType>Executable</OutputType>
|
||||||
|
<Language>CPP</Language>
|
||||||
|
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
|
||||||
|
<OutputFileExtension>.elf</OutputFileExtension>
|
||||||
|
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
|
||||||
|
<AssemblyName>uDCCD</AssemblyName>
|
||||||
|
<Name>uDCCD</Name>
|
||||||
|
<RootNamespace>uDCCD</RootNamespace>
|
||||||
|
<ToolchainFlavour>Native</ToolchainFlavour>
|
||||||
|
<KeepTimersRunning>true</KeepTimersRunning>
|
||||||
|
<OverrideVtor>false</OverrideVtor>
|
||||||
|
<CacheFlash>true</CacheFlash>
|
||||||
|
<ProgFlashFromRam>true</ProgFlashFromRam>
|
||||||
|
<RamSnippetAddress>0x20000000</RamSnippetAddress>
|
||||||
|
<UncachedRange />
|
||||||
|
<preserveEEPROM>true</preserveEEPROM>
|
||||||
|
<OverrideVtorValue>exception_table</OverrideVtorValue>
|
||||||
|
<BootSegment>2</BootSegment>
|
||||||
|
<ResetRule>0</ResetRule>
|
||||||
|
<eraseonlaunchrule>0</eraseonlaunchrule>
|
||||||
|
<EraseKey />
|
||||||
|
<AsfFrameworkConfig>
|
||||||
|
<framework-data xmlns="">
|
||||||
|
<options />
|
||||||
|
<configurations />
|
||||||
|
<files />
|
||||||
|
<documentation help="" />
|
||||||
|
<offline-documentation help="" />
|
||||||
|
<dependencies>
|
||||||
|
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.52.0" />
|
||||||
|
</dependencies>
|
||||||
|
</framework-data>
|
||||||
|
</AsfFrameworkConfig>
|
||||||
|
<avrtool>com.atmel.avrdbg.tool.atmelice</avrtool>
|
||||||
|
<avrtoolserialnumber>J42700001490</avrtoolserialnumber>
|
||||||
|
<avrdeviceexpectedsignature>0x1E9516</avrdeviceexpectedsignature>
|
||||||
|
<com_atmel_avrdbg_tool_atmelice>
|
||||||
|
<ToolOptions>
|
||||||
|
<InterfaceProperties>
|
||||||
|
<IspClock>249992</IspClock>
|
||||||
|
</InterfaceProperties>
|
||||||
|
<InterfaceName>ISP</InterfaceName>
|
||||||
|
</ToolOptions>
|
||||||
|
<ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
|
||||||
|
<ToolNumber>J42700001490</ToolNumber>
|
||||||
|
<ToolName>Atmel-ICE</ToolName>
|
||||||
|
</com_atmel_avrdbg_tool_atmelice>
|
||||||
|
<avrtoolinterface>ISP</avrtoolinterface>
|
||||||
|
<avrtoolinterfaceclock>249992</avrtoolinterfaceclock>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<ToolchainSettings>
|
||||||
|
<AvrGccCpp>
|
||||||
|
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega328pb"</avrgcc.common.Device>
|
||||||
|
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||||
|
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||||
|
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||||
|
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
||||||
|
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
||||||
|
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||||
|
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||||
|
<avrgcc.compiler.symbols.DefSymbols><ListValues>
|
||||||
|
<Value>F_CPU=8000000UL</Value>
|
||||||
|
<Value>NDEBUG</Value>
|
||||||
|
</ListValues></avrgcc.compiler.symbols.DefSymbols>
|
||||||
|
<avrgcc.compiler.directories.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcc.compiler.directories.IncludePaths>
|
||||||
|
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
||||||
|
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
||||||
|
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
||||||
|
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||||
|
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||||
|
<avrgcccpp.compiler.symbols.DefSymbols><ListValues>
|
||||||
|
<Value>F_CPU=8000000UL</Value>
|
||||||
|
<Value>NDEBUG</Value>
|
||||||
|
</ListValues></avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
|
<avrgcccpp.compiler.directories.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcccpp.compiler.directories.IncludePaths>
|
||||||
|
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
|
||||||
|
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
|
||||||
|
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
|
||||||
|
<avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
|
||||||
|
<avrgcccpp.assembler.general.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcccpp.assembler.general.IncludePaths>
|
||||||
|
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
||||||
|
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
|
||||||
|
</AvrGccCpp>
|
||||||
|
</ToolchainSettings>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<ToolchainSettings>
|
||||||
|
<AvrGccCpp>
|
||||||
|
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega328pb"</avrgcc.common.Device>
|
||||||
|
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
||||||
|
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
||||||
|
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
||||||
|
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
||||||
|
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
||||||
|
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||||
|
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||||
|
<avrgcc.compiler.symbols.DefSymbols><ListValues>
|
||||||
|
<Value>F_CPU=8000000UL</Value>
|
||||||
|
<Value>DEBUG</Value>
|
||||||
|
</ListValues></avrgcc.compiler.symbols.DefSymbols>
|
||||||
|
<avrgcc.compiler.directories.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcc.compiler.directories.IncludePaths>
|
||||||
|
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
||||||
|
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
||||||
|
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
||||||
|
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
|
||||||
|
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
|
||||||
|
<avrgcccpp.compiler.symbols.DefSymbols><ListValues>
|
||||||
|
<Value>F_CPU=8000000UL</Value>
|
||||||
|
<Value>DEBUG</Value>
|
||||||
|
</ListValues></avrgcccpp.compiler.symbols.DefSymbols>
|
||||||
|
<avrgcccpp.compiler.directories.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcccpp.compiler.directories.IncludePaths>
|
||||||
|
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
|
||||||
|
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
|
||||||
|
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
|
||||||
|
<avrgcccpp.linker.libraries.Libraries><ListValues><Value>libm</Value></ListValues></avrgcccpp.linker.libraries.Libraries>
|
||||||
|
<avrgcccpp.assembler.general.IncludePaths><ListValues><Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value></ListValues></avrgcccpp.assembler.general.IncludePaths>
|
||||||
|
<avrgcc.compiler.optimization.level>Optimize debugging experience (-Og)</avrgcc.compiler.optimization.level>
|
||||||
|
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
|
||||||
|
<avrgcccpp.compiler.optimization.level>Optimize debugging experience (-Og)</avrgcccpp.compiler.optimization.level>
|
||||||
|
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
|
||||||
|
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
|
||||||
|
</AvrGccCpp>
|
||||||
|
</ToolchainSettings>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="bsp\ain.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\ain.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\ain_lpf.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\ain_lpf.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\board.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\board.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\din.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\din.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\dout.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\dout.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\memory.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\memory.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\pwm_out.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\pwm_out.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\mcu\mcu_hal.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="bsp\mcu\mcu_hal_r8.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="dccd\dccd.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="dccd\dccd.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="dccd\dccd_hw.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="dccd\dccd_hw.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\button.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\button.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\led_display.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\led_display.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\out_reg.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\out_reg.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\safe_ain.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\safe_ain.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\out_driver.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\out_driver.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\potentiometer.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="hw\potentiometer.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="main.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\interpolate.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\interpolate.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\utils.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\utils.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\vcounter.cpp">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="utils\vcounter.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="bsp" />
|
||||||
|
<Folder Include="bsp\mcu" />
|
||||||
|
<Folder Include="hw" />
|
||||||
|
<Folder Include="dccd" />
|
||||||
|
<Folder Include="utils" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
||||||
|
</Project>
|
||||||
163
firmware/src/utils/interpolate.cpp
Normal file
163
firmware/src/utils/interpolate.cpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "utils.h"
|
||||||
|
#include "interpolate.h"
|
||||||
|
|
||||||
|
using namespace util;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
uint16_t util::interpolate_1d(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(x, x_axis[i-1], x_axis[i], y_values[i-1], y_values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::interpolate_2d(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(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(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(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(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(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(x, x0, x1, z0, z1);
|
||||||
|
|
||||||
|
// Do calculation in y axis on xz line
|
||||||
|
return interpolate(y, y0, y1, zy0, zy1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::interpolate(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::sat_cast(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::index2d_to_index1d(uint8_t ix, uint8_t iy, uint8_t len_x)
|
||||||
|
{
|
||||||
|
return ((uint16_t)len_x * iy) + ix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
23
firmware/src/utils/interpolate.h
Normal file
23
firmware/src/utils/interpolate.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef UTILS_INTERPOLATE_H_
|
||||||
|
#define UTILS_INTERPOLATE_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
uint16_t interpolate_1d(uint16_t x, uint16_t* x_axis, uint16_t* y_values, uint8_t len_axis);
|
||||||
|
uint16_t interpolate_2d(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);
|
||||||
|
|
||||||
|
uint8_t find_interval_end_index(uint16_t val, uint16_t* axis_values, uint8_t len_axis);
|
||||||
|
uint16_t interpolate(uint16_t x, uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1);
|
||||||
|
uint16_t index2d_to_index1d(uint8_t ix, uint8_t iy, uint8_t len_x);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* UTILS_INTERPOLATE_H_ */
|
||||||
216
firmware/src/utils/utils.cpp
Normal file
216
firmware/src/utils/utils.cpp
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
using namespace util;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
#ifndef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
uint8_t util::invert(uint8_t x)
|
||||||
|
{
|
||||||
|
if(x!=0) return 0;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::invert(uint16_t x)
|
||||||
|
{
|
||||||
|
if(x!=0) return 0;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::invert(uint32_t x)
|
||||||
|
{
|
||||||
|
if(x!=0) return 0;
|
||||||
|
else return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::sat_add(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
uint8_t z = x + y;
|
||||||
|
// Check for overflow
|
||||||
|
if((z < x)||(z < y)) return 0xFF;
|
||||||
|
else return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::sat_add(uint16_t x, uint16_t y)
|
||||||
|
{
|
||||||
|
uint16_t z = x + y;
|
||||||
|
// Check for overflow
|
||||||
|
if((z < x)||(z < y)) return 0xFF;
|
||||||
|
else return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::sat_add(uint32_t x, uint32_t y)
|
||||||
|
|
||||||
|
{
|
||||||
|
uint32_t z = x + y;
|
||||||
|
// Check for overflow
|
||||||
|
if((z < x)||(z < y)) return 0xFF;
|
||||||
|
else return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::sat_subtract(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_subtract(uint16_t x, uint16_t y)
|
||||||
|
{
|
||||||
|
uint16_t z = x - y;
|
||||||
|
// Check for underflow
|
||||||
|
if(z > x) return 0;
|
||||||
|
else return z;
|
||||||
|
}
|
||||||
|
uint32_t util::sat_subtract(uint32_t x, uint32_t y)
|
||||||
|
{
|
||||||
|
uint32_t z = x - y;
|
||||||
|
// Check for underflow
|
||||||
|
if(z > x) return 0;
|
||||||
|
else return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::abs_subtract(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
if(x > y) return x - y;
|
||||||
|
else return y-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::abs_subtract(uint16_t x, uint16_t y)
|
||||||
|
{
|
||||||
|
if(x > y) return x - y;
|
||||||
|
else return y-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::abs_subtract(uint32_t x, uint32_t y)
|
||||||
|
{
|
||||||
|
if(x > y) return x - y;
|
||||||
|
else return y-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t util::sat_cast(uint32_t x)
|
||||||
|
{
|
||||||
|
if(x > 0x0000FFFF) return 0xFFFF;
|
||||||
|
else return (uint16_t)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::sat_cast(int32_t x)
|
||||||
|
{
|
||||||
|
if(x < 0) return 0x0000;
|
||||||
|
else if(x > 0x0000FFFF) return 0xFFFF;
|
||||||
|
else return (uint16_t)x;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::is_timed_out(uint16_t time, uint16_t limit)
|
||||||
|
{
|
||||||
|
if(time >= limit) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t util::is_in_range(uint16_t value, uint16_t min, uint16_t max)
|
||||||
|
{
|
||||||
|
if((value >= min)&&(value <= max)) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::time_delta(uint16_t start, uint16_t end)
|
||||||
|
{
|
||||||
|
if(end >= start) return (end-start);
|
||||||
|
uint16_t temp = 0xFFFF - start;
|
||||||
|
return temp + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::time_delta(uint32_t start, uint32_t end)
|
||||||
|
{
|
||||||
|
if(end >= start) return (end-start);
|
||||||
|
uint32_t temp = 0xFFFFFFFF - start;
|
||||||
|
return temp + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::time_delta(uint16_t start, uint16_t end, uint16_t max)
|
||||||
|
{
|
||||||
|
if(end >= start) return (end-start);
|
||||||
|
uint16_t temp = max - start;
|
||||||
|
return temp + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::time_delta(uint32_t start, uint32_t end, uint32_t max)
|
||||||
|
{
|
||||||
|
if(end >= start) return (end-start);
|
||||||
|
uint32_t temp = max - start;
|
||||||
|
return temp + end;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 sat_cast(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 sat_cast(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 sat_cast(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::sat_ratio(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 sat_cast(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 = sat_cast(temp);
|
||||||
|
|
||||||
|
return pwm;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::percent_of(uint8_t percent, uint16_t value)
|
||||||
|
{
|
||||||
|
if(percent == 0) return 0;
|
||||||
|
else if(percent >= 100) return value;
|
||||||
|
|
||||||
|
uint32_t temp = (uint32_t)value * percent;
|
||||||
|
return temp/100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
52
firmware/src/utils/utils.h
Normal file
52
firmware/src/utils/utils.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef UTILS_H_
|
||||||
|
#define UTILS_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
uint8_t invert(uint8_t x);
|
||||||
|
uint16_t invert(uint16_t x);
|
||||||
|
uint32_t invert(uint32_t x);
|
||||||
|
|
||||||
|
uint8_t sat_add(uint8_t x, uint8_t y);
|
||||||
|
uint16_t sat_add(uint16_t x, uint16_t y);
|
||||||
|
uint32_t sat_add(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
|
uint8_t sat_subtract(uint8_t x, uint8_t y);
|
||||||
|
uint16_t sat_subtract(uint16_t x, uint16_t y);
|
||||||
|
uint32_t sat_subtract(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
|
uint8_t abs_subtract(uint8_t x, uint8_t y);
|
||||||
|
uint16_t abs_subtract(uint16_t x, uint16_t y);
|
||||||
|
uint32_t abs_subtract(uint32_t x, uint32_t y);
|
||||||
|
|
||||||
|
uint16_t sat_cast(uint32_t x);
|
||||||
|
uint16_t sat_cast(int32_t x);
|
||||||
|
|
||||||
|
uint8_t is_timed_out(uint16_t time, uint16_t limit);
|
||||||
|
uint8_t is_in_range(uint16_t value, uint16_t min, uint16_t max);
|
||||||
|
|
||||||
|
uint16_t time_delta(uint16_t start, uint16_t end);
|
||||||
|
uint32_t time_delta(uint32_t start, uint32_t end);
|
||||||
|
|
||||||
|
uint16_t time_delta(uint16_t start, uint16_t end, uint16_t max);
|
||||||
|
uint32_t time_delta(uint32_t start, uint32_t end, uint32_t max);
|
||||||
|
|
||||||
|
uint16_t convert_muldivoff(uint16_t raw, uint8_t mul, uint8_t div, int16_t offset);
|
||||||
|
uint16_t sat_mul_kilo(uint16_t xk, uint16_t yk);
|
||||||
|
uint16_t sat_div_kilo(uint16_t top, uint16_t bot);
|
||||||
|
uint16_t sat_ratio(uint16_t top, uint16_t bot);
|
||||||
|
uint16_t percent_to_16b(uint8_t percent);
|
||||||
|
|
||||||
|
uint16_t percent_of(uint8_t percent, uint16_t value);
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* UTILS_H_ */
|
||||||
67
firmware/src/utils/vcounter.cpp
Normal file
67
firmware/src/utils/vcounter.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/**** Includes ****/
|
||||||
|
#include "utils.h"
|
||||||
|
#include "vcounter.h"
|
||||||
|
|
||||||
|
using namespace util;
|
||||||
|
|
||||||
|
/**** Private definitions ****/
|
||||||
|
/**** Private constants ****/
|
||||||
|
/**** Private variables ****/
|
||||||
|
/**** Private function declarations ****/
|
||||||
|
/**** Public function definitions ****/
|
||||||
|
util::VCounter::VCounter(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
util::VCounter::~VCounter(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void util::VCounter::init(uint16_t top, uint16_t step_us)
|
||||||
|
{
|
||||||
|
this->counter = 0;
|
||||||
|
this->top = top;
|
||||||
|
this->step_us = step_us;
|
||||||
|
this->disabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void util::VCounter::reset(void)
|
||||||
|
{
|
||||||
|
this->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void util::VCounter::increment(void)
|
||||||
|
{
|
||||||
|
if(this->disabled) return;
|
||||||
|
this->counter++;
|
||||||
|
if(this->counter > this->top) this->counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::VCounter::read(void)
|
||||||
|
{
|
||||||
|
return this->counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::VCounter::read_ms(void)
|
||||||
|
{
|
||||||
|
return this->convert_ms(this->counter);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t util::VCounter::read_top(void)
|
||||||
|
{
|
||||||
|
return this->top;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t util::VCounter::convert_ms(uint16_t raw)
|
||||||
|
{
|
||||||
|
if(this->step_us==0) return 0;
|
||||||
|
|
||||||
|
uint32_t out = (uint32_t)raw * (uint32_t)this->step_us;
|
||||||
|
return out/1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**** Private function definitions ****/
|
||||||
|
|
||||||
42
firmware/src/utils/vcounter.h
Normal file
42
firmware/src/utils/vcounter.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#ifndef VIRTUAL_COUNTER_H_
|
||||||
|
#define VIRTUAL_COUNTER_H_
|
||||||
|
|
||||||
|
/**** Includes ****/
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
/**** Public definitions ****/
|
||||||
|
class VCounter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VCounter(void);
|
||||||
|
~VCounter(void);
|
||||||
|
|
||||||
|
void init(uint16_t top, uint16_t step_us);
|
||||||
|
|
||||||
|
uint8_t disabled;
|
||||||
|
|
||||||
|
void reset(void);
|
||||||
|
void increment(void);
|
||||||
|
uint16_t read(void);
|
||||||
|
uint32_t read_ms(void);
|
||||||
|
uint16_t read_top(void);
|
||||||
|
uint32_t convert_ms(uint16_t raw);
|
||||||
|
|
||||||
|
#ifndef TESTING
|
||||||
|
protected:
|
||||||
|
#endif
|
||||||
|
uint16_t step_us;
|
||||||
|
uint16_t counter;
|
||||||
|
uint16_t top;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**** Public function declarations ****/
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif /* VIRTUAL_COUNTER_H_ */
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
|
|
||||||
<PropertyGroup>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
<ProjectVersion>7.0</ProjectVersion>
|
|
||||||
<ToolchainName>com.Atmel.AVRGCC8.C</ToolchainName>
|
|
||||||
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
|
|
||||||
<avrdevice>ATmega328PB</avrdevice>
|
|
||||||
<avrdeviceseries>none</avrdeviceseries>
|
|
||||||
<OutputType>Executable</OutputType>
|
|
||||||
<Language>C</Language>
|
|
||||||
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
|
|
||||||
<OutputFileExtension>.elf</OutputFileExtension>
|
|
||||||
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
|
|
||||||
<AssemblyName>uDCCD_Controller</AssemblyName>
|
|
||||||
<Name>uDCCD_Controller</Name>
|
|
||||||
<RootNamespace>uDCCD_Controller</RootNamespace>
|
|
||||||
<ToolchainFlavour>Native</ToolchainFlavour>
|
|
||||||
<KeepTimersRunning>true</KeepTimersRunning>
|
|
||||||
<OverrideVtor>false</OverrideVtor>
|
|
||||||
<CacheFlash>true</CacheFlash>
|
|
||||||
<ProgFlashFromRam>true</ProgFlashFromRam>
|
|
||||||
<RamSnippetAddress>0x20000000</RamSnippetAddress>
|
|
||||||
<UncachedRange />
|
|
||||||
<preserveEEPROM>true</preserveEEPROM>
|
|
||||||
<OverrideVtorValue>exception_table</OverrideVtorValue>
|
|
||||||
<BootSegment>2</BootSegment>
|
|
||||||
<ResetRule>0</ResetRule>
|
|
||||||
<eraseonlaunchrule>0</eraseonlaunchrule>
|
|
||||||
<EraseKey />
|
|
||||||
<AsfFrameworkConfig>
|
|
||||||
<framework-data>
|
|
||||||
<options />
|
|
||||||
<configurations />
|
|
||||||
<files />
|
|
||||||
<documentation help="" />
|
|
||||||
<offline-documentation help="" />
|
|
||||||
<dependencies>
|
|
||||||
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.42.0" />
|
|
||||||
</dependencies>
|
|
||||||
</framework-data>
|
|
||||||
</AsfFrameworkConfig>
|
|
||||||
<avrtool>com.atmel.avrdbg.tool.atmelice</avrtool>
|
|
||||||
<avrtoolserialnumber>J42700001490</avrtoolserialnumber>
|
|
||||||
<avrdeviceexpectedsignature>0x1E9516</avrdeviceexpectedsignature>
|
|
||||||
<com_atmel_avrdbg_tool_atmelice>
|
|
||||||
<ToolOptions>
|
|
||||||
<InterfaceProperties>
|
|
||||||
<IspClock>125000</IspClock>
|
|
||||||
</InterfaceProperties>
|
|
||||||
<InterfaceName>ISP</InterfaceName>
|
|
||||||
</ToolOptions>
|
|
||||||
<ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
|
|
||||||
<ToolNumber>J42700001490</ToolNumber>
|
|
||||||
<ToolName>Atmel-ICE</ToolName>
|
|
||||||
</com_atmel_avrdbg_tool_atmelice>
|
|
||||||
<avrtoolinterface>ISP</avrtoolinterface>
|
|
||||||
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
|
||||||
<ToolchainSettings>
|
|
||||||
<AvrGcc>
|
|
||||||
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega328pb"</avrgcc.common.Device>
|
|
||||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
|
||||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
|
||||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
|
||||||
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
|
||||||
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
|
||||||
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
|
||||||
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
|
||||||
<avrgcc.compiler.symbols.DefSymbols>
|
|
||||||
<ListValues>
|
|
||||||
<Value>NDEBUG</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.compiler.symbols.DefSymbols>
|
|
||||||
<avrgcc.compiler.directories.IncludePaths>
|
|
||||||
<ListValues>
|
|
||||||
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.compiler.directories.IncludePaths>
|
|
||||||
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
|
||||||
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
|
||||||
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
|
||||||
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
|
||||||
<avrgcc.linker.libraries.Libraries>
|
|
||||||
<ListValues>
|
|
||||||
<Value>libm</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.linker.libraries.Libraries>
|
|
||||||
<avrgcc.assembler.general.IncludePaths>
|
|
||||||
<ListValues>
|
|
||||||
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.assembler.general.IncludePaths>
|
|
||||||
</AvrGcc>
|
|
||||||
</ToolchainSettings>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
|
||||||
<ToolchainSettings>
|
|
||||||
<AvrGcc>
|
|
||||||
<avrgcc.common.Device>-mmcu=atmega328pb -B "%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\gcc\dev\atmega328pb"</avrgcc.common.Device>
|
|
||||||
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
|
|
||||||
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
|
|
||||||
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
|
|
||||||
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
|
|
||||||
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
|
|
||||||
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
|
|
||||||
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
|
|
||||||
<avrgcc.compiler.symbols.DefSymbols>
|
|
||||||
<ListValues>
|
|
||||||
<Value>DEBUG</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.compiler.symbols.DefSymbols>
|
|
||||||
<avrgcc.compiler.directories.IncludePaths>
|
|
||||||
<ListValues>
|
|
||||||
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.compiler.directories.IncludePaths>
|
|
||||||
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
|
|
||||||
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
|
|
||||||
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
|
|
||||||
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
|
|
||||||
<avrgcc.linker.libraries.Libraries>
|
|
||||||
<ListValues>
|
|
||||||
<Value>libm</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.linker.libraries.Libraries>
|
|
||||||
<avrgcc.assembler.general.IncludePaths>
|
|
||||||
<ListValues>
|
|
||||||
<Value>%24(PackRepoDir)\atmel\ATmega_DFP\1.7.374\include\</Value>
|
|
||||||
</ListValues>
|
|
||||||
</avrgcc.assembler.general.IncludePaths>
|
|
||||||
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
|
|
||||||
</AvrGcc>
|
|
||||||
</ToolchainSettings>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="devices\analog.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\analog.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\common\level.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\config.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\config.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\led_display.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\led_display.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\filter_iir_lpf.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\filter_iir_lpf.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\halfbridge.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\halfbridge.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\hal\udccd_r7_hal.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\hal\udccd_hal.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\inputs.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\inputs.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\memory.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="devices\memory.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="drivers\display.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="drivers\display.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="drivers\output.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="drivers\output.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\coil.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\coil.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\force.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\force.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\settings.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="logic\settings.h">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="main.c">
|
|
||||||
<SubType>compile</SubType>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="devices" />
|
|
||||||
<Folder Include="devices\hal" />
|
|
||||||
<Folder Include="devices\common" />
|
|
||||||
<Folder Include="drivers" />
|
|
||||||
<Folder Include="logic" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
|
||||||
</Project>
|
|
||||||
BIN
pcb/dev board/udccd_dev_board.eprj
Normal file
BIN
pcb/dev board/udccd_dev_board.eprj
Normal file
Binary file not shown.
Reference in New Issue
Block a user