--- /dev/null
+subdirs(Led0 DCMotor PowerSwitch ShutterCtrl)
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+#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<<m_DirShift);
+ m_Params->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<<COM2B0); // direction !!!
+ m_Params->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<<m_DirShift); // direction !!!
+ } else
+ {
+ (*m_Port) &= ~_BV( m_Mapping.pinOut);
+ (*m_Tccr) &= ~(3<<m_DirShift); // direction !!!
+ (*m_Tccr) |= (2<<m_DirShift); // direction !!!
+ }
+}
+
+const bool
+Motor::enabled() const
+{
+ return ( ((*m_Port) & _BV( PIN_MOTOR_ENABLE) ) == 0 );
+}
+
+void
+Motor::update()
+{
+ Uint8_t l_Mode;
+
+ if ( ((*m_Port) & _BV( PIN_MOTOR_ENABLE) ) == 0 )
+ {
+ // don't do anything if motor is disabled
+ return ;
+ }
+ m_Params->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<Float32_t>( consigneRpm )- static_cast<Float32_t>(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<Uint8_t>(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<Uint16_t>(static_cast<Float32_t>(l_Pot) * 256.0 / 1024.0);
+ m_Params->writeValue(PID_MotorPwm,l_Pot);
+}
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+
+#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<<m_DirShift);
+ m_Params->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<<m_DirShift); // direction !!!
+#else
+#endif
+ } else
+ {
+ (*m_Port) &= ~_BV( m_Mapping.pinOut);
+#if 0
+ (*m_Tccr) &= ~(3<<m_DirShift); // direction !!!
+ (*m_Tccr) |= (2<<m_DirShift); // direction !!!
+#else
+#endif
+ }
+}
+
+const bool
+Motor::enabled() const
+{
+ return ( ((*m_Port) & _BV( PIN_MOTOR_ENABLE) ) == 0 );
+}
+
+void
+Motor::update()
+{
+ Uint8_t l_Mode;
+
+ updateUsingPot0();
+ if ( ((*m_Port) & _BV( PIN_MOTOR_ENABLE) ) == 0 )
+ {
+ // don't do anything if motor is disabled
+ return ;
+ }
+ m_Params->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<Float32_t>( consigneRpm )- static_cast<Float32_t>(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<Uint8_t>(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<Uint16_t>(static_cast<Float32_t>(l_Pot) * 256.0 / 1024.0);
+ m_Params->writeValue(PID_MotorPwm,l_Pot);
+}
--- /dev/null
+#####################################################################
+# 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
+ )
+
--- /dev/null
+#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();
+}
+
--- /dev/null
+#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
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+#include "Led0.h"
+#include "Abstract/IPwm.h"
+#include "DCMotor.h"
+
+#if defined (__AVR_ATmega32U4__)
+#include "32u4_DCMotor.cpp"
+#else
+#include "328p_DCMotor.cpp"
+#endif
--- /dev/null
+#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
--- /dev/null
+/**
+ * \brief simple class for port access for LEDs
+ *
+ * \file Led0.cpp
+ * \author Ebersold Andre
+ */
+
+//#include <avr/io.h>
+#include <Utils/StdTypes.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+#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();
+ }
+}
--- /dev/null
+/**
+ * \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;
+};
+
--- /dev/null
+#include "Utils/StdTypes.h"
+
+#include "Application/ITask.h"
+#include "Abstract/IAdc.h"
+#include "Abstract/IPwm.h"
+#include <Platform/IParameterHandler.h>
+
+#include <AVR/AvrTimer1.h>
+#include <Metadata/DCMotorParamIds.h>
+#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<Float32_t>(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<Float32_t>(l_cpr);
+ _conv *= 60.0;
+ _conv *= count;
+ _rpm = static_cast<Uint16_t>(_conv);
+}
--- /dev/null
+#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
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+#include <util/delay.h>
+
+#include <Abstract/IInterruptActivity.h>
+#include <Abstract/IProtocolLayer2.h>
+#include <Abstract/IUart.h>
+#include <Abstract/IAdc.h>
+#include <Abstract/IEeprom.h>
+#include <Abstract/IPwm.h>
+#include <Application/ITask.h>
+#include <AVR/AvrTimer0.h>
+#include <AVR/AvrTimer1.h>
+#include <AVR/AvrUart.h>
+#include <AVR/AvrAdc.h>
+#include <AVR/AvrEeprom.h>
+#include <AVR/AvrPwm.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+#include <Platform/DCMotorParameterHandler.h>
+#include <Platform/PersistentStorage.h>
+#include <Communication/CommunicationHandler.h>
+
+
+#include <Drivers/NetString.h>
+#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<Uint16_t >(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();
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#####################################################################
+# simple AVR executable
+#####################################################################
+add_avr_executable(
+ toggle-led-cpp
+ main.cpp
+ Led0.cpp
+ )
+
--- /dev/null
+/**
+ * \brief simple class for port access for LEDs
+ *
+ * \file Led0.cpp
+ * \author Ebersold Andre
+ */
+
+#include <avr/io.h>
+
+#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);
+}
+
--- /dev/null
+/**
+ * \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;
+};
+
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "Led0.h"
+
+/**
+ * \brief main loop
+ */
+int main(void)
+{
+ Led0 led(&PORTB, &DDRB, PINB1);
+
+ while(1)
+ {
+ led.toggle();
+ _delay_ms(500);
+ }
+}
--- /dev/null
+#####################################################################
+# 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
+ )
+
--- /dev/null
+/**
+ * \brief simple class for port access for LEDs
+ *
+ * \file Led0.cpp
+ * \author Ebersold Andre
+ */
+
+//#include <avr/io.h>
+#include <Utils/StdTypes.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/PowerswitchParamIds.h>
+#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();
+ }
+}
--- /dev/null
+/**
+ * \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;
+};
+
--- /dev/null
+#include "Utils/StdTypes.h"
+
+#include "Application/ITask.h"
+#include "Abstract/ISwitch.h"
+#include <Platform/IParameterHandler.h>
+
+#include <Metadata/PowerswitchParamIds.h>
+#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:
+ ;
+ }
+}
--- /dev/null
+#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
--- /dev/null
+
+/**
+ * \brief simple class for port access for LEDs
+ *
+ * \file Switch.cpp
+ * \author Ebersold Andre
+ */
+
+//#include <avr/io.h>
+#include <Utils/StdTypes.h>
+#include <Abstract/ISwitch.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/PowerswitchParamIds.h>
+#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;
+}
+
--- /dev/null
+/**
+ * \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;
+};
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+#include <util/delay.h>
+
+#include <Abstract/IInterruptActivity.h>
+#include <Abstract/IProtocolLayer2.h>
+#include <Abstract/IUart.h>
+#include <Abstract/ISwitch.h>
+#include <Abstract/IEeprom.h>
+#include <Application/ITask.h>
+#include <AVR/AvrTimer0.h>
+#include <AVR/AvrTimer1.h>
+#include <AVR/AvrUart.h>
+#include <AVR/AvrEeprom.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/PowerswitchParamIds.h>
+#include <Platform/PowerswitchParameterHandler.h>
+#include <Platform/PersistentStorage.h>
+#include <Communication/CommunicationHandler.h>
+
+
+#include <Drivers/NetString.h>
+#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();
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#####################################################################
+# 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
+ )
+
--- /dev/null
+/**
+ * \brief simple class for port access for LEDs
+ *
+ * \file Led0.cpp
+ * \author Ebersold Andre
+ */
+
+//#include <avr/io.h>
+#include <Utils/StdTypes.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/ShutterCtrlParamIds.h>
+#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();
+ }
+}
--- /dev/null
+/**
+ * \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;
+};
+
--- /dev/null
+#include "Utils/StdTypes.h"
+
+#include "Application/ITask.h"
+#include <Platform/IParameterHandler.h>
+
+#include <AVR/AvrTimer1.h>
+#include <Metadata/ShutterCtrlParamIds.h>
+#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;
+ }
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+#include <util/delay.h>
+
+#include <Abstract/IProtocolLayer2.h>
+#include <Abstract/IUart.h>
+#include <Abstract/ISPI.h>
+#include <Application/ITask.h>
+#include <AVR/AvrSpi.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/ShutterCtrlParamIds.h>
+#include <Platform/ShutterCtrlParameterHandler.h>
+#include <Communication/CommunicationHandler.h>
+
+
+#include <Drivers/XPT2046_Touchscreen.h>
+#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<uint16_t>(p.x));
+ m_Param->writeValue(PID_Py,static_cast<uint16_t>(p.y));
+ m_Param->writeValue(PID_Pz,static_cast<uint16_t>(p.z));
+ }
+ } else
+ {
+ m_Counter++;
+ }
+}
--- /dev/null
+#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
--- /dev/null
+/**
+ * \brief simple application to test the C++ toolchain
+ *
+ * \file main.cc
+ * \author Andre Ebersold
+ */
+
+#include <Utils/StdTypes.h>
+#include <util/delay.h>
+
+#include <Abstract/IInterruptActivity.h>
+#include <Abstract/IProtocolLayer2.h>
+#include <Abstract/IUart.h>
+#include <Abstract/IAdc.h>
+#include <Abstract/IEeprom.h>
+#include <Abstract/ISPI.h>
+#include <Application/ITask.h>
+#include <AVR/AvrTimer0.h>
+#include <AVR/AvrTimer1.h>
+#include <AVR/AvrUart.h>
+#include <AVR/AvrAdc.h>
+#include <AVR/AvrEeprom.h>
+#include <AVR/AvrSpi.h>
+//#include <AVR/AvrPwm.h>
+#include <Platform/IParameterHandler.h>
+#include <Metadata/ShutterCtrlParamIds.h>
+#include <Platform/ShutterCtrlParameterHandler.h>
+#include <Platform/PersistentStorage.h>
+#include <Communication/CommunicationHandler.h>
+
+
+#include <Drivers/NetString.h>
+#include <Drivers/Ili9341.h>
+#include <Drivers/XPT2046_Touchscreen.h>
+#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<Uint16_t >(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);
+ }
+}
--- /dev/null
+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)
--- /dev/null
+#####################################################################
+# simple AVR library
+#####################################################################
+add_avr_library(
+ avrComm
+ CommunicationHandler.cpp
+ )
+
--- /dev/null
+
+#include <Utils/StdTypes.h>
+#include <stdlib.h> // for itoa
+#include <Abstract/IProtocolLayer2.h>
+#if 0
+#include <Metadata/DCMotorParamIds.h> // To be removed
+#endif
+#include <Platform/IParameterHandler.h>
+#include <Communication/CommunicationHandler.h>
+
+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++;
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+
+#include <avr/interrupt.h>
+
+#include "Abstract/IInterruptActivity.h"
+#include "AVR/AvrTimer0.h"
+
+
+Timer0* Timer0::gTimer0 = 0;
+
+ISR(TIMER0_OVF_vect)
+{
+ Timer0::gTimer0->process_interrupt();
+ //TCNT0 = 0x01;
+ TIFR0 &= ~(1<<TOV0);
+}
+
+
+Timer0::Timer0(IInterruptActivity &_int)
+ : m_Interrupt(&_int)
+{
+ Timer0::gTimer0 = this;
+}
+#define MY_COUNT_FROM 0xF8
+void
+Timer0::init()
+{
+ cli();
+ // Enable Overflow Interrupt Enable
+ TIMSK0 = (1<<TOIE0);
+ // Set Control Register 16MHz / 1024 = 15,625KHz
+ // Tick = 1/15,625KHz = 64us
+ // So overflow every 16ms
+ //TCCR0B = (1<<CS00) | (1<<CS02);
+ //Division / 8
+ TCCR0B = (0<<CS00) | (1<<CS01);
+ //TCCR0A = (1<< WGM01);
+ TCCR0A |= (3<< WGM00);
+ // Initialize counter
+ TCNT0 = MY_COUNT_FROM;
+ PRR &= ~(1<<PRTIM0);
+ initT2();
+ sei();
+}
+
+void
+Timer0::initT2()
+{
+ //Division / 8
+ TCCR2B = (0<<CS00) | (1<<CS01);
+ //TCCR0A = (1<< WGM01);
+ TCCR2A |= (3<< WGM00);
+ // Initialize counter
+ TCNT2 = MY_COUNT_FROM;
+ PRR &= ~(1<<PRTIM2);
+}
+
+///
+void
+Timer0::process_interrupt()
+{
+ m_Interrupt->tick();
+}
+
--- /dev/null
+
+#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<<CS00); // Disable Clock for Timer 1
+ TCCR1A &= ~(3 << WGM10);
+ TCCR0A |= (2 << COM0A0);
+#endif
+}
+
+
+/// From Interface
+void
+AvrPwm::enable(const Bool_t _OnOff) const
+{
+}
+
+
+/// From Interface
+void
+AvrPwm::setFreq(Uint16_t freq) const
+{
+}
+
+
+/// From Interface
+void
+AvrPwm::setDutyCycle(const Uint8_t _d) const
+{
+#ifdef USE_T1
+ OCR1C = (4 * _d);
+#else
+ OCR0A = _d;
+#endif
+}
+
+
--- /dev/null
+#include <avr/interrupt.h>
+
+#include "Abstract/IInterruptActivity.h"
+#include "AVR/AvrTimer0.h"
+
+
+Timer0* Timer0::gTimer0 = 0;
+
+ISR(TIMER0_OVF_vect)
+{
+ Timer0::gTimer0->process_interrupt();
+ TIFR0 &= ~(1<<TOV0);
+}
+
+
+Timer0::Timer0(IInterruptActivity &_int)
+ : m_Interrupt(&_int)
+{
+ Timer0::gTimer0 = this;
+}
+#define MY_COUNT_FROM 0xF8
+void
+Timer0::init()
+{
+ cli();
+ // Enable Overflow Interrupt Enable
+ TIMSK0 = (1<<TOIE0);
+ // Set Control Register 16MHz / 1024 = 15,625KHz
+ // Tick = 1/15,625KHz = 64us
+ // So overflow every 16ms
+ //TCCR0B = (1<<CS00) | (1<<CS02);
+ //Division / 8
+ TCCR0B = (0<<CS00) | (1<<CS01);
+#if 1
+ TCCR0A |= (3<< WGM00);
+#else
+ //TCCR0A = (1<< WGM01);
+#endif
+ // Initialize counter
+ TCNT0 = MY_COUNT_FROM;
+ PRR0 &= ~(1<<PRTIM0);
+ initT2();
+ sei();
+}
+
+void
+Timer0::initT2()
+{
+#if defined (__AVR_ATmega32U4__)
+ PRR0 &= ~(1<<PRTIM0);
+#else
+ //Division / 8
+ TCCR2B = (0<<CS00) | (1<<CS01);
+ //TCCR0A = (1<< WGM01);
+ TCCR2A |= (3<< WGM00);
+ // Initialize counter
+ TCNT2 = MY_COUNT_FROM;
+ PRR &= ~(1<<PRTIM2);
+#endif
+}
+
+///
+void
+Timer0::process_interrupt()
+{
+ m_Interrupt->tick();
+}
+
--- /dev/null
+
+#include <Utils/StdTypes.h>
+
+#include <Abstract/IAdc.h>
+#include <Application/ITask.h>
+#include <AVR/AvrAdc.h>
+
+
+AvrADC::AvrADC()
+ : m_Value(0),m_Channel(0),m_State(ADC_IDLE)
+{
+ init();
+}
+
+void
+AvrADC::init()
+{
+ // Select Vref = AVcc
+ ADMUX |= (1<<REFS0);
+
+ // Set prescaller to 128 and enable ADC
+ ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0) |(1<<ADEN) ;
+}
+
+/**
+*
+*/
+void
+AvrADC::run()
+{
+ switch (m_State)
+ {
+ case ADC_IDLE:
+ m_State = ADC_START;
+ break;
+ case ADC_START:
+ ADMUX = (ADMUX & 0xF0) | (m_Channel & 0x0F);
+ // Start single conversion mode
+ ADCSRA |= (1<<ADSC);
+ m_State = ADC_CONVERTING;
+ break;
+ case ADC_CONVERTING:
+ if ( !(ADCSRA & (1<<ADSC) ) )
+ {
+ // Conversion done
+ m_Value = ADC;
+ m_State = ADC_START;
+ }
+ break;
+ default:
+ m_State = ADC_IDLE;
+
+ };
+}
+
+/**
+*
+*/
+Uint16_t
+AvrADC::read(Uint8_t _channel) const
+{
+ return read();
+}
--- /dev/null
+#ifndef AVR_ADC_H__
+#define AVR_ADC_H__
+
+/**
+ * \brief Adc interface is responsible to continously read
+ * the ADC value. Not that read value will return an already
+ * converted value.
+ *
+ *
+ */
+class AvrADC : public virtual IAdc , public virtual ITask
+{
+
+ private:
+ enum _AdcState {ADC_IDLE, ADC_START,ADC_CONVERTING, ADC_READ};
+ public:
+ AvrADC();
+
+ void init();
+ /**
+ *
+ */
+ virtual void run();
+
+ /**
+ *
+ */
+ virtual Uint16_t read(const Uint8_t) const;
+ /**
+ *
+ */
+ Uint16_t read() const { return m_Value; };
+ private:
+ Uint16_t m_Value;
+ Uint8_t m_Channel;
+ _AdcState m_State;
+};
+
+#endif
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#include <Abstract/IEeprom.h>
+#include <AVR/AvrEeprom.h>
+
+
+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);
+}
+
+
--- /dev/null
+#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
--- /dev/null
+#ifndef __AVRINTERRUPT_H__
+
+class AvrInterrupt
+{
+ public:
+ AvrInterrupt(IInterruptActivity *);
+
+ /**
+ * Initialize timer so that a scheduling
+ * will occure every 500us
+ */
+ void init();
+ private:
+};
+#endif
--- /dev/null
+#include <avr/interrupt.h>
+
+#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
--- /dev/null
+#ifndef AVR_PWM_H__
+#define AVR_PWM_H__
+
+/**
+ *
+ *
+ */
+//template <typename _ioTimer>
+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
--- /dev/null
+
+#include <Utils/StdTypes.h>
+#include <Abstract/ISPI.h>
+#include <AVR/AvrSpi.h>
+
+
+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<<SPE) | (1<<MSTR);
+#if 0
+ SPSR |=(1<<SPI2X); // doubling spi speed.i.e final spi speed-fosc/2
+
+ LCD_CSN_PORT |= (1<<LCD_CSN); // cs(low active) off during startup
+#endif
+}
+
+void
+AvrSpi::begin(const SPISettings &_settings)
+{
+ /* Set mode */
+ SPCR |= (_settings.m_Mode<<2);
+ switch(_settings.m_Freq)
+ {
+ case 8000000: SPSR |= _BV(SPI2X); break;
+ case 4000000: break;
+ case 2000000: SPSR |= _BV(SPI2X); SPCR |= _BV(SPR0); break;
+ case 1000000: SPCR |= _BV(SPR0) ; break;
+ case 500000: SPSR |= _BV(SPI2X); SPCR |= _BV(SPR1); break;
+ case 250000: SPSR |= _BV(SPI2X); SPCR |= (_BV(SPR1) | _BV(SPR0)) ; break;
+ case 125000: SPCR |= _BV(SPR1) | _BV(SPR1); break;
+ default: ;
+ }
+}
+
+
+void AvrSpi::end()
+{
+ /* disable SPI */
+ //SPCR &= ~(_BV(SPE) | _BV(MSTR));
+ SPSR &= ~_BV(SPI2X); SPCR &= ~(_BV(SPR1) | _BV(SPR0)) ; // Be sure everyting is back to 0
+}
+
+
+/// 8 bits data tx/rx
+void
+AvrSpi::transceive(const Uint8_t txData,Uint8_t * const &rxData)
+{
+ SPDR = txData;
+ while ( !(SPSR & (1<<SPIF)) );
+ *rxData = SPDR;
+}
+
+/// 16 bits data tx / rx
+void
+AvrSpi::transceive(const Uint16_t txData,Uint16_t *const &rxData)
+{
+ union {
+ uint16_t val;
+ struct {
+ uint8_t msb;
+ uint8_t lsb;
+ } s;
+ } in,out;
+ in.val = txData;
+
+ transceive(in.s.msb,&out.s.msb);
+ transceive(in.s.lsb,&out.s.lsb);
+ //*rxData = *rxData | static_cast<uint16_t>(0x00FF & result);
+ *rxData = out.val;
+}
--- /dev/null
+#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
--- /dev/null
+
+#include <avr/interrupt.h>
+
+#include "Abstract/IInterruptActivity.h"
+#include "AVR/AvrTimer0.h"
+
+#if defined (__AVR_ATmega32U4__)
+#include "32u4_Timer0.cpp"
+#else
+#include "328p_Timer0.cpp"
+#endif
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#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<<PRTIM1);
+#else
+ PRR &= ~(1<<PRTIM1);
+#endif
+ //sei();
+}
+
+///
+Uint16_t
+Timer1::readCounter(bool _reset)
+{
+ //Uint8_t _sreg=SREG;
+ //cli();
+ Uint16_t _ret = TCNT1;
+#if 0
+ if (_reset == true)
+ {
+ TCNT1 =0;
+ }
+#endif
+ //SREG = sreg;
+ return _ret;
+}
+
--- /dev/null
+#ifndef __AVR_TIMER1_H__
+#define __AVR_TIMER1_H__
+
+class Timer1
+{
+ public:
+ Timer1();
+ /// setup timer
+ void init();
+ ///
+ Uint16_t readCounter(bool _reset = false);
+ ///
+
+ private:
+};
+
+
+#endif
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#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<<PRTIM3);
+}
+
+///
+Uint16_t
+Timer3::readCounter(bool _reset)
+{
+ //Uint8_t _sreg=SREG;
+ //cli();
+ Uint16_t _ret = TCNT3;
+ if (_reset == true)
+ {
+ TCNT1 =0;
+ }
+ //SREG = sreg;
+ return _ret;
+}
+
--- /dev/null
+#ifndef __AVR_TIMER1_H__
+#define __AVR_TIMER1_H__
+
+class Timer1
+{
+ public:
+ Timer1();
+ /// setup timer
+ void init();
+ ///
+ Uint16_t readCounter(bool _reset = false);
+ ///
+
+ private:
+};
+
+
+#endif
--- /dev/null
+
+#include <avr/interrupt.h>
+
+#include <Abstract/IUart.h>
+#include <AVR/AvrUart.h>
+
+
+
+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<<PRUSART1);
+#else
+ PRR &= ~(1<<PRUSART0);
+#endif
+ setParameters(m_Baudrate,m_Parity,m_StopBits);
+ enableReceive(true);
+
+ return;
+}
+
+/**
+*
+*
+*/
+void
+AvrUart::transmit(uint8_t tx)
+{
+#if defined (__AVR_ATmega32U4__)
+ UDR1 = tx;
+#else
+ UDR0 = tx;
+#endif
+}
+
+/**
+* \brief get the character received
+*
+*/
+uint8_t
+AvrUart::receive()
+{
+#if defined (__AVR_ATmega32U4__)
+ return UDR1;
+#else
+ return UDR0;
+#endif
+}
+
+
+/**
+* \brief return true when data can
+* be sent. Eg previous character was sent.
+*/
+bool
+AvrUart::transmit_ready()
+{
+#if defined (__AVR_ATmega32U4__)
+ return (UCSR1A & _BV(UDRE1)) ;
+#else
+ return (UCSR0A & _BV(UDRE0)) ;
+#endif
+}
+
+/**
+* \brief return true when data have been
+* received
+*/
+bool
+AvrUart::receive_ready()
+{
+#if defined (__AVR_ATmega32U4__)
+ return (UCSR1A & _BV(RXC1));
+#else
+ return (UCSR0A & _BV(RXC0));
+#endif
+}
+
+/**
+*
+*/
+void
+AvrUart::switchSetup(const Baudrate_t _baud,const Parity_t _p,StopBits_t _stb)
+{
+}
+
+/// Allow / Disable ReceiveInterrupt
+void
+AvrUart::enableReceive(bool _set)
+{
+#if defined (__AVR_ATmega32U4__)
+ if (_set)
+ UCSR1B |= (1 << RXEN1);
+ else
+ UCSR1B &= ~(1<< RXEN1);
+#else
+ if (_set)
+ UCSR0B |= (1 << RXEN0);
+ else
+ UCSR0B &= ~(1<< RXEN0);
+#endif
+}
+
+
+/// Allow Transmit interrupt vector to
+// be triggered
+void
+AvrUart::enableTransmit(bool _set)
+{
+#if defined (__AVR_ATmega32U4__)
+ if (_set)
+ UCSR1B |= _BV( TXEN1);
+ else
+ UCSR1B &= ~_BV( TXEN1);
+#else
+ if (_set)
+ UCSR0B |= _BV( TXEN0);
+ else
+ UCSR0B &= ~_BV( TXEN0);
+#endif
+}
+
+void
+AvrUart::setParameters(IUart::Baudrate_t _baud,IUart::Parity_t _parity, IUart::StopBits_t _bits)
+{
+ // Enable Rx / Tx
+#if defined (__AVR_ATmega32U4__)
+ UCSR1B = (1 << TXEN1) | ( 1 << RXEN1 );
+#else
+ UCSR0B = (1 << TXEN0) | ( 1 << RXEN0 );
+#endif
+ uint16_t speed = 103;
+ switch (_baud)
+ {
+ case BAUD_9600 : speed = 103; break;
+ case BAUD_19200 : speed = 51 ; break;
+ case BAUD_57600 : speed = 16 ; break;
+ case BAUD_115200: speed = 16 ; break;
+ break;
+ default: ;
+ }
+#if defined (__AVR_ATmega32U4__)
+ UBRR1H = speed >> 8;
+ UBRR1L = speed;
+ // Set 8 bits and Stop bits
+ if (_bits == STB_TWO)
+ {
+ UCSR1C = (1<<USBS1) | (3<<UCSZ10);
+ }
+ else
+ {
+ UCSR1C = (3<<UCSZ10);
+ }
+#else
+ UBRR0H = speed >> 8;
+ UBRR0L = speed;
+ // Set 8 bits and Stop bits
+ if (_bits == STB_TWO)
+ {
+ UCSR0C = (1<<USBS0) | (3<<UCSZ00);
+ }
+ else
+ {
+ UCSR0C = (3<<UCSZ00);
+ }
+#endif
+}
--- /dev/null
+#ifndef AVR_UART_H__
+#define AVR_UART_H__
+
+
+class AvrUart : public IUart
+{
+ public:
+
+ AvrUart(Baudrate_t _baud,Parity_t _p,StopBits_t _stb);
+
+ virtual void init();
+ /**
+ *
+ *
+ */
+ virtual void transmit(uint8_t tx);
+
+ /**
+ * \brief get the character received
+ *
+ */
+ virtual uint8_t receive() ;
+
+ /**
+ * \brief return true when data can
+ * be sent. Eg previous character was sent.
+ */
+ virtual bool transmit_ready() ;
+ /**
+ * \brief return true when data have been
+ * received
+ */
+ virtual bool receive_ready() ;
+
+ /**
+ *
+ */
+ void switchSetup(const Baudrate_t _baud,const Parity_t _p,StopBits_t _stb) ;
+
+ /// Allow / Disable ReceiveInterrupt
+ virtual void enableReceive(bool _set);
+ /// Allow Transmit interrupt vector to
+ // be triggered
+ virtual void enableTransmit(bool _set);
+
+ virtual void setParameters(IUart::Baudrate_t _baud,IUart::Parity_t _parity, IUart::StopBits_t _bits);
+ private:
+ Baudrate_t m_Baudrate;
+ Parity_t m_Parity;
+ StopBits_t m_StopBits;
+};
+
+#endif
--- /dev/null
+#####################################################################
+# simple AVR library
+#####################################################################
+add_avr_library(
+ avrHAL
+ AvrTimer0.cpp
+ AvrTimer1.cpp
+ AvrUart.cpp
+ AvrEeprom.cpp
+ AvrAdc.cpp
+ AvrPwm.cpp
+ AvrSpi.cpp
+ )
+
--- /dev/null
+#ifndef __IADC_H__
+#define __IADC_H__
+
+class IAdc
+{
+ public:
+ IAdc() {} ;
+
+ virtual Uint16_t read(const Uint8_t _channel) const = 0;
+};
+
+#endif
--- /dev/null
+#ifndef __IEEPROM_H__
+#define __IEEPROM_H__
+
+/**
+ * \brief Eeprom interface exposed for all Eeprom implementation.
+ * can be usefull so that at the hight level I don't have to be
+ * bother with low level access issues.
+ *
+ */
+class IEeprom
+{
+ public:
+ ///
+ IEeprom() {};
+ /// Initialize
+ virtual void init() = 0;
+ /// Is eeprom busy, might be of interest, as eeprom access is performed through
+ /// SPI
+ virtual Bool_t isBusy() = 0;
+ /// 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
--- /dev/null
+#ifndef __IINTERRUPTACTIVITY_H__
+#define __IINTERRUPTACTIVITY_H__
+
+class IInterruptActivity
+{
+ public:
+ IInterruptActivity() {}
+
+ virtual void tick() = 0;
+
+};
+
+#endif
--- /dev/null
+#ifndef __IProtocolLayer2_H__
+#define __IProtocolLayer2_H__
+
+/**
+ * \brief Interface for Layer2 protocols
+ *
+ */
+class IProtocolLayer2
+{
+ public:
+ IProtocolLayer2() {};
+
+ virtual void init() = 0;
+ /**
+ * @return the size of the receiveMessage.
+ */
+ virtual const uint8_t getRxSize() const;
+ /**
+ * @return a pointer to the received message
+ * if no message is available, return NULL.
+ * a message is considered to be received on CR.
+ * If message is too long ? erase or error
+ */
+ virtual const uint8_t *receiveMsg() = 0;
+
+ virtual void setTxMsg(const uint8_t *_src,uint8_t _length) = 0;
+ /**
+ * \bried transmit message stored in m_Buffer.
+ * The message must previously be set by
+ * setTxMsg()
+ */
+ virtual void transmitMsg() = 0;
+ /**
+ * @brief called by scheduler I think.
+ */
+ virtual void tick() = 0;
+
+};
+
+#endif
--- /dev/null
+#ifndef __IPWM_H__
+#define __IPWM_H__
+
+/**
+ * @brief General interface for PWM pins.
+ *
+ */
+class IPwm
+{
+ public:
+ IPwm() {} ;
+
+ virtual void enable(const Bool_t _OnOff) const = 0;
+
+ virtual void setFreq(Uint16_t freq) const = 0;
+
+ virtual void setDutyCycle(const Uint8_t _OnOff) const = 0;
+
+};
+
+#endif
--- /dev/null
+#ifndef __ISPI_H__
+#define __ISPI_H__
+
+#define SPI_MODE0 0x0
+#define SPI_MODE1 0x1
+#define SPI_MODE2 0x2
+#define SPI_MODE3 0x3
+
+#define MSBFIRST 0x0
+#define LSBFIRST 0x1
+/**
+ * For transaction based SPI commands.
+ *
+ */
+struct SPISettings
+{
+ public:
+ SPISettings(const uint32_t _freq
+ ,const uint8_t _endian
+ ,const uint8_t _mode
+ )
+ : m_Freq(_freq),m_Mode(_mode),m_Endian(_endian) {}
+ uint32_t m_Freq;
+ uint8_t m_Mode;
+ uint8_t m_Endian;
+};
+
+/**
+ *
+ *
+ */
+class ISpi
+{
+ public:
+ ISpi() {};
+
+ /// Initialize Spi interface
+ virtual void init() = 0;
+
+ virtual void begin(const SPISettings &_settings) = 0;
+
+ virtual void end() = 0 ;
+ /// 8 bits data tx/rx
+ virtual void transceive(const uint8_t txData,uint8_t *const &rxData) = 0;
+ /// 16 bits data tx / rx
+ virtual void transceive(const uint16_t txData,uint16_t *const &rxData) = 0;
+};
+
+#endif
--- /dev/null
+#ifndef ISWITCH_H__
+#define ISWITCH_H__
+
+class ISwitch
+{
+ public:
+ enum State { SwitchOff = 0 , SwitchOn = 1 };
+
+ ISwitch() {};
+
+ virtual void set(State _state) = 0;
+ virtual void toggle() = 0;
+ virtual State state() const = 0;
+};
+
+#endif
--- /dev/null
+#ifndef __IUART_H__
+#define __IUART_H__
+
+
+/**
+ * \brief Abstrasct UArt Interface
+ * will be used by upper classes to
+ * send and transmit data
+ */
+class IUart
+{
+ public:
+#if 0
+ enum Baudrate_t { BAUD_2400 = 2400
+ ,BAUD_9600 = 9600
+ ,BAUD_19200 = 19200
+ ,BAUD_33600 = 33600
+ ,BAUD_57600 = 57600
+ ,BAUD_115200 = 115200
+ };
+#else
+ enum Baudrate_t { BAUD_2400 = 0
+ ,BAUD_9600 = 1
+ ,BAUD_19200 = 2
+ ,BAUD_57600 = 4
+ ,BAUD_115200 = 6
+ };
+#endif
+
+ enum Parity_t { PARITY_ODD,PARITY_EVEN,PARITY_NONE };
+
+ enum StopBits_t { STB_ONE = 0 ,STB_TWO = 1};
+
+ IUart() {};
+
+ virtual void init() = 0;
+ /**
+ *
+ *
+ */
+ virtual void transmit(uint8_t tx) = 0;
+
+ /**
+ * \brief get the character received
+ *
+ */
+ virtual uint8_t receive() = 0;
+
+ /**
+ * \brief return true when data can
+ * be sent. Eg previous character was sent.
+ */
+ virtual bool transmit_ready() = 0;
+ /**
+ * \brief return true when data have been
+ * received
+ */
+ virtual bool receive_ready() = 0;
+
+ /// Allow / Disable ReceiveInterrupt
+ virtual void enableReceive(bool _set) = 0;
+ /// Allow Transmit interrupt vector to
+ // be triggered
+ virtual void enableTransmit(bool _set) = 0;
+
+ /**
+ *
+ */
+ virtual void switchSetup(const Baudrate_t _baud,const Parity_t _p,StopBits_t _stb) = 0;
+};
+
+#endif
--- /dev/null
+subdirs(AVR Drivers)
--- /dev/null
+#####################################################################
+# simple AVR library
+#####################################################################
+add_avr_library(
+ avrDrivers
+ NetString.cpp
+ Ili9341.cpp
+ XPT2046_Touchscreen.cpp
+ )
+
--- /dev/null
+#include <Utils/StdTypes.h>
+#include <util/delay.h>
+
+#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<<LCD_CSN); // set nCS for output port
+ LCD_CMD_DDR |= (1<<LCD_CMD); // set D/C for output port
+ LCD_RST_DDR |= (1<<LCD_RST); // set reset pin for output port
+
+ LCD_RST_PORT |= (1<<LCD_RST); // pull high reset pin for normal operation
+}
+
+
+void Ili9341::spi_init(void)//set spi speed and settings
+{
+#if 0
+ /* initial SPI */
+ /* atmega88: PB3=MOSI, PB5=SCK, PB2=nSS, PB4=MISO */
+ //PORTB |= ( 1<<2 ) | ( 1<<1 ) | ( 1<<6 );
+ PORTB |= _BV( PIN2) | _BV( PIN3) | _BV( PIN5);
+ //DDRB |= ( 1<<2 ) | ( 1<<1 ) | ( 1<<6 ) | ( 1<<3 );
+ DDRB |= _BV( PIN2 ) | _BV( PIN3 ) | _BV( PIN5) ;
+ DDRB &= ~_BV( PIN4 );
+ SPCR = (1<<SPE) | (1<<MSTR); // mode 0,fosc/4
+ SPSR |=(1<<SPI2X); // doubling spi speed.i.e final spi speed-fosc/2
+#else
+ m_Spi->begin(SPI_SETTINGS);
+#endif
+ LCD_CSN_PORT |= (1<<LCD_CSN); // cs(low active) off during startup
+}
+
+
+void Ili9341::writecommand8(uint8_t com)//command write
+{
+#if CMD_ACTIF_LOW
+ LCD_CMD_PORT &=~(1<<LCD_CMD); // dc low to send command
+#else
+ LCD_CMD_PORT |= (1<<LCD_CMD); // dc high to send command
+#endif
+ _delay_us(1); // little delay
+ LCD_CSN_PORT &=~(1<<LCD_CSN); // cs low to send command
+
+ _delay_us(5); // little delay
+ SPI_ExchangeByte(com);
+ LCD_CSN_PORT |=(1<<LCD_CSN); // pull high cs
+}
+
+uint8_t Ili9341::SPI_ExchangeByte( uint8_t input )
+{
+#if 0
+ SPDR = input;
+ while ( !(SPSR & (1<<SPIF)) );
+ return SPDR;
+#else
+ uint8_t result;
+ m_Spi->transceive(input,&result);
+ return result;
+#endif
+}
+
+void Ili9341::writedata8(uint8_t data)//data write
+{
+#if CMD_ACTIF_LOW
+ LCD_CMD_PORT |= (1<<LCD_CMD); // dc high to send data
+#else
+ LCD_CMD_PORT &=~(1<<LCD_CMD); // dc low to send data
+#endif
+ LCD_CSN_PORT &=~(1<<LCD_CSN); // cs low to send data
+
+ _delay_us(5); // little delay
+ SPI_ExchangeByte(data);
+ LCD_CSN_PORT |=(1<<LCD_CSN); // pull high cs
+}
+
+void Ili9341::setaddress(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)//set coordinate for print or other function
+{
+ writecommand8(0x2A);
+ writedata8(x1>>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<<LCD_RST); // pull high if low previously
+ _delay_ms(2);
+ LCD_RST_PORT &= ~(1<<LCD_RST); // pull high if low previously
+ _delay_ms(2);
+ LCD_RST_PORT |= (1<<LCD_RST); // again pull high for normal operation
+ _delay_ms(2);
+
+ writecommand8(0x01); // soft reset
+ _delay_ms(10);
+}
+
+
+void Ili9341::init(void)//set up display using predefined command sequence
+{
+ hard_init();
+ spi_init();
+ hard_reset();
+ writecommand8(0x01);//soft reset
+ _delay_ms(1000);
+
+#ifdef LG_2_8inch_ILI9341
+ // LG 2.8" ILI9341 Initial Code
+ //power control A
+ writecommand8(0xCB);
+ writedata8(0x39);
+ writedata8(0x2C);
+ writedata8(0x00);
+ writedata8(0x34);
+ writedata8(0x02);
+
+ //power control B
+ writecommand8(0xCF);
+ writedata8(0x00);
+ writedata8(0xC1);
+ writedata8(0x30);
+
+ //driver timing control A
+ writecommand8(0xE8);
+ writedata8(0x85);
+ writedata8(0x00);
+ writedata8(0x78);
+
+ //driver timing control B
+ writecommand8(0xEA);
+ writedata8(0x00);
+ writedata8(0x00);
+
+ //power on sequence control
+ writecommand8(0xED);
+ writedata8(0x64);
+ writedata8(0x03);
+ writedata8(0x12);
+ writedata8(0x81);
+
+ //pump ratio control
+ writecommand8(0xF7);
+ writedata8(0x20);
+
+ //power control,VRH[5:0]
+ writecommand8(0xC0);
+ writedata8(0x23);
+
+ //Power control,SAP[2:0];BT[3:0]
+ writecommand8(0xC1);
+ writedata8(0x10);
+
+ //vcm control
+ writecommand8(0xC5);
+ writedata8(0x3E);
+ writedata8(0x28);
+
+ //vcm control 2
+ writecommand8(0xC7);
+ writedata8(0x86);
+
+ //memory access control
+ writecommand8(0x36);
+ writedata8(0x48);
+
+ //pixel format
+ writecommand8(0x3A);
+ writedata8(0x55);
+
+ //frameration control,normal mode full colours
+ writecommand8(0xB1);
+ writedata8(0x00);
+ writedata8(0x18);
+
+ //display function control
+ writecommand8(0xB6);
+ writedata8(0x08);
+ writedata8(0x82);
+ writedata8(0x27);
+
+ //3gamma function disable
+ writecommand8(0xF2);
+ writedata8(0x00);
+
+ //gamma curve selected
+ writecommand8(0x26);
+ writedata8(0x01);
+
+ //set positive gamma correction
+ writecommand8(0xE0);
+ writedata8(0x0F);
+ writedata8(0x31);
+ writedata8(0x2B);
+ writedata8(0x0C);
+ writedata8(0x0E);
+ writedata8(0x08);
+ writedata8(0x4E);
+ writedata8(0xF1);
+ writedata8(0x37);
+ writedata8(0x07);
+ writedata8(0x10);
+ writedata8(0x03);
+ writedata8(0x0E);
+ writedata8(0x09);
+ writedata8(0x00);
+
+ //set negative gamma correction
+ writecommand8(0xE1);
+ writedata8(0x00);
+ writedata8(0x0E);
+ writedata8(0x14);
+ writedata8(0x03);
+ writedata8(0x11);
+ writedata8(0x07);
+ writedata8(0x31);
+ writedata8(0xC1);
+ writedata8(0x48);
+ writedata8(0x08);
+ writedata8(0x0F);
+ writedata8(0x0C);
+ writedata8(0x31);
+ writedata8(0x36);
+ writedata8(0x0F);
+#endif
+
+#ifdef TianMa_2_4inch_ILI9341
+ // TianMa 2.4" ILI9341 Initial Code
+
+ // xxxx
+ writecommand8(0xEF);
+ writedata8(0x03);
+ writedata8(0x80);
+ //writedata8(0x30);
+ writedata8(0x02);
+
+ //power control B
+ writecommand8(0xCF);
+ writedata8(0x00);
+ //writedata8(0x81);
+ writedata8(0xC1);
+ writedata8(0x30);
+
+ //power on sequence control
+ writecommand8(0xED);
+ writedata8(0x64);
+ writedata8(0x03);
+ writedata8(0x12);
+ writedata8(0x81);
+
+ //driver timing control A
+ writecommand8(0xE8);
+ writedata8(0x85);
+ //writedata8(0x10);
+ writedata8(0x00);
+ //writedata8(0x7A);
+ writedata8(0x78);
+
+ //power control A
+ writecommand8(0xCB);
+ writedata8(0x39);
+ writedata8(0x2C);
+ writedata8(0x00);
+ writedata8(0x34);
+ writedata8(0x02);
+
+ //pump ratio control
+ writecommand8(0xF7);
+ writedata8(0x20);
+
+ //driver timing control B
+ writecommand8(0xEA);
+ writedata8(0x00);
+ writedata8(0x00);
+
+ //power control,VRH[5:0]
+ writecommand8(0xC0);
+ //writedata8(0x21);
+ writedata8(0x23);
+
+ //Power control,SAP[2:0];BT[3:0]
+ writecommand8(0xC1);
+ writedata8(0x10);
+
+ //vcm control
+ writecommand8(0xC5);
+ //writedata8(0x3F);
+ //writedata8(0x3C);
+ writedata8(0x3E);
+ writedata8(0x28);
+
+ //vcm control 2
+ writecommand8(0xC7);
+ //writedata8(0xA7);
+ writedata8(0x86);
+
+ //memory access control
+ writecommand8(0x36);
+ writedata8(0x48);
+
+ //frameration control,normal mode full colours
+ writecommand8(0xB1);
+ writedata8(0x00);
+ //writedata8(0x1B);
+ writedata8(0x18);
+
+ //display function control
+ writecommand8(0xB6);
+ //writedata8(0x0A);
+ writedata8(0x08);
+ //writedata8(0xA2);
+ writedata8(0x82);
+ writedata8(0x27);
+
+ //3gamma function disable
+ writecommand8(0xF2);
+ writedata8(0x00);
+
+ //gamma curve selected
+ writecommand8(0x26);
+ writedata8(0x01);
+
+ //set positive gamma correction
+ writecommand8(0xE0);
+ writedata8(0x0F);
+ writedata8(0x23);
+ writedata8(0x1F);
+ writedata8(0x0B);
+ writedata8(0x0E);
+ writedata8(0x08);
+ writedata8(0x4B);
+ writedata8(0xA8);
+ writedata8(0x3B);
+ writedata8(0x0A);
+ writedata8(0x14);
+ writedata8(0x09);
+ writedata8(0x10);
+ writedata8(0x09);
+ writedata8(0x00);
+
+ //set negative gamma correction
+ writecommand8(0xE1);
+ writedata8(0x00);
+ writedata8(0x1C);
+ writedata8(0x20);
+ writedata8(0x04);
+ writedata8(0x10);
+ writedata8(0x08);
+ writedata8(0x34);
+ writedata8(0x47);
+ writedata8(0x44);
+ writedata8(0x05);
+ writedata8(0x0B);
+ writedata8(0x09);
+ writedata8(0x2F);
+ writedata8(0x36);
+ writedata8(0x0F);
+
+ //pixel format
+ writecommand8(0x3A);
+ writedata8(0x55);
+#endif
+
+ //exit sleep
+ writecommand8(0x11);
+ _delay_ms(150);
+ //display on
+ writecommand8(0x29);
+ _delay_ms(150);
+ m_Spi->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;i<LCD_W;i++)
+ {
+ for(j=0;j<LCD_H;j++)
+ {
+ pushcolour(colour);
+ }
+ }
+
+ m_Spi->end();
+}
+
+
+
+//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();
+}
--- /dev/null
+#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
--- /dev/null
+
+#include <avr/interrupt.h>
+
+#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);
+ }
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+
+
+#include <Utils/StdTypes.h>
+#include <Abstract/ISPI.h>
+#include <Drivers/XPT2046_Touchscreen.h>
+
+#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<uint8_t>(0xB1),(uint8_t *)&result8);
+
+ m_Spi->transceive(static_cast<uint16_t>(0xC100),(uint16_t *)&z1);
+ z1>>=3;
+ z = z1 + 4095;
+
+ m_Spi->transceive(static_cast<uint16_t>(0x9100),(uint16_t *)&z2);
+ z2>>=3;
+ z -= z2;
+
+ if (z >= Z_THRESHOLD)
+ {
+ // Dummy read
+ m_Spi->transceive(static_cast<uint16_t>(0x9100),(uint16_t *)&dummy);
+ // Read Y
+ m_Spi->transceive(static_cast<uint16_t>(0xD100),(uint16_t *)&data[0]); data[0]>>=3;
+ // Read X
+ m_Spi->transceive(static_cast<uint16_t>(0x9100),(uint16_t *)&data[1]); data[1]>>=3;
+ // Read Y
+ m_Spi->transceive(static_cast<uint16_t>(0xD100),(uint16_t *)&data[2]); data[2]>>=3;
+ // Read X
+ m_Spi->transceive(static_cast<uint16_t>(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<uint16_t>(0xD000),(uint16_t *)&data[4]); data[4]>>=3;
+ m_Spi->transceive(static_cast<uint16_t>(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;
+ }
+}
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#####################################################################
+# simple AVR library
+#####################################################################
+add_avr_library(
+ avrPowerswitchParameters
+ PowerswitchParameterTable.cpp
+ )
+
+add_avr_library(
+ avrDCMotorParameters
+ DCMotorParameterTable.cpp
+ )
+
+add_avr_library(
+ avrShutterCtrlParameters
+ ShutterCtrlParameterTable.cpp
+ )
+
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+#include <stdlib.h> // 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}
+
+};
--- /dev/null
+#ifndef DCMOTORPARAMETERTABLE_H__
+#define DCMOTORPARAMETERTABLE_H__
+
+#include "Metadata/Metadata.h"
+extern
+ParameterValue m_Values[PID_MAX];
+#endif
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+#include <stdlib.h> // 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}
+
+};
--- /dev/null
+#ifndef POWERSWITCHPARAMETERTABLE_H__
+#define POWERSWITCHPARAMETERTABLE_H__
+
+#include "Metadata/Metadata.h"
+extern
+ParameterValue m_Values[PID_MAX];
+#endif
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+#include <stdlib.h> // 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}
+
+};
--- /dev/null
+#ifndef POWERSWITCHPARAMETERTABLE_H__
+#define POWERSWITCHPARAMETERTABLE_H__
+
+#include "Metadata/Metadata.h"
+extern
+ParameterValue m_Values[PID_MAX];
+#endif
--- /dev/null
+#####################################################################
+# 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
+ )
+
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/DCMotorParamIds.h>
+#include <Metadata/DCMotorParameterTable.h>
+#include <Platform/DCMotorParameterHandler.h>
+
+#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;
+ }
+
+}
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#include <HAL/Abstract/IEeprom.h>
+#include <Application/ITask.h>
+#include <Platform/IParameterHandler.h>
+#include <Platform/PersistentStorage.h>
+
+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()
+{
+}
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/PowerswitchParamIds.h>
+#include <Metadata/PowerswitchParameterTable.h>
+#include <Platform/PowerswitchParameterHandler.h>
+
+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;
+ }
+
+}
--- /dev/null
+#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
--- /dev/null
+#include <Utils/StdTypes.h>
+
+#include <Platform/IParameterHandler.h>
+#include <Metadata/ShutterCtrlParamIds.h>
+#include <Metadata/ShutterCtrlParameterTable.h>
+#include <Platform/ShutterCtrlParameterHandler.h>
+
+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;
+ }
+
+}
--- /dev/null
+#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
--- /dev/null
+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
+--------------------
--- /dev/null
+#ifndef __STD_TYPES_H__
+#define __STD_TYPES_H__
+#include <avr/io.h>
+/**
+ * @ 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
--- /dev/null
+
+##########################################################################
+# 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")
+
--- /dev/null
+##########################################################################
+# "THE ANY BEVERAGE-WARE LICENSE" (Revision 42 - based on beer-ware
+# license):
+# <dev@layer128.net> 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(<EXECUTABLE_NAME>-${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
+# <LIBRARY_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