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 () {}
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);
}
}
int waitAndReadKey (uint32_t ms) {
+ keyUart0 = EOF;
int key = wait(ms);
keyUart0 = EOF;
return key;
#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__
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;
// 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
}
#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);
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) {
}
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;
}
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