From 65071b5bc9cbe3e0f2aab43aa024cfce4b9be0cc Mon Sep 17 00:00:00 2001 From: andre Ebersold Date: Tue, 24 Oct 2023 23:15:28 +0200 Subject: [PATCH] improved I2C interface, DS3231 Interface and implementation, Created WorkhourMeter Application --- .gitignore | 3 + Application/CMakeLists.txt | 2 +- Application/WorkhourMeter/CMakeLists.txt | 28 ++++ Application/WorkhourMeter/Led0.cpp | 81 ++++++++++ Application/WorkhourMeter/Led0.h | 52 ++++++ Application/WorkhourMeter/main.cpp | 196 +++++++++++++++++++++++ CMakeLists.txt | 10 +- HAL/AVR/AvrI2C.cpp | 29 +++- HAL/AVR/AvrI2C.h | 3 + HAL/AVR/CMakeLists.txt | 1 + HAL/Abstract/II2C.h | 8 +- HAL/Abstract/IRtc.h | 27 ++++ HAL/Drivers/CMakeLists.txt | 1 + HAL/Drivers/DS3231.cpp | 25 ++- HAL/Drivers/DS3231.h | 10 +- HAL/Drivers/Eeprom32C32_64.cpp | 1 + HAL/Drivers/Eeprom32C32_64.h | 1 + setupenv.bat | 1 + 18 files changed, 465 insertions(+), 14 deletions(-) create mode 100644 .gitignore create mode 100644 Application/WorkhourMeter/CMakeLists.txt create mode 100644 Application/WorkhourMeter/Led0.cpp create mode 100644 Application/WorkhourMeter/Led0.h create mode 100644 Application/WorkhourMeter/main.cpp create mode 100644 HAL/Abstract/IRtc.h create mode 100644 HAL/Drivers/Eeprom32C32_64.cpp create mode 100644 HAL/Drivers/Eeprom32C32_64.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5c19d70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*~ +*.bat~ +*.swp diff --git a/Application/CMakeLists.txt b/Application/CMakeLists.txt index cd6f986..e365e03 100644 --- a/Application/CMakeLists.txt +++ b/Application/CMakeLists.txt @@ -1 +1 @@ -subdirs(Led0 DCMotor PowerSwitch ShutterCtrl) +subdirs(Led0 DCMotor PowerSwitch ShutterCtrl WorkhourMeter) diff --git a/Application/WorkhourMeter/CMakeLists.txt b/Application/WorkhourMeter/CMakeLists.txt new file mode 100644 index 0000000..51e7506 --- /dev/null +++ b/Application/WorkhourMeter/CMakeLists.txt @@ -0,0 +1,28 @@ +##################################################################### +# simple AVR executable +##################################################################### +add_avr_executable( + workmeter + main.cpp + Led0.cpp + ) + +target_link_libraries( + workmeter-${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") + diff --git a/Application/WorkhourMeter/Led0.cpp b/Application/WorkhourMeter/Led0.cpp new file mode 100644 index 0000000..48c9153 --- /dev/null +++ b/Application/WorkhourMeter/Led0.cpp @@ -0,0 +1,81 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.cpp + * \author Ebersold Andre + */ + +//#include +#include +#include +#include +#include "Led0.h" + +/** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ +Led0::Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *_ph) +: m_Port(PORT) +, m_Ddr(DDR) +, m_Pin(PIN) +, m_Counter(0) +, m_Param(_ph) +{ + uint16_t cycle = 50; + _ph->writeValue(PID_LedCycle,cycle); + *(m_Ddr) |= (1 << m_Pin); +} + +//! destructor +Led0::~Led0() +{ +} + +//! switches the LED on +void Led0::on(void) +{ + *(m_Port) |= (1 << m_Pin); +} + +//! switches the LED off +void Led0::off(void) +{ + *(m_Port) &= ~(1 << m_Pin); +} + +//! toggles the LED +void Led0::toggle(void) +{ + *(m_Port) ^= (1 << m_Pin); +} + +/// +void +Led0::setCycle(uint16_t _cycle) +{ + m_Param->writeValue(PID_LedCycle,_cycle); +} +/// +void +Led0::reloadCounter() +{ + uint16_t cycle = 100; + m_Param->readValue(PID_LedCycle,cycle); + m_Counter = cycle; +} +/// +void +Led0::tick() +{ + if (m_Counter > 0) + { + m_Counter--; + } else + { + toggle(); + reloadCounter(); + } +} diff --git a/Application/WorkhourMeter/Led0.h b/Application/WorkhourMeter/Led0.h new file mode 100644 index 0000000..e8f4209 --- /dev/null +++ b/Application/WorkhourMeter/Led0.h @@ -0,0 +1,52 @@ +/** + * \brief simple class for port access for LEDs + * + * \file Led0.h + * \author Ebersold Andre + */ + +/** + * \brief simple access class for LEDs + */ +class Led0 +{ + public: + /** + * \brief constructor of LED access class + * \param PORT to access the LED + * \param DDR to set the LED port pin to output + * \param PIN to access the LED + */ + Led0(volatile uint8_t *PORT, volatile uint8_t *DDR, uint8_t PIN,IParameterHandler *); + //! destructor + ~Led0(); + + //! switches the LED on + void on(void); + //! switches the LED off + void off(void); + //! toggles the LED + void toggle(void); + /// + void setCycle(uint16_t _cycle); + /// + void reloadCounter(); + /// + void tick(); + private: + Led0(); + Led0( Led0 const &src ); + Led0& operator=(const Led0 &src ) ; + + //! pointer to the LED port + volatile uint8_t *m_Port; + //! pointer to the LED port's data direction register + volatile uint8_t *m_Ddr; + //! pin the LED is connected to + uint8_t m_Pin; + //! reset count + uint16_t m_Counter; + /// + IParameterHandler *m_Param; +}; + diff --git a/Application/WorkhourMeter/main.cpp b/Application/WorkhourMeter/main.cpp new file mode 100644 index 0000000..dfde31d --- /dev/null +++ b/Application/WorkhourMeter/main.cpp @@ -0,0 +1,196 @@ +/** + * \brief simple application to test the C++ toolchain + * + * \file main.cc + * \author Andre Ebersold + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include "Led0.h" +#if 0 +#include "Switch.h" +#include "PowerswitchHandler.h" +#endif +/** + * @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 = 10, + BLOCK3_FIRST_TIME_SLOT = 30, + LAST_TIME_SLOT = 60, + TIME_SLOT_COUNT = 99 + }; + 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,IRtc *_argRtc + ,ITask *_Storage + ) + : + m_Led(_led) + , m_Netstring(_net) + , m_Com(_com) + , m_Rtc(_argRtc) + , 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(); + m_Rtc->getTime(m_Time); + //m_Led->tick(); + break; + case TASK2: + m_Led->tick(); + 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; + IRtc *m_Rtc; + ITask *m_Storage; + volatile TIME_SLOTS m_CurrentTimeslot; + ETASK_ID m_CurrentTask; + RtcTime_t m_Time; + + +}; + +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); + AvrI2C gI2c; + DS3231 gRtc(&gI2c); + AvrEeprom gEeprom; + NetString netstring(&uart); + CommunicationHandler gCom(&netstring,&gParam); + PersistentStorage gStorage(&gEeprom,&gParam); + Scheduler sched(&led,&netstring,&gCom,&gRtc,&gStorage); + + uart.init(); + gI2c.init(); + netstring.init(); + + Timer0 lTimer(sched); + + led.on(); + _delay_ms(300); + led.off(); + _delay_ms(300); + + lTimer.init(); + init(&gParam); + gEeprom.init(); + while(1) + { + sched.schedule(); + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c74b10..a325540 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,9 @@ cmake_minimum_required(VERSION 2.8) ########################################################################## # tools to beused for programming the AVR ########################################################################## -set(AVR_UPLOADTOOL avrdude) +set(AVR_UPLOADTOOL avrdude CACHE STRING "AVR MCU Programmer ") set(AVR_PROGRAMMER arduino) -set(AVR_UPLOADTOOL_PORT /dev/ttyS5) +set(AVR_UPLOADTOOL_PORT CACHE STRING "AVRdude upload port") set(AVR_UPLOADTOOL_BAUDRATE 57600) ########################################################################## @@ -44,7 +44,13 @@ OPTION(TINYAPP_LED0 "Build Led application" ON) OPTION(TINYAPP_DC_MOTOR "Build DC Motor application" OFF) OPTION(TINYAPP_SHUTTERCTRL "Build Shutter Handler application" ON) +IF (WIN32) + SET(AVRDUDE_PORT "COM3" CACHE STRING "Avrdude port to use for flashing") +ENDIF(WIN32) + +IF(LINUX) SET(AVRDUDE_PORT "/dev/ttyS3" CACHE STRING "Avrdude port to use for flashing") +ENDIF(LINUX) # new way #CONFIGURE_FILE(${antcc_SOURCE_DIR}/src/antcc/config.h.cmake diff --git a/HAL/AVR/AvrI2C.cpp b/HAL/AVR/AvrI2C.cpp index 042213f..e76bc7b 100644 --- a/HAL/AVR/AvrI2C.cpp +++ b/HAL/AVR/AvrI2C.cpp @@ -8,29 +8,50 @@ #ifndef F_CPU #define F_CPU 16000000 #endif -#define SCL_CLOCK 50000 +#define SCL_CLOCK 400000 + +AvrI2C::AvrI2C() +{ +} void AvrI2C::init() { - uint8_t twst; TWSR = 0; // no prescaler TWBR = ((F_CPU/SCL_CLOCK)-16)/2; TWCR = (1<<(TWINT))|(1< #include "Abstract/II2C.h" -#include "DS3241.h" +#include "Abstract/IRtc.h" +#include "Drivers/DS3231.h" + +#define DS3231_ADDRESS 0xD0 DS3231::DS3231(II2C *argI2c) : itsII2C(argI2c) { } + + +void DS3231::getTime(RtcTime_t &argTime) +{ + Uint8_t cmd[2] ; + cmd[0] = 0x00; + itsII2C->read(DS3231_ADDRESS,cmd,2); + + argTime.seconds = cmd[1]; +} + +void DS3231::setTime(const RtcTime_t &argTime) +{ +} + +void DS3231::toString(Uint8_t *argOutTime) +{ +} diff --git a/HAL/Drivers/DS3231.h b/HAL/Drivers/DS3231.h index 957c4ac..beeee42 100644 --- a/HAL/Drivers/DS3231.h +++ b/HAL/Drivers/DS3231.h @@ -4,10 +4,16 @@ /** * Rtc Driver using DS3231 */ -class DS3231 +class DS3231 : public IRtc { public: - DS3241(II2C *); + DS3231(II2C *); + + void getTime(RtcTime_t &argTime); + + void setTime(const RtcTime_t &argTime); + + void toString(Uint8_t *argOutTime); private: II2C *itsII2C; }; diff --git a/HAL/Drivers/Eeprom32C32_64.cpp b/HAL/Drivers/Eeprom32C32_64.cpp new file mode 100644 index 0000000..1e5b1a8 --- /dev/null +++ b/HAL/Drivers/Eeprom32C32_64.cpp @@ -0,0 +1 @@ +Commande ECHO activ‚e. diff --git a/HAL/Drivers/Eeprom32C32_64.h b/HAL/Drivers/Eeprom32C32_64.h new file mode 100644 index 0000000..1e5b1a8 --- /dev/null +++ b/HAL/Drivers/Eeprom32C32_64.h @@ -0,0 +1 @@ +Commande ECHO activ‚e. diff --git a/setupenv.bat b/setupenv.bat index 3deebd2..4187288 100644 --- a/setupenv.bat +++ b/setupenv.bat @@ -2,5 +2,6 @@ SET PATH=%PATH%;C:\Tools\avr8-gnu-toolchain-3.7.0.1796-win32.any.x86_64\avr8-gnu-toolchain-win32_x86_64\bin SET PATH=%PATH%;C:\Program Files\CMake\bin SET PATH=%PATH%;C:\msys64\usr\bin +SET PATH=%PATH%;C:\tools\avrdude SET AVR_FIND_ROOT_PATH=C:\Tools\avr8-gnu-toolchain-3.7.0.1796-win32.any.x86_64\avr8-gnu-toolchain-win32_x86_64\ -- 2.30.2