From 0ddffbaf925cb5e84ed68e49988f996280a49296 Mon Sep 17 00:00:00 2001 From: Manfred Steiner Date: Fri, 16 Aug 2024 18:07:20 +0200 Subject: [PATCH] ... --- .../nano-644/test_2024-07-23/src/main.cpp | 27 ++- .../nano-644/test_2024-07-23/src/main.hpp | 5 + .../test_2024-07-23/src/units/rtc8563.cpp | 206 +++++++++++++----- .../test_2024-07-23/src/units/rtc8563.hpp | 23 +- 4 files changed, 196 insertions(+), 65 deletions(-) diff --git a/software/nano-644/test_2024-07-23/src/main.cpp b/software/nano-644/test_2024-07-23/src/main.cpp index dfbe397..2971b6e 100644 --- a/software/nano-644/test_2024-07-23/src/main.cpp +++ b/software/nano-644/test_2024-07-23/src/main.cpp @@ -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; diff --git a/software/nano-644/test_2024-07-23/src/main.hpp b/software/nano-644/test_2024-07-23/src/main.hpp index b10f038..a7f2ae8 100644 --- a/software/nano-644/test_2024-07-23/src/main.hpp +++ b/software/nano-644/test_2024-07-23/src/main.hpp @@ -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); diff --git a/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp b/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp index 9d26265..5dc07fd 100644 --- a/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp +++ b/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp @@ -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 diff --git a/software/nano-644/test_2024-07-23/src/units/rtc8563.hpp b/software/nano-644/test_2024-07-23/src/units/rtc8563.hpp index 6155831..07dbf44 100644 --- a/software/nano-644/test_2024-07-23/src/units/rtc8563.hpp +++ b/software/nano-644/test_2024-07-23/src/units/rtc8563.hpp @@ -10,23 +10,42 @@ 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 -- 2.39.5