improved I2C interface, DS3231 Interface and implementation, Created WorkhourMeter...
authorandre Ebersold <andre.ebersold@free.fr>
Tue, 24 Oct 2023 21:15:28 +0000 (23:15 +0200)
committerandre Ebersold <andre.ebersold@free.fr>
Tue, 24 Oct 2023 21:15:28 +0000 (23:15 +0200)
18 files changed:
.gitignore [new file with mode: 0644]
Application/CMakeLists.txt
Application/WorkhourMeter/CMakeLists.txt [new file with mode: 0644]
Application/WorkhourMeter/Led0.cpp [new file with mode: 0644]
Application/WorkhourMeter/Led0.h [new file with mode: 0644]
Application/WorkhourMeter/main.cpp [new file with mode: 0644]
CMakeLists.txt
HAL/AVR/AvrI2C.cpp
HAL/AVR/AvrI2C.h
HAL/AVR/CMakeLists.txt
HAL/Abstract/II2C.h
HAL/Abstract/IRtc.h [new file with mode: 0644]
HAL/Drivers/CMakeLists.txt
HAL/Drivers/DS3231.cpp
HAL/Drivers/DS3231.h
HAL/Drivers/Eeprom32C32_64.cpp [new file with mode: 0644]
HAL/Drivers/Eeprom32C32_64.h [new file with mode: 0644]
setupenv.bat

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..5c19d70
--- /dev/null
@@ -0,0 +1,3 @@
+*~
+*.bat~
+*.swp
index cd6f9862bbc7367924a8714ea37072ce8c96dbd7..e365e03ed1e2923a43aa9a0c99776c6627338b99 100644 (file)
@@ -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 (file)
index 0000000..51e7506
--- /dev/null
@@ -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 (file)
index 0000000..48c9153
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ * \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 = 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 (file)
index 0000000..e8f4209
--- /dev/null
@@ -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 (file)
index 0000000..dfde31d
--- /dev/null
@@ -0,0 +1,196 @@
+/**
+ * \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/II2C.h>
+#include <Abstract/IRtc.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 <AVR/AvrI2C.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 <Drivers/DS3231.h>
+#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();
+   }
+}
index 1c74b10aa29d43cd54a8b7ff8518362292ef9a19..a32554033fc78ddd6e7e45f35b9be0d306420d09 100644 (file)
@@ -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
index 042213f21b141bc47768fae1a884ab59f363de16..e76bc7b248da33141574e8606ee225d286ba0ce0 100644 (file)
@@ -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<<TWSTA )|(1<<TWEN);
+#if 0
     printf("TWCR 0x%x \n",TWCR);
+#endif
     while( !( TWCR & (1<< TWINT) ) ) ;
+#if 0
     printf(" Start condition has been transmitted \n");
-    if( (TWSR&0xF8) != TW_START){
+    if( (TWSR&0xF8) != TW_START)
+    {
+
      printf(" Error \n");
     }
+#endif
     // Setting Address 
     TWDR = 0x1C; 
     // cleating TWCR 
     TWCR = (1<<TWINT) |(1<<TWEN);
 
-    while ( !(TWRC & (1<<TWINT))) ; 
+    while ( !(TWCR & (1<<TWINT))) ; 
     if ((TWSR & 0xF8) != TW_MT_SLA_ACK)
     {
+#if 0
        printf(" Error at TWSR   0x%x\n", TWSR);  // here is the problem !!!!!!!!!  TWSR value should be 0x18
+#endif
        return; 
     }        
 }
+
+void AvrI2C::write(Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen)
+{
+    return;
+}
+
+void AvrI2C::read(Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen)
+{
+    return;
+}
index 8e98cff43f5b35b6d4383dc434af5b21f0c7a9ca..47d9abf37e45931c342007f60a8fbec9a2323403 100644 (file)
@@ -8,6 +8,9 @@ class AvrI2C : public II2C
 
         void init();
 
+        void write(Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen);
+        
+        void read(Uint8_t argAddress,Uint8_t *argData,Uint8_t argLen);
         
 };
 
index 68542115c362d443596bd6dc8509c9bb72789a49..b8cb2e8cace8a73cc75fb8f21be314ba78c7489e 100644 (file)
@@ -10,5 +10,6 @@ add_avr_library(
   AvrAdc.cpp
   AvrPwm.cpp
   AvrSpi.cpp
+  AvrI2C.cpp
    )
 
index 121b6ddda82c4fae19a7bedb2f9b293846e4773a..a8fc34f87e5c7fb66607113272c72da33ec0515f 100644 (file)
@@ -3,10 +3,12 @@
 
 class II2C
 {
-    void II2C() {}
+    public:
+    II2C() {};
 
-    virtual write(Uint8_t);
-    virtual read(Uint8_t);
+    virtual void write(Uint8_t argAddress,Uint8_t *argData, Uint8_t argLen);
+
+    virtual void read(Uint8_t argAddress,Uint8_t *argData ,Uint8_t argLen);
 };
 
 #endif
diff --git a/HAL/Abstract/IRtc.h b/HAL/Abstract/IRtc.h
new file mode 100644 (file)
index 0000000..7d46330
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __IRTC_H__
+#define __IRTC_H__
+
+typedef struct {
+    Uint8_t seconds;
+    Uint8_t min;
+    Uint8_t hour;
+    Uint8_t day;
+    Uint8_t month;
+    Uint8_t year;
+} RtcTime_t;
+
+/**
+ * \brief Abstract interface of services an Rtc must Provide
+ *
+ */
+class IRtc
+{
+    public:
+    virtual void setTime(const RtcTime_t &argTime) = 0;
+    
+    virtual void getTime(RtcTime_t &argTime) = 0;
+
+    virtual void toString(Uint8_t *argOutTime) = 0;
+};
+
+#endif
index fe4b380a44afb41f029af3ba4de7225cfe0372e1..4983705023db12de65c786dc1a692f335b0292f5 100644 (file)
@@ -5,6 +5,7 @@ add_avr_library(
   avrDrivers
   NetString.cpp
   Ili9341.cpp
+  DS3231.cpp
   XPT2046_Touchscreen.cpp
    )
 
index 5b1c1452f4c6d24cb601c9c46a9eaca7ded8d5d8..755d03fdd8532d621434e6153f85fa49f8bffa90 100644 (file)
@@ -1,9 +1,30 @@
-
+#include <Utils/StdTypes.h>
 #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)
+{
+}
index 957c4ac2fea41e344688fb0656b1d34b994c9145..beeee42137fccaf7f310a16c3ca0a25ad702e83a 100644 (file)
@@ -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 (file)
index 0000000..1e5b1a8
--- /dev/null
@@ -0,0 +1 @@
+Commande ECHO activ\82e.
diff --git a/HAL/Drivers/Eeprom32C32_64.h b/HAL/Drivers/Eeprom32C32_64.h
new file mode 100644 (file)
index 0000000..1e5b1a8
--- /dev/null
@@ -0,0 +1 @@
+Commande ECHO activ\82e.
index 3deebd21633ec9d62100a878f155334ad487b356..4187288a9dfe4449079547325eff52cfe9d97059 100644 (file)
@@ -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\