From 8e3174be21bd9100a249b118c74629b84d080fb9 Mon Sep 17 00:00:00 2001 From: Ebersold Andre Date: Tue, 21 Dec 2021 19:45:51 +0100 Subject: [PATCH] Import revision 9 from svn --- Application/CMakeLists.txt | 1 + Application/DCMotor/328p_DCMotor.cpp | 214 +++++++ Application/DCMotor/32u4_DCMotor.cpp | 210 +++++++ Application/DCMotor/CMakeLists.txt | 36 ++ Application/DCMotor/DCM_InterruptActivity.cpp | 21 + Application/DCMotor/DCM_InterruptActivity.h | 21 + Application/DCMotor/DCMotor.cpp | 21 + Application/DCMotor/DCMotor.h | 90 +++ Application/DCMotor/Led0.cpp | 81 +++ Application/DCMotor/Led0.h | 52 ++ Application/DCMotor/MotorHandler.cpp | 81 +++ Application/DCMotor/MotorHandler.h | 36 ++ Application/DCMotor/main.cpp | 201 +++++++ Application/ICommandHandler.h | 0 Application/ITask.h | 18 + Application/Led0/CMakeLists.txt | 9 + Application/Led0/Led0.cpp | 48 ++ Application/Led0/Led0.h | 43 ++ Application/Led0/main.cpp | 25 + Application/PowerSwitch/CMakeLists.txt | 38 ++ Application/PowerSwitch/Led0.cpp | 81 +++ Application/PowerSwitch/Led0.h | 52 ++ .../PowerSwitch/PowerswitchHandler.cpp | 94 ++++ Application/PowerSwitch/PowerswitchHandler.h | 34 ++ Application/PowerSwitch/Switch.cpp | 60 ++ Application/PowerSwitch/Switch.h | 44 ++ Application/PowerSwitch/main.cpp | 186 ++++++ Application/Scheduler/Scheduler.h | 14 + Application/ShutterCtrl/CMakeLists.txt | 36 ++ Application/ShutterCtrl/Led0.cpp | 81 +++ Application/ShutterCtrl/Led0.h | 52 ++ Application/ShutterCtrl/ShutterHandler.cpp | 103 ++++ Application/ShutterCtrl/ShutterHandler.h | 56 ++ Application/ShutterCtrl/TouchScrHandler.cpp | 42 ++ Application/ShutterCtrl/TouchScrHandler.h | 16 + Application/ShutterCtrl/main.cpp | 218 +++++++ CMakeLists.txt | 51 ++ Communication/CMakeLists.txt | 8 + Communication/CommunicationHandler.cpp | 145 +++++ Communication/CommunicationHandler.h | 19 + Communication/ICommunication.h | 41 ++ Communication/ModbusSerial/ModbusSerial.h | 47 ++ HAL/AVR/328p_Pwm.cpp | 0 HAL/AVR/328p_Timer0.cpp | 63 +++ HAL/AVR/32u4_Pwm.cpp | 63 +++ HAL/AVR/32u4_Timer0.cpp | 68 +++ HAL/AVR/AvrAdc.cpp | 63 +++ HAL/AVR/AvrAdc.h | 39 ++ HAL/AVR/AvrEeprom.cpp | 50 ++ HAL/AVR/AvrEeprom.h | 34 ++ HAL/AVR/AvrInterrupt.h | 15 + HAL/AVR/AvrPwm.cpp | 11 + HAL/AVR/AvrPwm.h | 26 + HAL/AVR/AvrSpi.cpp | 82 +++ HAL/AVR/AvrSpi.h | 24 + HAL/AVR/AvrTimer0.cpp | 11 + HAL/AVR/AvrTimer0.h | 21 + HAL/AVR/AvrTimer1.cpp | 52 ++ HAL/AVR/AvrTimer1.h | 18 + HAL/AVR/AvrTimer3.cpp | 41 ++ HAL/AVR/AvrTimer3.h | 18 + HAL/AVR/AvrUart.cpp | 175 ++++++ HAL/AVR/AvrUart.h | 53 ++ HAL/AVR/CMakeLists.txt | 14 + HAL/Abstract/IAdc.h | 12 + HAL/Abstract/IEeprom.h | 25 + HAL/Abstract/IInterruptActivity.h | 13 + HAL/Abstract/IIo.h | 0 HAL/Abstract/IProtocolLayer2.h | 40 ++ HAL/Abstract/IPwm.h | 21 + HAL/Abstract/ISPI.h | 49 ++ HAL/Abstract/ISwitch.h | 16 + HAL/Abstract/ITimer.h | 0 HAL/Abstract/IUart.h | 72 +++ HAL/CMakeLists.txt | 1 + HAL/Drivers/CMakeLists.txt | 10 + HAL/Drivers/Eeprom.h | 0 HAL/Drivers/Ili9341.cpp | 531 ++++++++++++++++++ HAL/Drivers/Ili9341.h | 87 +++ HAL/Drivers/NetString.cpp | 310 ++++++++++ HAL/Drivers/NetString.h | 88 +++ HAL/Drivers/Rs485.h | 33 ++ HAL/Drivers/XPT2046_Touchscreen.cpp | 149 +++++ HAL/Drivers/XPT2046_Touchscreen.h | 39 ++ HAL/Drivers/glcdfont.c | 263 +++++++++ Metadata/CMakeLists.txt | 18 + Metadata/DCMotorParamIds.h | 30 + Metadata/DCMotorParameterTable.cpp | 30 + Metadata/DCMotorParameterTable.h | 7 + Metadata/Metadata.h | 21 + Metadata/PowerswitchParamIds.h | 29 + Metadata/PowerswitchParameterTable.cpp | 30 + Metadata/PowerswitchParameterTable.h | 7 + Metadata/ShutterCtrlParamIds.h | 29 + Metadata/ShutterCtrlParameterTable.cpp | 30 + Metadata/ShutterCtrlParameterTable.h | 7 + Platform/CMakeLists.txt | 21 + Platform/DCMotorParameterHandler.cpp | 96 ++++ Platform/DCMotorParameterHandler.h | 47 ++ Platform/ErrorHandler.h | 21 + Platform/Errors.h | 12 + Platform/IErrorHandler.h | 16 + Platform/IParameterHandler.h | 50 ++ Platform/PersistentStorage.cpp | 60 ++ Platform/PersistentStorage.h | 38 ++ Platform/PowerswitchParameterHandler.cpp | 92 +++ Platform/PowerswitchParameterHandler.h | 34 ++ Platform/ShutterCtrlParameterHandler.cpp | 92 +++ Platform/ShutterCtrlParameterHandler.h | 34 ++ README | 12 + Utils/StdTypes.h | 34 ++ rules/gcc-avr-common.cmake | 73 +++ rules/gcc-avr-generic.cmake | 404 +++++++++++++ 113 files changed, 6800 insertions(+) create mode 100644 Application/CMakeLists.txt create mode 100644 Application/DCMotor/328p_DCMotor.cpp create mode 100644 Application/DCMotor/32u4_DCMotor.cpp create mode 100644 Application/DCMotor/CMakeLists.txt create mode 100644 Application/DCMotor/DCM_InterruptActivity.cpp create mode 100644 Application/DCMotor/DCM_InterruptActivity.h create mode 100644 Application/DCMotor/DCMotor.cpp create mode 100644 Application/DCMotor/DCMotor.h create mode 100644 Application/DCMotor/Led0.cpp create mode 100644 Application/DCMotor/Led0.h create mode 100644 Application/DCMotor/MotorHandler.cpp create mode 100644 Application/DCMotor/MotorHandler.h create mode 100644 Application/DCMotor/main.cpp create mode 100644 Application/ICommandHandler.h create mode 100644 Application/ITask.h create mode 100644 Application/Led0/CMakeLists.txt create mode 100644 Application/Led0/Led0.cpp create mode 100644 Application/Led0/Led0.h create mode 100644 Application/Led0/main.cpp create mode 100644 Application/PowerSwitch/CMakeLists.txt create mode 100644 Application/PowerSwitch/Led0.cpp create mode 100644 Application/PowerSwitch/Led0.h create mode 100644 Application/PowerSwitch/PowerswitchHandler.cpp create mode 100644 Application/PowerSwitch/PowerswitchHandler.h create mode 100644 Application/PowerSwitch/Switch.cpp create mode 100644 Application/PowerSwitch/Switch.h create mode 100644 Application/PowerSwitch/main.cpp create mode 100644 Application/Scheduler/Scheduler.h create mode 100644 Application/ShutterCtrl/CMakeLists.txt create mode 100644 Application/ShutterCtrl/Led0.cpp create mode 100644 Application/ShutterCtrl/Led0.h create mode 100644 Application/ShutterCtrl/ShutterHandler.cpp create mode 100644 Application/ShutterCtrl/ShutterHandler.h create mode 100644 Application/ShutterCtrl/TouchScrHandler.cpp create mode 100644 Application/ShutterCtrl/TouchScrHandler.h create mode 100644 Application/ShutterCtrl/main.cpp create mode 100644 CMakeLists.txt create mode 100644 Communication/CMakeLists.txt create mode 100644 Communication/CommunicationHandler.cpp create mode 100644 Communication/CommunicationHandler.h create mode 100644 Communication/ICommunication.h create mode 100644 Communication/ModbusSerial/ModbusSerial.h create mode 100644 HAL/AVR/328p_Pwm.cpp create mode 100644 HAL/AVR/328p_Timer0.cpp create mode 100644 HAL/AVR/32u4_Pwm.cpp create mode 100644 HAL/AVR/32u4_Timer0.cpp create mode 100644 HAL/AVR/AvrAdc.cpp create mode 100644 HAL/AVR/AvrAdc.h create mode 100644 HAL/AVR/AvrEeprom.cpp create mode 100644 HAL/AVR/AvrEeprom.h create mode 100644 HAL/AVR/AvrInterrupt.h create mode 100644 HAL/AVR/AvrPwm.cpp create mode 100644 HAL/AVR/AvrPwm.h create mode 100644 HAL/AVR/AvrSpi.cpp create mode 100644 HAL/AVR/AvrSpi.h create mode 100644 HAL/AVR/AvrTimer0.cpp create mode 100644 HAL/AVR/AvrTimer0.h create mode 100644 HAL/AVR/AvrTimer1.cpp create mode 100644 HAL/AVR/AvrTimer1.h create mode 100644 HAL/AVR/AvrTimer3.cpp create mode 100644 HAL/AVR/AvrTimer3.h create mode 100644 HAL/AVR/AvrUart.cpp create mode 100644 HAL/AVR/AvrUart.h create mode 100644 HAL/AVR/CMakeLists.txt create mode 100644 HAL/Abstract/IAdc.h create mode 100644 HAL/Abstract/IEeprom.h create mode 100644 HAL/Abstract/IInterruptActivity.h create mode 100644 HAL/Abstract/IIo.h create mode 100644 HAL/Abstract/IProtocolLayer2.h create mode 100644 HAL/Abstract/IPwm.h create mode 100644 HAL/Abstract/ISPI.h create mode 100644 HAL/Abstract/ISwitch.h create mode 100644 HAL/Abstract/ITimer.h create mode 100644 HAL/Abstract/IUart.h create mode 100644 HAL/CMakeLists.txt create mode 100644 HAL/Drivers/CMakeLists.txt create mode 100644 HAL/Drivers/Eeprom.h create mode 100644 HAL/Drivers/Ili9341.cpp create mode 100644 HAL/Drivers/Ili9341.h create mode 100644 HAL/Drivers/NetString.cpp create mode 100644 HAL/Drivers/NetString.h create mode 100644 HAL/Drivers/Rs485.h create mode 100644 HAL/Drivers/XPT2046_Touchscreen.cpp create mode 100644 HAL/Drivers/XPT2046_Touchscreen.h create mode 100644 HAL/Drivers/glcdfont.c create mode 100644 Metadata/CMakeLists.txt create mode 100644 Metadata/DCMotorParamIds.h create mode 100644 Metadata/DCMotorParameterTable.cpp create mode 100644 Metadata/DCMotorParameterTable.h create mode 100644 Metadata/Metadata.h create mode 100644 Metadata/PowerswitchParamIds.h create mode 100644 Metadata/PowerswitchParameterTable.cpp create mode 100644 Metadata/PowerswitchParameterTable.h create mode 100644 Metadata/ShutterCtrlParamIds.h create mode 100644 Metadata/ShutterCtrlParameterTable.cpp create mode 100644 Metadata/ShutterCtrlParameterTable.h create mode 100644 Platform/CMakeLists.txt create mode 100644 Platform/DCMotorParameterHandler.cpp create mode 100644 Platform/DCMotorParameterHandler.h create mode 100644 Platform/ErrorHandler.h create mode 100644 Platform/Errors.h create mode 100644 Platform/IErrorHandler.h create mode 100644 Platform/IParameterHandler.h create mode 100644 Platform/PersistentStorage.cpp create mode 100644 Platform/PersistentStorage.h create mode 100644 Platform/PowerswitchParameterHandler.cpp create mode 100644 Platform/PowerswitchParameterHandler.h create mode 100644 Platform/ShutterCtrlParameterHandler.cpp create mode 100644 Platform/ShutterCtrlParameterHandler.h create mode 100644 README create mode 100644 Utils/StdTypes.h create mode 100644 rules/gcc-avr-common.cmake create mode 100644 rules/gcc-avr-generic.cmake diff --git a/Application/CMakeLists.txt b/Application/CMakeLists.txt new file mode 100644 index 0000000..cd6f986 --- /dev/null +++ b/Application/CMakeLists.txt @@ -0,0 +1 @@ +subdirs(Led0 DCMotor PowerSwitch ShutterCtrl) diff --git a/Application/DCMotor/328p_DCMotor.cpp b/Application/DCMotor/328p_DCMotor.cpp new file mode 100644 index 0000000..19d897a --- /dev/null +++ b/Application/DCMotor/328p_DCMotor.cpp @@ -0,0 +1,214 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include + + +#include +#include +#include "Led0.h" + +#include "DCMotor.h" +#if defined (__AVR_ATmega32U4__) +#define PIN_MOTOR_ENABLE PINB2 +#else +#define PIN_MOTOR_ENABLE PIND2 +#endif +/** + * \brief + * + */ +Motor::Motor(volatile uint8_t *OCR,volatile uint8_t *ttcr,pinMapping_t _pin,uint8_t dirShift,IParameterHandler *_param) + : m_OCR(OCR) + , m_Tccr(ttcr) +#if ! defined (__AVR_ATmega32U4__) + , m_Port(&PORTD) + , m_Ddr(&DDRD) +#else + , m_Port(&PORTB) + , m_Ddr(&DDRB) +#endif + , m_Mapping(_pin) + , m_DirShift(dirShift) + , m_Params(_param) + , m_DeltaD(0.0) + , m_DeltaI(0.0) + , m_DeltaPrev(0.0) +{ + init(); +} + + +void +Motor::init() +{ + Uint8_t l_Mode; + + *(m_Ddr) |= _BV(m_Mapping.pinPwm) | _BV(m_Mapping.pinOut); //either PIND7 or PIND4 + *(m_Ddr) |= _BV(PIN_MOTOR_ENABLE); + + (*m_Tccr) |= (2<registerListener(PID_MotorState,this); /* State on or off */ + + if ( m_DirShift == COM0A0) + { + m_Params->registerListener(PID_MotorPwm,this); /* State on or off */ + m_Params->registerListener(PID_MotorDir,this); /* State on or off */ + } +#if ! defined (__AVR_ATmega32U4__) + else + { + TCCR2A |= (2<registerListener(PID_MotorBPwm,this); /* State on or off */ + m_Params->registerListener(PID_MotorBDir,this); /* State on or off */ + } +#else + // Compare Modulator set to OR + (*m_Port) |= _BV(PINB7); +#endif + // Read Motor State + m_Params->readValue(PID_MotorState,l_Mode); + enable(l_Mode); +} + +void +Motor::onWriteValue(const uint8_t paramID,const uint8_t _val) +{ + switch (paramID) + { + case PID_MotorState:/* State on or off */ + enable((bool)_val); + break; + case PID_MotorMode: /* DC Open loop,DC Closed loop, Stepper, brushless */ + break; + case PID_MotorBPwm: + case PID_MotorPwm: /* Used In case of open loop 10 - 90 % */ + *m_OCR =_val; + break; + case PID_MotorRpm: /* Used In case of closed loop uint16 I think */ + break; + case PID_MotorBDir: + case PID_MotorDir: /* 0 or 1 */ + direction( (bool)_val); + break; + default: + ; + }; +} + + +//! IParameterListener call +void +Motor::onWriteValue(const uint8_t paramID,const Float32_t _val) +{ +} + +void +Motor::enable(bool _val) + + if ( _val != 0 ) + { + (*m_Port) |= _BV( PIN_MOTOR_ENABLE); + // reset PID contants + m_DeltaD = 0.0f; + m_DeltaI = 0.0f; + m_DeltaPrev = 0.0f; + } else + { + (*m_Port) &= ~_BV( PIN_MOTOR_ENABLE); + } +} + +void +Motor::direction(bool _val) +{ + if ( _val != 0 ) + { + (*m_Port) |= _BV( m_Mapping.pinOut); + (*m_Tccr) |= (3<readValue(PID_MotorMode,l_Mode); + if (l_Mode == 1) + { // In case of closed loop mode compute correction + updateUsingPID(); + } else if (l_Mode == 2) + { + updateUsingPot0(); + } + +} + + +/// update motor using PID close loop computation +void +Motor::updateUsingPID() +{ + + Uint16_t countRpm,consigneRpm; + Uint8_t consigne; + m_Params->readValue(PID_MotorRpm,countRpm); + m_Params->readValue(PID_MAConsRpm,consigneRpm); + Float32_t delta = static_cast( consigneRpm )- static_cast(countRpm); + Float32_t Kp,Ki,Kd; + m_Params->readValue(PID_Kp,Kp); + m_Params->readValue(PID_Ki,Ki); + m_Params->readValue(PID_Kd,Kd); + + m_DeltaI+=delta; + m_DeltaD = delta - m_DeltaPrev; + Float32_t newConsigne = delta * Kp; + + newConsigne += ( m_DeltaI * Ki + m_DeltaD * Kd ); + + m_DeltaPrev = delta; + // Update consigne : + if ( newConsigne < 10) + { + consigne = 10; + } else if (newConsigne > 250) + { + consigne = 250; + } else + { + consigne = static_cast(newConsigne); + } + m_Params->writeValue(PID_MotorPwm,consigne); + +} + +/// update motor pwm using Pot0 value +void +Motor::updateUsingPot0() +{ + Uint16_t l_Pot; + m_Params->readValue(PID_Pot0,l_Pot); + l_Pot = static_cast(static_cast(l_Pot) * 256.0 / 1024.0); + m_Params->writeValue(PID_MotorPwm,l_Pot); +} diff --git a/Application/DCMotor/32u4_DCMotor.cpp b/Application/DCMotor/32u4_DCMotor.cpp new file mode 100644 index 0000000..f7ee8c6 --- /dev/null +++ b/Application/DCMotor/32u4_DCMotor.cpp @@ -0,0 +1,210 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include + + +#include +#include + +#include "DCMotor.h" +#if defined (__AVR_ATmega32U4__) +#define PIN_MOTOR_ENABLE PINB2 +#else +#define PIN_MOTOR_ENABLE PIND2 +#endif +/** + * \brief + * + */ +Motor::Motor(IPwm *_pwm,pinMapping_t _pin,uint8_t dirShift,IParameterHandler *_param) + : m_Pwm(_pwm) +#if ! defined (__AVR_ATmega32U4__) + , m_Port(&PORTD) + , m_Ddr(&DDRD) +#else + , m_Port(&PORTB) + , m_Ddr(&DDRB) +#endif + , m_Mapping(_pin) + , m_DirShift(dirShift) + , m_Params(_param) + , m_DeltaD(0.0) + , m_DeltaI(0.0) + , m_DeltaPrev(0.0) +{ + init(); +} + + +void +Motor::init() +{ + Uint8_t l_Mode; + + *(m_Ddr) |= _BV(m_Mapping.pinPwm) | _BV(m_Mapping.pinOut); //either PIND7 or PIND4 + *(m_Ddr) |= _BV(PIN_MOTOR_ENABLE); + + //(*m_Tccr) |= (2<registerListener(PID_MotorState,this); /* State on or off */ + + if ( m_DirShift == COM0A0) + { + m_Params->registerListener(PID_MotorPwm,this); /* State on or off */ + m_Params->registerListener(PID_MotorDir,this); /* State on or off */ + } + // Compare Modulator set to OR + (*m_Port) |= _BV(PINB7); + // Read Motor State + m_Params->readValue(PID_MotorState,l_Mode); + enable(l_Mode); +} + +void +Motor::onWriteValue(const uint8_t paramID,const uint8_t _val) +{ + switch (paramID) + { + case PID_MotorState:/* State on or off */ + enable((bool)_val); + break; + case PID_MotorMode: /* DC Open loop,DC Closed loop, Stepper, brushless */ + break; + case PID_MotorBPwm: + case PID_MotorPwm: /* Used In case of open loop 10 - 90 % */ + m_Pwm->setDutyCycle(_val); + break; + case PID_MotorRpm: /* Used In case of closed loop uint16 I think */ + break; + case PID_MotorBDir: + case PID_MotorDir: /* 0 or 1 */ + direction( (bool)_val); + break; + default: + ; + }; +} + + +//! IParameterListener call +void +Motor::onWriteValue(const uint8_t paramID,const Float32_t _val) +{ +} + +void +Motor::enable(bool _val) +{ + if ( _val != 0 ) + { + (*m_Port) |= _BV( PIN_MOTOR_ENABLE); + // reset PID contants + m_DeltaD = 0.0f; + m_DeltaI = 0.0f; + m_DeltaPrev = 0.0f; + } else + { + (*m_Port) &= ~_BV( PIN_MOTOR_ENABLE); + } +} + +void +Motor::direction(bool _val) +{ + if ( _val != 0 ) + { + (*m_Port) |= _BV( m_Mapping.pinOut); +#if 0 + (*m_Tccr) |= (3<readValue(PID_MotorMode,l_Mode); + if (l_Mode == 1) + { // In case of closed loop mode compute correction + updateUsingPID(); + } else if (l_Mode == 2) + { + updateUsingPot0(); + } + +} + + +/// update motor using PID close loop computation +void +Motor::updateUsingPID() +{ + + Uint16_t countRpm,consigneRpm; + Uint8_t consigne; + m_Params->readValue(PID_MotorRpm,countRpm); + m_Params->readValue(PID_MAConsRpm,consigneRpm); + Float32_t delta = static_cast( consigneRpm )- static_cast(countRpm); + Float32_t Kp,Ki,Kd; + m_Params->readValue(PID_Kp,Kp); + m_Params->readValue(PID_Ki,Ki); + m_Params->readValue(PID_Kd,Kd); + + m_DeltaI+=delta; + m_DeltaD = delta - m_DeltaPrev; + Float32_t newConsigne = delta * Kp; + + newConsigne += ( m_DeltaI * Ki + m_DeltaD * Kd ); + + m_DeltaPrev = delta; + // Update consigne : + if ( newConsigne < 10) + { + consigne = 10; + } else if (newConsigne > 250) + { + consigne = 250; + } else + { + consigne = static_cast(newConsigne); + } + m_Params->writeValue(PID_MotorPwm,consigne); + +} + +/// update motor pwm using Pot0 value +void +Motor::updateUsingPot0() +{ + Uint16_t l_Pot; + m_Params->readValue(PID_Pot0,l_Pot); + l_Pot = static_cast(static_cast(l_Pot) * 256.0 / 1024.0); + m_Params->writeValue(PID_MotorPwm,l_Pot); +} diff --git a/Application/DCMotor/CMakeLists.txt b/Application/DCMotor/CMakeLists.txt new file mode 100644 index 0000000..624792c --- /dev/null +++ b/Application/DCMotor/CMakeLists.txt @@ -0,0 +1,36 @@ +##################################################################### +# simple AVR executable +##################################################################### +add_avr_executable( + dcmotor + main.cpp + Led0.cpp + DCMotor.cpp + MotorHandler.cpp + ) + +target_link_libraries( + dcmotor-${AVR_MCU}.elf + avrHAL-${AVR_MCU} + avrDrivers-${AVR_MCU} + avrComm-${AVR_MCU} + avrPtf-${AVR_MCU} + avrDCMotorParameters-${AVR_MCU} +) + +IF (${AVR_MCU} EQUAL "atmega328p") + SET(AVRPROG arduino) + SET(AVRPROG_MCU Atmega328p) +ELSE(${AVR_MCU} EQUAL "atmega328p") + SET(AVRPROG avr109) + SET(AVRPROG_MCU m32u4) +ENDIF(${AVR_MCU} EQUAL "atmega328p") + +add_custom_target( + flash_dcmotor + COMMAND + # avrdude -c arduino -P ${AVRDUDE_PORT} -p Atmega328p -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/dcmotor-${AVR_MCU}.hex:i + avrdude -c ${AVRPROG} -P ${AVRDUDE_PORT} -p ${AVRPROG_MCU} -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/dcmotor-${AVR_MCU}.hex:i + DEPENDS dcmotor-${AVR_MCU}.hex + ) + diff --git a/Application/DCMotor/DCM_InterruptActivity.cpp b/Application/DCMotor/DCM_InterruptActivity.cpp new file mode 100644 index 0000000..4747003 --- /dev/null +++ b/Application/DCMotor/DCM_InterruptActivity.cpp @@ -0,0 +1,21 @@ +#include "HAL/Abstract/IInterruptActivity.h" +#include "DCM_InterruptActivity.h" +/** + * Interrupt Activity Implementation for + * DC motor... + * call tick method for all classes controled by + * Interupt activity. + * -> The scheduler must be able to + * make the processing in the given time line !!! 500us + */ +DCM_InterrupttActivity(IScheduler &_scheduler) + : m_Scheduler(_scheduler) +{ +} + +void +DCM_InterruptyActivity::tick() +{ + m_Scheduler.tick(); +} + diff --git a/Application/DCMotor/DCM_InterruptActivity.h b/Application/DCMotor/DCM_InterruptActivity.h new file mode 100644 index 0000000..7cbfddf --- /dev/null +++ b/Application/DCMotor/DCM_InterruptActivity.h @@ -0,0 +1,21 @@ +#ifndef DCM_INTERRUPT_ACTIVITY_H__ +#define DCM_INTERRUPT_ACTIVITY_H__ +/** + * Interrupt Activity Implementation for + * DC motor... + * call tick method for all classes controled by + * Interupt activity. + * -> The scheduler must be able to + * make the processing in the given time line !!! 500us + */ + +class DCM_InterruptActivity : public IInterruptActivity +{ + public: + DCM_InterrupttActivity(IScheduler &_scheduler) + + void tick(); + +}; + +#endif diff --git a/Application/DCMotor/DCMotor.cpp b/Application/DCMotor/DCMotor.cpp new file mode 100644 index 0000000..e57ff36 --- /dev/null +++ b/Application/DCMotor/DCMotor.cpp @@ -0,0 +1,21 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include + + +#include +#include +#include "Led0.h" +#include "Abstract/IPwm.h" +#include "DCMotor.h" + +#if defined (__AVR_ATmega32U4__) +#include "32u4_DCMotor.cpp" +#else +#include "328p_DCMotor.cpp" +#endif diff --git a/Application/DCMotor/DCMotor.h b/Application/DCMotor/DCMotor.h new file mode 100644 index 0000000..854c286 --- /dev/null +++ b/Application/DCMotor/DCMotor.h @@ -0,0 +1,90 @@ +#ifndef __DCMOTOR_H__ +#define __DCMOTOR_H__ +/** + * \brief simple class for port access for DCMotor + * Motor is PWM. + * controls enable / direction + * 2 output pins ocrA (Fast PWM) + Port D + * ocrB () + * + * direction is controled my + * \file Motor.h + * \author Ebersold Andre + */ + +/** + * \brief + */ +class Motor : public virtual IParameterListener +{ + public: + typedef struct _PinMapping_t + { + uint8_t pinPwm:3; + uint8_t pinOut:3; + uint8_t unused:2; + } pinMapping_t; + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +#if defined (__AVR_ATmega32U4__) + Motor(IPwm *pwm,pinMapping_t PIN,uint8_t _dirshift,IParameterHandler *); +#else + Motor(volatile uint8_t *OCR, volatile uint8_t *tccr,pinMapping_t PIN,uint8_t _dirshift,IParameterHandler *); +#endif + //! destructor + ~Motor(); + + void init(); + /** + * \brief in case of close loop, update PWM according to measured value + * to get as close as possible to order. + * + */ + void update(); + //! IParameterListener call + void onWriteValue(const uint8_t paramID,const uint8_t _val) ; + //! IParameterListener call + void onWriteValue(const uint8_t paramID,const Float32_t _val) ; + private: + //! enable disable motor + void enable(bool _on); + //! returns true if motor is enabled + const bool enabled() const; + //! change motor direction + void direction(bool _on); + /// update motor using PID close loop computation + void updateUsingPID(); + /// update motor pwm using Pot0 value + void updateUsingPot0(); + private: +#if defined (__AVR_ATmega32U4__) + IPwm *m_Pwm; +#else + //! pointer to the Motor pwm register OCR0A or OCR0B + volatile uint8_t *m_OCR; + //! pointer to pwm direction + volatile uint8_t *m_Tccr; +#endif + //! pointer to the Motor port (direction ) + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + pinMapping_t m_Mapping; + //! position for compare direction shift position + uint8_t m_DirShift; + //! Parameter handler + IParameterHandler *m_Params; + //! Previous delta error + Float32_t m_DeltaD; + //! Integral + Float32_t m_DeltaI; + //! Keep n-1 error + Float32_t m_DeltaPrev; +}; + +#endif diff --git a/Application/DCMotor/Led0.cpp b/Application/DCMotor/Led0.cpp new file mode 100644 index 0000000..a2b7de8 --- /dev/null +++ b/Application/DCMotor/Led0.cpp @@ -0,0 +1,81 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.cpp + * \author Ebersold Andre + */ + +//#include +#include +#include +#include +#include "Led0.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Led0::Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *_ph) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +, m_Counter(0) +, m_Param(_ph) +{ + uint16_t cycle = 350; + _ph->writeValue(PID_LedCycle,cycle); + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Led0::~Led0() +{ +} + +//! switches the LED on +void Led0::on(void) +{ + *(m_Port) |= (1 << m_Pin); +} + +//! switches the LED off +void Led0::off(void) +{ + *(m_Port) &= ~(1 << m_Pin); +} + +//! toggles the LED +void Led0::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + +/// +void +Led0::setCycle(uint16_t _cycle) +{ + m_Param->writeValue(PID_LedCycle,_cycle); +} +/// +void +Led0::reloadCounter() +{ + uint16_t cycle = 100; + m_Param->readValue(PID_LedCycle,cycle); + m_Counter = cycle; +} +/// +void +Led0::tick() +{ + if (m_Counter > 0) + { + m_Counter--; + } else + { + toggle(); + reloadCounter(); + } +} diff --git a/Application/DCMotor/Led0.h b/Application/DCMotor/Led0.h new file mode 100644 index 0000000..e8f4209 --- /dev/null +++ b/Application/DCMotor/Led0.h @@ -0,0 +1,52 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Led0 +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *); + //! destructor + ~Led0(); + + //! switches the LED on + void on(void); + //! switches the LED off + void off(void); + //! toggles the LED + void toggle(void); + /// + void setCycle(uint16_t _cycle); + /// + void reloadCounter(); + /// + void tick(); + private: + Led0(); + Led0( Led0 const &src ); + Led0& operator=(const Led0 &src ) ; + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + //! reset count + uint16_t m_Counter; + /// + IParameterHandler *m_Param; +}; + diff --git a/Application/DCMotor/MotorHandler.cpp b/Application/DCMotor/MotorHandler.cpp new file mode 100644 index 0000000..e1d8e3c --- /dev/null +++ b/Application/DCMotor/MotorHandler.cpp @@ -0,0 +1,81 @@ +#include "Utils/StdTypes.h" + +#include "Application/ITask.h" +#include "Abstract/IAdc.h" +#include "Abstract/IPwm.h" +#include + +#include +#include +#include "DCMotor.h" +#include "MotorHandler.h" + + +#if ! defined (__AVR_ATmega32U4__) +static Motor::pinMapping_t GmA = {PIND6,PIND7,0}; +static Motor::pinMapping_t GmB = {PIND3,PIND4,0}; +#else +static Motor::pinMapping_t GmA = {PINB7,PINB6,0}; +#endif + +MotorHandler::MotorHandler(IParameterHandler *_p,IAdc *_adc,Timer1 *_t1,IPwm *_pwma) + : m_Params(_p) + , m_Adc(_adc) + , m_Counter(_t1) +#if defined (__AVR_ATmega32U4__) + , m_MotorA(_pwma,GmA,COM0A0,_p) +#else + , m_MotorA(&OCR0A,&TCCR0A,GmA,COM0A0,_p) + , m_MotorB(&OCR2B,&TCCR2A,GmB,COM2B0,_p) +#endif + , m_Ticks(0) +{ +} + +#define TICK_COUNT 20 +/** + * Well try processing evey 2ms + */ +void +MotorHandler::run() +{ + Uint8_t l_Mode; + m_Ticks = (m_Ticks < TICK_COUNT) + ? m_Ticks + 1 + : 0; + + m_Params->readValue(PID_MotorMode,l_Mode); + if ( m_Ticks == 0) + { // In case of closed loop mode compute correction +#if defined (__AVR_ATmega32U4__) + Uint16_t _Rpm = 0; + Uint16_t count = m_Counter->readCounter(true); + // convert to Rpm ! + computeRpm(static_cast(count),_Rpm); + m_Params->writeValue(PID_MotorRpm,_Rpm); + +#endif + updatePot0(); + m_MotorA.update(); + } +} + +void +MotorHandler::updatePot0() +{ + Uint16_t l_pot = m_Adc->read(0); + m_Params->writeValue(PID_Pot0,l_pot); +} + + +void +MotorHandler::computeRpm(const Float32_t count,Uint16_t &_rpm) +{ + Uint16_t l_cpr; + + m_Params->readValue(PID_CPR,l_cpr); + Float32_t _conv = 100.0/static_cast(l_cpr); + _conv *= 60.0; + _conv *= count; + _rpm = static_cast(_conv); +} diff --git a/Application/DCMotor/MotorHandler.h b/Application/DCMotor/MotorHandler.h new file mode 100644 index 0000000..1cb74b5 --- /dev/null +++ b/Application/DCMotor/MotorHandler.h @@ -0,0 +1,36 @@ +#ifndef MOTORHANDLER_H__ +#define MOTORHANDLER_H__ + +/** + * \brief Controls the motor behavior depending + * on the motor mode. + * + */ +class MotorHandler : public ITask +{ + public: + MotorHandler(IParameterHandler *_ph,IAdc *_adc,Timer1 *_t1,IPwm *_pwma ); + + virtual void run(); + private: + /** + * Read Adc channel 0 and update Pot0 parameter + * with the read value + */ + void updatePot0(); + /** + * + */ + void computeRpm(const Float32_t count,Uint16_t &_rpm); + private: + IParameterHandler *m_Params; + IAdc *m_Adc; + Timer1 *m_Counter; + Motor m_MotorA; +#if ! defined (__AVR_ATmega32U4__) + Motor m_MotorB; +#endif + Uint8_t m_Ticks; // 500us ticks +}; + +#endif diff --git a/Application/DCMotor/main.cpp b/Application/DCMotor/main.cpp new file mode 100644 index 0000000..6d313af --- /dev/null +++ b/Application/DCMotor/main.cpp @@ -0,0 +1,201 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "Led0.h" +#include "DCMotor.h" +#include "MotorHandler.h" + +/** + * @brief the scheduler will still slice the execution + * flow. The whole cycle is now 40 ticks ! + * 40 * + * 250ns * 4 = 1us * 10 = 10 us. On fast devices. + * + * 16MHz / 8 / 256 = 100us each tick + * + */ +class Scheduler : public IInterruptActivity +{ + private: + enum TIME_SLOTS { + FIRST_TIME_SLOT = 0, + BLOCK2_FIRST_TIME_SLOT = 1, + BLOCK3_FIRST_TIME_SLOT = 3, + LAST_TIME_SLOT = 5, + TIME_SLOT_COUNT = 5 + }; + enum ETASK_ID { + TASK1 = 0, + TASK2 = 1, + TASK3 = 2, + TASK_COUNT = 3 + }; + typedef struct Task_t { + TIME_SLOTS m_FirstTimeslot; + ETASK_ID m_NextTask; + } Task_type ; + + static Task_type gTasks[TASK_COUNT]; + public: + Scheduler(Led0 *_led,IProtocolLayer2 *_net,CommunicationHandler *_com,MotorHandler *_mh + ,ITask *_Adc + ,ITask *_Storage + ) + : + m_Led(_led) + , m_Netstring(_net) + , m_Com(_com) + , m_Motor(_mh) + , m_Adc(_Adc) + , m_Storage(_Storage) + , m_CurrentTimeslot(FIRST_TIME_SLOT) + , m_CurrentTask(TASK1) + { + } + // main entry point + void schedule() + { + waitForTimeslot(); + m_Com->run(); + switch (m_CurrentTask) + { + case TASK1: + m_Adc->run(); + break; + case TASK2: + m_Motor->run(); + break; + case TASK3: + m_Led->tick(); + m_Storage->run(); + break; + default: + ; + + } + m_CurrentTask = gTasks[m_CurrentTask].m_NextTask; + } + // called by the interrupt timer handler + virtual void tick() + { + m_CurrentTimeslot = (m_CurrentTimeslot < LAST_TIME_SLOT) + ? (TIME_SLOTS)(m_CurrentTimeslot+1) + : (FIRST_TIME_SLOT); + m_Netstring->tick(); + } + + private: + void waitForTimeslot( void ) + { + /// prevent instant scheduling + while (m_CurrentTimeslot == gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + // beginning of the timeslot + while (m_CurrentTimeslot != gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + } + private: + Led0 *m_Led; + IProtocolLayer2 *m_Netstring; + CommunicationHandler *m_Com; + MotorHandler *m_Motor; + ITask *m_Adc; + ITask *m_Storage; + volatile TIME_SLOTS m_CurrentTimeslot; + ETASK_ID m_CurrentTask; + + +}; + +Scheduler::Task_type Scheduler::gTasks[TASK_COUNT] = { + { FIRST_TIME_SLOT , TASK2 } + , { BLOCK2_FIRST_TIME_SLOT, TASK3 } + , { BLOCK3_FIRST_TIME_SLOT, TASK1 } +}; + +/** + * \brief Init database .... + */ +void init(IParameterHandler *m_Param) +{ + m_Param->writeValue(PID_MotorPwm,(uint8_t)60); + m_Param->writeValue(PID_CPR,static_cast(500)); + m_Param->writeValue(PID_MAConsRpm,(uint8_t)600); + m_Param->writeValue(PID_Kp,0.08f); + m_Param->writeValue(PID_Kp,0.003f); + m_Param->writeValue(PID_Kp,0.004f); +} + + +/** + * \brief main loop + */ +int main(void) +{ + Timer1 lCounter; + DCMotorParameterHandler gParam; +#if defined (__AVR_ATmega32U4__) + Led0 led(&PORTC, &DDRC, PINB7,&gParam); + AvrPwm pwmA; +#else + Led0 led(&PORTB, &DDRB, PINB5,&gParam); +#endif + AvrUart uart(IUart::BAUD_9600,IUart::PARITY_NONE,IUart::STB_ONE); + AvrADC gAdc; + AvrEeprom gEeprom; + NetString netstring(&uart); + CommunicationHandler gCom(&netstring,&gParam); + PersistentStorage gStorage(&gEeprom,&gParam); + MotorHandler motorH(&gParam,&gAdc,&lCounter,&pwmA); + Scheduler sched(&led,&netstring,&gCom,&motorH,&gAdc,&gStorage); + + uart.init(); + netstring.init(); + + Timer0 lTimer(sched); + + led.on(); + _delay_ms(300); + led.off(); + _delay_ms(300); + + lTimer.init(); + init(&gParam); + gEeprom.init(); + while(1) + { + sched.schedule(); + } +} diff --git a/Application/ICommandHandler.h b/Application/ICommandHandler.h new file mode 100644 index 0000000..e69de29 diff --git a/Application/ITask.h b/Application/ITask.h new file mode 100644 index 0000000..e06be46 --- /dev/null +++ b/Application/ITask.h @@ -0,0 +1,18 @@ +#ifndef __ITASK_H__ +#define __ITASK_H__ + +/** + * Abstract class for all Handlers. + * Only run can be invoked + * Maybe add a parameter for tasks that might need + * an event or state information to be able to run. + * For example multiple runs during a global cycle + */ +class ITask +{ + public: + ITask() {} + + virtual void run() = 0; +}; +#endif diff --git a/Application/Led0/CMakeLists.txt b/Application/Led0/CMakeLists.txt new file mode 100644 index 0000000..8da43c8 --- /dev/null +++ b/Application/Led0/CMakeLists.txt @@ -0,0 +1,9 @@ +##################################################################### +# simple AVR executable +##################################################################### +add_avr_executable( + toggle-led-cpp + main.cpp + Led0.cpp + ) + diff --git a/Application/Led0/Led0.cpp b/Application/Led0/Led0.cpp new file mode 100644 index 0000000..149eab0 --- /dev/null +++ b/Application/Led0/Led0.cpp @@ -0,0 +1,48 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.cpp + * \author Ebersold Andre + */ + +#include + +#include "Led0.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Led0::Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +{ + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Led0::~Led0() +{ +} + +//! switches the LED on +void Led0::on(void) +{ + *(m_Port) |= (1 << m_Pin); +} + +//! switches the LED off +void Led0::off(void) +{ + *(m_Port) &= ~(1 << m_Pin); +} + +//! toggles the LED +void Led0::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + diff --git a/Application/Led0/Led0.h b/Application/Led0/Led0.h new file mode 100644 index 0000000..2e26073 --- /dev/null +++ b/Application/Led0/Led0.h @@ -0,0 +1,43 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Led0 +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN); + //! destructor + ~Led0(); + + //! switches the LED on + void on(void); + //! switches the LED off + void off(void); + //! toggles the LED + void toggle(void); + + private: + Led0(); + Led0( Led0 const &src ); + Led0& operator=(const Led0 &src ); + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; +}; + diff --git a/Application/Led0/main.cpp b/Application/Led0/main.cpp new file mode 100644 index 0000000..37da27e --- /dev/null +++ b/Application/Led0/main.cpp @@ -0,0 +1,25 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include +#include + +#include "Led0.h" + +/** + * \brief main loop + */ +int main(void) +{ + Led0 led(&PORTB, &DDRB, PINB1); + + while(1) + { + led.toggle(); + _delay_ms(500); + } +} diff --git a/Application/PowerSwitch/CMakeLists.txt b/Application/PowerSwitch/CMakeLists.txt new file mode 100644 index 0000000..ee360ec --- /dev/null +++ b/Application/PowerSwitch/CMakeLists.txt @@ -0,0 +1,38 @@ +##################################################################### +# simple AVR executable +##################################################################### +add_avr_executable( + powerswitch + main.cpp + Led0.cpp + Switch.cpp + PowerswitchHandler.cpp + ) + +target_link_libraries( + powerswitch-${AVR_MCU}.elf + avrHAL-${AVR_MCU} + avrDrivers-${AVR_MCU} + avrComm-${AVR_MCU} + avrPS-Ptf-${AVR_MCU} + avrPowerswitchParameters-${AVR_MCU} +) + +IF ( "${AVR_MCU}" STREQUAL "atmega328p") + SET(AVRPROG arduino) + SET(AVRPROG_MCU Atmega328p) + MESSAGE("AVR_MCU = ${AVR_MCU} Yes atmega") +ELSE( "${AVR_MCU}" STREQUAL "atmega32u4") + SET(AVRPROG avr109) + SET(AVRPROG_MCU m32u4) + MESSAGE("AVR_MCU = '${AVR_MCU}' if atmega328p not goot at all") +ENDIF("${AVR_MCU}" STREQUAL "atmega328p") + +add_custom_target( + flash_powerswitch + COMMAND + # avrdude -c arduino -P ${AVRDUDE_PORT} -p Atmega328p -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/dcmotor-${AVR_MCU}.hex:i + avrdude -c ${AVRPROG} -P ${AVRDUDE_PORT} -p ${AVRPROG_MCU} -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/powerswitch-${AVR_MCU}.hex:i + DEPENDS powerswitch-${AVR_MCU}.hex + ) + diff --git a/Application/PowerSwitch/Led0.cpp b/Application/PowerSwitch/Led0.cpp new file mode 100644 index 0000000..22a9c5c --- /dev/null +++ b/Application/PowerSwitch/Led0.cpp @@ -0,0 +1,81 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.cpp + * \author Ebersold Andre + */ + +//#include +#include +#include +#include +#include "Led0.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Led0::Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *_ph) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +, m_Counter(0) +, m_Param(_ph) +{ + uint16_t cycle = 350; + _ph->writeValue(PID_LedCycle,cycle); + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Led0::~Led0() +{ +} + +//! switches the LED on +void Led0::on(void) +{ + *(m_Port) |= (1 << m_Pin); +} + +//! switches the LED off +void Led0::off(void) +{ + *(m_Port) &= ~(1 << m_Pin); +} + +//! toggles the LED +void Led0::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + +/// +void +Led0::setCycle(uint16_t _cycle) +{ + m_Param->writeValue(PID_LedCycle,_cycle); +} +/// +void +Led0::reloadCounter() +{ + uint16_t cycle = 100; + m_Param->readValue(PID_LedCycle,cycle); + m_Counter = cycle; +} +/// +void +Led0::tick() +{ + if (m_Counter > 0) + { + m_Counter--; + } else + { + toggle(); + reloadCounter(); + } +} diff --git a/Application/PowerSwitch/Led0.h b/Application/PowerSwitch/Led0.h new file mode 100644 index 0000000..e8f4209 --- /dev/null +++ b/Application/PowerSwitch/Led0.h @@ -0,0 +1,52 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Led0 +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *); + //! destructor + ~Led0(); + + //! switches the LED on + void on(void); + //! switches the LED off + void off(void); + //! toggles the LED + void toggle(void); + /// + void setCycle(uint16_t _cycle); + /// + void reloadCounter(); + /// + void tick(); + private: + Led0(); + Led0( Led0 const &src ); + Led0& operator=(const Led0 &src ) ; + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + //! reset count + uint16_t m_Counter; + /// + IParameterHandler *m_Param; +}; + diff --git a/Application/PowerSwitch/PowerswitchHandler.cpp b/Application/PowerSwitch/PowerswitchHandler.cpp new file mode 100644 index 0000000..e2ad9a1 --- /dev/null +++ b/Application/PowerSwitch/PowerswitchHandler.cpp @@ -0,0 +1,94 @@ +#include "Utils/StdTypes.h" + +#include "Application/ITask.h" +#include "Abstract/ISwitch.h" +#include + +#include +#include "Switch.h" +#include "PowerswitchHandler.h" + + +PowerswitchHandler::PowerswitchHandler(IParameterHandler *_p) + : m_Params(_p) + , m_Ticks(0) +{ + //DDRD |= 0x7C; + DDRD &= ~0x7C; + //PIND = 0x7C; + PORTD = 0x7C; + DDRC = 0x0F; + PORTC = 0XFF; + m_Params->registerListener(PID_SwitchAll,this); /* State on or off */ + m_Params->registerListener(PID_Switch1,this); /* State on or off */ + m_Params->registerListener(PID_Switch2,this); /* State on or off */ + m_Params->registerListener(PID_Switch3,this); /* State on or off */ + m_Params->registerListener(PID_Switch4,this); /* State on or off */ +} + +#define TICK_COUNT 200 +/** + * Well try processing evey 2s + */ +void +PowerswitchHandler::run() +{ + m_Ticks = (m_Ticks < TICK_COUNT) + ? m_Ticks + 1 + : 0; + + if ( m_Ticks == 0) + { // In case of closed loop mode compute correction + readPushButtons(); + // convert to Rpm ! + //m_Params->writeValue(PID_PowerswitchRpm,_Rpm); + } +} + +void +PowerswitchHandler::readPushButtons() +{ + Uint8_t pids[SWITCH_NUMBER + 1 ] = { PID_SwitchAll,PID_Switch4,PID_Switch3,PID_Switch2,PID_Switch1 }; + Uint8_t mask = 0; + + for (Uint8_t i = 0 ; i < SWITCH_NUMBER + 1; ++i) + { + mask = 1<<(i + 2); + /* Button press */ + if ( (PIND & mask) == 0) + { + Uint8_t val = 0; + m_Params->readValue(pids[i],val); + if (val > 0) + { + val = 0; + } else val = 1; + m_Params->writeValue(pids[i],val); + } + } +} + +void +PowerswitchHandler::onWriteValue(const uint8_t paramID,const uint8_t _val) +{ + switch (paramID) + { + case PID_Switch1: + PORTC ^= _BV(PINC0); + break; + case PID_Switch2: + PORTC ^= _BV(PINC1); + break; + case PID_Switch3: + PORTC ^= _BV(PINC2); + break; + case PID_Switch4: + PORTC ^= _BV(PINC3); + break; + case PID_SwitchAll: + PORTC = 0xFF; + break; + default: + ; + } +} diff --git a/Application/PowerSwitch/PowerswitchHandler.h b/Application/PowerSwitch/PowerswitchHandler.h new file mode 100644 index 0000000..80b34f3 --- /dev/null +++ b/Application/PowerSwitch/PowerswitchHandler.h @@ -0,0 +1,34 @@ +#ifndef POWERSWITCHHANDLER_H__ +#define POWERSWITCHHANDLER_H__ + +#define SWITCH_NUMBER 4 +/** + * \brief Controls the motor behavior depending + * on the motor mode. + * + */ +class PowerswitchHandler : public ITask, public IParameterListener +{ + public: + PowerswitchHandler(IParameterHandler *_ph); + + virtual void run(); + private: + /** + * Read Input pins + * with the read value + */ + void readPushButtons(); + /** + * + */ + virtual void onWriteValue(const uint8_t paramID,const uint8_t _val) ; + //! IParameterListener call + virtual void onWriteValue(const uint8_t paramID,const Float32_t _val) {}; + private: + IParameterHandler *m_Params; + Switch *m_Switchs; + Uint8_t m_Ticks; // 500us ticks +}; + +#endif diff --git a/Application/PowerSwitch/Switch.cpp b/Application/PowerSwitch/Switch.cpp new file mode 100644 index 0000000..ee10f61 --- /dev/null +++ b/Application/PowerSwitch/Switch.cpp @@ -0,0 +1,60 @@ + +/** + * \brief simple class for port access for LEDs + * + * \file Switch.cpp + * \author Ebersold Andre + */ + +//#include +#include +#include +#include +#include +#include "Switch.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Switch::Switch(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *_ph) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +, m_Param(_ph) +{ + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Switch::~Switch() +{ +} + +//! switches the LED on +void Switch::set(State e) +{ + if (e == SwitchOn) + { + *(m_Port) |= (1 << m_Pin); + } else + { + *(m_Port) &= ~(1 << m_Pin); + } +} + + +//! toggles the LED +void Switch::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + +ISwitch::State +Switch::state(void) const +{ + return SwitchOff; +} + diff --git a/Application/PowerSwitch/Switch.h b/Application/PowerSwitch/Switch.h new file mode 100644 index 0000000..5d6e569 --- /dev/null +++ b/Application/PowerSwitch/Switch.h @@ -0,0 +1,44 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Switch : public ISwitch +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Switch(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *); + //! destructor + ~Switch(); + + //! switches the LED on + virtual void set(State _eState); + //! switches the LED off + //! toggles the LED + virtual void toggle(void); + /// + virtual State state() const; + private: + Switch(); + Switch( Switch const &src ); + Switch& operator=(const Switch &src ) ; + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + /// + IParameterHandler *m_Param; +}; diff --git a/Application/PowerSwitch/main.cpp b/Application/PowerSwitch/main.cpp new file mode 100644 index 0000000..6ede18c --- /dev/null +++ b/Application/PowerSwitch/main.cpp @@ -0,0 +1,186 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "Led0.h" +#include "Switch.h" +#include "PowerswitchHandler.h" + +/** + * @brief the scheduler will still slice the execution + * flow. The whole cycle is now 40 ticks ! + * 40 * + * 250ns * 4 = 1us * 10 = 10 us. On fast devices. + * + * 16MHz / 8 / 256 = 100us each tick + * + */ +class Scheduler : public IInterruptActivity +{ + private: + enum TIME_SLOTS { + FIRST_TIME_SLOT = 0, + BLOCK2_FIRST_TIME_SLOT = 1, + BLOCK3_FIRST_TIME_SLOT = 3, + LAST_TIME_SLOT = 5, + TIME_SLOT_COUNT = 5 + }; + enum ETASK_ID { + TASK1 = 0, + TASK2 = 1, + TASK3 = 2, + TASK_COUNT = 3 + }; + typedef struct Task_t { + TIME_SLOTS m_FirstTimeslot; + ETASK_ID m_NextTask; + } Task_type ; + + static Task_type gTasks[TASK_COUNT]; + public: + Scheduler(Led0 *_led,IProtocolLayer2 *_net,CommunicationHandler *_com,PowerswitchHandler *_mh + ,ITask *_Storage + ) + : + m_Led(_led) + , m_Netstring(_net) + , m_Com(_com) + , m_Powerswitch(_mh) + , m_Storage(_Storage) + , m_CurrentTimeslot(FIRST_TIME_SLOT) + , m_CurrentTask(TASK1) + { + } + // main entry point + void schedule() + { + waitForTimeslot(); + m_Com->run(); + switch (m_CurrentTask) + { + case TASK1: + //m_Adc->run(); + break; + case TASK2: + m_Powerswitch->run(); + break; + case TASK3: + m_Led->tick(); + m_Storage->run(); + break; + default: + ; + + } + m_CurrentTask = gTasks[m_CurrentTask].m_NextTask; + } + // called by the interrupt timer handler + virtual void tick() + { + m_CurrentTimeslot = (m_CurrentTimeslot < LAST_TIME_SLOT) + ? (TIME_SLOTS)(m_CurrentTimeslot+1) + : (FIRST_TIME_SLOT); + m_Netstring->tick(); + } + + private: + void waitForTimeslot( void ) + { + /// prevent instant scheduling + while (m_CurrentTimeslot == gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + // beginning of the timeslot + while (m_CurrentTimeslot != gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + } + private: + Led0 *m_Led; + IProtocolLayer2 *m_Netstring; + CommunicationHandler *m_Com; + PowerswitchHandler *m_Powerswitch; + ITask *m_Storage; + volatile TIME_SLOTS m_CurrentTimeslot; + ETASK_ID m_CurrentTask; + + +}; + +Scheduler::Task_type Scheduler::gTasks[TASK_COUNT] = { + { FIRST_TIME_SLOT , TASK2 } + , { BLOCK2_FIRST_TIME_SLOT, TASK3 } + , { BLOCK3_FIRST_TIME_SLOT, TASK1 } +}; + +/** + * \brief Init database .... + */ +void init(IParameterHandler *m_Param) +{ +} + + +/** + * \brief main loop + */ +int main(void) +{ + PowerswitchParameterHandler gParam; +#if defined (__AVR_ATmega32U4__) + Led0 led(&PORTC, &DDRC, PINB7,&gParam); +#else + Led0 led(&PORTB, &DDRB, PINB5,&gParam); +#endif + AvrUart uart(IUart::BAUD_9600,IUart::PARITY_NONE,IUart::STB_ONE); + AvrEeprom gEeprom; + NetString netstring(&uart); + CommunicationHandler gCom(&netstring,&gParam); + PersistentStorage gStorage(&gEeprom,&gParam); + PowerswitchHandler motorH(&gParam); + Scheduler sched(&led,&netstring,&gCom,&motorH,&gStorage); + + uart.init(); + netstring.init(); + + Timer0 lTimer(sched); + + led.on(); + _delay_ms(300); + led.off(); + _delay_ms(300); + + lTimer.init(); + init(&gParam); + gEeprom.init(); + while(1) + { + sched.schedule(); + } +} diff --git a/Application/Scheduler/Scheduler.h b/Application/Scheduler/Scheduler.h new file mode 100644 index 0000000..bc19cc7 --- /dev/null +++ b/Application/Scheduler/Scheduler.h @@ -0,0 +1,14 @@ +#ifndef __AVR_SCHEDULER_H__ +#define __AVR_SCHEDULER_H__ + +class Scheduler : IInterruptActivity +{ + public: + Scheduler(); + // main entry point + void schedule(); + // called by the interrupt timer handler + virtual tick(); + private: +}; +#endif diff --git a/Application/ShutterCtrl/CMakeLists.txt b/Application/ShutterCtrl/CMakeLists.txt new file mode 100644 index 0000000..647737e --- /dev/null +++ b/Application/ShutterCtrl/CMakeLists.txt @@ -0,0 +1,36 @@ +##################################################################### +# simple AVR executable +##################################################################### +add_avr_executable( + shutterctrl + main.cpp + Led0.cpp + ShutterHandler.cpp + TouchScrHandler.cpp + ) + +target_link_libraries( + shutterctrl-${AVR_MCU}.elf + avrHAL-${AVR_MCU} + avrDrivers-${AVR_MCU} + avrComm-${AVR_MCU} + avrSC-Ptf-${AVR_MCU} + avrShutterCtrlParameters-${AVR_MCU} +) + +IF (${AVR_MCU} EQUAL "atmega328p") + SET(AVRPROG arduino) + SET(AVRPROG_MCU Atmega328p) +ELSE(${AVR_MCU} EQUAL "atmega328p") + SET(AVRPROG avr109) + SET(AVRPROG_MCU m32u4) +ENDIF(${AVR_MCU} EQUAL "atmega328p") + +add_custom_target( + flash_shutter + COMMAND + # avrdude -c arduino -P ${AVRDUDE_PORT} -p Atmega328p -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/dcmotor-${AVR_MCU}.hex:i + avrdude -c ${AVRPROG} -P ${AVRDUDE_PORT} -p ${AVRPROG_MCU} -b 57600 -Uflash:w:${CMAKE_CURRENT_BINARY_DIR}/dcmotor-${AVR_MCU}.hex:i + DEPENDS dcmotor-${AVR_MCU}.hex + ) + diff --git a/Application/ShutterCtrl/Led0.cpp b/Application/ShutterCtrl/Led0.cpp new file mode 100644 index 0000000..06df758 --- /dev/null +++ b/Application/ShutterCtrl/Led0.cpp @@ -0,0 +1,81 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.cpp + * \author Ebersold Andre + */ + +//#include +#include +#include +#include +#include "Led0.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Led0::Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *_ph) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +, m_Counter(0) +, m_Param(_ph) +{ + uint16_t cycle = 350; + _ph->writeValue(PID_LedCycle,cycle); + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Led0::~Led0() +{ +} + +//! switches the LED on +void Led0::on(void) +{ + *(m_Port) |= (1 << m_Pin); +} + +//! switches the LED off +void Led0::off(void) +{ + *(m_Port) &= ~(1 << m_Pin); +} + +//! toggles the LED +void Led0::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + +/// +void +Led0::setCycle(uint16_t _cycle) +{ + m_Param->writeValue(PID_LedCycle,_cycle); +} +/// +void +Led0::reloadCounter() +{ + uint16_t cycle = 100; + m_Param->readValue(PID_LedCycle,cycle); + m_Counter = cycle; +} +/// +void +Led0::tick() +{ + if (m_Counter > 0) + { + m_Counter--; + } else + { + toggle(); + reloadCounter(); + } +} diff --git a/Application/ShutterCtrl/Led0.h b/Application/ShutterCtrl/Led0.h new file mode 100644 index 0000000..e8f4209 --- /dev/null +++ b/Application/ShutterCtrl/Led0.h @@ -0,0 +1,52 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Led0 +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *); + //! destructor + ~Led0(); + + //! switches the LED on + void on(void); + //! switches the LED off + void off(void); + //! toggles the LED + void toggle(void); + /// + void setCycle(uint16_t _cycle); + /// + void reloadCounter(); + /// + void tick(); + private: + Led0(); + Led0( Led0 const &src ); + Led0& operator=(const Led0 &src ) ; + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + //! reset count + uint16_t m_Counter; + /// + IParameterHandler *m_Param; +}; + diff --git a/Application/ShutterCtrl/ShutterHandler.cpp b/Application/ShutterCtrl/ShutterHandler.cpp new file mode 100644 index 0000000..b25b331 --- /dev/null +++ b/Application/ShutterCtrl/ShutterHandler.cpp @@ -0,0 +1,103 @@ +#include "Utils/StdTypes.h" + +#include "Application/ITask.h" +#include + +#include +#include +#include "ShutterHandler.h" + + +/** +* +*/ +Shutter::Shutter(volatile uint8_t *_port,volatile uint8_t *_ddr,uint8_t _pin) + : m_Port(_port),m_Ddr(_ddr),m_Pin(_pin) +{ + idle(); // Be sure, the signal is high + *(m_Ddr) |= _BV(m_Pin); + *(m_Ddr) |= _BV(m_Pin+1); +} +/** +* +*/ +void +Shutter::open() +{ + *m_Port &= ~_BV(m_Pin); +} + +/** +* +*/ +void +Shutter::close() +{ + *m_Port &= ~_BV(m_Pin+1); +} +/** +* +*/ +void +Shutter::idle() +{ + *m_Port |= _BV(m_Pin); + *m_Port |= _BV(m_Pin+1); +} + + + + +ShutterHandler::ShutterHandler(IParameterHandler *_ph,Timer1 *_t1) + : m_Params(_ph),m_Counter(_t1) + ,m_Shutter1(&PORTD,&DDRD,PIN2) + ,m_Shutter2(&PORTD,&DDRD,PIN4) + ,m_Shutter3(&PORTD,&DDRD,PIN6) + ,m_Shutter4(&PORTB,&DDRB,PIN0) +{ + m_Shutters[0] = &m_Shutter1; + m_Shutters[1] = &m_Shutter2; + m_Shutters[2] = &m_Shutter3; + m_Shutters[3] = &m_Shutter4; + for (uint8_t i = 0 ; i < 4 ; ++i) + m_Shutters[i]-> idle(); +} + +void ShutterHandler::run() +{ + Uint8_t l_Mode; + + m_Ticks = (m_Ticks < TICK_COUNT) + ? m_Ticks + 1 + : 0; + + m_Params->readValue(PID_Shutter1,l_Mode); + Shutter *shutter = m_Shutters[l_Mode & 0x03]; + return ; + if ( m_Ticks == 0) + { // In case of closed loop mode compute correction + //updatePot0(); + //m_MotorA.update(); + switch (m_State) + { + case 0: + shutter->open(); + m_State++; + break; + case 1: + shutter->idle(); + shutter->close(); + m_State++; + break; + case 2: + shutter->idle(); + m_State++; + break; + default: + l_Mode = (l_Mode + 1) & 0x03; + m_Params->writeValue(PID_Shutter1,l_Mode ); + m_State = 0; + break; + } + } +} diff --git a/Application/ShutterCtrl/ShutterHandler.h b/Application/ShutterCtrl/ShutterHandler.h new file mode 100644 index 0000000..1c8a170 --- /dev/null +++ b/Application/ShutterCtrl/ShutterHandler.h @@ -0,0 +1,56 @@ +#ifndef __SHUTTER_HANDLER_H__ +#define __SHUTTER_HANDLER_H__ + +#define TICK_COUNT 3000 + + +class Shutter +{ + public: + /** + * + */ + Shutter(volatile uint8_t *_port,volatile uint8_t *_ddr,uint8_t _pin); + /** + * + */ + void open(); + /** + * + */ + void close(); + /** + * + */ + void idle(); + + private: + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + +}; + + +class ShutterHandler : public ITask +{ + public: + /// Default constructor + ShutterHandler(IParameterHandler *_ph,Timer1 *_t1); + + virtual void run(); + private: + IParameterHandler *m_Params; + Timer1 *m_Counter; + uint16_t m_Ticks; + uint8_t m_State; // ShutterHandlerState + Shutter m_Shutter1; + Shutter m_Shutter2; + Shutter m_Shutter3; + Shutter m_Shutter4; + Shutter *m_Shutters[4]; +}; +#endif diff --git a/Application/ShutterCtrl/TouchScrHandler.cpp b/Application/ShutterCtrl/TouchScrHandler.cpp new file mode 100644 index 0000000..75429e7 --- /dev/null +++ b/Application/ShutterCtrl/TouchScrHandler.cpp @@ -0,0 +1,42 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include "TouchScrHandler.h" + + +TouchScreenHandler::TouchScreenHandler(XPT2046Touchscreen *_tc, IParameterHandler *_param) + : m_Tc(_tc),m_Param(_param) ,m_Counter(0) +{ + +} + +void +TouchScreenHandler::run() +{ + if ((m_Counter % 200) == 0) + { + if (m_Tc->isTouched()) + { + // Read Position and update X / Y position + TSPoint p = m_Tc->getPoint(); + m_Param->writeValue(PID_Px,static_cast(p.x)); + m_Param->writeValue(PID_Py,static_cast(p.y)); + m_Param->writeValue(PID_Pz,static_cast(p.z)); + } + } else + { + m_Counter++; + } +} diff --git a/Application/ShutterCtrl/TouchScrHandler.h b/Application/ShutterCtrl/TouchScrHandler.h new file mode 100644 index 0000000..8df11b4 --- /dev/null +++ b/Application/ShutterCtrl/TouchScrHandler.h @@ -0,0 +1,16 @@ +#ifndef __TOUCHSCRHANDLER_H__ +#define __TOUCHSCRHANDLER_H__ + +class TouchScreenHandler : virtual public ITask +{ + public: + TouchScreenHandler(XPT2046Touchscreen *_tc, IParameterHandler *_param); + + virtual void run(); + private: + XPT2046Touchscreen *m_Tc; + IParameterHandler *m_Param; + uint32_t m_Counter; +}; + +#endif diff --git a/Application/ShutterCtrl/main.cpp b/Application/ShutterCtrl/main.cpp new file mode 100644 index 0000000..e0ee6d3 --- /dev/null +++ b/Application/ShutterCtrl/main.cpp @@ -0,0 +1,218 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include "Led0.h" + +#include "TouchScrHandler.h" +#include "ShutterHandler.h" + +/** + * @brief the scheduler will still slice the execution + * flow. The whole cycle is now 40 ticks ! + * 40 * + * 250ns * 4 = 1us * 10 = 10 us. On fast devices. + * + * 16MHz / 8 / 256 = 100us each tick + * + */ +class Scheduler : public IInterruptActivity +{ + private: + enum TIME_SLOTS { + FIRST_TIME_SLOT = 0, + BLOCK2_FIRST_TIME_SLOT = 1, + BLOCK3_FIRST_TIME_SLOT = 3, + LAST_TIME_SLOT = 5, + TIME_SLOT_COUNT = 5 + }; + enum ETASK_ID { + TASK1 = 0, + TASK2 = 1, + TASK3 = 2, + TASK_COUNT = 3 + }; + typedef struct Task_t { + TIME_SLOTS m_FirstTimeslot; + ETASK_ID m_NextTask; + } Task_type ; + + static Task_type gTasks[TASK_COUNT]; + public: + Scheduler(Led0 *_led,IProtocolLayer2 *_net + ,CommunicationHandler *_com + ,ShutterHandler *_mh + ,ITask *_Storage + ,TouchScreenHandler *_tch + ) + : + m_Led(_led) + , m_Netstring(_net) + , m_Com(_com) + , m_Shutter(_mh) + , m_Storage(_Storage) + , m_Tch(_tch) + , m_CurrentTimeslot(FIRST_TIME_SLOT) + , m_CurrentTask(TASK1) + { + } + // main entry point + void schedule() + { + waitForTimeslot(); + m_Com->run(); + switch (m_CurrentTask) + { + case TASK1: + //m_Adc->run(); + m_Tch->run(); + break; + case TASK2: + m_Shutter->run(); + break; + case TASK3: + //m_Led->tick(); + m_Storage->run(); + break; + default: + ; + + } + m_CurrentTask = gTasks[m_CurrentTask].m_NextTask; + } + // called by the interrupt timer handler + virtual void tick() + { + m_CurrentTimeslot = (m_CurrentTimeslot < LAST_TIME_SLOT) + ? (TIME_SLOTS)(m_CurrentTimeslot+1) + : (FIRST_TIME_SLOT); + m_Netstring->tick(); + } + + private: + void waitForTimeslot( void ) + { + /// prevent instant scheduling + while (m_CurrentTimeslot == gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + // beginning of the timeslot + while (m_CurrentTimeslot != gTasks[m_CurrentTask].m_FirstTimeslot ) + { + ; + } + } + private: + Led0 *m_Led; + IProtocolLayer2 *m_Netstring; + CommunicationHandler *m_Com; + ShutterHandler *m_Shutter; + ITask *m_Storage; + TouchScreenHandler *m_Tch; + volatile TIME_SLOTS m_CurrentTimeslot; + ETASK_ID m_CurrentTask; + + +}; + +Scheduler::Task_type Scheduler::gTasks[TASK_COUNT] = { + { FIRST_TIME_SLOT , TASK2 } + , { BLOCK2_FIRST_TIME_SLOT, TASK3 } + , { BLOCK3_FIRST_TIME_SLOT, TASK1 } +}; + +/** + * \brief Init database .... + */ +void init(IParameterHandler *m_Param) +{ +// m_Param->writeValue(PID_MotorPwm,(uint8_t)60); +// m_Param->writeValue(PID_CPR,static_cast(500)); +} + + +/** + * \brief main loop + */ +int main(void) +{ + Timer1 lCounter; + ShutterCtrlParameterHandler gParam; + Led0 led(&PORTB, &DDRB, PINB5,&gParam); + AvrUart uart(IUart::BAUD_9600,IUart::PARITY_NONE,IUart::STB_ONE); + AvrEeprom gEeprom; + AvrSpi gSpi; + NetString netstring(&uart); + CommunicationHandler gCom(&netstring,&gParam); + PersistentStorage gStorage(&gEeprom,&gParam); + ShutterHandler shutterH(&gParam,&lCounter); + XPT2046Touchscreen tc(&gSpi,PINC2); + TouchScreenHandler tch(&tc,&gParam); + Scheduler sched(&led,&netstring,&gCom,&shutterH,&gStorage,&tch); + + Ili9341 ili(&gSpi); + + //ili.fillrect(10,60,50,50,0x07E0); + + uart.init(); + netstring.init(); + ili.init(); + //ili.clear(ILI9341_NAVY); + ili.clear(0x0); + ili.setRotation(0); + ili.drawhline(5,5,225,ILI9341_WHITE); + ili.drawhline(5,315,225,ILI9341_WHITE); + ili.drawvline(5,5,310,ILI9341_GREEN); + ili.drawvline(230,5,310,ILI9341_GREEN); + ili.fillrect(10,10,50,50,0xF800); + ili.fillrect(10,70,50,50,ILI9341_GREEN); + ili.fillrect(10,130,50,50,ILI9341_CYAN); + ili.fillrect(10,190,50,50,ILI9341_ORANGE); + ili.fillrect(10,250,50,50,ILI9341_PINK); + Timer0 lTimer(sched); +#if 0 + led.on(); + _delay_ms(300); + led.off(); + _delay_ms(300); +#endif + lTimer.init(); + init(&gParam); + gEeprom.init(); + while(1) + { + sched.schedule(); + //ili.drawhline(15,15,50,ILI9341_RED); + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1c74b10 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 2.8) + + +########################################################################## +# tools to beused for programming the AVR +########################################################################## +set(AVR_UPLOADTOOL avrdude) +set(AVR_PROGRAMMER arduino) +set(AVR_UPLOADTOOL_PORT /dev/ttyS5) +set(AVR_UPLOADTOOL_BAUDRATE 57600) + +########################################################################## +# AVR and fuses needs to be set +########################################################################## +#set(AVR_MCU atmega32) +set(AVR_MCU atmega328p CACHE STRING "AVR MCU type choose between atmega32_p or atmega32 atmega328p") +set(AVR_H_FUSE 0xd9) +set(AVR_L_FUSE 0xc3) + +### END TOOLCHAIN SETUP AREA ############################################# + +include(${CMAKE_CURRENT_SOURCE_DIR}/rules/gcc-avr-generic.cmake) + +PROJECT(tinyapp) + +include(${CMAKE_CURRENT_SOURCE_DIR}/rules/gcc-avr-common.cmake) + +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE "Debug") +ENDIF(NOT CMAKE_BUILD_TYPE) + +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") + +SUBDIRS(HAL Application Platform Communication Metadata) + +INCLUDE_DIRECTORIES("${tinyapp_SOURCE_DIR}") +INCLUDE_DIRECTORIES("${tinyapp_SOURCE_DIR}/HAL") +INCLUDE_DIRECTORIES("${tinyapp_BINARY_DIR}") +INCLUDE_DIRECTORIES("${tinyapp_BINARY_DIR}/Application") + + + +OPTION(TINYAPP_LED0 "Build Led application" ON) +OPTION(TINYAPP_DC_MOTOR "Build DC Motor application" OFF) +OPTION(TINYAPP_SHUTTERCTRL "Build Shutter Handler application" ON) + +SET(AVRDUDE_PORT "/dev/ttyS3" CACHE STRING "Avrdude port to use for flashing") + +# new way +#CONFIGURE_FILE(${antcc_SOURCE_DIR}/src/antcc/config.h.cmake +# ${antcc_BINARY_DIR}/src/antcc/config.h) diff --git a/Communication/CMakeLists.txt b/Communication/CMakeLists.txt new file mode 100644 index 0000000..bc83acd --- /dev/null +++ b/Communication/CMakeLists.txt @@ -0,0 +1,8 @@ +##################################################################### +# simple AVR library +##################################################################### +add_avr_library( + avrComm + CommunicationHandler.cpp + ) + diff --git a/Communication/CommunicationHandler.cpp b/Communication/CommunicationHandler.cpp new file mode 100644 index 0000000..587de6d --- /dev/null +++ b/Communication/CommunicationHandler.cpp @@ -0,0 +1,145 @@ + +#include +#include // for itoa +#include +#if 0 +#include // To be removed +#endif +#include +#include + +CommunicationHandler::CommunicationHandler(IProtocolLayer2 *_l2,IParameterHandler *_p) + : m_L2(_l2), m_Params(_p) +{ +} + +void +CommunicationHandler::run() +{ + const Uint8_t len = m_L2->getRxSize(); + const uint8_t *msg = m_L2->receiveMsg(); + if ( msg != 0) + { + switch (msg[0]) + { +#if 0 + case 'G': + { + uint16_t nv = 650; + m_Params->writeValue(PID_LedCycle,nv); + m_L2->setTxMsg((const uint8_t *)"OK Go",5); + } + break; + case 'D': + m_L2->setTxMsg((const uint8_t *)"OK Dir",6); + break; + case 'S': + { + uint16_t nv = 150; + m_Params->writeValue(PID_LedCycle,nv); + m_L2->setTxMsg((const uint8_t *)"OK SPEED",8); + } + break; + case 'R': + { + uint16_t nv = 0; + parse_num(msg+1,len -1,nv); + m_Params->writeValue(PID_LedCycle,nv); + m_L2->setTxMsg((const uint8_t *)"OK RPM",6); + } + break; +#endif + case 'M': + { + parse_msg(msg,len ,IParameterHandler::TYPE_U16); + } + break; + case 'F': + { + parse_msg(msg,len ,IParameterHandler::TYPE_FLOAT); + } + break; + default: + m_L2->setTxMsg((const uint8_t *)"KO MSG",10); + } + m_L2->transmitMsg(); + } +} + +#define OUTPUT_BUFFER_SIZE 16 +void +CommunicationHandler::parse_msg(const Uint8_t *_msg,const Uint8_t len,IParameterHandler::eParameterType _eType) +{ + uint16_t nv = 0; + uint16_t val = 0; + uint8_t pos = 0; + + parse_num(_msg+1,len -1,nv); + if ( nv < 0xA) + { + pos = 2; + } else { + pos = 3; + } + if ( _msg[pos] == '=' ) + { + if (_eType == IParameterHandler::TYPE_FLOAT) + { + Float32_t result; + result = atof((const char *)(_msg+1+pos)); + m_Params->writeValue(nv,result); + } + else + { + parse_num(_msg+1+pos,len - 1 - pos,val); + m_Params->writeValue(nv,val); + } + m_L2->setTxMsg((const uint8_t *)"OK\r\n",4); + } else if (_msg[pos] == '?') + { + char l_OutBuffer[OUTPUT_BUFFER_SIZE]; + for (Uint8_t i = 0 ; i < OUTPUT_BUFFER_SIZE; i++) l_OutBuffer[i] = '\0'; + if (_eType == IParameterHandler::TYPE_FLOAT) + { + Float32_t fval; + m_Params->readValue(nv,fval); + //dtostre(fval,(char *)l_OutBuffer,4,0); + dtostrf(fval,8,4,(char *)l_OutBuffer); + } else + { + m_Params->readValue(nv,val); + itoa(val,(char *)l_OutBuffer,10); + } + nv = 0; + while ( l_OutBuffer[nv] != '\0' && nv < OUTPUT_BUFFER_SIZE) nv++; + l_OutBuffer[nv++] = '\r'; + l_OutBuffer[nv++] = '\n'; + m_L2->setTxMsg((const uint8_t *)l_OutBuffer,nv); + } else + { + m_L2->setTxMsg((const uint8_t *)"KO\r\n",4); + } +} + +void +CommunicationHandler::parse_num(const Uint8_t *_msg,const Uint8_t len,Uint16_t &_out) +{ + Uint8_t chr = 0x00; + Uint8_t pchr = 0x00; + _out = 0; + Uint8_t i = len; + while ((*_msg) != 0x00 && i--) + { + chr = *_msg - 0x30; + if (chr < 0x0A) + { + _out *= 0x0A; + _out += chr; + } else if (pchr < 0x0A ) + { + break; + } + pchr = chr; + _msg++; + } +} diff --git a/Communication/CommunicationHandler.h b/Communication/CommunicationHandler.h new file mode 100644 index 0000000..2d7ba92 --- /dev/null +++ b/Communication/CommunicationHandler.h @@ -0,0 +1,19 @@ +#ifndef __COMMUNICATIONHANDLER_H__ +#define __COMMUNICATIONHANDLER_H__ + +class CommunicationHandler +/* : public ITask */ +{ + public: + CommunicationHandler(IProtocolLayer2 *_l2,IParameterHandler *_p); + + virtual void run(); + private: + void parse_msg(const Uint8_t *_msg,const Uint8_t len,IParameterHandler::eParameterType _eT); + /// + void parse_num(const Uint8_t *_msg,const Uint8_t len, Uint16_t &_out); + private: + IProtocolLayer2 *m_L2; + IParameterHandler *m_Params; +}; +#endif diff --git a/Communication/ICommunication.h b/Communication/ICommunication.h new file mode 100644 index 0000000..cfec6bd --- /dev/null +++ b/Communication/ICommunication.h @@ -0,0 +1,41 @@ +#ifndef __ICOMMUNICATION_H__ +#define __ICOMMUNICATION_H__ + +/** + * Commuinication application interface to + * be used by the application to send + * received messages over the selected + * physical interface. (Eg: the physical layer + * cannot be changed dynamically. + * + */ +class ICommunication +{ + public: + + ICommuncation() = 0; + + /** + * @brief transmit the message + * to the physical interface + */ + virtual void transmit() = 0; + /** + * @brief receive message from + * thephysical layer. + */ + virtual void receive() = 0; + /** + * @brief retrieve message received. + * + */ + virtual const uint8_t *getPayload( ) const = 0; + + virtual const uint8_t getPayloadSize() const = 0; + /** + * @brief set message to be sent + */ + virtual void setPayload(uint8_t *_msg,const uint_8 _length) = 0; +}; + +#endif diff --git a/Communication/ModbusSerial/ModbusSerial.h b/Communication/ModbusSerial/ModbusSerial.h new file mode 100644 index 0000000..1b574d2 --- /dev/null +++ b/Communication/ModbusSerial/ModbusSerial.h @@ -0,0 +1,47 @@ +#ifndef __MODBUSERIAL_H__ +#ifndef __MODBUSERIAL_H__ + +/** + * @brief Modbus application layer + * implementation. + * + */ +class ModbusSerial : public ICommunication +{ + public: + + /** + * @brief constructor.... + * @param Layer2 protocol stack Rs485 + * @param Error handler ? + */ + ModbusSerial(); + /** + * @brief transmit the message + * to the physical interface + */ + virtual void transmit() ; + /** + * @brief receive message from + * thephysical layer. + */ + virtual void receive() ; + /** + * @brief retrieve message received. + * + */ + virtual const uint8_t *getPayload( ) const ; + + /** + * @brief return payload size of + * the received message + */ + virtual const uint8_t getPayloadSize() const ; + /** + * @brief set message to be sent + */ + virtual void setPayload(uint8_t *_msg,const uint_8 _length) ; + +}; + +#endif diff --git a/HAL/AVR/328p_Pwm.cpp b/HAL/AVR/328p_Pwm.cpp new file mode 100644 index 0000000..e69de29 diff --git a/HAL/AVR/328p_Timer0.cpp b/HAL/AVR/328p_Timer0.cpp new file mode 100644 index 0000000..5a88bbc --- /dev/null +++ b/HAL/AVR/328p_Timer0.cpp @@ -0,0 +1,63 @@ + +#include + +#include "Abstract/IInterruptActivity.h" +#include "AVR/AvrTimer0.h" + + +Timer0* Timer0::gTimer0 = 0; + +ISR(TIMER0_OVF_vect) +{ + Timer0::gTimer0->process_interrupt(); + //TCNT0 = 0x01; + TIFR0 &= ~(1<tick(); +} + diff --git a/HAL/AVR/32u4_Pwm.cpp b/HAL/AVR/32u4_Pwm.cpp new file mode 100644 index 0000000..bb55a0f --- /dev/null +++ b/HAL/AVR/32u4_Pwm.cpp @@ -0,0 +1,63 @@ + +#include "HAL/Abstract/IPwm.h" + + +#if 0 +static Motor::pinMapping_t GmA = {PINB7,PINB6,0}; + + , m_MotorA(&OCR0A,&TCCR0A,GmA,COM0A0,_p) +#if ! defined (__AVR_ATmega32U4__) + , m_MotorB(&OCR2B,&TCCR2A,GmB,COM2B0,_p) +#endif +#endif + +#define USE_T1 1 +/// +AvrPwm::AvrPwm() + : IPwm() +{ + _init(); +} + +void AvrPwm::_init() +{ +#ifdef USE_T1 + TCCR1A |= (3 << WGM10); + OCR1C = 150; + + TCCR1A |= (2 << COM1C0); + TCCR0A &= ~(3 << COM0A0); +#else + TCCR1B &= ~(7< + +#include "Abstract/IInterruptActivity.h" +#include "AVR/AvrTimer0.h" + + +Timer0* Timer0::gTimer0 = 0; + +ISR(TIMER0_OVF_vect) +{ + Timer0::gTimer0->process_interrupt(); + TIFR0 &= ~(1<tick(); +} + diff --git a/HAL/AVR/AvrAdc.cpp b/HAL/AVR/AvrAdc.cpp new file mode 100644 index 0000000..cb7d1d7 --- /dev/null +++ b/HAL/AVR/AvrAdc.cpp @@ -0,0 +1,63 @@ + +#include + +#include +#include +#include + + +AvrADC::AvrADC() + : m_Value(0),m_Channel(0),m_State(ADC_IDLE) +{ + init(); +} + +void +AvrADC::init() +{ + // Select Vref = AVcc + ADMUX |= (1< + +#include +#include + + +AvrEeprom::AvrEeprom() +{ +} + + +void +AvrEeprom::init() +{ +} + +/// Is eeprom busy, might be of interest, as eeprom access is performed through +/// SPI +Bool_t +AvrEeprom::isBusy() +{ + return EECR & _BV(EEPE); +} + +/// read values from Eeprom +void +AvrEeprom::read(const Uint16_t _addr,const Uint16_t _len,Uint8_t *_dest) +{ + // Not sure if this is a good idea + while (isBusy() ) ; + EEAR = _addr; + EECR |= _BV(EERE); + *_dest = EEDR; +} + +/// Interesting that eeprom is written page wise +void +AvrEeprom::writePage(const Uint8_t pageCount,const Uint8_t _Offset,const Uint8_t byteCount,Uint8_t *_data) +{ + // Not sure if this is a good idea + while (isBusy() ) ; + // + EEAR = (16 * pageCount) + _Offset; + EEDR = _data[0]; + // Start Programming Sequence + EECR |= _BV(EEMPE); + EECR |= _BV(EEPE); +} + + diff --git a/HAL/AVR/AvrEeprom.h b/HAL/AVR/AvrEeprom.h new file mode 100644 index 0000000..0f6841e --- /dev/null +++ b/HAL/AVR/AvrEeprom.h @@ -0,0 +1,34 @@ +#ifndef AVR_EEPROM_H__ +#define AVR_EEPROM_H__ + +/** + * + * + */ +class AvrEeprom : public IEeprom +{ + public: + /// + AvrEeprom(); + + /// + virtual void init(); + + /// Is eeprom busy, might be of interest, as eeprom access + /// + virtual Bool_t isBusy(); + + /// read values from Eeprom + virtual void read( const Uint16_t _addr + , const Uint16_t _len + , Uint8_t *_dest); + + /// Interesting that eeprom is written page wise + virtual void writePage( const Uint8_t pageCount + , const Uint8_t _Offset + , const Uint8_t byteCount + , Uint8_t *_data); +}; + + +#endif diff --git a/HAL/AVR/AvrInterrupt.h b/HAL/AVR/AvrInterrupt.h new file mode 100644 index 0000000..674616c --- /dev/null +++ b/HAL/AVR/AvrInterrupt.h @@ -0,0 +1,15 @@ +#ifndef __AVRINTERRUPT_H__ + +class AvrInterrupt +{ + public: + AvrInterrupt(IInterruptActivity *); + + /** + * Initialize timer so that a scheduling + * will occure every 500us + */ + void init(); + private: +}; +#endif diff --git a/HAL/AVR/AvrPwm.cpp b/HAL/AVR/AvrPwm.cpp new file mode 100644 index 0000000..8a81bcd --- /dev/null +++ b/HAL/AVR/AvrPwm.cpp @@ -0,0 +1,11 @@ +#include + +#include "Utils/StdTypes.h" +#include "HAL/Abstract/IPwm.h" +#include "AVR/AvrPwm.h" + +#if defined (__AVR_ATmega32U4__) +#include "32u4_Pwm.cpp" +#else +#include "328p_Pwm.cpp" +#endif diff --git a/HAL/AVR/AvrPwm.h b/HAL/AVR/AvrPwm.h new file mode 100644 index 0000000..27a19b8 --- /dev/null +++ b/HAL/AVR/AvrPwm.h @@ -0,0 +1,26 @@ +#ifndef AVR_PWM_H__ +#define AVR_PWM_H__ + +/** + * + * + */ +//template +class AvrPwm : public IPwm +{ + public: + /// + AvrPwm(); + + /// From Interface + virtual void enable(const Bool_t _OnOff) const; + + /// From Interface + virtual void setFreq(Uint16_t freq) const; + + /// From Interface + virtual void setDutyCycle(const Uint8_t _OnOff) const; + private: + void _init(); +}; +#endif diff --git a/HAL/AVR/AvrSpi.cpp b/HAL/AVR/AvrSpi.cpp new file mode 100644 index 0000000..05450b4 --- /dev/null +++ b/HAL/AVR/AvrSpi.cpp @@ -0,0 +1,82 @@ + +#include +#include +#include + + +AvrSpi::AvrSpi() +{ + init(); +} + +void +AvrSpi::init( void ) +{ + /* initial SPI */ + /* atmega88: PB3=MOSI, PB5=SCK, PB2=nSS, PB4=MISO */ + PORTB |= _BV( PIN2) | _BV( PIN3) | _BV( PIN5); + DDRB |= _BV( PIN2 ) | _BV( PIN3 ) | _BV( PIN5) ; + DDRB &= ~_BV( PIN4 ); + /* enable SPI as Master */ + SPCR = (1<(0x00FF & result); + *rxData = out.val; +} diff --git a/HAL/AVR/AvrSpi.h b/HAL/AVR/AvrSpi.h new file mode 100644 index 0000000..808d7ee --- /dev/null +++ b/HAL/AVR/AvrSpi.h @@ -0,0 +1,24 @@ +#ifndef AVR_SPI_H__ +#define AVR_SPI_H__ + +/** + * \brief SPI interface for ATMEGA 328p + * should be simple and fast + * + */ +class AvrSpi : public ISpi +{ + public: + AvrSpi(); + + virtual void init( void ); + // Begin SPI transaction + virtual void begin(const SPISettings &_settings) ; + /// End SPI transaction + virtual void end(); + /// 8 bits data tx/rx + virtual void transceive(const Uint8_t txData,Uint8_t *const &rxData); + /// 16 bits data tx / rx + virtual void transceive(const Uint16_t txData,Uint16_t *const &rxData); +}; +#endif diff --git a/HAL/AVR/AvrTimer0.cpp b/HAL/AVR/AvrTimer0.cpp new file mode 100644 index 0000000..b363895 --- /dev/null +++ b/HAL/AVR/AvrTimer0.cpp @@ -0,0 +1,11 @@ + +#include + +#include "Abstract/IInterruptActivity.h" +#include "AVR/AvrTimer0.h" + +#if defined (__AVR_ATmega32U4__) +#include "32u4_Timer0.cpp" +#else +#include "328p_Timer0.cpp" +#endif diff --git a/HAL/AVR/AvrTimer0.h b/HAL/AVR/AvrTimer0.h new file mode 100644 index 0000000..7c0fcfd --- /dev/null +++ b/HAL/AVR/AvrTimer0.h @@ -0,0 +1,21 @@ +#ifndef __AVR_TIMER0_H__ +#define __AVR_TIMER0_H__ + +class Timer0 +{ + public: + Timer0(IInterruptActivity &_int); + /// setup timer + void init(); + /// + void process_interrupt(); + /// Global pointer for ISR processing + static Timer0* gTimer0; + private: + /// setup timer + void initT2(); + IInterruptActivity *m_Interrupt; +}; + + +#endif diff --git a/HAL/AVR/AvrTimer1.cpp b/HAL/AVR/AvrTimer1.cpp new file mode 100644 index 0000000..8831a40 --- /dev/null +++ b/HAL/AVR/AvrTimer1.cpp @@ -0,0 +1,52 @@ +#include + +#include "AVR/AvrTimer1.h" + + +Timer1::Timer1() +{ + init(); +} +void +Timer1::init() +{ + //cli(); + + // Set Control Register 16MHz / 1024 = 15,625KHz + // Tick = 1/15,625KHz = 64us + // So overflow every 16ms + // No Division + TCCR1B = 3<< CS10 ; + //TCCR1B = _BV(CS10) | _BV(CS11) | _BV(CS12); + //TCCR0A = (1<< WGM01); +#if 0 + TCCR1A |= (3<< WGM10); + TCCR1B |= (1<< WGM12); +#endif + // Initialize counter + TCNT1 = 0; +#if defined (__AVR_ATmega32U4__) + PRR0 &= ~(1< + +#include "AVR/AvrTimer3.h" + + +Timer3::Timer3() +{ + init(); +} +void +Timer3::init() +{ + //cli(); + + // Set Control Register 16MHz / 1024 = 15,625KHz + // Tick = 1/15,625KHz = 64us + // So overflow every 16ms + // No Division + TCCR3B = _BV(CS30) | _BV(CS31) | _BV(CS32); + //TCCR0A = (1<< WGM01); + TCCR3A |= (3<< WGM00); + // Initialize counter + TCNT3 = 0; + PRR0 &= ~(1< + +#include +#include + + + +AvrUart::AvrUart(Baudrate_t _baud,Parity_t _p,StopBits_t _stb) + : m_Baudrate(_baud),m_Parity(_p),m_StopBits(_stb) +{ + init(); +} + +void +AvrUart::init() +{ + +#if defined (__AVR_ATmega32U4__) + PRR1 &= ~(1<> 8; + UBRR1L = speed; + // Set 8 bits and Stop bits + if (_bits == STB_TWO) + { + UCSR1C = (1<> 8; + UBRR0L = speed; + // Set 8 bits and Stop bits + if (_bits == STB_TWO) + { + UCSR0C = (1< +#include + +#include "Abstract/ISPI.h" +#include "Ili9341.h" + + + + +#define TianMa_2_4inch_ILI9341 1 +#define CMD_ACTIF_LOW 1 +#define SPI_SETTINGS SPISettings(8000000,MSBFIRST,SPI_MODE0) + +volatile uint16_t LCD_W=ILI9341_TFTWIDTH; +volatile uint16_t LCD_H=ILI9341_TFTHEIGHT; + +Ili9341::Ili9341(ISpi *_spi) + : m_Spi(_spi) +{ +} + +void Ili9341::hard_init(void)//init hardware +{ + /* initial hardware bit */ + // set port C/ D & E to output + LCD_CSN_DDR |= (1<begin(SPI_SETTINGS); +#endif + LCD_CSN_PORT |= (1<transceive(input,&result); + return result; +#endif +} + +void Ili9341::writedata8(uint8_t data)//data write +{ +#if CMD_ACTIF_LOW + LCD_CMD_PORT |= (1<>8); + writedata8(x1); + writedata8(x2>>8); + writedata8(x2); + + writecommand8(0x2B); + writedata8(y1>>8); + writedata8(y1); + writedata8(y2>>8); + writedata8(y2); + + writecommand8(0x2C);//meory write +} + + +void Ili9341::hard_reset(void)//hard reset display +{ + LCD_RST_PORT |= (1<end(); +} + +//set colour for drawing +void Ili9341::pushcolour(uint16_t colour) +{ + writedata8(colour>>8); + writedata8(colour); +} + + +//clear lcd and fill with colour +void Ili9341::clear(uint16_t colour) +{ + uint16_t i,j; + m_Spi->begin(SPI_SETTINGS); + + setaddress(0,0,LCD_W-1,LCD_H-1); + + for(i=0;iend(); +} + + + +//draw pixel +void Ili9341::drawpixel(uint16_t x3,uint16_t y3,uint16_t colour1) //pixels will always be counted from right side.x is representing LCD width which will always be less tha 240.Y is representing LCD height which will always be less than 320 +{ + if((x3 < 0) ||(x3 >=LCD_W) || (y3 < 0) || (y3 >=LCD_H)) return; + + m_Spi->begin(SPI_SETTINGS); + setaddress(x3,y3,x3+1,y3+1); + + pushcolour(colour1); + m_Spi->end(); +} + + +//draw vertical line +void Ili9341::drawvline(uint16_t x,uint16_t y,uint16_t h,uint16_t colour)//basically we will see this line horizental if we see the display 320*240 +{ + if((x >=LCD_W) || (y >=LCD_H)) return; + if((y+h-1)>=LCD_H) + h=LCD_H-y; + m_Spi->begin(SPI_SETTINGS); + setaddress(x,y,x,y+h-1); + while(h--) + { + pushcolour(colour); + } + m_Spi->end(); +} + + +//draw horizental line + +void Ili9341::drawhline(uint16_t x,uint16_t y,uint16_t w,uint16_t colour) +{ + if((x >=LCD_W) || (y >=LCD_H)) return; + if((x+w-1)>=LCD_W) + w=LCD_W-x; + m_Spi->begin(SPI_SETTINGS); + setaddress(x,y,x+w-1,y); + while(w--) + { + pushcolour(colour); + } + m_Spi->end(); +} + + +//draw colour filled rectangle +void Ili9341::fillrect(uint16_t x,uint16_t y,uint16_t w,uint16_t h,uint16_t colour) +{ + if((x >=LCD_W) || (y >=LCD_H)) return; + if((x+w-1)>=LCD_W) + w=LCD_W-x; + if((y+h-1)>=LCD_H) + h=LCD_H-y; + + m_Spi->begin(SPI_SETTINGS); + setaddress(x, y, x+w-1, y+h-1); + + for(y=h; y>0; y--) + { + for(x=w; x>0; x--) + { + pushcolour(colour); + } + } + m_Spi->end(); +} + +//rotate screen at desired orientation +void Ili9341::setRotation(uint8_t m) +{ + uint8_t rotation; + m_Spi->begin(SPI_SETTINGS); + writecommand8(0x36); + rotation=m%4; + switch (rotation) + { + case 0: + writedata8(0x40|0x08); + LCD_W = 240; + LCD_H = 320; + break; + + case 1: + writedata8(0x20|0x08); + LCD_W = 320; + LCD_H = 240; + break; + + case 2: + writedata8(0x80|0x08); + LCD_W = 240; + LCD_H = 320; + break; + + case 3: + writedata8(0x40|0x80|0x20|0x08); + LCD_W = 320; + LCD_H = 240; + break; + } + m_Spi->end(); +} diff --git a/HAL/Drivers/Ili9341.h b/HAL/Drivers/Ili9341.h new file mode 100644 index 0000000..6d5d7a4 --- /dev/null +++ b/HAL/Drivers/Ili9341.h @@ -0,0 +1,87 @@ +#ifndef __ILI9341_H__ +#define __ILI9341_H__ + +#define ILI9341_TFTWIDTH 240 +#define ILI9341_TFTHEIGHT 320 + +#define LCD_CSN_PORT PORTB +#define LCD_CSN_DDR DDRB +#define LCD_CSN PIN2 + +#define LCD_CMD_PORT PORTC +#define LCD_CMD_DDR DDRC +#define LCD_CMD PIN0 + +#define LCD_RST_PORT PORTC +#define LCD_RST_DDR DDRC +#define LCD_RST PIN1 +/** + * + */ +#define ILI9341_BLACK 0x0000 +#define ILI9341_NAVY 0x000F +#define ILI9341_DARKGREEN 0x03E0 +#define ILI9341_DARKCYAN 0x03EF +#define ILI9341_MAROON 0x7800 +#define ILI9341_PURPLE 0x780F +#define ILI9341_OLIVE 0x7BE0 +#define ILI9341_LIGHTGREY 0xC618 +#define ILI9341_DARKGREY 0x7BEF +#define ILI9341_BLUE 0x001F +#define ILI9341_GREEN 0x07E0 +#define ILI9341_CYAN 0x07FF +#define ILI9341_RED 0xF800 +#define ILI9341_MAGENTA 0xF81F +#define ILI9341_YELLOW 0xFFE0 +#define ILI9341_WHITE 0xFFFF +#define ILI9341_ORANGE 0xFD20 +#define ILI9341_GREENYELLOW 0xAFE5 +#define ILI9341_PINK 0xFC18 + + + +/** + * ILI 9341 LDC 2.2" LDC driver + */ +class Ili9341 +{ + public: + Ili9341(ISpi *_spi); + public: + + void hard_reset(void) ; //hard reset display + + void init(void) ; //set up display using predefined command sequence + //clear lcd and fill with colour + void clear(uint16_t colour); + //draw pixel + void drawpixel(uint16_t x3,uint16_t y3,uint16_t colour1); //pixels will always be counted from right side.x is representing LCD width which will always be less tha 240.Y is representing LCD height which will always be less than 320 + //draw vertical line + void drawvline(uint16_t x,uint16_t y,uint16_t h,uint16_t colour); //basically we will see this line horizental if we see the display 320*240 + /// draw horizental line + void drawhline(uint16_t x,uint16_t y,uint16_t w,uint16_t colour); + /// draw colour filled rectangle + void fillrect(uint16_t x,uint16_t y,uint16_t w,uint16_t h,uint16_t colour); + + void setRotation(uint8_t m); + protected: + //set colour for drawing + void pushcolour(uint16_t colour); + + void setaddress(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); //set coordinate for print or other function + private: + void hard_init(); + + void spi_init(); + + uint8_t SPI_ExchangeByte( uint8_t input ); + + void writedata8(uint8_t data);//data write + + void writecommand8(uint8_t com);//command write + + private: + ISpi *m_Spi; +}; + +#endif diff --git a/HAL/Drivers/NetString.cpp b/HAL/Drivers/NetString.cpp new file mode 100644 index 0000000..1ca77f4 --- /dev/null +++ b/HAL/Drivers/NetString.cpp @@ -0,0 +1,310 @@ + +#include + +#include "Abstract/IInterruptActivity.h" +#include "Abstract/IUart.h" +#include "Abstract/IProtocolLayer2.h" +#include "AVR/AvrUart.h" +#include "Drivers/NetString.h" + + +NetString::NetString(IUart *_Uart) + : m_Uart(_Uart) + , m_TxFrameSize(0) + , m_CurrentState(STATE_INIT) + , m_RxByteCount(0) + , m_TxByteCount(0) + , m_CharTickCount(3) + , m_CharTimeout(0) + , m_RxLength(0) +{ + init(); +} + +void +NetString::init() +{ + uint8_t i = 0; + // Copy buffer + for ( ; i < BUFFER_SIZE ; i++) + { + m_RxBuffer[i] = 0; + m_TxBuffer[i] = 0; + } + setMode(MODE_RX); + m_Uart->enableReceive(false); + m_Uart->enableReceive(true); +} +/** + * @return a pointer to the received message + * if no message is available, return NULL. + */ +void +NetString::setTxMsg(const uint8_t *_src,uint8_t _length) +{ + // guard, dont overwrite + if ( (_length < BUFFER_SIZE ) + && ( m_TxFrameSize == 0) + ) + { + uint8_t i = 0; + // Copy buffer + for ( ; i < _length ; i++) + { + m_TxBuffer[i] = _src[i]; + } + m_TxFrameSize = _length; + + m_TxByteCount = 0; + } +} + + +const uint8_t +NetString::getRxSize() const +{ + return m_RxLength; +} +/** + * @brief be sure that the state machine is in state + * IDle or else the upper layer will not be + * able to send data. + */ +const uint8_t * +NetString::receiveMsg() +{ + // Only return the the buffer if the message is complete eg CRLF + if (( m_RxLength > 0 ) + ) + { + m_RxLength = 0; + m_RxByteCount = 0; + return &m_RxBuffer[0]; + } else + { + return 0; + } +} + +/** + * \brief transmit message stored in m_RxBuffer. + * The message must previously be set by + * setTxMsg() + */ +void +NetString::transmitMsg() +{ + if (m_TxFrameSize > 0) + { + updateState(EVT_TRANSMIT); + } +} +/** + * @brief called by scheduler I think. + */ + +void +NetString::tick() +{ + // Is a character ready ? + m_CharReceived = m_Uart->receive_ready(); + if (m_CharReceived == true) + { + if (m_RxByteCount < BUFFER_SIZE) + { + m_RxBuffer[m_RxByteCount] = m_Uart->receive(); + m_RxByteCount++; + } else + { + m_RxByteCount = 0; + } + } + if ( m_CharTimeout != 0) + { + m_CharTimeout--; + } + updateState(EVT_TICK); +} + +/* State Machine actions */ +NetString::State_t +NetString::doEntry(const Event_t _Event) +{ + State_t newState = STATE_INIT; + return newState; +} + +NetString::State_t +NetString::doInit(const Event_t _Event) +{ + State_t newState = STATE_INIT; + + if (_Event == EVT_TICK) + { + if (! m_CharReceived) + { + newState = STATE_IDLE; + } + } + return newState; +} + +NetString::State_t +NetString::doIDle(const Event_t _Event) +{ + State_t newState = STATE_IDLE; + if (_Event == EVT_TRANSMIT) + { + setMode(MODE_TX); + newState = STATE_SEND; + + } else if (_Event == EVT_TICK) + { + if (m_CharReceived ) + { + startCharTimer(); + newState = STATE_RECEIVE; + } + } + return newState; +} + +NetString::State_t +NetString::doSend(const Event_t _Event) +{ + State_t newState = STATE_SEND; + if (_Event == EVT_TICK) + { + if (m_Uart->transmit_ready()) + { + if (m_TxByteCount < m_TxFrameSize) + { + m_Uart->transmit(m_TxBuffer[m_TxByteCount]); + m_TxByteCount ++; + } else + { + m_TxFrameSize = 0; + m_TxByteCount = 0; + newState = STATE_IDLE; + setMode(MODE_RX); + } + + } else + { + } + } + return newState; +} + +NetString::State_t +NetString::doReceive(const Event_t _Event) +{ + State_t newState = STATE_RECEIVE; + if (_Event == EVT_TICK) + { + // Check If char Received + if (!m_CharReceived) + { + if (charTimeout()) + { + newState = STATE_CONTROL; + } + } + else + { // char received, reset timer + startCharTimer(); + } + } else + { + } + return newState; +} + +NetString::State_t +NetString::doControl(const Event_t _Event) +{ + State_t newState = STATE_CONTROL; + if (_Event == EVT_TICK) + { + // Check If char Received + if ( ! m_CharReceived) + { // Ok, no more char + if ( + (m_RxBuffer[m_RxByteCount - 1] == 0x0A) + || (m_RxBuffer[m_RxByteCount - 1] == 0x0D) + ) + { + m_RxLength = m_RxByteCount; + } + newState = STATE_IDLE; + } else + { // Ok, that's an error. + if ( + (m_RxBuffer[m_RxByteCount - 1] == 0x0A) + || (m_RxBuffer[m_RxByteCount - 1] == 0x0D) + ) + { + m_RxLength = m_RxByteCount; + newState = STATE_IDLE; + } else + { + startCharTimer(); + newState = STATE_RECEIVE; + } + } + } else + { + } + return newState; +} + +void +NetString::updateState(const Event_t _evt) +{ + State_t oldState = m_CurrentState; + // Does work on AVR!? + static const NetString::pFunction_t laction[5] = { + &NetString::doInit + ,&NetString::doIDle + ,&NetString::doSend + ,&NetString::doReceive + ,&NetString::doControl + }; + + m_CurrentState = (this->*(laction[m_CurrentState]))(_evt); + if (oldState != m_CurrentState) + { + // Run entry action .... + (this->*(laction[m_CurrentState]))(EVT_ENTRY); + } +} + +// Timing control + +bool +NetString::charTimeout() const +{ + + return m_CharTimeout == 0; +} +// +void +NetString::startCharTimer() +{ + m_CharTimeout = m_CharTickCount; +} + +void +NetString::setMode(const Mode_t _mode) +{ + if (_mode == MODE_TX) + { + m_Uart->enableReceive(false); + m_Uart->enableTransmit(true); + } + else + { // Ok, it's RX mode + m_Uart->enableTransmit(false); + m_Uart->enableReceive(true); + } +} diff --git a/HAL/Drivers/NetString.h b/HAL/Drivers/NetString.h new file mode 100644 index 0000000..abf3c41 --- /dev/null +++ b/HAL/Drivers/NetString.h @@ -0,0 +1,88 @@ +#ifndef __NETSTRING_H__ +#define __NETSTRING_H__ + +const uint8_t BUFFER_SIZE = 64; + +/** + * \brief this class is responsible to arbitrat + * between send and receive request. A state + * machine controls the behavior. + * On reception of a character, we start a timer + * to limit the receive time. CR return shall + * be sent before time out + * + */ +class NetString : public IProtocolLayer2 +{ + enum State_t { + STATE_INIT = 0 + , STATE_IDLE = 1 + , STATE_SEND = 2 + , STATE_RECEIVE = 3 + , STATE_CONTROL = 4 + }; + enum Event_t { EVT_NONE,EVT_TICK,EVT_TRANSMIT,EVT_ENTRY}; + + enum Mode_t { MODE_RX, MODE_TX}; + + typedef State_t (NetString::*pFunction_t)(const Event_t); + public: + NetString(IUart *_uart); + + virtual void init(); + + virtual const uint8_t getRxSize() const; + /** + * @return a pointer to the received message + * if no message is available, return NULL. + */ + virtual const uint8_t *receiveMsg(); + + virtual void setTxMsg(const uint8_t *_src,uint8_t _length); + /** + * \bried transmit message stored in m_Buffer. + * The message must previously be set by + * setTxMsg() + */ + virtual void transmitMsg(); + /** + * @brief called by scheduler I think. + */ + virtual void tick(); + + private: + /* State Machine actions */ + State_t doEntry(const Event_t _Event); + State_t doInit(const Event_t _Event); + State_t doIDle(const Event_t _Event); + State_t doSend(const Event_t _Event); + State_t doReceive(const Event_t _Event); + State_t doControl(const Event_t _Event); + + void updateState(const Event_t _Event); + // Timing control + /// + void startCharTimer(); + /// + bool charTimeout() const; + /// + void setMode(const Mode_t _mode); + private: + IUart *m_Uart; + uint8_t m_RxBuffer[BUFFER_SIZE]; + uint8_t m_TxBuffer[BUFFER_SIZE]; + uint8_t m_TxFrameSize; + State_t m_CurrentState; + bool m_CharReceived; + uint8_t m_RxByteCount; + uint8_t m_TxByteCount; + /// Number of ticks for char input timeout + uint8_t m_CharTickCount; + /// If zero reached timeout for char input. + /// State machine goes back to state Idle + uint8_t m_CharTimeout; + /// Set to RxByteCount once check complete + uint8_t m_RxLength; +}; + +#endif diff --git a/HAL/Drivers/Rs485.h b/HAL/Drivers/Rs485.h new file mode 100644 index 0000000..d6931a9 --- /dev/null +++ b/HAL/Drivers/Rs485.h @@ -0,0 +1,33 @@ +#ifndef __RS485_H__ +#define __RS485_H__ + +/** + * @brief Layer 2 protocol stack, + * Maybe I should inherit from a so called + * layer 2 interface that only exports + * methods required by layer 3. + * + */ +class Rs485 : public IProtocolLayer2 +{ + public: + Rs485(IUart &_itsUart); + + /** + * @return a pointer to the received message + * if no message is available, return NULL. + */ + virtual const uint8_t *receiveMsg(); + /** + * + */ + virtual void transmitMsg(); + /** + * @brief called by scheduler I think. + */ + void tick(); + private: + IUart &m_Uart; +}; + +#endif diff --git a/HAL/Drivers/XPT2046_Touchscreen.cpp b/HAL/Drivers/XPT2046_Touchscreen.cpp new file mode 100644 index 0000000..ddce05a --- /dev/null +++ b/HAL/Drivers/XPT2046_Touchscreen.cpp @@ -0,0 +1,149 @@ + + +#include +#include +#include + +#define Z_THRESHOLD 400 +#define MSEC_THRESHOLD 3 +//#define SPI_SETTING SPISettings(2000000,MSBFIRST,SPI_MODE0) +#define SPI_SETTING SPISettings(1000000,MSBFIRST,SPI_MODE0) + +#define CS_HIGH() (PORTC |= _BV(m_CsPin)) +#define CS_LOW() (PORTC &= ~_BV(m_CsPin)) + +XPT2046Touchscreen::XPT2046Touchscreen(ISpi *_spi,uint8_t _cspin) + : m_Spi(_spi), m_x(0),m_y(0),m_z(0),m_CsPin(_cspin) +{ + PORTC |= _BV(_cspin); + DDRC |= _BV(_cspin); +} + + +bool +XPT2046Touchscreen::isTouched() +{ + update(); + return (m_z >= Z_THRESHOLD); +} + + +TSPoint +XPT2046Touchscreen::getPoint() +{ + update(); + return TSPoint(m_x,m_y,m_z); +} + + +void +XPT2046Touchscreen::setRotation(uint8_t _r) +{ + m_Rotation = _r; +} + +/** + * Try to find out what this does + */ +static int16_t besttwoavg( int16_t x , int16_t y , int16_t z ) +{ + int16_t da, db, dc; + int16_t reta = 0; + + if ( x > y ) da = x - y; else da = y - x; + if ( x > z ) db = x - z; else db = z - x; + if ( z > y ) dc = z - y; else dc = y - z; + + if ( da <= db && da <= dc ) reta = (x + y) >> 1; + else if ( db <= da && db <= dc ) reta = (x + z) >> 1; + else reta = (y + z) >> 1; // else if ( dc <= da && dc <= db ) reta = (x + y) >> 1; + + return (reta); +} + +void +XPT2046Touchscreen::update() +{ + int16_t data[6],z1,z2,z,dummy; + uint8_t result8; + /* Verify last update. In ms */ + uint32_t now = 1 ; //millis(); + //if ( (now - m_ms) < MSEC_THRESHOLD) return; + + /**/ + if (m_Spi) + { + m_Spi->begin(SPI_SETTING); + // low csPin + CS_LOW(); + // Read Z1 + m_Spi->transceive(static_cast(0xB1),(uint8_t *)&result8); + + m_Spi->transceive(static_cast(0xC100),(uint16_t *)&z1); + z1>>=3; + z = z1 + 4095; + + m_Spi->transceive(static_cast(0x9100),(uint16_t *)&z2); + z2>>=3; + z -= z2; + + if (z >= Z_THRESHOLD) + { + // Dummy read + m_Spi->transceive(static_cast(0x9100),(uint16_t *)&dummy); + // Read Y + m_Spi->transceive(static_cast(0xD100),(uint16_t *)&data[0]); data[0]>>=3; + // Read X + m_Spi->transceive(static_cast(0x9100),(uint16_t *)&data[1]); data[1]>>=3; + // Read Y + m_Spi->transceive(static_cast(0xD100),(uint16_t *)&data[2]); data[2]>>=3; + // Read X + m_Spi->transceive(static_cast(0x9100),(uint16_t *)&data[3]); data[3]>>=3; + } else + { + for (uint8_t i = 0 ; i < 4 ; ++i) data[i] = 0; + } + + m_Spi->transceive(static_cast(0xD000),(uint16_t *)&data[4]); data[4]>>=3; + m_Spi->transceive(static_cast(0x0000),(uint16_t *)(&data[5])); data[5]>>=3; + // Ok, low cs + CS_HIGH(); + m_Spi->end(); + } else + return ; // No SPI do nothing + + if (z < 0) z = 0; // No negatif value for z + + if ( z < Z_THRESHOLD) // isTouched + { + m_z = 0; + return ; + } + // Ok, touched update raw values + m_z = z; + + int16_t x = besttwoavg( data[0], data[2], data[4] ); + int16_t y = besttwoavg( data[1], data[3], data[5] ); + + m_ms = now; + switch (m_Rotation) + { + case 0: + m_x = 4095 -y; + m_y = x; + break; + case 1: + m_x = x; + m_y = y; + break; + case 2: + m_x = 4095 -y; + m_y = x; + break; + default: + m_x = 4095 - x; + m_y = 4095 - y; + break; + } +} + diff --git a/HAL/Drivers/XPT2046_Touchscreen.h b/HAL/Drivers/XPT2046_Touchscreen.h new file mode 100644 index 0000000..23a5ee5 --- /dev/null +++ b/HAL/Drivers/XPT2046_Touchscreen.h @@ -0,0 +1,39 @@ +#ifndef __XPT2046_TOUCHSCREEN__ +#define __XPT2046_TOUCHSCREEN__ + +class TSPoint { + public: + TSPoint(void) : x(0), y(0), z(0) {} + TSPoint(int16_t x, int16_t y, int16_t z) : x(x), y(y), z(z) {} + bool operator==(TSPoint p) { return ((p.x == x) && (p.y == y) && (p.z == z)); } + bool operator!=(TSPoint p) { return ((p.x != x) || (p.y != y) || (p.z != z)); } + int16_t x, y, z; +}; + +/** + * XPT2046 Touch screen implementation. + * + */ +class XPT2046Touchscreen +{ + public: + XPT2046Touchscreen(ISpi *_spi,const uint8_t _cspin); + + bool isTouched(); + + TSPoint getPoint(); + + void setRotation(const uint8_t _r); + + void tick(); + private: + void update(); + private: + ISpi *m_Spi; + int16_t m_x,m_y,m_z; + uint32_t m_ms; + uint8_t m_Rotation; + uint8_t m_CsPin; + uint32_t m_Ticks; +}; +#endif diff --git a/HAL/Drivers/glcdfont.c b/HAL/Drivers/glcdfont.c new file mode 100644 index 0000000..ae45aa6 --- /dev/null +++ b/HAL/Drivers/glcdfont.c @@ -0,0 +1,263 @@ +#ifndef FONT5X7_H +#define FONT5X7_H + +// Standard ASCII 5x7 font + +const unsigned char glcdfont[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x21, 0x54, 0x54, 0x78, 0x41, + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0xF0, 0x29, 0x24, 0x29, 0xF0, + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x32, 0x48, 0x48, 0x48, 0x32, + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x39, 0x44, 0x44, 0x44, 0x39, + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0xAA, 0x00, 0x55, 0x00, 0xAA, + 0xAA, 0x55, 0xAA, 0x55, 0xAA, + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0x7C, 0x2A, 0x2A, 0x3E, 0x14, + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#endif // FONT5X7_H \ No newline at end of file diff --git a/Metadata/CMakeLists.txt b/Metadata/CMakeLists.txt new file mode 100644 index 0000000..37acbe5 --- /dev/null +++ b/Metadata/CMakeLists.txt @@ -0,0 +1,18 @@ +##################################################################### +# simple AVR library +##################################################################### +add_avr_library( + avrPowerswitchParameters + PowerswitchParameterTable.cpp + ) + +add_avr_library( + avrDCMotorParameters + DCMotorParameterTable.cpp + ) + +add_avr_library( + avrShutterCtrlParameters + ShutterCtrlParameterTable.cpp + ) + diff --git a/Metadata/DCMotorParamIds.h b/Metadata/DCMotorParamIds.h new file mode 100644 index 0000000..08dd5a1 --- /dev/null +++ b/Metadata/DCMotorParamIds.h @@ -0,0 +1,30 @@ +#ifndef __DCMOTORPARAMIDS_H__ +#define __DCMOTORPARAMIDS_H__ + + +/** + * Maybe put this in an include file + * DCMotorParamIds.h + */ +enum ParameterIds { + PID_MotorState = 0 /* State on or off */ + , PID_MotorMode = 1 /* DC Open loop,DC Closed loop, Stepper, brushless */ + , PID_MotorPwm = 2 /* Used In case of open loop 10 - 90 % */ + , PID_MotorRpm = 3 /* Used In case of closed loop uint16 I think */ + , PID_MotorDir = 4 /* 0 or 1 */ + , PID_MotorBPwm = 5 + , PID_MotorBDir = 6 + , PID_LedCycle = 7 /* Ye Blinking led cycle. 0 is off */ + , PID_LedState = 8 /* Set let state ... */ + , PID_CPR = 9 /* Cycle Per rotation used in closed loop */ + , PID_Kp = 10 /* Set PID constant factor */ + , PID_Ki = 11 /* Set PID integral factor */ + , PID_Kd = 12 /* Set PID derivation factor */ + , PID_MAConsPwm = 13 /* Pwm modulation instruction, Applied in open loop, ignore in closed loop */ + , PID_MAConsRpm = 14 /* Rpm instruction used as reference in closed loop */ + , PID_LowLevelError1 = 15 /* Low Level Error1 up to 32 errors */ + , PID_LowLevelError2 = 16 /* Low Level Error2 up to 32 errors */ + , PID_Pot0 = 17 /* Potentiometer value of Adc 0 */ + , PID_MAX = 18 +}; +#endif diff --git a/Metadata/DCMotorParameterTable.cpp b/Metadata/DCMotorParameterTable.cpp new file mode 100644 index 0000000..59386a6 --- /dev/null +++ b/Metadata/DCMotorParameterTable.cpp @@ -0,0 +1,30 @@ +#include +#include // for itoa +#include "Metadata/Metadata.h" +#include "Platform/IParameterHandler.h" +#include "DCMotorParamIds.h" +#include "DCMotorParameterTable.h" + + +ParameterValue m_Values[PID_MAX] = +{ + {1,NULL} + ,{2,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + +}; diff --git a/Metadata/DCMotorParameterTable.h b/Metadata/DCMotorParameterTable.h new file mode 100644 index 0000000..d6788fd --- /dev/null +++ b/Metadata/DCMotorParameterTable.h @@ -0,0 +1,7 @@ +#ifndef DCMOTORPARAMETERTABLE_H__ +#define DCMOTORPARAMETERTABLE_H__ + +#include "Metadata/Metadata.h" +extern +ParameterValue m_Values[PID_MAX]; +#endif diff --git a/Metadata/Metadata.h b/Metadata/Metadata.h new file mode 100644 index 0000000..e630bec --- /dev/null +++ b/Metadata/Metadata.h @@ -0,0 +1,21 @@ +#ifndef __METADATA_H__ +#define __METADATA_H__ + +/* Forward declaration */ +class IParameterListener; + +/** + * ParameterTable Structure + */ +typedef struct _ParameterValue_t +{ + union ParameterValue + { + uint8_t m_U8; + uint16_t m_U16; + uint32_t m_U32; + Float32_t m_Float; + } u; + IParameterListener *m_Listener; +} ParameterValue; +#endif diff --git a/Metadata/PowerswitchParamIds.h b/Metadata/PowerswitchParamIds.h new file mode 100644 index 0000000..78a641f --- /dev/null +++ b/Metadata/PowerswitchParamIds.h @@ -0,0 +1,29 @@ +#ifndef __DCMOTORPARAMIDS_H__ +#define __DCMOTORPARAMIDS_H__ + + +/** + * Maybe put this in an include file + * DCMotorParamIds.h + */ +enum ParameterIds { + PID_SwitchAll = 0 /* State on or off */ + , PID_Switch1 = 1 /* On / Off Socket 1 */ + , PID_Switch2 = 2 /* On / Off Socket 2 */ + , PID_Switch3 = 3 /* On / Off Socket 3 */ + , PID_Switch4 = 4 /* On / Off Socket 4 */ + , PID_LedCycle = 5 /* Ye Blinking led cycle. 0 is off */ + , PID_LedState = 6 /* Set let state ... */ + , PID_DelayP1 = 7 + , PID_DelayP2 = 8 + , PID_DelayP3 = 9 /* Cycle Per rotation used in closed loop */ + , PID_DelayP4 = 10 /* Set PID constant factor */ + , PID_Ki = 11 /* Set PID integral factor */ + , PID_Kd = 12 /* Set PID derivation factor */ + , PID_MAConsPwm = 13 /* Pwm modulation instruction, Applied in open loop, ignore in closed loop */ + , PID_MAConsRpm = 14 /* Rpm instruction used as reference in closed loop */ + , PID_LowLevelError1 = 15 /* Low Level Error1 up to 32 errors */ + , PID_LowLevelError2 = 16 /* Low Level Error2 up to 32 errors */ + , PID_MAX = 17 +}; +#endif diff --git a/Metadata/PowerswitchParameterTable.cpp b/Metadata/PowerswitchParameterTable.cpp new file mode 100644 index 0000000..46f94c8 --- /dev/null +++ b/Metadata/PowerswitchParameterTable.cpp @@ -0,0 +1,30 @@ +#include +#include // for itoa +#include "Metadata/Metadata.h" +#include "Platform/IParameterHandler.h" +#include "DCMotorParamIds.h" +#include "DCMotorParameterTable.h" + + +ParameterValue m_Values[PID_MAX] = +{ + {0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + +}; diff --git a/Metadata/PowerswitchParameterTable.h b/Metadata/PowerswitchParameterTable.h new file mode 100644 index 0000000..45a52d0 --- /dev/null +++ b/Metadata/PowerswitchParameterTable.h @@ -0,0 +1,7 @@ +#ifndef POWERSWITCHPARAMETERTABLE_H__ +#define POWERSWITCHPARAMETERTABLE_H__ + +#include "Metadata/Metadata.h" +extern +ParameterValue m_Values[PID_MAX]; +#endif diff --git a/Metadata/ShutterCtrlParamIds.h b/Metadata/ShutterCtrlParamIds.h new file mode 100644 index 0000000..84a9c7d --- /dev/null +++ b/Metadata/ShutterCtrlParamIds.h @@ -0,0 +1,29 @@ +#ifndef __DCMOTORPARAMIDS_H__ +#define __DCMOTORPARAMIDS_H__ + + +/** + * Maybe put this in an include file + * DCMotorParamIds.h + */ +enum ParameterIds { + PID_SwitchAll = 0 /* State on or off */ + , PID_Shutter1 = 1 /* On / Off Socket 1 */ + , PID_Shutter2 = 2 /* On / Off Socket 2 */ + , PID_Shutter3 = 3 /* On / Off Socket 3 */ + , PID_Shutter4 = 4 /* On / Off Socket 4 */ + , PID_LedCycle = 5 /* Ye Blinking led cycle. 0 is off */ + , PID_LedState = 6 /* Set let state ... */ + , PID_DelayP1 = 7 + , PID_DelayP2 = 8 + , PID_DelayP3 = 9 /* Cycle Per rotation used in closed loop */ + , PID_DelayP4 = 10 /* Set PID constant factor */ + , PID_Px = 11 /* Set PID integral factor */ + , PID_Py = 12 /* Set PID derivation factor */ + , PID_Pz = 13 /* Pwm modulation instruction, Applied in open loop, ignore in closed loop */ + , PID_MAConsRpm = 14 /* Rpm instruction used as reference in closed loop */ + , PID_LowLevelError1 = 15 /* Low Level Error1 up to 32 errors */ + , PID_LowLevelError2 = 16 /* Low Level Error2 up to 32 errors */ + , PID_MAX = 17 +}; +#endif diff --git a/Metadata/ShutterCtrlParameterTable.cpp b/Metadata/ShutterCtrlParameterTable.cpp new file mode 100644 index 0000000..46f94c8 --- /dev/null +++ b/Metadata/ShutterCtrlParameterTable.cpp @@ -0,0 +1,30 @@ +#include +#include // for itoa +#include "Metadata/Metadata.h" +#include "Platform/IParameterHandler.h" +#include "DCMotorParamIds.h" +#include "DCMotorParameterTable.h" + + +ParameterValue m_Values[PID_MAX] = +{ + {0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + ,{0,NULL} + +}; diff --git a/Metadata/ShutterCtrlParameterTable.h b/Metadata/ShutterCtrlParameterTable.h new file mode 100644 index 0000000..45a52d0 --- /dev/null +++ b/Metadata/ShutterCtrlParameterTable.h @@ -0,0 +1,7 @@ +#ifndef POWERSWITCHPARAMETERTABLE_H__ +#define POWERSWITCHPARAMETERTABLE_H__ + +#include "Metadata/Metadata.h" +extern +ParameterValue m_Values[PID_MAX]; +#endif diff --git a/Platform/CMakeLists.txt b/Platform/CMakeLists.txt new file mode 100644 index 0000000..244b2d2 --- /dev/null +++ b/Platform/CMakeLists.txt @@ -0,0 +1,21 @@ +##################################################################### +# simple AVR library +##################################################################### +add_avr_library( + avrPtf + DCMotorParameterHandler.cpp + PersistentStorage.cpp + ) + +add_avr_library( + avrPS-Ptf + PowerswitchParameterHandler.cpp + PersistentStorage.cpp + ) + +add_avr_library( + avrSC-Ptf + ShutterCtrlParameterHandler.cpp + PersistentStorage.cpp + ) + diff --git a/Platform/DCMotorParameterHandler.cpp b/Platform/DCMotorParameterHandler.cpp new file mode 100644 index 0000000..d7e4f5f --- /dev/null +++ b/Platform/DCMotorParameterHandler.cpp @@ -0,0 +1,96 @@ +#include + +#include +#include +#include +#include + +#if 0 +DCMotorParameterHandler::ParameterValue +DCMotorParameterHandler::m_Values[PID_MAX] = { 0 }; +#endif +DCMotorParameterHandler::DCMotorParameterHandler() +{ + +} +/// +void +DCMotorParameterHandler::readValue(const uint8_t paramID,uint8_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U8; + } +} + +/// +void +DCMotorParameterHandler::writeValue(const uint8_t paramID,const uint8_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U8 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,_val); + } + } +} + +/// Handle UInt16_t +void +DCMotorParameterHandler::readValue(const uint8_t paramID,uint16_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U16; + } +} + +/// +void +DCMotorParameterHandler::writeValue(const uint8_t paramID,const uint16_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U16 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_U8); + } + } +} + +/// Handle Float32_t +void +DCMotorParameterHandler::readValue(const uint8_t paramID,Float32_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_Float; + } +} + +/// +void +DCMotorParameterHandler::writeValue(const uint8_t paramID,const Float32_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_Float = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_Float); + } + } +} + +void +DCMotorParameterHandler::registerListener(const uint8_t paramID,IParameterListener *_val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].m_Listener = _val; + } + +} diff --git a/Platform/DCMotorParameterHandler.h b/Platform/DCMotorParameterHandler.h new file mode 100644 index 0000000..42a80d4 --- /dev/null +++ b/Platform/DCMotorParameterHandler.h @@ -0,0 +1,47 @@ +#ifndef __DCMOTOR_PARAMETERHANDLER_H__ +#define __DCMOTOR_PARAMETERHANDLER_H__ + + +/** + * @brief storage class + * + */ +class DCMotorParameterHandler : public IParameterHandler +{ +#if 0 + typedef struct _ParameterValue_t + { + union ParameterValue + { + uint8_t m_U8; + uint16_t m_U16; + uint32_t m_U32; + Float32_t m_Float; + } u; + IParameterListener *m_Listener; + } ParameterValue; +#endif + public: + DCMotorParameterHandler(); + /// + virtual void readValue(const uint8_t paramID,uint8_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint8_t _val); + /// + virtual void readValue(const uint8_t paramID,uint16_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint16_t _val); + + /// + virtual void readValue(const uint8_t paramID,Float32_t &_val) ; + /// + virtual void writeValue(const uint8_t paramID,const Float32_t _val) ; + /// + /// + virtual void registerListener(const uint8_t paramID,IParameterListener *_val); + + + private: +}; + +#endif diff --git a/Platform/ErrorHandler.h b/Platform/ErrorHandler.h new file mode 100644 index 0000000..ff03c17 --- /dev/null +++ b/Platform/ErrorHandler.h @@ -0,0 +1,21 @@ +#ifndef __ERROR_HANDLER_H__ +#define __ERROR_HANDLER_H__ + +/** + * \brief good, lets implement basic error handler + * that reports the error through the serial communication + * May be I have to got through the communication handler + * + * + */ +class ErrorHandler : public IErrorHandler , public ITask +{ + public: + ErrorHandler(); + /// Method available to modules so that errors can be reported + virtual void setError(Uint16_t _error); + /// Alright process some stuff in case an errors has been raised + virtual void run(); +}; + +#endif diff --git a/Platform/Errors.h b/Platform/Errors.h new file mode 100644 index 0000000..c457426 --- /dev/null +++ b/Platform/Errors.h @@ -0,0 +1,12 @@ +#ifndef __ERRORS_H__ +#define __ERRORS_H__ + +enum ErrorIds_t { + ERROR_Application_Starting = 0 + ,ERROR_Eeprom_Read_Invalid_Length = 1 + ,ERROR_Eeprom_Read_Invalid_Address = 2 + ,ERROR_Eeprom_Write_Invalid_Length = 3 + ,ERROR_Eeprom_Write_Invalid_Address = 4 + ,ERROR_MAX = 5 +}; +#endif diff --git a/Platform/IErrorHandler.h b/Platform/IErrorHandler.h new file mode 100644 index 0000000..6f7c9b0 --- /dev/null +++ b/Platform/IErrorHandler.h @@ -0,0 +1,16 @@ +#ifndef __IERROR_HANDLER_H__ +#define __IERROR_HANDLER_H__ + +/** + * \brief well, except setting an error, there is not mutch to be + * done there. The handler might eventually trigger the communication + * handler to report the error or what ever. + */ +class IErrorHandler +{ + public: + IErrorHandler() {}; + /// + virtual setError(Uint16_t error_id) = 0 ; +}; +#endif diff --git a/Platform/IParameterHandler.h b/Platform/IParameterHandler.h new file mode 100644 index 0000000..af19049 --- /dev/null +++ b/Platform/IParameterHandler.h @@ -0,0 +1,50 @@ +#ifndef __IPARAMETER_HANDLER_H__ +#define __IPARAMETER_HANDLER_H__ + +/** + * \brief interface to be implemented by + * objects that need to be informed that a parameter + * value has changed or that a command needs to be + * executed + */ +class IParameterListener +{ + public: + IParameterListener() {}; + + virtual void onWriteValue(const uint8_t paramID,const uint8_t _val) = 0; + + virtual void onWriteValue(const uint8_t paramID,const Float32_t _val) = 0; +}; + +/** + * \brief Parameter Handling interface. Offer a unique space for + * dynamic storage. + * + */ +class IParameterHandler +{ + public: + enum eParameterType { + TYPE_U8 = 0 + , TYPE_U16 = 1 + , TYPE_FLOAT = 2 + }; + public: + IParameterHandler() {}; + + virtual void readValue(const uint8_t paramID,uint8_t &_val) = 0; + /// + virtual void writeValue(const uint8_t paramID,const uint8_t _val) = 0; + /// + virtual void readValue(const uint8_t paramID,uint16_t &_val) = 0; + /// + virtual void writeValue(const uint8_t paramID,const uint16_t _val) = 0; + /// + virtual void readValue(const uint8_t paramID,Float32_t &_val) = 0; + /// + virtual void writeValue(const uint8_t paramID,const Float32_t _val) = 0; + /// + virtual void registerListener(const uint8_t paramID,IParameterListener *_val) = 0; +}; +#endif diff --git a/Platform/PersistentStorage.cpp b/Platform/PersistentStorage.cpp new file mode 100644 index 0000000..526ba3a --- /dev/null +++ b/Platform/PersistentStorage.cpp @@ -0,0 +1,60 @@ +#include + +#include +#include +#include +#include + +PersistentStorage::PersistentStorage(IEeprom *_eeprom,IParameterHandler *_params) + : m_Eeprom(_eeprom),m_ParameterHandler(_params) , m_State(PS_Idle),m_CurrentParamId(0) +{ +} + +void +PersistentStorage::run() +{ + switch (m_State) + { + case PS_Idle: + doIdle(); + break; + case PS_Init: + doInit(); + break; + case PS_Saving: + doSave(); + break; + case PS_Reading: + doRead(); + break; + case PS_Done: + doDone(); + break; + default: + ; + } +} + +void +PersistentStorage::doSave() +{ +} + +void +PersistentStorage::doRead() +{ +} + +void +PersistentStorage::doInit() +{ +} + +void +PersistentStorage::doIdle() +{ +} +void +PersistentStorage::doDone() +{ +} diff --git a/Platform/PersistentStorage.h b/Platform/PersistentStorage.h new file mode 100644 index 0000000..50d4eb6 --- /dev/null +++ b/Platform/PersistentStorage.h @@ -0,0 +1,38 @@ +#ifndef __PERSISTENT_STORAGE_H__ +#define __PERSISTENT_STORAGE_H__ + +/** + * \brief This class is responsible to store + * parameters into eeprom. Parameters flaged as modified + * will be stored. + * + */ +class PersistentStorage : public virtual ITask +{ + enum eState {PS_Idle, PS_Init,PS_Saving, PS_Reading,PS_Done }; + public: + /** + * Well, need the EEProm Interface and the ParameterHandler + */ + PersistentStorage(IEeprom *_eeprom,IParameterHandler *_params); + + virtual void run(); + private: + /// Methods that will perform the work + void doSave(); + /// Read parameters from Eeprom + void doRead(); + /// Start Reading of Saving process + void doInit(); + /// Check if save or read command is activated + void doIdle(); + /// Command completed + void doDone(); + private: + /// Private Attributes + IEeprom *m_Eeprom; + IParameterHandler *m_ParameterHandler; + eState m_State; + Uint8_t m_CurrentParamId; +}; +#endif diff --git a/Platform/PowerswitchParameterHandler.cpp b/Platform/PowerswitchParameterHandler.cpp new file mode 100644 index 0000000..7797a0c --- /dev/null +++ b/Platform/PowerswitchParameterHandler.cpp @@ -0,0 +1,92 @@ +#include + +#include +#include +#include +#include + +PowerswitchParameterHandler::PowerswitchParameterHandler() +{ + +} +/// +void +PowerswitchParameterHandler::readValue(const uint8_t paramID,uint8_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U8; + } +} + +/// +void +PowerswitchParameterHandler::writeValue(const uint8_t paramID,const uint8_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U8 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,_val); + } + } +} + +/// Handle UInt16_t +void +PowerswitchParameterHandler::readValue(const uint8_t paramID,uint16_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U16; + } +} + +/// +void +PowerswitchParameterHandler::writeValue(const uint8_t paramID,const uint16_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U16 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_U8); + } + } +} + +/// Handle Float32_t +void +PowerswitchParameterHandler::readValue(const uint8_t paramID,Float32_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_Float; + } +} + +/// +void +PowerswitchParameterHandler::writeValue(const uint8_t paramID,const Float32_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_Float = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_Float); + } + } +} + +void +PowerswitchParameterHandler::registerListener(const uint8_t paramID,IParameterListener *_val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].m_Listener = _val; + } + +} diff --git a/Platform/PowerswitchParameterHandler.h b/Platform/PowerswitchParameterHandler.h new file mode 100644 index 0000000..13f48e8 --- /dev/null +++ b/Platform/PowerswitchParameterHandler.h @@ -0,0 +1,34 @@ +#ifndef __DCMOTOR_PARAMETERHANDLER_H__ +#define __DCMOTOR_PARAMETERHANDLER_H__ + + +/** + * @brief storage class + * + */ +class PowerswitchParameterHandler : public IParameterHandler +{ + public: + PowerswitchParameterHandler(); + /// + virtual void readValue(const uint8_t paramID,uint8_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint8_t _val); + /// + virtual void readValue(const uint8_t paramID,uint16_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint16_t _val); + + /// + virtual void readValue(const uint8_t paramID,Float32_t &_val) ; + /// + virtual void writeValue(const uint8_t paramID,const Float32_t _val) ; + /// + /// + virtual void registerListener(const uint8_t paramID,IParameterListener *_val); + + + private: +}; + +#endif diff --git a/Platform/ShutterCtrlParameterHandler.cpp b/Platform/ShutterCtrlParameterHandler.cpp new file mode 100644 index 0000000..1d2d863 --- /dev/null +++ b/Platform/ShutterCtrlParameterHandler.cpp @@ -0,0 +1,92 @@ +#include + +#include +#include +#include +#include + +ShutterCtrlParameterHandler::ShutterCtrlParameterHandler() +{ + +} +/// +void +ShutterCtrlParameterHandler::readValue(const uint8_t paramID,uint8_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U8; + } +} + +/// +void +ShutterCtrlParameterHandler::writeValue(const uint8_t paramID,const uint8_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U8 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,_val); + } + } +} + +/// Handle UInt16_t +void +ShutterCtrlParameterHandler::readValue(const uint8_t paramID,uint16_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_U16; + } +} + +/// +void +ShutterCtrlParameterHandler::writeValue(const uint8_t paramID,const uint16_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_U16 = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_U8); + } + } +} + +/// Handle Float32_t +void +ShutterCtrlParameterHandler::readValue(const uint8_t paramID,Float32_t &_val) +{ + if (paramID < PID_MAX) + { + _val = m_Values[paramID].u.m_Float; + } +} + +/// +void +ShutterCtrlParameterHandler::writeValue(const uint8_t paramID,const Float32_t _val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].u.m_Float = _val; + if (m_Values[paramID].m_Listener != 0 ) + { + m_Values[paramID].m_Listener->onWriteValue(paramID,m_Values[paramID].u.m_Float); + } + } +} + +void +ShutterCtrlParameterHandler::registerListener(const uint8_t paramID,IParameterListener *_val) +{ + if (paramID < PID_MAX) + { + m_Values[paramID].m_Listener = _val; + } + +} diff --git a/Platform/ShutterCtrlParameterHandler.h b/Platform/ShutterCtrlParameterHandler.h new file mode 100644 index 0000000..d448d6e --- /dev/null +++ b/Platform/ShutterCtrlParameterHandler.h @@ -0,0 +1,34 @@ +#ifndef __DCMOTOR_PARAMETERHANDLER_H__ +#define __DCMOTOR_PARAMETERHANDLER_H__ + + +/** + * @brief storage class + * + */ +class ShutterCtrlParameterHandler : public IParameterHandler +{ + public: + ShutterCtrlParameterHandler(); + /// + virtual void readValue(const uint8_t paramID,uint8_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint8_t _val); + /// + virtual void readValue(const uint8_t paramID,uint16_t &_val); + /// + virtual void writeValue(const uint8_t paramID,const uint16_t _val); + + /// + virtual void readValue(const uint8_t paramID,Float32_t &_val) ; + /// + virtual void writeValue(const uint8_t paramID,const Float32_t _val) ; + /// + /// + virtual void registerListener(const uint8_t paramID,IParameterListener *_val); + + + private: +}; + +#endif diff --git a/README b/README new file mode 100644 index 0000000..d34ea4c --- /dev/null +++ b/README @@ -0,0 +1,12 @@ +Packages to install on linux +---------------------------- +sudo apt-get install gcc-avr avr-libc avrdude + +Create Build environment: +------------------------ +Create a Build dir and launch the command below: + +cmake -DCMAKE_TOOLCHAIN_FILE=/home/aebersol/Devs/avr/rules/gcc-avr-generic.cmake ../ + +Flashing instruction +-------------------- diff --git a/Utils/StdTypes.h b/Utils/StdTypes.h new file mode 100644 index 0000000..4b53b30 --- /dev/null +++ b/Utils/StdTypes.h @@ -0,0 +1,34 @@ +#ifndef __STD_TYPES_H__ +#define __STD_TYPES_H__ +#include +/** + * @ brief Abstract all native types to be + * platform / compiler type independant + * + */ + +/// +typedef void Void; + +/// +typedef bool Bool_t; + +/// +typedef uint8_t Uint8_t; + +/// +typedef uint16_t Uint16_t; + +/// +typedef uint32_t Uint32_t; + +/// +typedef int8_t Int8_t; + +/// +typedef int16_t Int16_t; + +/// +typedef double Float32_t; + +#endif diff --git a/rules/gcc-avr-common.cmake b/rules/gcc-avr-common.cmake new file mode 100644 index 0000000..fa27335 --- /dev/null +++ b/rules/gcc-avr-common.cmake @@ -0,0 +1,73 @@ + +########################################################################## +# needs to be defined for AVR toolchain +########################################################################## +#set(MCU_SPEED "4000000UL") +set(MCU_SPEED "16000000UL") + +########################################################################## +# some cmake cross-compile necessities +########################################################################## + +if(DEFINED ENV{AVR_FIND_ROOT_PATH}) + set(CMAKE_FIND_ROOT_PATH $ENV{AVR_FIND_ROOT_PATH}) +else(DEFINED ENV{AVR_FIND_ROOT_PATH}) + if(EXISTS "/opt/local/avr") + set(CMAKE_FIND_ROOT_PATH "/opt/local/avr") + elseif(EXISTS "/usr/avr") + set(CMAKE_FIND_ROOT_PATH "/usr/avr") + elseif(EXISTS "/usr/lib/avr") + set(CMAKE_FIND_ROOT_PATH "/usr/lib/avr") + elseif(EXISTS "/usr/local/CrossPack-AVR") + set(CMAKE_FIND_ROOT_PATH "/usr/local/CrossPack-AVR") + else(EXISTS "/opt/local/avr") + message(FATAL_ERROR "Please set AVR_FIND_ROOT_PATH in your environment.") + endif(EXISTS "/opt/local/avr") +endif(DEFINED ENV{AVR_FIND_ROOT_PATH}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +# not added automatically, since CMAKE_SYSTEM_NAME is "generic" +set(CMAKE_SYSTEM_INCLUDE_PATH "${CMAKE_FIND_ROOT_PATH}/include") +set(CMAKE_SYSTEM_LIBRARY_PATH "${CMAKE_FIND_ROOT_PATH}/lib") + +########################################################################## +# status messages for generating +########################################################################## +message(STATUS "Set CMAKE_FIND_ROOT_PATH to ${CMAKE_FIND_ROOT_PATH}") +message(STATUS "Set CMAKE_SYSTEM_INCLUDE_PATH to ${CMAKE_SYSTEM_INCLUDE_PATH}") +message(STATUS "Set CMAKE_SYSTEM_LIBRARY_PATH to ${CMAKE_SYSTEM_LIBRARY_PATH}") + +########################################################################## +# set compiler options for build types +########################################################################## +if(CMAKE_BUILD_TYPE MATCHES Release) + set(CMAKE_C_FLAGS_RELEASE "-Os") + set(CMAKE_CXX_FLAGS_RELEASE "-Os") +endif(CMAKE_BUILD_TYPE MATCHES Release) + +if(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-Os -save-temps -g -gdwarf-3 -gstrict-dwarf") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-Os -save-temps -g -gdwarf-3 -gstrict-dwarf") +endif(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) + +if(CMAKE_BUILD_TYPE MATCHES Debug) + set(CMAKE_C_FLAGS_DEBUG "-O0 -save-temps -g -gdwarf-3 -gstrict-dwarf") + set(CMAKE_CXX_FLAGS_DEBUG "-O0 -save-temps -g -gdwarf-3 -gstrict-dwarf") +endif(CMAKE_BUILD_TYPE MATCHES Debug) + +########################################################################## +# compiler options for all build types +########################################################################## +add_definitions("-DF_CPU=${MCU_SPEED}") +add_definitions("-fpack-struct") +add_definitions("-fshort-enums") +add_definitions("-Wall") +add_definitions("-Werror") +add_definitions("-pedantic") +add_definitions("-pedantic-errors") +add_definitions("-funsigned-char") +add_definitions("-funsigned-bitfields") +add_definitions("-ffunction-sections") +add_definitions("-c") + diff --git a/rules/gcc-avr-generic.cmake b/rules/gcc-avr-generic.cmake new file mode 100644 index 0000000..e59850a --- /dev/null +++ b/rules/gcc-avr-generic.cmake @@ -0,0 +1,404 @@ +########################################################################## +# "THE ANY BEVERAGE-WARE LICENSE" (Revision 42 - based on beer-ware +# license): +# wrote this file. As long as you retain this notice +# you can do whatever you want with this stuff. If we meet some day, and +# you think this stuff is worth it, you can buy me a be(ve)er(age) in +# return. (I don't like beer much.) +# +# Matthias Kleemann +########################################################################## + +########################################################################## +# The toolchain requires some variables set. +# +# AVR_MCU (default: atmega8) +# the type of AVR the application is built for +# AVR_L_FUSE (NO DEFAULT) +# the LOW fuse value for the MCU used +# AVR_H_FUSE (NO DEFAULT) +# the HIGH fuse value for the MCU used +# AVR_UPLOADTOOL (default: avrdude) +# the application used to upload to the MCU +# NOTE: The toolchain is currently quite specific about +# the commands used, so it needs tweaking. +# AVR_UPLOADTOOL_PORT (default: usb) +# the port used for the upload tool, e.g. usb +# AVR_PROGRAMMER (default: avrispmkII) +# the programmer hardware used, e.g. avrispmkII +########################################################################## + +########################################################################## +# options +########################################################################## +option(WITH_MCU "Add the mCU type to the target file name." ON) + +########################################################################## +# executables in use +########################################################################## +find_program(AVR_CC avr-gcc) +find_program(AVR_CXX avr-g++) +find_program(AVR_OBJCOPY avr-objcopy) +find_program(AVR_SIZE_TOOL avr-size) +find_program(AVR_OBJDUMP avr-objdump) + +########################################################################## +# toolchain starts with defining mandatory variables +########################################################################## +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR avr) +set(CMAKE_C_COMPILER ${AVR_CC}) +set(CMAKE_CXX_COMPILER ${AVR_CXX}) + +########################################################################## +# Identification +########################################################################## +set(AVR 1) + +########################################################################## +# some necessary tools and variables for AVR builds, which may not +# defined yet +# - AVR_UPLOADTOOL +# - AVR_UPLOADTOOL_PORT +# - AVR_PROGRAMMER +# - AVR_MCU +# - AVR_SIZE_ARGS +########################################################################## + +# default upload tool +if(NOT AVR_UPLOADTOOL) + set( + AVR_UPLOADTOOL avrdude + CACHE STRING "Set default upload tool: avrdude" + ) + find_program(AVR_UPLOADTOOL avrdude) +endif(NOT AVR_UPLOADTOOL) + +# default upload tool port +if(NOT AVR_UPLOADTOOL_PORT) + set( + AVR_UPLOADTOOL_PORT usb + CACHE STRING "Set default upload tool port: usb" + ) +endif(NOT AVR_UPLOADTOOL_PORT) + +# default programmer (hardware) +if(NOT AVR_PROGRAMMER) + set( + AVR_PROGRAMMER avrispmkII + CACHE STRING "Set default programmer hardware model: avrispmkII" + ) +endif(NOT AVR_PROGRAMMER) + +# default MCU (chip) +if(NOT AVR_MCU) + set( + AVR_MCU atmega8 + CACHE STRING "Set default MCU: atmega8 (see 'avr-gcc --target-help' for valid values)" + ) +endif(NOT AVR_MCU) + +#default avr-size args +if(NOT AVR_SIZE_ARGS) + if(APPLE) + set(AVR_SIZE_ARGS -B) + else(APPLE) + set(AVR_SIZE_ARGS -C;--mcu=${AVR_MCU}) + endif(APPLE) +endif(NOT AVR_SIZE_ARGS) + +# prepare base flags for upload tool +set(AVR_UPLOADTOOL_BASE_OPTIONS -p ${AVR_MCU} -c ${AVR_PROGRAMMER}) + +# use AVR_UPLOADTOOL_BAUDRATE as baudrate for upload tool (if defined) +if(AVR_UPLOADTOOL_BAUDRATE) + set(AVR_UPLOADTOOL_BASE_OPTIONS ${AVR_UPLOADTOOL_BASE_OPTIONS} -b ${AVR_UPLOADTOOL_BAUDRATE}) +endif() + +########################################################################## +# check build types: +# - Debug +# - Release +# - RelWithDebInfo +# +# Release is chosen, because of some optimized functions in the +# AVR toolchain, e.g. _delay_ms(). +########################################################################## +if(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR +(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR +(CMAKE_BUILD_TYPE MATCHES Debug) OR +(CMAKE_BUILD_TYPE MATCHES MinSizeRel))) + set( + CMAKE_BUILD_TYPE Release + CACHE STRING "Choose cmake build type: Debug Release RelWithDebInfo MinSizeRel" + FORCE + ) +endif(NOT ((CMAKE_BUILD_TYPE MATCHES Release) OR +(CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) OR +(CMAKE_BUILD_TYPE MATCHES Debug) OR +(CMAKE_BUILD_TYPE MATCHES MinSizeRel))) + + + +########################################################################## + +########################################################################## +# target file name add-on +########################################################################## +if(WITH_MCU) + set(MCU_TYPE_FOR_FILENAME "-${AVR_MCU}") +else(WITH_MCU) + set(MCU_TYPE_FOR_FILENAME "") +endif(WITH_MCU) + +########################################################################## +# add_avr_executable +# - IN_VAR: EXECUTABLE_NAME +# +# Creates targets and dependencies for AVR toolchain, building an +# executable. Calls add_executable with ELF file as target name, so +# any link dependencies need to be using that target, e.g. for +# target_link_libraries(-${AVR_MCU}.elf ...). +########################################################################## +function(add_avr_executable EXECUTABLE_NAME) + + if(NOT ARGN) + message(FATAL_ERROR "No source files given for ${EXECUTABLE_NAME}.") + endif(NOT ARGN) + + # set file names + set(elf_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.elf) + set(hex_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.hex) + set(lst_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.lst) + set(map_file ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}.map) + set(eeprom_image ${EXECUTABLE_NAME}${MCU_TYPE_FOR_FILENAME}-eeprom.hex) + + # elf file + add_executable(${elf_file} EXCLUDE_FROM_ALL ${ARGN}) + + set_target_properties( + ${elf_file} + PROPERTIES + COMPILE_FLAGS "-mmcu=${AVR_MCU}" + LINK_FLAGS "-mmcu=${AVR_MCU} -Wl,--gc-sections -mrelax -Wl,-Map,${map_file}" + ) + + add_custom_command( + OUTPUT ${hex_file} + COMMAND + ${AVR_OBJCOPY} -j .text -j .data -O ihex ${elf_file} ${hex_file} + COMMAND + ${AVR_SIZE_TOOL} ${AVR_SIZE_ARGS} ${elf_file} + DEPENDS ${elf_file} + ) + + add_custom_command( + OUTPUT ${lst_file} + COMMAND + ${AVR_OBJDUMP} -d ${elf_file} > ${lst_file} + DEPENDS ${elf_file} + ) + + # eeprom + add_custom_command( + OUTPUT ${eeprom_image} + COMMAND + ${AVR_OBJCOPY} -j .eeprom --set-section-flags=.eeprom=alloc,load + --change-section-lma .eeprom=0 --no-change-warnings + -O ihex ${elf_file} ${eeprom_image} + DEPENDS ${elf_file} + ) + + add_custom_target( + ${EXECUTABLE_NAME} + ALL + DEPENDS ${hex_file} ${lst_file} ${eeprom_image} + ) + + set_target_properties( + ${EXECUTABLE_NAME} + PROPERTIES + OUTPUT_NAME "${elf_file}" + ) + + # clean + get_directory_property(clean_files ADDITIONAL_MAKE_CLEAN_FILES) + set_directory_properties( + PROPERTIES + ADDITIONAL_MAKE_CLEAN_FILES "${map_file}" + ) + + # upload - with avrdude + add_custom_target( + upload_${EXECUTABLE_NAME} + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} ${AVR_UPLOADTOOL_OPTIONS} + -U flash:w:${hex_file} + -P ${AVR_UPLOADTOOL_PORT} + DEPENDS ${hex_file} + COMMENT "Uploading ${hex_file} to ${AVR_MCU} using ${AVR_PROGRAMMER}" + ) + + # upload eeprom only - with avrdude + # see also bug http://savannah.nongnu.org/bugs/?40142 + add_custom_target( + upload_${EXECUTABLE_NAME}_eeprom + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} ${AVR_UPLOADTOOL_OPTIONS} + -U eeprom:w:${eeprom_image} + -P ${AVR_UPLOADTOOL_PORT} + DEPENDS ${eeprom_image} + COMMENT "Uploading ${eeprom_image} to ${AVR_MCU} using ${AVR_PROGRAMMER}" + ) + + # disassemble + add_custom_target( + disassemble_${EXECUTABLE_NAME} + ${AVR_OBJDUMP} -h -S ${elf_file} > ${EXECUTABLE_NAME}.lst + DEPENDS ${elf_file} + ) +endfunction(add_avr_executable) + + +########################################################################## +# add_avr_library +# - IN_VAR: LIBRARY_NAME +# +# Calls add_library with an optionally concatenated name +# ${MCU_TYPE_FOR_FILENAME}. +# This needs to be used for linking against the library, e.g. calling +# target_link_libraries(...). +########################################################################## +function(add_avr_library LIBRARY_NAME) + if(NOT ARGN) + message(FATAL_ERROR "No source files given for ${LIBRARY_NAME}.") + endif(NOT ARGN) + + set(lib_file ${LIBRARY_NAME}${MCU_TYPE_FOR_FILENAME}) + + add_library(${lib_file} STATIC ${ARGN}) + + set_target_properties( + ${lib_file} + PROPERTIES + COMPILE_FLAGS "-mmcu=${AVR_MCU}" + OUTPUT_NAME "${lib_file}" + ) + + if(NOT TARGET ${LIBRARY_NAME}) + add_custom_target( + ${LIBRARY_NAME} + ALL + DEPENDS ${lib_file} + ) + + set_target_properties( + ${LIBRARY_NAME} + PROPERTIES + OUTPUT_NAME "${lib_file}" + ) + endif(NOT TARGET ${LIBRARY_NAME}) + +endfunction(add_avr_library) + +########################################################################## +# avr_target_link_libraries +# - IN_VAR: EXECUTABLE_TARGET +# - ARGN : targets and files to link to +# +# Calls target_link_libraries with AVR target names (concatenation, +# extensions and so on. +########################################################################## +function(avr_target_link_libraries EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "Nothing to link to ${EXECUTABLE_TARGET}.") + endif(NOT ARGN) + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + + foreach(TGT ${ARGN}) + if(TARGET ${TGT}) + get_target_property(ARG_NAME ${TGT} OUTPUT_NAME) + list(APPEND NON_TARGET_LIST ${ARG_NAME}) + else(TARGET ${TGT}) + list(APPEND NON_TARGET_LIST ${TGT}) + endif(TARGET ${TGT}) + endforeach(TGT ${ARGN}) + + target_link_libraries(${TARGET_LIST} ${NON_TARGET_LIST}) +endfunction(avr_target_link_libraries EXECUTABLE_TARGET) + +########################################################################## +# avr_target_include_directories +# +# Calls target_include_directories with AVR target names +########################################################################## + +function(avr_target_include_directories EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "No include directories to add to ${EXECUTABLE_TARGET}.") + endif() + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + set(extra_args ${ARGN}) + + target_include_directories(${TARGET_LIST} ${extra_args}) +endfunction() + +########################################################################## +# avr_target_compile_definitions +# +# Calls target_compile_definitions with AVR target names +########################################################################## + +function(avr_target_compile_definitions EXECUTABLE_TARGET) + if(NOT ARGN) + message(FATAL_ERROR "No compile definitions to add to ${EXECUTABLE_TARGET}.") + endif() + + get_target_property(TARGET_LIST ${EXECUTABLE_TARGET} OUTPUT_NAME) + set(extra_args ${ARGN}) + + target_compile_definitions(${TARGET_LIST} ${extra_args}) +endfunction() + +function(avr_generate_fixed_targets) + # get status + add_custom_target( + get_status + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} -n -v + COMMENT "Get status from ${AVR_MCU}" + ) + + # get fuses + add_custom_target( + get_fuses + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} -n + -U lfuse:r:-:b + -U hfuse:r:-:b + COMMENT "Get fuses from ${AVR_MCU}" + ) + + # set fuses + add_custom_target( + set_fuses + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} + -U lfuse:w:${AVR_L_FUSE}:m + -U hfuse:w:${AVR_H_FUSE}:m + COMMENT "Setup: High Fuse: ${AVR_H_FUSE} Low Fuse: ${AVR_L_FUSE}" + ) + + # get oscillator calibration + add_custom_target( + get_calibration + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} + -U calibration:r:${AVR_MCU}_calib.tmp:r + COMMENT "Write calibration status of internal oscillator to ${AVR_MCU}_calib.tmp." + ) + + # set oscillator calibration + add_custom_target( + set_calibration + ${AVR_UPLOADTOOL} ${AVR_UPLOADTOOL_BASE_OPTIONS} -P ${AVR_UPLOADTOOL_PORT} + -U calibration:w:${AVR_MCU}_calib.hex + COMMENT "Program calibration status of internal oscillator from ${AVR_MCU}_calib.hex." + ) +endfunction() \ No newline at end of file -- 2.30.2