Commit 0ddffbaf925cb5e84ed68e49988f996280a49296
receivedFri, 16. Aug 2024, 18:07:27 (by user sx)
Fri, 16 Aug 2024 16:07:27 +0000 (18:07 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Fri, 16 Aug 2024 16:07:20 +0000 (18:07 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Fri, 16 Aug 2024 16:07:20 +0000 (18:07 +0200)
4 files changed:
software/nano-644/test_2024-07-23/src/main.cpp
software/nano-644/test_2024-07-23/src/main.hpp
software/nano-644/test_2024-07-23/src/units/rtc8563.cpp
software/nano-644/test_2024-07-23/src/units/rtc8563.hpp

index dfbe39770bd9961653081db309aedaf8deee34cd..2971b6e5809b44f238d1c6c871c638a16fcffc9d 100644 (file)
@@ -37,8 +37,10 @@ const char MAIN_CPP_TIME[] PROGMEM = __TIME__;
    const char MAIN_CPP_PART_NAME[] PROGMEM = "ATmega1284P";
 #endif
 
-const char DIVIDER[] PROGMEM = "\n====================================\n ";
-const char LINEFEED[] PROGMEM = "\n";
+const char PSTR_DIVIDER[] PROGMEM = "\n====================================\n ";
+const char PSTR_LINEFEED[] PROGMEM = "\n";
+const char PSTR_ERROR[] PROGMEM = "ERROR";
+const char PSTR_Done[] PROGMEM = "Done";
 
 extern "C" {
    void __cxa_pure_virtual () {}
@@ -138,7 +140,7 @@ extern "C" {
    I2c i2cSparkfun(I2c::SparkFunEnvCombo);
    I2c i2cMaster(I2c::Master);
    I2c i2cSlave(I2c::Slave);
-   Rtc8563 rtc8563;
+   Rtc8563 rtc8563(Rtc8563::NORMAL);
    Cc1101 cc1101Send(Cc1101::Send);
    Cc1101 cc1101Receive(Cc1101::Receive);
 }
@@ -160,6 +162,7 @@ int wait (uint32_t ms) {
 }
 
 int waitAndReadKey (uint32_t ms) {
+   keyUart0 = EOF;
    int key = wait(ms);
    keyUart0 = EOF;
    return key;
@@ -169,12 +172,12 @@ int main () {
 
    #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
    // Nano-644 LEDs (Green, Orange, Red)
-   DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2);
-   PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2));
+   DDRC |= (1 << PC7) | (1 << PC4) | (1 << PC3) | (1 << PC2);
+   PORTC &= ~((1 << PC7) | (1 << PC4) | (1 << PC3) | (1 << PC2));
 
    // Nano-644 push button SW2
-   DDRC &= ~(1 << DDC5); 
-   PORTC |= (1 << PORT5); // enable internal pullup resistor
+   DDRC &= ~(1 << PC5); 
+   PORTC |= (1 << PC5); // enable internal pullup resistor
    #endif
 
    #ifdef __AVR_ATmega328P__
@@ -217,19 +220,19 @@ int main () {
       uint16_t i;
       char s[4];
       do {
-         printf_P(LINEFEED);
-         printf_P(DIVIDER);
+         printf_P(PSTR_LINEFEED);
+         printf_P(PSTR_DIVIDER);
          printf_P(MAIN_CPP_PART_NAME); printf_P(PSTR(" / "));
          printf_P(MAIN_CPP_DATE); printf_P(PSTR(" / "));
          printf_P(MAIN_CPP_TIME);
-         printf_P(DIVIDER);
-         printf_P(LINEFEED);
+         printf_P(PSTR_DIVIDER);
+         printf_P(PSTR_LINEFEED);
          printf_P(PSTR("Available units:\n\n"));
          for (i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
             TestUnit *pu = unit[i];
             printf_P(PSTR("%3x ... "), i);
             printf_P(pu->getName());
-            printf_P(LINEFEED);
+            printf_P(PSTR_LINEFEED);
          }
          printf_P(PSTR("\nSelect unit: "));
          rIndex = 0; wIndex = 0;
index b10f038219a344fa559338fc3b8247651fa749a8..a7f2ae8068c509d9b81625c189d3c1ed6860105e 100644 (file)
@@ -12,6 +12,11 @@ extern int wait (uint32_t ms);
 extern int waitAndReadKey (uint32_t ms);
 extern uint64_t millis ();
 
+extern const char PSTR_DIVIDER[];
+extern const char PSTR_LINEFEED[];
+extern const char PSTR_ERROR[];
+extern const char PSTR_Done[];
+
 #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
    extern "C" {
       extern void flashRedLed (uint16_t ms);
index 9d262656f74633700ba5542b8e76a2bac1af10a2..5dc07fde3c1a19d65f8b235197796a613612d73e 100644 (file)
@@ -10,6 +10,8 @@
 
 // RTC BME653EMA on Nano-644
 
+const char PSTR_WEEKDAYS[] PROGMEM = "So\0Mo\0Di\0Mi\0Do\0Fr\0Sa\0";
+
 void Rtc8563::handleTwiIrq () {
    TWCR |= (1 << TWINT); // clear Interrupt Request
 }
@@ -23,8 +25,8 @@ int8_t Rtc8563::run (uint8_t subtest) { return -1; }
 #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
 
 void Rtc8563::init () {
-   PORTC |= (1 << PC7); // nInt
-   DDRC &= ~(1 << PC7);
+   PORTC &= ~(1 << PC7); // nInt and nPowerOn (Q7 -> BATTERY)
+   DDRC |= (1 << PC7);
    TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
    TWBR = 28; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
    TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
@@ -36,8 +38,12 @@ void Rtc8563::cleanup () {
    enabled = false;
    TWCR = (1 << TWEN);
    TWBR = 0;
-   PORTC &= ~(1 << PC7);
-   DDRC &= ~(1 << PC7);
+   // PORTC &= ~(1 << PC7);
+   // DDRC &= ~(1 << PC7);
+}
+
+PGM_P Rtc8563::getName () {
+   return PSTR("RTC-8563");
 }
 
 uint8_t Rtc8563::bcd2bin (uint8_t value) {
@@ -45,66 +51,91 @@ uint8_t Rtc8563::bcd2bin (uint8_t value) {
 }
 
 int8_t Rtc8563::run (uint8_t subtest) {
+   int key = EOF;
    if (subtest == 0) {
       // printf_P(PSTR(" BM280 ... "));
       rtc8563.begin(0x51);
+      Clock_t clock; memset(&clock, 0, sizeof(clock));
+      uint8_t bufferConfig[] = { 0x00, 0x00, 0x01, 0x01 };
+      // uint8_t bufferSetClock[] = { 0x02, 0x00, 0x00, 0x08, 0x16, 0x02, 0x08, 0x24 };
 
       uint8_t buffer[16] = {
          /* config       -> */ 0x00, 0x00,
-         /* enable timer -> */ 0x0d, 0x83,
-         /* set clock    -> */ 0x02, 0x00, 0x00, 0x08, 0x06, 0x02, 0x08, 0x24 
+         /* enable nINT  -> */ 0x01, 0x01, // TIE = 1
+         /* set clock    -> */ 0x02, 0x00, 0x00, 0x08, 0x16, 0x02, 0x08, 0x24 
       } ;
 
-      printf_P(PSTR("\n => init write: 0x00:0x00 0x00;  0x0d:0x83 0x80 => "));
-      if (!rtc8563.write(buffer, 2) || !rtc8563.write(&buffer[2], 2)) {
-      // if (!rtc8563.write(&buffer[2], 2)) {
-         printf_P(PSTR("E1"));
-      } else {
-         printf_P(PSTR("done"));
-      }
-
-      
-      printf_P(PSTR("\n => write clock ... "));
-      if (!rtc8563.write(&buffer[4], 8)) {
-      // if (!rtc8563.write(&buffer[2], 2)) {
-         printf_P(PSTR("E1"));
+      printf_P(PSTR("\n => config 8563 ... "));
+      if (!rtc8563.write(&bufferConfig[0], 2) || !rtc8563.write(&bufferConfig[2], 2)) {
+         printf_P(PSTR_ERROR);
       } else {
-         printf_P(PSTR("done"));
+         printf_P(PSTR_Done);
       }
-
+      printf_P(PSTR("\n press:"));
+      printf_P(PSTR("\n   t .... set timer"));
+      printf_P(PSTR("\n   p .... power off (PC7=1)"));
+      printf_P(PSTR("\n   c .... init clock"));
+      printf_P(PSTR("\n   w/W .. weekday (+/-)\n"));
+      printf_P(PSTR("\n   y/Y .. year (+/-)"));
+      printf_P(PSTR("\n   m/M .. month (+/-)"));
+      printf_P(PSTR("\n   d/D .. day (+/-)"));
+      printf_P(PSTR("\n   h/H .. hour (+/-)"));
+      printf_P(PSTR("\n   n/N .. minute (+/-)"));
+      printf_P(PSTR("\n   s/S .. second (+/-)\n"));
 
       do {
-         printf_P(PSTR("\n => read: 0x02:"));
-         buffer[0] = 2;
-         if (!rtc8563.write_then_read(buffer, 1, buffer, 7)) {
-            printf_P(PSTR("E2"));
-         } else {
-            for (uint8_t i = 0; i < 7; i++) {
-               printf_P(PSTR(" 0x%02x"), buffer[i]);
-            }
-            uint8_t sec = bcd2bin(buffer[0]);
-            uint8_t min = bcd2bin(buffer[1]);
-            uint8_t hrs = bcd2bin(buffer[2]);
-            uint8_t days = bcd2bin(buffer[3]);
-            uint8_t weekDay = bcd2bin(buffer[4]);
-            uint8_t month = bcd2bin(buffer[5]);
-            uint16_t year = 2000 + bcd2bin(buffer[6]);
-            PGM_P d;
-            switch (weekDay) {
-               case 0: d = PSTR("So"); break;
-               case 1: d = PSTR("Mo"); break;
-               case 2: d = PSTR("Di"); break;
-               case 3: d = PSTR("Mi"); break;
-               case 4: d = PSTR("Do"); break;
-               case 5: d = PSTR("Fr"); break;
-               case 6: d = PSTR("Sa"); break;
-               default: d = PSTR("??"); break;
-            }
-            printf_P(PSTR(" --> "));
-            printf_P(d);
-            printf_P(PSTR(", %04d-%02d-%02d %02d:%02d:%02d"), year, month, days, hrs, min, sec);
+         buffer[0] = 0;
+         printf_P(PSTR("\n => read register 0-15: "));
+         if (!rtc8563.write_then_read(buffer, 1, buffer, 16)) {
+            printf_P(PSTR_ERROR);
+            key = waitAndReadKey(1000);
+            continue;
+         }
+         memccpy(&clock, &buffer[2], sizeof(clock), sizeof(clock));
+         for (uint8_t i = 0; i < 7; i++) {
+            printf_P(PSTR(" 0x%02x"), buffer[i]);
+         }
+         uint16_t year = (clock.century ? 2100 : 2000) + bcd2bin(clock.yearH << 4 | clock.yearL);
+         int8_t month = bcd2bin(clock.monthH << 4 | clock.monthL);
+         int8_t day = bcd2bin(clock.dayH << 4 | clock.dayL);
+         int8_t hrs = bcd2bin(clock.hourH << 4 | clock.hourL);
+         int8_t min = bcd2bin(clock.minH << 4 | clock.minL);
+         int8_t sec = bcd2bin(clock.secH << 4 | clock.secL);
+         int8_t weekday = clock.weekday;
+
+         PGM_P d = clock.weekday >= 0 && clock.weekday < 7 ? &PSTR_WEEKDAYS[clock.weekday * 3] : PSTR("??");
+         printf_P(PSTR(" --> "));
+         printf_P(d);
+         printf_P(PSTR(", %04d-%02d-%02d %02d:%02d:%02d"), year, month, day, hrs, min, sec);
+         printf_P(PSTR(" - Timer=0x%02x"), buffer[15]);
+
+         key = waitAndReadKey(1000);
+         bool ok = true;
+         bool change = false;
+         switch (key) {
+            case 't': ok &= setTimer(10); break;
+            case 'c': ok &= setClock(5, 2024,8,16, 17,12,10 ); break; // ok &= rtc8563.write(bufferSetClock, sizeof(bufferSetClock)); break;
+            case 'p': powerOff(); break;
+            case 'y': year++; change = true; break;
+            case 'Y': year--; change = true; break;
+            case 'm': month++; change = true; break;
+            case 'M': month--; change = true; break;
+            case 'd': day++; change = true; break;
+            case 'D': day--; change = true; break;
+            case 'h': hrs++; change = true; break;
+            case 'H': hrs--; change = true; break;
+            case 'n': min++; change = true; break;
+            case 'N': min--; change = true; break;
+            case 's': sec++; change = true; break;
+            case 'S': sec--; change = true; break;
+            case 'w': weekday++; change = true; break;
+            case 'W': weekday--; change = true; break;
+         }
+         if (change) {
+            setClock(weekday, year, month, day, hrs, min, sec);
          }
-      } while (wait(1000) == EOF);
+         
+      } while (key != ESCAPE);
 
       return 0;
    }
@@ -112,5 +143,78 @@ int8_t Rtc8563::run (uint8_t subtest) {
    return -1;
 }
 
+bool Rtc8563::setTimer (uint8_t seconds) {
+   uint8_t i2cTimer[] = { 0x0f, seconds };
+   uint8_t i2cControl[] = { 0x0e, 0x80 | 0x02 }; // timer enable, 1Hz clock
+   printf_P(PSTR("\n Timer set to %ds ... "), seconds);
+   if (rtc8563.write(i2cTimer, 2) && rtc8563.write(i2cControl, 2)) {
+      printf_P(PSTR("OK"));
+      return true;
+   } else {
+      printf_P(PSTR("fails"));
+      return false;
+   }
+}
+
+bool Rtc8563::powerOff () {
+   int key = EOF;
+   if (PORTC & (1 << PC7)) {
+      printf_P(PSTR("\n power on ..."));
+      DDRC |= ( 1<< PC7);
+      PORTC &= ~(1 << PC7);
+   } else {
+      printf_P(PSTR("\n"));
+      key = EOF;
+      for (int8_t i = 9; i > 0 && key != ESCAPE; i--) {
+         printf_P(PSTR("\r press escape or power off in %ds  "), i);
+         key = waitAndReadKey(1000);
+      }
+      setTimer(10);
+      uint8_t b = 0x01; // clear timer flag and activate TIE
+      rtc8563.writeByteAndBuffer(0x01, &b, 1);
+      printf_P(PSTR("\n power off now ..."));
+      DDRC |= ( 1<< PC7);
+      PORTC |= (1 << PC7);
+      _delay_ms(5);
+      DDRC &= ~( 1<< PC7);
+      PORTC &= ~(1 << PC7);
+      waitAndReadKey(5000);
+      printf_P(PSTR("proceed"));
+   }
+   return true;
+}
+
+bool Rtc8563::setClock (int8_t weekday, uint16_t year, int8_t month, int8_t day, int8_t hour, int8_t min, int8_t sec) {
+   Clock_t clock;
+   clock.century = (year < 2000 || year > 2100) ? 1: 0;
+   uint8_t y = year % 100; clock.yearL = y % 10; clock.yearH = y / 10;
+
+   while (weekday < 0) { weekday += 7; }
+   while (weekday > 6) { weekday -= 7; }
+   clock.weekday =  weekday;
+
+   while (month < 1) { month += 12; }
+   while (month > 12) { month -= 12; }
+   clock.monthL = month % 10; clock.monthH = month / 10;
+   
+   while (day < 1) { day += 31; }
+   while (day > 31) { day -= 31; }
+   clock.dayL = day % 10; clock.dayH = day / 10;
+   
+   while (hour < 0) { hour += 24; }
+   while (hour > 23) { hour -= 24; }
+   clock.hourL = hour % 10; clock.hourH = hour / 10;
+   
+   while (min < 0) { min += 60; }
+   while (min > 59) { min -= 60; }
+   clock.minL = min % 10; clock.minH = min / 10;
+
+   while (sec < 0) { sec += 60; }
+   while (sec > 59) { sec -= 60; }
+   clock.secL = sec % 10; clock.secH = sec / 10;
+
+   return rtc8563.writeByteAndBuffer(0x02, (uint8_t *)(void *)&clock, sizeof(clock));
+}
+
 #endif
 
index 615583147591c52c1ff52907dadaa2361b2da864..07dbf441912d10ed1b30e5bd2ea9ec77064880e3 100644 (file)
 
 
 class Rtc8563 : public TestUnit {
+   public:
+      typedef enum { NORMAL } Rtc8563Mode_t;
+   
    private:
       I2cMaster rtc8563;
+      typedef struct {
+         uint8_t secL:4; uint8_t secH:3; uint8_t voltageLow:1;
+         uint8_t minL:4; uint8_t minH:2; uint8_t minuteBit76:2;
+         uint8_t hourL:4; uint8_t hourH:2; uint8_t hourBit76:2;
+         uint8_t dayL:4; uint8_t dayH:2; uint8_t dayBit76:2;
+         uint8_t weekday:3; uint8_t bit73:5;
+         uint8_t monthL:4; uint8_t monthH:1; uint8_t bit65:2; uint8_t century:1;
+         uint8_t yearL:4; uint8_t yearH:4;
+      } Clock_t; // identical to 8563 register 2..8
+      
 
    public:
       bool enabled;
 
    public:
-      Rtc8563 () { enabled = false; }
+      Rtc8563 (Rtc8563Mode_t mode) { enabled = false; this->mode = mode; }
       void tick1ms () { rtc8563.tick1ms(); }
       virtual void init ();
       virtual void cleanup ();
       virtual int8_t run (uint8_t subtest);
-      virtual PGM_P getName () { return PSTR("RTC-8563"); };
+      virtual PGM_P getName ();
       void handleTwiIrq ();
 
    private:
+      Rtc8563Mode_t mode;
       uint8_t bcd2bin (uint8_t value);
+      int8_t runModeNormal (uint8_t subtest);
+      int8_t runModeBattery (uint8_t subtest);
+      bool setTimer (uint8_t seconds);
+      bool powerOff ();
+      bool setClock (int8_t weekday, uint16_t year, int8_t month, int8_t day, int8_t hour, int8_t min, int8_t sec);
 };
 
 #endif
\ No newline at end of file