From 70e4425ffe9e93508e53f28de46071243a459d88 Mon Sep 17 00:00:00 2001 From: Firemark Date: Mon, 20 Nov 2023 22:53:42 +0100 Subject: [PATCH 1/9] WIP arduino code --- zegar_pkp/zegar_pkp.ino | 125 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 zegar_pkp/zegar_pkp.ino diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino new file mode 100644 index 0000000..bc5eede --- /dev/null +++ b/zegar_pkp/zegar_pkp.ino @@ -0,0 +1,125 @@ +#include +#include + +#define PIN_ALARM 3 +#define PIN_A 4 +#define PIN_B 5 +#define PIN_BTN 6 +#define PIN_BTN_GND 7 +#define PIN_BTN_TURN_ON 8 +#define PIN_LED 13 + +#define TICK 250L +#define MINUTE ((60L * 1000L) / TICK) + +static bool polarity = false; +static int16_t slow_counter = 0; + +byte rtc_read(byte addr) { + Wire.beginTransmission(RTC_ADDR); + Wire.write((addr << 1) | 0x01); + byte data = Wire.read(); + Wire.endTransmission(); + return data; +} + +void rtc_write(byte addr, byte data) { + Wire.beginTransmission(RTC_ADDR); + Wire.write(addr << 1); + Wire.write(data); + Wire.endTransmission(); +} + +void setup() { + pinMode(PIN_A, OUTPUT); + pinMode(PIN_B, OUTPUT); + pinMode(PIN_LED, OUTPUT); + + pinMode(PIN_ALARM, INPUT_PULLUP); + pinMode(PIN_BTN, INPUT_PULLUP); + pinMode(PIN_BTN_TURN_ON, INPUT_PULLUP); + pinMode(PIN_BTN_GND, OUTPUT); + + digitalWrite(PIN_A, LOW); + digitalWrite(PIN_B, LOW); + digitalWrite(PIN_LED, LOW); + digitalWrite(PIN_BTN_GND, LOW); + + LowPower.attachInterruptWakeup(PIN_ALARM, alarm, FALLING); + LowPower.attachInterruptWakeup(PIN_BTN, change_time, FALLING); + + Wire.begin(); + if (rtc_read(0x0F) >> 7) { // When the microcontroller was turned off but RTC has working. + // TODO restore time + } else { // When RTC lost the power. + { // set time to 12:00:00AM (12h mode because of clock face). + rtc_write(0x00, 0b00000000); // 00 seconds. + rtc_write(0x01, 0b00000000); // 00 minutes. + rtc_write(0x02, 0b01000000); // 12AM hour. + } + { // set alarm1 (as last time) to 12:00:00AM + rtc_write(0x07, 0b00000000); // 00 seconds. + rtc_write(0x08, 0b00000000); // 00 minutes. + rtc_write(0x09, 0b01000000); // 12AM hour. + } + { // set alarm2 to 12:01PM + rtc_write(0x07, 0b00000000); // 00 seconds. + rtc_write(0x08, 0b00000000); // 00 minutes. + rtc_write(0x09, 0b01000000); // 12AM hour. + } + + rtc_write(0x0E, 0b00000110); // Set INT pin + set alarm2. + //rtc_write(0x0F, 0b00000000); // Reset oscillator stop flag. + } +} + +void tick() { + if (digitalRead(PIN_BTN_TURN_ON) == LOW) { + return; + } + if (polarity) { + digitalWrite(PIN_A, LOW); + digitalWrite(PIN_B, HIGH); + digitalWrite(PIN_LED, HIGH); + } else { + digitalWrite(PIN_A, HIGH); + digitalWrite(PIN_B, LOW); + digitalWrite(PIN_LED, LOW); + } + polarity = !polarity; +} + +void turn_off() { + digitalWrite(PIN_A, LOW); + digitalWrite(PIN_B, LOW); + digitalWrite(PIN_LED, LOW); +} + +int rtc_format_to_int(byte val) { + return val + (val >> 4) * 60; +} + +void loop() { + LowPower.sleep(); +} + +void alarm() { + tick(); + int minutes = rtc_format_to_int(rtc_read(0x01)); + int alarm_minutes = (minutes + 1) % 60; + rct_write(0x07, 0)); + rct_write(0x0B, int_to_rtc_format(alarm_minutes)); + turn_off(); +} + +void change_time() { + while (digitalRead(PIN_BTN) == LOW) { + tick(); + int minutes = rtc_format_to_int(rtc_read(0x01)); + int change_minutes = (minutes + 1) % 60; + rct_write(0x00, 0)); + rct_write(0x01, int_to_rtc_format(change_minutes)); + delayMicroseconds(1000L * TICK); + } + turn_off(); +} From ffa34526b41619d0e672a33a4855cb8f6aa21a99 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sat, 25 Nov 2023 23:48:22 +0100 Subject: [PATCH 2/9] Support interrupts and first try with RTC --- zegar_pkp/rtc.h | 99 +++++++++++++++++++++++++++++++++ zegar_pkp/zegar_pkp.ino | 119 +++++++++++++++++++--------------------- 2 files changed, 155 insertions(+), 63 deletions(-) create mode 100644 zegar_pkp/rtc.h diff --git a/zegar_pkp/rtc.h b/zegar_pkp/rtc.h new file mode 100644 index 0000000..e95c341 --- /dev/null +++ b/zegar_pkp/rtc.h @@ -0,0 +1,99 @@ +#pragma once + +#include + +class _Rtc { + public: + void begin() { + Wire.begin(); + } + + void reset() { + { // set time to 12:00:00AM (12h mode because of clock face). + _write(TIME_SECONDS_ADDR, 0b00000000); // 00 seconds. + _write(TIME_MINUTES_ADDR, 0b00000000); // 00 minutes. + _write(TIME_HOURS_ADDR, 0b01000000); // 12AM hour. + } + { // set alarm1 (as last time) to 12:00:00AM + _write(ALARM1_SECONDS_ADDR, 0b00000000); // 00 seconds. + _write(ALARM1_MINUTES_ADDR, 0b00000000); // 00 minutes. + _write(ALARM2_HOURS_ADDR, 0b01000000); // 12AM hour. + } + { // set alarm2 to 12:01PM + ALARM every second + _write(ALARM2_MINUTES_ADDR, 0b10000000); // 00 minutes. + _write(ALARM2_HOURS_ADDR, 0b11000000); // 12AM hour. + _write(ALARM2_DAYS_ADDR, 0b100000001); // 1 day? + } + + _write(CONTROL_ADDR, 0b00000110); // Set INT pin + set alarm2. + _write(STATUS_ADDR, 0b00000000); // Reset oscillator stop flag. + } + + byte get_seconds() { + return _seconds_decode(_read(TIME_SECONDS_ADDR)); + } + + byte get_minutes() { + return _minutes_decode(_read(TIME_MINUTES_ADDR)); + } + + byte get_hours() { + return _hours_decode(_read(TIME_HOURS_ADDR)); + } + + private: + const byte TIME_SECONDS_ADDR = 0x00; + const byte TIME_MINUTES_ADDR = 0x01; + const byte TIME_HOURS_ADDR = 0x02; + const byte ALARM1_SECONDS_ADDR = 0x07; + const byte ALARM1_MINUTES_ADDR = 0x08; + const byte ALARM1_HOURS_ADDR = 0x09; + const byte ALARM2_MINUTES_ADDR = 0x0B; + const byte ALARM2_HOURS_ADDR = 0x0C; + const byte ALARM2_DAYS_ADDR = 0x0D; + const byte CONTROL_ADDR = 0x0E; + const byte STATUS_ADDR = 0x0F; + const int RTC_ADDR = 0x68; + + byte _read(byte addr) { + Wire.beginTransmission(RTC_ADDR); + Wire.write(addr); + Wire.endTransmission(); + Wire.requestFrom(RTC_ADDR, 1); + while (Wire.available()) { + return Wire.read(); + } + } + + void _write(byte addr, byte data) { + Wire.beginTransmission(RTC_ADDR); + Wire.write(addr); + Wire.write(data); + Wire.endTransmission(); + } + + byte _seconds_decode(byte val) { + return (val & 0b1111) + ((val >> 4) & 0b111) * 10; + } + + byte _minutes_decode(byte val) { + return (val & 0b1111) + ((val >> 4) & 0b111) * 10; + } + + byte _hours_decode(byte val) { + return (val & 0b1111) + ((val >> 4) & 0b1) * 10; + } + + byte _seconds_encode(byte val) { + return (val % 10) + (((val / 10) % 6) << 4); + } + + byte _minutes_encode(byte val) { + return (val % 10) + (((val / 10) % 6) << 4); + } + + byte _hours_encode(byte val) { + return (val % 10) + (((val / 10) % 2) << 4); + } + +} Rtc; diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index bc5eede..43e6ef7 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -1,34 +1,21 @@ +#include "rtc.h" #include -#include +#include -#define PIN_ALARM 3 +#define PIN_ALARM 2 #define PIN_A 4 #define PIN_B 5 -#define PIN_BTN 6 -#define PIN_BTN_GND 7 -#define PIN_BTN_TURN_ON 8 +#define PIN_BTN 3 +#define PIN_BTN_TURN_ON 6 #define PIN_LED 13 #define TICK 250L #define MINUTE ((60L * 1000L) / TICK) +#define CLOCK_DEBUG 1 static bool polarity = false; -static int16_t slow_counter = 0; +static int16_t slow_counter = 0; -byte rtc_read(byte addr) { - Wire.beginTransmission(RTC_ADDR); - Wire.write((addr << 1) | 0x01); - byte data = Wire.read(); - Wire.endTransmission(); - return data; -} - -void rtc_write(byte addr, byte data) { - Wire.beginTransmission(RTC_ADDR); - Wire.write(addr << 1); - Wire.write(data); - Wire.endTransmission(); -} void setup() { pinMode(PIN_A, OUTPUT); @@ -38,39 +25,26 @@ void setup() { pinMode(PIN_ALARM, INPUT_PULLUP); pinMode(PIN_BTN, INPUT_PULLUP); pinMode(PIN_BTN_TURN_ON, INPUT_PULLUP); - pinMode(PIN_BTN_GND, OUTPUT); digitalWrite(PIN_A, LOW); digitalWrite(PIN_B, LOW); digitalWrite(PIN_LED, LOW); - digitalWrite(PIN_BTN_GND, LOW); - - LowPower.attachInterruptWakeup(PIN_ALARM, alarm, FALLING); - LowPower.attachInterruptWakeup(PIN_BTN, change_time, FALLING); - Wire.begin(); - if (rtc_read(0x0F) >> 7) { // When the microcontroller was turned off but RTC has working. - // TODO restore time - } else { // When RTC lost the power. - { // set time to 12:00:00AM (12h mode because of clock face). - rtc_write(0x00, 0b00000000); // 00 seconds. - rtc_write(0x01, 0b00000000); // 00 minutes. - rtc_write(0x02, 0b01000000); // 12AM hour. - } - { // set alarm1 (as last time) to 12:00:00AM - rtc_write(0x07, 0b00000000); // 00 seconds. - rtc_write(0x08, 0b00000000); // 00 minutes. - rtc_write(0x09, 0b01000000); // 12AM hour. - } - { // set alarm2 to 12:01PM - rtc_write(0x07, 0b00000000); // 00 seconds. - rtc_write(0x08, 0b00000000); // 00 minutes. - rtc_write(0x09, 0b01000000); // 12AM hour. - } - - rtc_write(0x0E, 0b00000110); // Set INT pin + set alarm2. - //rtc_write(0x0F, 0b00000000); // Reset oscillator stop flag. - } + attachInterrupt(digitalPinToInterrupt(PIN_ALARM), alarm, FALLING); + attachInterrupt(digitalPinToInterrupt(PIN_BTN), change_time, FALLING); + + Rtc.begin(); + Rtc.reset(); + +#if CLOCK_DEBUG + Serial.begin(19200); + Serial.println("INIT"); +#endif + + //if (rtc_read(0x0F) >> 7) { // When the microcontroller was turned off but RTC has working. + // // TODO restore time + //} else { // When RTC lost the power. + //} } void tick() { @@ -92,34 +66,53 @@ void tick() { void turn_off() { digitalWrite(PIN_A, LOW); digitalWrite(PIN_B, LOW); - digitalWrite(PIN_LED, LOW); -} - -int rtc_format_to_int(byte val) { - return val + (val >> 4) * 60; + digitalWrite(PIN_LED, LOW); } void loop() { - LowPower.sleep(); +#if CLOCK_DEBUG + byte seconds = Rtc.get_seconds(); + byte minutes = Rtc.get_minutes(); + byte hours = Rtc.get_hours(); + Serial.print("time: "); + if (hours < 10) Serial.print('0'); + Serial.print(hours); + Serial.print(':'); + if (minutes < 10) Serial.print('0'); + Serial.print(minutes); + Serial.print(':'); + if (seconds < 10) Serial.print('0'); + Serial.print(seconds); + Serial.print('\n'); + delay(1000L); +#else + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); +#endif + //change_time(); } void alarm() { + #if CLOCK_DEBUG + Serial.println("ALARM"); + #endif tick(); - int minutes = rtc_format_to_int(rtc_read(0x01)); - int alarm_minutes = (minutes + 1) % 60; - rct_write(0x07, 0)); - rct_write(0x0B, int_to_rtc_format(alarm_minutes)); + //int minutes = rtc_format_to_int(rtc_read(0x01)); + //int alarm_minutes = (minutes + 1) % 60; + //rtc_write(0x07, 0)); + //rtc_write(0x0B, int_to_rtc_format(alarm_minutes)); turn_off(); } void change_time() { while (digitalRead(PIN_BTN) == LOW) { tick(); - int minutes = rtc_format_to_int(rtc_read(0x01)); - int change_minutes = (minutes + 1) % 60; - rct_write(0x00, 0)); - rct_write(0x01, int_to_rtc_format(change_minutes)); - delayMicroseconds(1000L * TICK); + //int minutes = rtc_format_to_int(rtc_read(0x01)); + //int change_minutes = (minutes + 1) % 60; + //rtc_write(0x00, 0); + //rtc_write(0x01, int_to_rtc_format(change_minutes)); + for(int tick = 0; tick < 1000L; tick++) { + delayMicroseconds(TICK); + } } turn_off(); } From f09d6f6a42a6378e2db8ca83d3e41302039579b5 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sun, 26 Nov 2023 01:35:17 +0100 Subject: [PATCH 3/9] manage logic, correctly support time and alarms --- zegar_pkp/rtc.h | 81 ++++++++++++++++++---- zegar_pkp/zegar_pkp.ino | 146 ++++++++++++++++++++++++++++++---------- 2 files changed, 179 insertions(+), 48 deletions(-) diff --git a/zegar_pkp/rtc.h b/zegar_pkp/rtc.h index e95c341..fc3cfa2 100644 --- a/zegar_pkp/rtc.h +++ b/zegar_pkp/rtc.h @@ -2,6 +2,11 @@ #include +#define RTC_STATUS_FLAG_OSF 7 +#define RTC_STATUS_FLAG_BSY 2 +#define RTC_STATUS_FLAG_A2F 1 +#define RTC_STATUS_FLAG_A1F 0 + class _Rtc { public: void begin() { @@ -10,21 +15,21 @@ class _Rtc { void reset() { { // set time to 12:00:00AM (12h mode because of clock face). - _write(TIME_SECONDS_ADDR, 0b00000000); // 00 seconds. - _write(TIME_MINUTES_ADDR, 0b00000000); // 00 minutes. - _write(TIME_HOURS_ADDR, 0b01000000); // 12AM hour. + _write(TIME_SECONDS_ADDR, _seconds_encode(0)); + _write(TIME_MINUTES_ADDR, _minutes_encode(0)); + _write(TIME_HOURS_ADDR, _hours_encode(12)); // 12AM hour. } { // set alarm1 (as last time) to 12:00:00AM - _write(ALARM1_SECONDS_ADDR, 0b00000000); // 00 seconds. - _write(ALARM1_MINUTES_ADDR, 0b00000000); // 00 minutes. - _write(ALARM2_HOURS_ADDR, 0b01000000); // 12AM hour. + _write(ALARM1_SECONDS_ADDR, _seconds_encode(0)); + _write(ALARM1_MINUTES_ADDR, _minutes_encode(0)); + _write(ALARM1_HOURS_ADDR, _hours_encode(12)); } { // set alarm2 to 12:01PM + ALARM every second - _write(ALARM2_MINUTES_ADDR, 0b10000000); // 00 minutes. - _write(ALARM2_HOURS_ADDR, 0b11000000); // 12AM hour. - _write(ALARM2_DAYS_ADDR, 0b100000001); // 1 day? + _write(ALARM2_MINUTES_ADDR, ALARM_FLAG |_minutes_encode(0)); + _write(ALARM2_HOURS_ADDR, ALARM_FLAG | _hours_encode(12)); + _write(ALARM2_DAYS_ADDR, ALARM_FLAG | 1); } - + _write(CONTROL_ADDR, 0b00000110); // Set INT pin + set alarm2. _write(STATUS_ADDR, 0b00000000); // Reset oscillator stop flag. } @@ -40,6 +45,54 @@ class _Rtc { byte get_hours() { return _hours_decode(_read(TIME_HOURS_ADDR)); } + + byte get_alarm1_seconds() { + return _seconds_decode(_read(ALARM1_SECONDS_ADDR)); + } + + byte get_alarm1_minutes() { + return _minutes_decode(_read(ALARM1_MINUTES_ADDR)); + } + + byte get_alarm1_hours() { + return _hours_decode(_read(ALARM1_HOURS_ADDR)); + } + + byte get_status() { + return _read(STATUS_ADDR); + } + + void set_seconds(byte seconds) { + _write(TIME_SECONDS_ADDR, _seconds_encode(seconds)); + } + + void set_minutes(byte minutes) { + _write(TIME_MINUTES_ADDR, _seconds_encode(minutes)); + } + + void set_hours(byte hours) { + _write(TIME_HOURS_ADDR, _seconds_encode(hours)); + } + + void set_alarm1_seconds(byte seconds) { + _write(ALARM1_SECONDS_ADDR, _seconds_encode(seconds)); + } + + void set_alarm1_minutes(byte minutes) { + _write(ALARM1_MINUTES_ADDR, _seconds_encode(minutes)); + } + + void set_alarm1_hours(byte hours) { + _write(ALARM1_HOURS_ADDR, _seconds_encode(hours)); + } + + void clear_alarm1() { + _write(STATUS_ADDR, get_status() & ~0b01); + } + + void clear_alarm2() { + _write(STATUS_ADDR, get_status() & ~0b10); + } private: const byte TIME_SECONDS_ADDR = 0x00; @@ -53,6 +106,8 @@ class _Rtc { const byte ALARM2_DAYS_ADDR = 0x0D; const byte CONTROL_ADDR = 0x0E; const byte STATUS_ADDR = 0x0F; + const byte HOUR12_FLAG = 0b01000000; + const byte ALARM_FLAG = 0b10000000; const int RTC_ADDR = 0x68; byte _read(byte addr) { @@ -85,15 +140,15 @@ class _Rtc { } byte _seconds_encode(byte val) { - return (val % 10) + (((val / 10) % 6) << 4); + return (val % 10) | (((val / 10) % 6) << 4); } byte _minutes_encode(byte val) { - return (val % 10) + (((val / 10) % 6) << 4); + return (val % 10) | (((val / 10) % 6) << 4); } byte _hours_encode(byte val) { - return (val % 10) + (((val / 10) % 2) << 4); + return HOUR12_FLAG | (val % 10) | (((val / 10) % 2) << 4); } } Rtc; diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index 43e6ef7..f4df8e5 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -10,12 +10,13 @@ #define PIN_LED 13 #define TICK 250L -#define MINUTE ((60L * 1000L) / TICK) #define CLOCK_DEBUG 1 -static bool polarity = false; -static int16_t slow_counter = 0; +enum class Event {WAIT=0, ALARM=1, CHANGE_TIME=2, SYNC=3}; + +static bool polarity = false; +static Event event = Event::WAIT; void setup() { pinMode(PIN_A, OUTPUT); @@ -34,17 +35,18 @@ void setup() { attachInterrupt(digitalPinToInterrupt(PIN_BTN), change_time, FALLING); Rtc.begin(); - Rtc.reset(); + if (Rtc.get_status() & RTC_STATUS_FLAG_OSF) { // When RTC lost the power. + Rtc.reset(); + } else { // When the microcontroller was turned off but RTC was working. + Rtc.clear_alarm2(); + // TODO + } #if CLOCK_DEBUG Serial.begin(19200); + while(!Serial); Serial.println("INIT"); #endif - - //if (rtc_read(0x0F) >> 7) { // When the microcontroller was turned off but RTC has working. - // // TODO restore time - //} else { // When RTC lost the power. - //} } void tick() { @@ -69,12 +71,8 @@ void turn_off() { digitalWrite(PIN_LED, LOW); } -void loop() { #if CLOCK_DEBUG - byte seconds = Rtc.get_seconds(); - byte minutes = Rtc.get_minutes(); - byte hours = Rtc.get_hours(); - Serial.print("time: "); +void print_time(byte hours, byte minutes, byte seconds) { if (hours < 10) Serial.print('0'); Serial.print(hours); Serial.print(':'); @@ -83,36 +81,114 @@ void loop() { Serial.print(':'); if (seconds < 10) Serial.print('0'); Serial.print(seconds); +} + +void print_byte(byte val) { + String a(8); + for(byte i = 0; i < 8; i++) { + a[7-i] = val & 1 ? '1' : '0'; + val = val >> 1; + } + Serial.print(a); +} +#endif + +void manage_event() { + switch(event) { + case Event::ALARM: + tick(); + delayMicroseconds(100L); // wait some time to move the motor. + turn_off(); + Rtc.clear_alarm2(); + // save last viewed time + byte seconds = Rtc.get_seconds(); + byte minutes = Rtc.get_minutes(); + byte hours = Rtc.get_hours(); + Rtc.set_alarm1_seconds(seconds); + Rtc.set_alarm1_minutes(minutes); + Rtc.set_alarm1_hours(hours); + event = Event::WAIT; + break; + case Event::CHANGE_TIME: + event = Event::WAIT; + while (digitalRead(PIN_BTN) == LOW) { + tick(); + byte minutes = Rtc.get_minutes(); + byte hours = Rtc.get_hours(); + minutes += 1; + if (minutes >= 60) { + minutes = 0; + hours += 1; + } + if (hours > 12) { + hours = 1; + } + Rtc.set_minutes(minutes); + Rtc.set_hours(hours); + Rtc.set_alarm1_minutes(minutes); + Rtc.set_alarm1_hours(hours); + for(int t = 0; t < 1000L; t++) { + delayMicroseconds(TICK); + } + } + turn_off(); + break; + default: + event = Event::WAIT; + break; + } +} + +void loop() { +#if CLOCK_DEBUG +static unsigned int iii = 0; +static unsigned char iiii = 0; +static Event prev_event = event; +if (event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { + prev_event = event; + Serial.print("event: "); + switch(event) { + case Event::WAIT: + Serial.print("WAIT "); + break; + case Event::ALARM: + Serial.print("ALARM "); + break; + case Event::CHANGE_TIME: + Serial.print("CHANGE_TIME"); + break; + case Event::SYNC: + Serial.print("SYNC "); + break; + default: + Serial.print("??? "); + break; + } + Serial.print(" time: "); + print_time(Rtc.get_hours(), Rtc.get_minutes(), Rtc.get_seconds()); + Serial.print(" alarm1: "); + print_time(Rtc.get_alarm1_hours(), Rtc.get_alarm1_minutes(), Rtc.get_alarm1_seconds()); + Serial.print(" status: "); + print_byte(Rtc.get_status()); Serial.print('\n'); - delay(1000L); + delayMicroseconds(10000L); +} #else LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); #endif - //change_time(); + manage_event(); } void alarm() { - #if CLOCK_DEBUG - Serial.println("ALARM"); - #endif - tick(); - //int minutes = rtc_format_to_int(rtc_read(0x01)); - //int alarm_minutes = (minutes + 1) % 60; - //rtc_write(0x07, 0)); - //rtc_write(0x0B, int_to_rtc_format(alarm_minutes)); - turn_off(); + if (event >= Event::ALARM) { + return; + } + event = Event::ALARM; } void change_time() { - while (digitalRead(PIN_BTN) == LOW) { - tick(); - //int minutes = rtc_format_to_int(rtc_read(0x01)); - //int change_minutes = (minutes + 1) % 60; - //rtc_write(0x00, 0); - //rtc_write(0x01, int_to_rtc_format(change_minutes)); - for(int tick = 0; tick < 1000L; tick++) { - delayMicroseconds(TICK); - } + if (event >= Event::CHANGE_TIME) { + return; } - turn_off(); + event = Event::CHANGE_TIME; } From 8c8f72f9faba014e4e5debeadc6fbfbf935da205 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sun, 26 Nov 2023 02:05:14 +0100 Subject: [PATCH 4/9] support sync --- zegar_pkp/zegar_pkp.ino | 82 +++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index f4df8e5..c94a190 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -35,11 +35,12 @@ void setup() { attachInterrupt(digitalPinToInterrupt(PIN_BTN), change_time, FALLING); Rtc.begin(); - if (Rtc.get_status() & RTC_STATUS_FLAG_OSF) { // When RTC lost the power. + if (Rtc.get_status() & (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. Rtc.reset(); + event = Event::WAIT; } else { // When the microcontroller was turned off but RTC was working. Rtc.clear_alarm2(); - // TODO + event = Event::SYNC; } #if CLOCK_DEBUG @@ -93,9 +94,20 @@ void print_byte(byte val) { } #endif +inline void inc_time(byte* minutes, byte* hours) { + *minutes += 1; + if (*minutes >= 60) { + *minutes = 0; + *hours += 1; + } + if (*hours > 12) { + *hours = 1; + } +} + void manage_event() { switch(event) { - case Event::ALARM: + case Event::ALARM: { tick(); delayMicroseconds(100L); // wait some time to move the motor. turn_off(); @@ -108,21 +120,14 @@ void manage_event() { Rtc.set_alarm1_minutes(minutes); Rtc.set_alarm1_hours(hours); event = Event::WAIT; - break; - case Event::CHANGE_TIME: + } break; + case Event::CHANGE_TIME: { event = Event::WAIT; while (digitalRead(PIN_BTN) == LOW) { tick(); byte minutes = Rtc.get_minutes(); byte hours = Rtc.get_hours(); - minutes += 1; - if (minutes >= 60) { - minutes = 0; - hours += 1; - } - if (hours > 12) { - hours = 1; - } + inc_time(&minutes, &hours); Rtc.set_minutes(minutes); Rtc.set_hours(hours); Rtc.set_alarm1_minutes(minutes); @@ -132,10 +137,40 @@ void manage_event() { } } turn_off(); - break; - default: + Rtc.clear_alarm2(); + } break; + case Event::SYNC: { + byte last_set_minutes = Rtc.get_alarm1_minutes(); + byte last_set_hours = Rtc.get_alarm1_hours(); + int last_set_total_minutes = (int)last_set_minutes + ((int)last_set_hours % 12) * 60; + + byte current_minutes = Rtc.get_minutes(); + byte current_hours = Rtc.get_hours(); + int current_total_minutes = (int)current_minutes + ((int)current_hours % 12) * 60; + + int lack_minutes; + if (last_set_total_minutes <= current_total_minutes) { + lack_minutes = current_total_minutes - last_set_total_minutes; + } else { + lack_minutes = current_total_minutes + 12 * 60 - last_set_total_minutes; + } + + for (int i = 0; i < lack_minutes; i++) { + tick(); + inc_time(&last_set_minutes, &last_set_hours); + Rtc.set_alarm1_minutes(last_set_minutes); + Rtc.set_alarm1_hours(last_set_hours); + for(int t = 0; t < 1000L; t++) { + delayMicroseconds(TICK); + } + } + turn_off(); + Rtc.clear_alarm2(); event = Event::WAIT; - break; + } break; + default: { + event = Event::WAIT; + } break; } } @@ -179,16 +214,17 @@ if (event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { manage_event(); } -void alarm() { - if (event >= Event::ALARM) { +inline void int_change_event(Event e) { + if (event >= e) { return; } - event = Event::ALARM; + event = e; +} + +void alarm() { + int_change_event(Event::ALARM); } void change_time() { - if (event >= Event::CHANGE_TIME) { - return; - } - event = Event::CHANGE_TIME; + int_change_event(Event::CHANGE_TIME); } From d3452262228dc47bb371936a84ae25f78a2c54a0 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sun, 26 Nov 2023 19:54:38 +0100 Subject: [PATCH 5/9] manage event now dont use global variable, move alarm action to sync action --- zegar_pkp/rtc.h | 4 +++ zegar_pkp/zegar_pkp.ino | 69 +++++++++++++++++------------------------ 2 files changed, 33 insertions(+), 40 deletions(-) diff --git a/zegar_pkp/rtc.h b/zegar_pkp/rtc.h index fc3cfa2..cf63af7 100644 --- a/zegar_pkp/rtc.h +++ b/zegar_pkp/rtc.h @@ -62,6 +62,10 @@ class _Rtc { return _read(STATUS_ADDR); } + byte get_control() { + return _read(CONTROL_ADDR); + } + void set_seconds(byte seconds) { _write(TIME_SECONDS_ADDR, _seconds_encode(seconds)); } diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index c94a190..b96aca5 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -9,14 +9,11 @@ #define PIN_BTN_TURN_ON 6 #define PIN_LED 13 -#define TICK 250L +#define TICK 500L #define CLOCK_DEBUG 1 - enum class Event {WAIT=0, ALARM=1, CHANGE_TIME=2, SYNC=3}; - -static bool polarity = false; -static Event event = Event::WAIT; +static Event global_event = Event::WAIT; void setup() { pinMode(PIN_A, OUTPUT); @@ -37,10 +34,10 @@ void setup() { Rtc.begin(); if (Rtc.get_status() & (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. Rtc.reset(); - event = Event::WAIT; + global_event = Event::WAIT; } else { // When the microcontroller was turned off but RTC was working. Rtc.clear_alarm2(); - event = Event::SYNC; + global_event = Event::SYNC; } #if CLOCK_DEBUG @@ -51,6 +48,7 @@ void setup() { } void tick() { + static bool polarity = false; if (digitalRead(PIN_BTN_TURN_ON) == LOW) { return; } @@ -85,7 +83,7 @@ void print_time(byte hours, byte minutes, byte seconds) { } void print_byte(byte val) { - String a(8); + char a[9] = {0}; for(byte i = 0; i < 8; i++) { a[7-i] = val & 1 ? '1' : '0'; val = val >> 1; @@ -105,24 +103,15 @@ inline void inc_time(byte* minutes, byte* hours) { } } -void manage_event() { +inline void delay_tick() { + for(int t = 0; t < 1000L; t++) { + delayMicroseconds(TICK); + } +} + +inline Event manage_event(Event event) { switch(event) { - case Event::ALARM: { - tick(); - delayMicroseconds(100L); // wait some time to move the motor. - turn_off(); - Rtc.clear_alarm2(); - // save last viewed time - byte seconds = Rtc.get_seconds(); - byte minutes = Rtc.get_minutes(); - byte hours = Rtc.get_hours(); - Rtc.set_alarm1_seconds(seconds); - Rtc.set_alarm1_minutes(minutes); - Rtc.set_alarm1_hours(hours); - event = Event::WAIT; - } break; case Event::CHANGE_TIME: { - event = Event::WAIT; while (digitalRead(PIN_BTN) == LOW) { tick(); byte minutes = Rtc.get_minutes(); @@ -132,13 +121,13 @@ void manage_event() { Rtc.set_hours(hours); Rtc.set_alarm1_minutes(minutes); Rtc.set_alarm1_hours(hours); - for(int t = 0; t < 1000L; t++) { - delayMicroseconds(TICK); - } + delay_tick(); } turn_off(); Rtc.clear_alarm2(); + return Event::WAIT; } break; + case Event::ALARM: case Event::SYNC: { byte last_set_minutes = Rtc.get_alarm1_minutes(); byte last_set_hours = Rtc.get_alarm1_hours(); @@ -160,16 +149,14 @@ void manage_event() { inc_time(&last_set_minutes, &last_set_hours); Rtc.set_alarm1_minutes(last_set_minutes); Rtc.set_alarm1_hours(last_set_hours); - for(int t = 0; t < 1000L; t++) { - delayMicroseconds(TICK); - } + delay_tick(); } turn_off(); Rtc.clear_alarm2(); - event = Event::WAIT; + return Event::WAIT; } break; default: { - event = Event::WAIT; + return Event::WAIT; } break; } } @@ -178,11 +165,11 @@ void loop() { #if CLOCK_DEBUG static unsigned int iii = 0; static unsigned char iiii = 0; -static Event prev_event = event; -if (event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { - prev_event = event; +static Event prev_event = global_event; +if (global_event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { + prev_event = global_event; Serial.print("event: "); - switch(event) { + switch(global_event) { case Event::WAIT: Serial.print("WAIT "); break; @@ -205,20 +192,22 @@ if (event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { print_time(Rtc.get_alarm1_hours(), Rtc.get_alarm1_minutes(), Rtc.get_alarm1_seconds()); Serial.print(" status: "); print_byte(Rtc.get_status()); + Serial.print(" control: "); + print_byte(Rtc.get_control()); Serial.print('\n'); delayMicroseconds(10000L); } #else LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); #endif - manage_event(); + global_event = manage_event(global_event); } -inline void int_change_event(Event e) { - if (event >= e) { +inline void int_change_event(Event event) { + if (global_event >= event) { return; } - event = e; + global_event = event; } void alarm() { From f673e5e9035a0686e141a1d66ebe473558efd114 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sun, 26 Nov 2023 20:24:10 +0100 Subject: [PATCH 6/9] Add Motor and Time classes, refactorning --- zegar_pkp/motor.h | 37 ++++++++++++++ zegar_pkp/time.h | 31 ++++++++++++ zegar_pkp/zegar_pkp.ino | 107 ++++++++++++++++------------------------ 3 files changed, 110 insertions(+), 65 deletions(-) create mode 100644 zegar_pkp/motor.h create mode 100644 zegar_pkp/time.h diff --git a/zegar_pkp/motor.h b/zegar_pkp/motor.h new file mode 100644 index 0000000..054b412 --- /dev/null +++ b/zegar_pkp/motor.h @@ -0,0 +1,37 @@ +#pragma once + +#define PIN_A 4 +#define PIN_B 5 +#define PIN_LED 13 + +class _Motor { + public: + void begin() { + _polarity = false; + pinMode(PIN_A, OUTPUT); + pinMode(PIN_B, OUTPUT); + pinMode(PIN_LED, OUTPUT); + turn_off(); + } + + void turn_off() { + digitalWrite(PIN_A, LOW); + digitalWrite(PIN_B, LOW); + digitalWrite(PIN_LED, LOW); + } + + void tick() { + if (_polarity) { + digitalWrite(PIN_A, LOW); + digitalWrite(PIN_B, HIGH); + digitalWrite(PIN_LED, HIGH); + } else { + digitalWrite(PIN_A, HIGH); + digitalWrite(PIN_B, LOW); + digitalWrite(PIN_LED, LOW); + } + _polarity = !_polarity; +} + private: + bool _polarity; +} Motor; diff --git a/zegar_pkp/time.h b/zegar_pkp/time.h new file mode 100644 index 0000000..d7c019a --- /dev/null +++ b/zegar_pkp/time.h @@ -0,0 +1,31 @@ +#pragma once + +class Time { + public: + Time(byte minutes, byte hours) : _minutes(minutes), _hours(hours) {} + inline byte minutes() { return _minutes; } + inline byte hours() { return _hours; } + + inline int get_total_minutes() { + return (int)_minutes + ((int)_hours % 12) * 60; + } + + inline void increment_minute() { + _minutes += 1; + if (_minutes >= 60) { + _minutes = 0; + increment_hour(); + } + } + + inline void increment_hour() { + _hours += 1; + if (_hours > 12) { + _hours = 1; + } + } + + private: + byte _minutes; + byte _hours; +}; diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index b96aca5..2e5438c 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -1,13 +1,13 @@ #include "rtc.h" +#include "motor.h" +#include "time.h" + #include #include #define PIN_ALARM 2 -#define PIN_A 4 -#define PIN_B 5 #define PIN_BTN 3 #define PIN_BTN_TURN_ON 6 -#define PIN_LED 13 #define TICK 500L #define CLOCK_DEBUG 1 @@ -16,22 +16,16 @@ enum class Event {WAIT=0, ALARM=1, CHANGE_TIME=2, SYNC=3}; static Event global_event = Event::WAIT; void setup() { - pinMode(PIN_A, OUTPUT); - pinMode(PIN_B, OUTPUT); - pinMode(PIN_LED, OUTPUT); - pinMode(PIN_ALARM, INPUT_PULLUP); pinMode(PIN_BTN, INPUT_PULLUP); pinMode(PIN_BTN_TURN_ON, INPUT_PULLUP); - digitalWrite(PIN_A, LOW); - digitalWrite(PIN_B, LOW); - digitalWrite(PIN_LED, LOW); - attachInterrupt(digitalPinToInterrupt(PIN_ALARM), alarm, FALLING); attachInterrupt(digitalPinToInterrupt(PIN_BTN), change_time, FALLING); + Motor.begin(); Rtc.begin(); + if (Rtc.get_status() & (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. Rtc.reset(); global_event = Event::WAIT; @@ -47,29 +41,6 @@ void setup() { #endif } -void tick() { - static bool polarity = false; - if (digitalRead(PIN_BTN_TURN_ON) == LOW) { - return; - } - if (polarity) { - digitalWrite(PIN_A, LOW); - digitalWrite(PIN_B, HIGH); - digitalWrite(PIN_LED, HIGH); - } else { - digitalWrite(PIN_A, HIGH); - digitalWrite(PIN_B, LOW); - digitalWrite(PIN_LED, LOW); - } - polarity = !polarity; -} - -void turn_off() { - digitalWrite(PIN_A, LOW); - digitalWrite(PIN_B, LOW); - digitalWrite(PIN_LED, LOW); -} - #if CLOCK_DEBUG void print_time(byte hours, byte minutes, byte seconds) { if (hours < 10) Serial.print('0'); @@ -92,50 +63,55 @@ void print_byte(byte val) { } #endif -inline void inc_time(byte* minutes, byte* hours) { - *minutes += 1; - if (*minutes >= 60) { - *minutes = 0; - *hours += 1; - } - if (*hours > 12) { - *hours = 1; - } -} - inline void delay_tick() { for(int t = 0; t < 1000L; t++) { delayMicroseconds(TICK); } } +inline Time get_time_from_rtc() { + return {Rtc.get_minutes(), Rtc.get_hours()}; +} + +inline Time get_alarm1_from_rtc() { + return {Rtc.get_alarm1_minutes(), Rtc.get_alarm1_hours()}; +} + +inline void set_time_in_rtc(const Time & t) { + Rtc.set_minutes(t.minutes()); + Rtc.set_hours(t.hours()); +} + +inline void set_alarm1_in_rtc(const Time & t) { + Rtc.set_alarm1_minutes(t.minutes()); + Rtc.set_alarm1_hours(t.hours()); +} + inline Event manage_event(Event event) { switch(event) { case Event::CHANGE_TIME: { while (digitalRead(PIN_BTN) == LOW) { - tick(); - byte minutes = Rtc.get_minutes(); - byte hours = Rtc.get_hours(); - inc_time(&minutes, &hours); - Rtc.set_minutes(minutes); - Rtc.set_hours(hours); - Rtc.set_alarm1_minutes(minutes); - Rtc.set_alarm1_hours(hours); + Motor.tick(); + + Time new_time = get_time_from_rtc(); + new_time.increment_minute(); + + set_time_in_rtc(new_time); + set_alarm1_in_rtc(new_time); + delay_tick(); } - turn_off(); + Motor.turn_off(); Rtc.clear_alarm2(); return Event::WAIT; } break; case Event::ALARM: case Event::SYNC: { - byte last_set_minutes = Rtc.get_alarm1_minutes(); - byte last_set_hours = Rtc.get_alarm1_hours(); - int last_set_total_minutes = (int)last_set_minutes + ((int)last_set_hours % 12) * 60; + Time last_set_time = get_alarm1_from_rtc(); + int last_set_total_minutes = last_set_time.get_total_minutes(); - byte current_minutes = Rtc.get_minutes(); - byte current_hours = Rtc.get_hours(); - int current_total_minutes = (int)current_minutes + ((int)current_hours % 12) * 60; + Time current_time = get_time_from_rtc(); + int current_total_minutes = current_time.get_total_minutes(); int lack_minutes; if (last_set_total_minutes <= current_total_minutes) { @@ -145,13 +121,14 @@ inline Event manage_event(Event event) { } for (int i = 0; i < lack_minutes; i++) { - tick(); - inc_time(&last_set_minutes, &last_set_hours); - Rtc.set_alarm1_minutes(last_set_minutes); - Rtc.set_alarm1_hours(last_set_hours); + if (digitalRead(PIN_BTN_TURN_ON) == HIGH) { + Motor.tick(); + } + last_set_time.increment_minute(); + set_alarm1_in_rtc(last_set_time); delay_tick(); } - turn_off(); + Motor.turn_off(); Rtc.clear_alarm2(); return Event::WAIT; } break; From f94a0cdd8e50e2dba890753abdc9eb3db5e71311 Mon Sep 17 00:00:00 2001 From: Firemark Date: Sun, 26 Nov 2023 20:27:01 +0100 Subject: [PATCH 7/9] Clang format --- zegar_pkp/motor.h | 9 ++- zegar_pkp/rtc.h | 64 ++++++--------- zegar_pkp/time.h | 8 +- zegar_pkp/zegar_pkp.ino | 174 ++++++++++++++++++++-------------------- 4 files changed, 119 insertions(+), 136 deletions(-) diff --git a/zegar_pkp/motor.h b/zegar_pkp/motor.h index 054b412..31c6a2e 100644 --- a/zegar_pkp/motor.h +++ b/zegar_pkp/motor.h @@ -5,7 +5,7 @@ #define PIN_LED 13 class _Motor { - public: +public: void begin() { _polarity = false; pinMode(PIN_A, OUTPUT); @@ -14,7 +14,7 @@ class _Motor { turn_off(); } - void turn_off() { + void turn_off() { digitalWrite(PIN_A, LOW); digitalWrite(PIN_B, LOW); digitalWrite(PIN_LED, LOW); @@ -31,7 +31,8 @@ class _Motor { digitalWrite(PIN_LED, LOW); } _polarity = !_polarity; -} - private: + } + +private: bool _polarity; } Motor; diff --git a/zegar_pkp/rtc.h b/zegar_pkp/rtc.h index cf63af7..a7b524f 100644 --- a/zegar_pkp/rtc.h +++ b/zegar_pkp/rtc.h @@ -8,10 +8,8 @@ #define RTC_STATUS_FLAG_A1F 0 class _Rtc { - public: - void begin() { - Wire.begin(); - } +public: + void begin() { Wire.begin(); } void reset() { { // set time to 12:00:00AM (12h mode because of clock face). @@ -25,46 +23,34 @@ class _Rtc { _write(ALARM1_HOURS_ADDR, _hours_encode(12)); } { // set alarm2 to 12:01PM + ALARM every second - _write(ALARM2_MINUTES_ADDR, ALARM_FLAG |_minutes_encode(0)); + _write(ALARM2_MINUTES_ADDR, ALARM_FLAG | _minutes_encode(0)); _write(ALARM2_HOURS_ADDR, ALARM_FLAG | _hours_encode(12)); - _write(ALARM2_DAYS_ADDR, ALARM_FLAG | 1); + _write(ALARM2_DAYS_ADDR, ALARM_FLAG | 1); } _write(CONTROL_ADDR, 0b00000110); // Set INT pin + set alarm2. - _write(STATUS_ADDR, 0b00000000); // Reset oscillator stop flag. + _write(STATUS_ADDR, 0b00000000); // Reset oscillator stop flag. } - byte get_seconds() { - return _seconds_decode(_read(TIME_SECONDS_ADDR)); - } - - byte get_minutes() { - return _minutes_decode(_read(TIME_MINUTES_ADDR)); - } - - byte get_hours() { - return _hours_decode(_read(TIME_HOURS_ADDR)); - } + byte get_seconds() { return _seconds_decode(_read(TIME_SECONDS_ADDR)); } + + byte get_minutes() { return _minutes_decode(_read(TIME_MINUTES_ADDR)); } + + byte get_hours() { return _hours_decode(_read(TIME_HOURS_ADDR)); } byte get_alarm1_seconds() { return _seconds_decode(_read(ALARM1_SECONDS_ADDR)); } - + byte get_alarm1_minutes() { return _minutes_decode(_read(ALARM1_MINUTES_ADDR)); } - - byte get_alarm1_hours() { - return _hours_decode(_read(ALARM1_HOURS_ADDR)); - } - byte get_status() { - return _read(STATUS_ADDR); - } + byte get_alarm1_hours() { return _hours_decode(_read(ALARM1_HOURS_ADDR)); } - byte get_control() { - return _read(CONTROL_ADDR); - } + byte get_status() { return _read(STATUS_ADDR); } + + byte get_control() { return _read(CONTROL_ADDR); } void set_seconds(byte seconds) { _write(TIME_SECONDS_ADDR, _seconds_encode(seconds)); @@ -90,15 +76,11 @@ class _Rtc { _write(ALARM1_HOURS_ADDR, _seconds_encode(hours)); } - void clear_alarm1() { - _write(STATUS_ADDR, get_status() & ~0b01); - } + void clear_alarm1() { _write(STATUS_ADDR, get_status() & ~0b01); } - void clear_alarm2() { - _write(STATUS_ADDR, get_status() & ~0b10); - } - - private: + void clear_alarm2() { _write(STATUS_ADDR, get_status() & ~0b10); } + +private: const byte TIME_SECONDS_ADDR = 0x00; const byte TIME_MINUTES_ADDR = 0x01; const byte TIME_HOURS_ADDR = 0x02; @@ -113,7 +95,7 @@ class _Rtc { const byte HOUR12_FLAG = 0b01000000; const byte ALARM_FLAG = 0b10000000; const int RTC_ADDR = 0x68; - + byte _read(byte addr) { Wire.beginTransmission(RTC_ADDR); Wire.write(addr); @@ -123,7 +105,7 @@ class _Rtc { return Wire.read(); } } - + void _write(byte addr, byte data) { Wire.beginTransmission(RTC_ADDR); Wire.write(addr); @@ -152,7 +134,7 @@ class _Rtc { } byte _hours_encode(byte val) { - return HOUR12_FLAG | (val % 10) | (((val / 10) % 2) << 4); + return HOUR12_FLAG | (val % 10) | (((val / 10) % 2) << 4); } - + } Rtc; diff --git a/zegar_pkp/time.h b/zegar_pkp/time.h index d7c019a..0f2590f 100644 --- a/zegar_pkp/time.h +++ b/zegar_pkp/time.h @@ -1,15 +1,15 @@ #pragma once class Time { - public: +public: Time(byte minutes, byte hours) : _minutes(minutes), _hours(hours) {} inline byte minutes() { return _minutes; } inline byte hours() { return _hours; } - + inline int get_total_minutes() { return (int)_minutes + ((int)_hours % 12) * 60; } - + inline void increment_minute() { _minutes += 1; if (_minutes >= 60) { @@ -25,7 +25,7 @@ class Time { } } - private: +private: byte _minutes; byte _hours; }; diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index 2e5438c..e5e2226 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -1,18 +1,18 @@ -#include "rtc.h" #include "motor.h" +#include "rtc.h" #include "time.h" -#include #include +#include #define PIN_ALARM 2 #define PIN_BTN 3 #define PIN_BTN_TURN_ON 6 #define TICK 500L -#define CLOCK_DEBUG 1 +#define CLOCK_DEBUG 0 -enum class Event {WAIT=0, ALARM=1, CHANGE_TIME=2, SYNC=3}; +enum class Event { WAIT = 0, ALARM = 1, CHANGE_TIME = 2, SYNC = 3 }; static Event global_event = Event::WAIT; void setup() { @@ -25,8 +25,9 @@ void setup() { Motor.begin(); Rtc.begin(); - - if (Rtc.get_status() & (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. + + if (Rtc.get_status() & + (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. Rtc.reset(); global_event = Event::WAIT; } else { // When the microcontroller was turned off but RTC was working. @@ -36,27 +37,31 @@ void setup() { #if CLOCK_DEBUG Serial.begin(19200); - while(!Serial); + while (!Serial) + ; Serial.println("INIT"); #endif } #if CLOCK_DEBUG void print_time(byte hours, byte minutes, byte seconds) { - if (hours < 10) Serial.print('0'); + if (hours < 10) + Serial.print('0'); Serial.print(hours); Serial.print(':'); - if (minutes < 10) Serial.print('0'); + if (minutes < 10) + Serial.print('0'); Serial.print(minutes); Serial.print(':'); - if (seconds < 10) Serial.print('0'); + if (seconds < 10) + Serial.print('0'); Serial.print(seconds); } void print_byte(byte val) { char a[9] = {0}; - for(byte i = 0; i < 8; i++) { - a[7-i] = val & 1 ? '1' : '0'; + for (byte i = 0; i < 8; i++) { + a[7 - i] = val & 1 ? '1' : '0'; val = val >> 1; } Serial.print(a); @@ -64,89 +69,87 @@ void print_byte(byte val) { #endif inline void delay_tick() { - for(int t = 0; t < 1000L; t++) { + for (int t = 0; t < 1000L; t++) { delayMicroseconds(TICK); } } -inline Time get_time_from_rtc() { - return {Rtc.get_minutes(), Rtc.get_hours()}; -} +inline Time get_time_from_rtc() { return {Rtc.get_minutes(), Rtc.get_hours()}; } inline Time get_alarm1_from_rtc() { return {Rtc.get_alarm1_minutes(), Rtc.get_alarm1_hours()}; } -inline void set_time_in_rtc(const Time & t) { +inline void set_time_in_rtc(const Time &t) { Rtc.set_minutes(t.minutes()); Rtc.set_hours(t.hours()); } -inline void set_alarm1_in_rtc(const Time & t) { +inline void set_alarm1_in_rtc(const Time &t) { Rtc.set_alarm1_minutes(t.minutes()); Rtc.set_alarm1_hours(t.hours()); } inline Event manage_event(Event event) { - switch(event) { - case Event::CHANGE_TIME: { - while (digitalRead(PIN_BTN) == LOW) { - Motor.tick(); - - Time new_time = get_time_from_rtc(); - new_time.increment_minute(); - - set_time_in_rtc(new_time); - set_alarm1_in_rtc(new_time); - - delay_tick(); - } - Motor.turn_off(); - Rtc.clear_alarm2(); - return Event::WAIT; - } break; - case Event::ALARM: - case Event::SYNC: { - Time last_set_time = get_alarm1_from_rtc(); - int last_set_total_minutes = last_set_time.get_total_minutes(); - - Time current_time = get_time_from_rtc(); - int current_total_minutes = current_time.get_total_minutes(); - - int lack_minutes; - if (last_set_total_minutes <= current_total_minutes) { - lack_minutes = current_total_minutes - last_set_total_minutes; - } else { - lack_minutes = current_total_minutes + 12 * 60 - last_set_total_minutes; - } + switch (event) { + case Event::CHANGE_TIME: { + while (digitalRead(PIN_BTN) == LOW) { + Motor.tick(); + + Time new_time = get_time_from_rtc(); + new_time.increment_minute(); + + set_time_in_rtc(new_time); + set_alarm1_in_rtc(new_time); - for (int i = 0; i < lack_minutes; i++) { - if (digitalRead(PIN_BTN_TURN_ON) == HIGH) { - Motor.tick(); - } - last_set_time.increment_minute(); - set_alarm1_in_rtc(last_set_time); - delay_tick(); + delay_tick(); + } + Motor.turn_off(); + Rtc.clear_alarm2(); + return Event::WAIT; + } break; + case Event::ALARM: + case Event::SYNC: { + Time last_set_time = get_alarm1_from_rtc(); + int last_set_total_minutes = last_set_time.get_total_minutes(); + + Time current_time = get_time_from_rtc(); + int current_total_minutes = current_time.get_total_minutes(); + + int lack_minutes; + if (last_set_total_minutes <= current_total_minutes) { + lack_minutes = current_total_minutes - last_set_total_minutes; + } else { + lack_minutes = current_total_minutes + 12 * 60 - last_set_total_minutes; + } + + for (int i = 0; i < lack_minutes; i++) { + if (digitalRead(PIN_BTN_TURN_ON) == HIGH) { + Motor.tick(); } - Motor.turn_off(); - Rtc.clear_alarm2(); - return Event::WAIT; - } break; - default: { - return Event::WAIT; - } break; + last_set_time.increment_minute(); + set_alarm1_in_rtc(last_set_time); + delay_tick(); + } + Motor.turn_off(); + Rtc.clear_alarm2(); + return Event::WAIT; + } break; + default: { + return Event::WAIT; + } break; } } void loop() { #if CLOCK_DEBUG -static unsigned int iii = 0; -static unsigned char iiii = 0; -static Event prev_event = global_event; -if (global_event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { - prev_event = global_event; - Serial.print("event: "); - switch(global_event) { + static unsigned int iii = 0; + static unsigned char iiii = 0; + static Event prev_event = global_event; + if (global_event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { + prev_event = global_event; + Serial.print("event: "); + switch (global_event) { case Event::WAIT: Serial.print("WAIT "); break; @@ -162,18 +165,19 @@ if (global_event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { default: Serial.print("??? "); break; + } + Serial.print(" time: "); + print_time(Rtc.get_hours(), Rtc.get_minutes(), Rtc.get_seconds()); + Serial.print(" alarm1: "); + print_time(Rtc.get_alarm1_hours(), Rtc.get_alarm1_minutes(), + Rtc.get_alarm1_seconds()); + Serial.print(" status: "); + print_byte(Rtc.get_status()); + Serial.print(" control: "); + print_byte(Rtc.get_control()); + Serial.print('\n'); + delayMicroseconds(10000L); } - Serial.print(" time: "); - print_time(Rtc.get_hours(), Rtc.get_minutes(), Rtc.get_seconds()); - Serial.print(" alarm1: "); - print_time(Rtc.get_alarm1_hours(), Rtc.get_alarm1_minutes(), Rtc.get_alarm1_seconds()); - Serial.print(" status: "); - print_byte(Rtc.get_status()); - Serial.print(" control: "); - print_byte(Rtc.get_control()); - Serial.print('\n'); - delayMicroseconds(10000L); -} #else LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); #endif @@ -187,10 +191,6 @@ inline void int_change_event(Event event) { global_event = event; } -void alarm() { - int_change_event(Event::ALARM); -} +void alarm() { int_change_event(Event::ALARM); } -void change_time() { - int_change_event(Event::CHANGE_TIME); -} +void change_time() { int_change_event(Event::CHANGE_TIME); } From 887ef1fab24ac96087c15ff1eee7610370d618df Mon Sep 17 00:00:00 2001 From: Firemark Date: Wed, 4 Dec 2024 19:57:07 +0100 Subject: [PATCH 8/9] Add attiny13 --- attiny13/.clang-format | 83 ++++ attiny13/.gitignore | 4 + attiny13/.vscode/c_cpp_properties.json | 26 ++ attiny13/.vscode/settings.json | 26 ++ attiny13/Makefile | 65 +++ attiny13/include/i2c.h | 7 + attiny13/include/motor.h | 8 + attiny13/include/rtc.h | 26 ++ attiny13/include/rtc_internal.h | 22 + attiny13/pkp.s | 547 +++++++++++++++++++++++++ attiny13/src/i2c.c | 152 +++++++ attiny13/src/main.c | 120 ++++++ attiny13/src/motor.c | 24 ++ attiny13/src/rtc.c | 88 ++++ attiny13/test/test.c | 258 ++++++++++++ 15 files changed, 1456 insertions(+) create mode 100644 attiny13/.clang-format create mode 100644 attiny13/.gitignore create mode 100644 attiny13/.vscode/c_cpp_properties.json create mode 100644 attiny13/.vscode/settings.json create mode 100644 attiny13/Makefile create mode 100644 attiny13/include/i2c.h create mode 100644 attiny13/include/motor.h create mode 100644 attiny13/include/rtc.h create mode 100644 attiny13/include/rtc_internal.h create mode 100644 attiny13/pkp.s create mode 100644 attiny13/src/i2c.c create mode 100644 attiny13/src/main.c create mode 100644 attiny13/src/motor.c create mode 100644 attiny13/src/rtc.c create mode 100644 attiny13/test/test.c diff --git a/attiny13/.clang-format b/attiny13/.clang-format new file mode 100644 index 0000000..df2202e --- /dev/null +++ b/attiny13/.clang-format @@ -0,0 +1,83 @@ +# Google C/C++ Code Style settings +# https://clang.llvm.org/docs/ClangFormatStyleOptions.html +# Author: Kehan Xue, kehan.xue (at) gmail.com + +Language: Cpp +BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: None +AlignOperands: Align +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never # To avoid conflict, set this "Never" and each "if statement" should include brace when coding +AllowShortLambdasOnASingleLine: Inline +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterStruct: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +ColumnLimit: 80 +CompactNamespaces: false +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false # Make sure the * or & align on the left +EmptyLineBeforeAccessModifier: LogicalBlock +FixNamespaceComments: true +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +KeepEmptyLinesAtTheStartOfBlocks: true +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PointerAlignment: Left +ReflowComments: false +# SeparateDefinitionBlocks: Always # Only support since clang-format 14 +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInContainerLiterals: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: c++11 +TabWidth: 4 +UseTab: Never diff --git a/attiny13/.gitignore b/attiny13/.gitignore new file mode 100644 index 0000000..1971709 --- /dev/null +++ b/attiny13/.gitignore @@ -0,0 +1,4 @@ +*.hex +*.o +*.elf +*.vcd diff --git a/attiny13/.vscode/c_cpp_properties.json b/attiny13/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..0b8d25d --- /dev/null +++ b/attiny13/.vscode/c_cpp_properties.json @@ -0,0 +1,26 @@ +{ + "configurations": [ + { + "name": "AVR", + "intelliSenseMode": "${default}", + "compilerPath": "/usr/bin/avr-gcc", + "cStandard": "${default}", + "cppStandard": "${default}", + "includePath": ["${workspaceRoot}/include", "/include/simavr", "/include/simavr/avr"], + "defines": ["__AVR_ATtiny13__"], + "compilerArgs": [ + "-g", + "-Os", + "-Wall", + "-Wextra", + "-fpermissive", + "-fno-exceptions", + "-fno-threadsafe-statics", + "-ffunction-sections", + "-fdata-sections", + "-pipe" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/attiny13/.vscode/settings.json b/attiny13/.vscode/settings.json new file mode 100644 index 0000000..5274f5e --- /dev/null +++ b/attiny13/.vscode/settings.json @@ -0,0 +1,26 @@ +{ + "AVR.reporter.arguments": [ + "-C" + ], + "AVR.source.compiler": "/usr/bin/avr-gcc", + "AVR.programmer.tool": "/usr/bin/avrdude", + "AVR.source.libraries": [], + "files.associations": { + "io.h": "c", + "sfr_defs.h": "c", + "motor.h": "c", + "i2c.h": "c", + "delay.h": "c", + "delay_basic.h": "c", + "sim_avr.h": "c", + "rtc_internal.h": "c" + }, + "makefile.configureOnOpen": true, + "clangd.arguments": [ + "--query-driver=/usr/bin/avr-gcc" + ], + "clangd.enable": false, + "C_Cpp.default.systemIncludePath": [ + "/usr/lib/avr/include" + ] +} \ No newline at end of file diff --git a/attiny13/Makefile b/attiny13/Makefile new file mode 100644 index 0000000..87e676d --- /dev/null +++ b/attiny13/Makefile @@ -0,0 +1,65 @@ +# -- +# Copyright (c) 2018, Lukasz Marcin Podkalicki +# https://github.com/lpodkalicki/attiny-onewire-library/blob/master/examples/attiny13/Makefile +# -- + +MCU=attiny13 +FUSE_L=0x3B +FUSE_H=0xFF +F_CPU=128000 +CC=avr-gcc +LD=avr-ld +OBJCOPY=avr-objcopy +OBJDUMP=avr-objdump +SIZE=avr-size +AVRDUDE=avrdude +CFLAGS =-std=c99 -Wall -g -Os +CFLAGS+=-flto -fno-reorder-blocks +CFLAGS+=-Iinclude +CFLAGS+=-mmcu=${MCU} -DF_CPU=${F_CPU} +TEST_CFLAGS =${CFLAGS} +TEST_CFLAGS+=-I/include/simavr/avr -DTEST +TEST_CFLAGS+=-Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000 +TEST_CFLAGS+=-Wl,--relax,--gc-sections +TARGET=pkp + +SRCS = src/main.c src/i2c.c src/motor.c src/rtc.c +TESTS = test/test.c + +.PHONY: all test flash fuse clean + +all: + ${CC} ${CFLAGS} -o ${TARGET}.o ${SRCS} + ${LD} -o ${TARGET}.elf ${TARGET}.o + ${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.o ${TARGET}.hex + ${OBJDUMP} -j .text -j .data -j .bss -d ${TARGET}.o > ${TARGET}.s + ${SIZE} -C --mcu=${MCU} ${TARGET}.elf + +test: + ${CC} ${TEST_CFLAGS} -o ${TARGET}_test.o ${SRCS} + gcc -Wall -Iinclude -I/include/simavr ${TESTS} -lsimavr -o test.o + ./test.o 12 00 12 00 0 + ./test.o 12 01 12 00 1 + ./test.o 01 00 12 50 10 + ./test.o 02 00 01 50 10 + ./test.o 03 00 02 50 10 + ./test.o 04 00 03 50 10 + ./test.o 05 00 04 50 10 + ./test.o 06 00 05 50 10 + ./test.o 07 00 06 50 10 + ./test.o 08 00 07 50 10 + ./test.o 09 00 08 50 10 + ./test.o 10 00 09 50 10 + ./test.o 11 00 10 50 10 + ./test.o 12 00 11 50 10 + ./test.o 12 59 12 00 59 + ./test.o 12 30 12 00 30 + +flash: + ${AVRDUDE} -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb + +fuse: + $(AVRDUDE) -p ${MCU} -c usbasp -U hfuse:w:${FUSE_H}:m -U lfuse:w:${FUSE_L}:m + +clean: + rm -f *.c~ *.o *.elf *.hex diff --git a/attiny13/include/i2c.h b/attiny13/include/i2c.h new file mode 100644 index 0000000..4bcf5be --- /dev/null +++ b/attiny13/include/i2c.h @@ -0,0 +1,7 @@ +#pragma once +#include + +uint8_t i2c_ddr_setup(void); +uint8_t i2c_port_setup(void); +uint8_t i2c_write(uint8_t addr, uint8_t *buff, uint8_t size); +uint8_t i2c_read(uint8_t addr, uint8_t *buff, uint8_t size); \ No newline at end of file diff --git a/attiny13/include/motor.h b/attiny13/include/motor.h new file mode 100644 index 0000000..4963e11 --- /dev/null +++ b/attiny13/include/motor.h @@ -0,0 +1,8 @@ +#pragma once +#include + +uint8_t motor_ddr_setup(void); +uint8_t motor_port_setup(void); +void motor_a(void); +void motor_b(void); +void motor_off(void); \ No newline at end of file diff --git a/attiny13/include/rtc.h b/attiny13/include/rtc.h new file mode 100644 index 0000000..4649695 --- /dev/null +++ b/attiny13/include/rtc.h @@ -0,0 +1,26 @@ +#pragma once +#include + +/// @brief Resets RTC. +void rtc_reset(void); + +uint8_t rtc_lost_power(void); + +/// @brief Sets time in time register. +/// @param time Minutes from 0 to 719. +void rtc_set_time(uint16_t time); + +/// @brief Sets time in alarm1 register. +/// @param time Minutes from 0 to 719. +void rtc_set_alarm1(uint16_t time); + +/// @brief Clears interupt flag in alarm2 register. +void rtc_clear_alarm2(void); + +/// @brief Returns time from time register. +/// @return Minutes from 0 to 719. +uint16_t rtc_get_time(void); + +/// @brief Returns time from alarm1 register. +/// @return Minutes from 0 to 719. +uint16_t rtc_get_alarm1(void); \ No newline at end of file diff --git a/attiny13/include/rtc_internal.h b/attiny13/include/rtc_internal.h new file mode 100644 index 0000000..2527c3c --- /dev/null +++ b/attiny13/include/rtc_internal.h @@ -0,0 +1,22 @@ +#pragma once +#define TIME_SECONDS_ADDR 0x00 +#define TIME_MINUTES_ADDR 0x01 +#define TIME_HOURS_ADDR 0x02 +#define ALARM1_SECONDS_ADDR 0x07 +#define ALARM1_MINUTES_ADDR 0x08 +#define ALARM1_HOURS_ADDR 0x09 +#define ALARM2_MINUTES_ADDR 0x0B +#define ALARM2_HOURS_ADDR 0x0C +#define ALARM2_DAYS_ADDR 0x0D +#define CONTROL_ADDR 0x0E +#define STATUS_ADDR 0x0F +#define RTC_ADDR 0x68 + +#define RTC_STATUS_FLAG 1 << 7 +#define HOUR12_FLAG 1 << 6 +#define ALARM_FLAG 1 << 7 + +#define _rtc_12_encode(val) (HOUR12_FLAG | (val % 10) | (((val / 10) % 2) << 4)) +#define _rtc_60_encode(val) ((val % 10) | (((val / 10) % 6) << 4)) +#define _rtc_12_decode(val) ((val & 0b1111) + ((val >> 4) & 0b1) * 10) +#define _rtc_60_decode(val) ((val & 0b1111) + ((val >> 4) & 0b111) * 10) \ No newline at end of file diff --git a/attiny13/pkp.s b/attiny13/pkp.s new file mode 100644 index 0000000..45b90ec --- /dev/null +++ b/attiny13/pkp.s @@ -0,0 +1,547 @@ + +pkp.o: file format elf32-avr + + +Disassembly of section .text: + +00000000 <__vectors>: + 0: 09 c0 rjmp .+18 ; 0x14 <__ctors_end> + 2: ff c0 rjmp .+510 ; 0x202 <__vector_1> + 4: 18 c0 rjmp .+48 ; 0x36 <__bad_interrupt> + 6: 17 c0 rjmp .+46 ; 0x36 <__bad_interrupt> + 8: 16 c0 rjmp .+44 ; 0x36 <__bad_interrupt> + a: 15 c0 rjmp .+42 ; 0x36 <__bad_interrupt> + c: 14 c0 rjmp .+40 ; 0x36 <__bad_interrupt> + e: 13 c0 rjmp .+38 ; 0x36 <__bad_interrupt> + 10: 12 c0 rjmp .+36 ; 0x36 <__bad_interrupt> + 12: 11 c0 rjmp .+34 ; 0x36 <__bad_interrupt> + +00000014 <__ctors_end>: + 14: 11 24 eor r1, r1 + 16: 1f be out 0x3f, r1 ; 63 + 18: cf e9 ldi r28, 0x9F ; 159 + 1a: cd bf out 0x3d, r28 ; 61 + +0000001c <__do_copy_data>: + 1c: 10 e0 ldi r17, 0x00 ; 0 + 1e: a0 e6 ldi r26, 0x60 ; 96 + 20: b0 e0 ldi r27, 0x00 ; 0 + 22: e2 eb ldi r30, 0xB2 ; 178 + 24: f3 e0 ldi r31, 0x03 ; 3 + 26: 02 c0 rjmp .+4 ; 0x2c <__do_copy_data+0x10> + 28: 05 90 lpm r0, Z+ + 2a: 0d 92 st X+, r0 + 2c: a6 37 cpi r26, 0x76 ; 118 + 2e: b1 07 cpc r27, r17 + 30: d9 f7 brne .-10 ; 0x28 <__do_copy_data+0xc> + 32: f1 d0 rcall .+482 ; 0x216
+ 34: bc c1 rjmp .+888 ; 0x3ae <_exit> + +00000036 <__bad_interrupt>: + 36: e4 cf rjmp .-56 ; 0x0 <__vectors> + +00000038 : + 38: c0 98 cbi 0x18, 0 ; 24 + 3a: 87 e0 ldi r24, 0x07 ; 7 + 3c: 98 e6 ldi r25, 0x68 ; 104 + 3e: c2 98 cbi 0x18, 2 ; 24 + 40: 96 ff sbrs r25, 6 + 42: 02 c0 rjmp .+4 ; 0x48 <__DATA_REGION_LENGTH__+0x8> + 44: c0 9a sbi 0x18, 0 ; 24 + 46: 01 c0 rjmp .+2 ; 0x4a <__DATA_REGION_LENGTH__+0xa> + 48: c0 98 cbi 0x18, 0 ; 24 + 4a: c2 9a sbi 0x18, 2 ; 24 + 4c: 99 0f add r25, r25 + 4e: 81 50 subi r24, 0x01 ; 1 + 50: b1 f7 brne .-20 ; 0x3e <__SP_L__+0x1> + 52: 08 95 ret + +00000054 <_rtc_decode>: + 54: 28 2f mov r18, r24 + 56: 36 2f mov r19, r22 + 58: 64 fb bst r22, 4 + 5a: 88 27 eor r24, r24 + 5c: 80 f9 bld r24, 0 + 5e: 90 e0 ldi r25, 0x00 ; 0 + 60: 6a e0 ldi r22, 0x0A ; 10 + 62: 70 e0 ldi r23, 0x00 ; 0 + 64: 73 d1 rcall .+742 ; 0x34c <__mulhi3> + 66: 3f 70 andi r19, 0x0F ; 15 + 68: 83 0f add r24, r19 + 6a: 91 1d adc r25, r1 + 6c: 01 97 sbiw r24, 0x01 ; 1 + 6e: 6c e0 ldi r22, 0x0C ; 12 + 70: 70 e0 ldi r23, 0x00 ; 0 + 72: 89 d1 rcall .+786 ; 0x386 <__udivmodhi4> + 74: 6c e3 ldi r22, 0x3C ; 60 + 76: 70 e0 ldi r23, 0x00 ; 0 + 78: 69 d1 rcall .+722 ; 0x34c <__mulhi3> + 7a: fc 01 movw r30, r24 + 7c: 82 2f mov r24, r18 + 7e: 82 95 swap r24 + 80: 87 70 andi r24, 0x07 ; 7 + 82: 90 e0 ldi r25, 0x00 ; 0 + 84: 6a e0 ldi r22, 0x0A ; 10 + 86: 70 e0 ldi r23, 0x00 ; 0 + 88: 61 d1 rcall .+706 ; 0x34c <__mulhi3> + 8a: 2f 70 andi r18, 0x0F ; 15 + 8c: 82 0f add r24, r18 + 8e: 91 1d adc r25, r1 + 90: 6c e3 ldi r22, 0x3C ; 60 + 92: 70 e0 ldi r23, 0x00 ; 0 + 94: 78 d1 rcall .+752 ; 0x386 <__udivmodhi4> + 96: 8e 0f add r24, r30 + 98: 9f 1f adc r25, r31 + 9a: 08 95 ret + +0000009c : + 9c: c4 98 cbi 0x18, 4 ; 24 + 9e: c3 9a sbi 0x18, 3 ; 24 + a0: 08 95 ret + +000000a2 : + a2: c3 98 cbi 0x18, 3 ; 24 + a4: c4 9a sbi 0x18, 4 ; 24 + a6: 08 95 ret + +000000a8 : + a8: c0 98 cbi 0x18, 0 ; 24 + aa: c2 9a sbi 0x18, 2 ; 24 + ac: 00 00 nop + ae: 00 00 nop + b0: 00 00 nop + b2: c0 9a sbi 0x18, 0 ; 24 + b4: 08 95 ret + +000000b6 : + b6: c2 98 cbi 0x18, 2 ; 24 + b8: b8 98 cbi 0x17, 0 ; 23 + ba: c0 9a sbi 0x18, 0 ; 24 + bc: c2 9a sbi 0x18, 2 ; 24 + be: 00 00 nop + c0: 00 00 nop + c2: 86 b3 in r24, 0x16 ; 22 + c4: c2 98 cbi 0x18, 2 ; 24 + c6: 81 70 andi r24, 0x01 ; 1 + c8: 08 95 ret + +000000ca : + ca: ef 92 push r14 + cc: ff 92 push r15 + ce: 0f 93 push r16 + d0: 1f 93 push r17 + d2: cf 93 push r28 + d4: df 93 push r29 + d6: 08 2f mov r16, r24 + d8: e9 2e mov r14, r25 + da: f6 2e mov r15, r22 + dc: ad df rcall .-166 ; 0x38 + de: c2 98 cbi 0x18, 2 ; 24 + e0: c0 98 cbi 0x18, 0 ; 24 + e2: 00 00 nop + e4: 00 00 nop + e6: c2 9a sbi 0x18, 2 ; 24 + e8: e6 df rcall .-52 ; 0xb6 + ea: 18 2f mov r17, r24 + ec: b8 9a sbi 0x17, 0 ; 23 + ee: c0 2f mov r28, r16 + f0: de 2d mov r29, r14 + f2: ce 01 movw r24, r28 + f4: 8f 0d add r24, r15 + f6: 91 1d adc r25, r1 + f8: 7c 01 movw r14, r24 + fa: 0f c0 rjmp .+30 ; 0x11a + fc: 99 91 ld r25, Y+ + fe: 88 e0 ldi r24, 0x08 ; 8 + 100: c2 98 cbi 0x18, 2 ; 24 + 102: 97 ff sbrs r25, 7 + 104: 02 c0 rjmp .+4 ; 0x10a + 106: c0 9a sbi 0x18, 0 ; 24 + 108: 01 c0 rjmp .+2 ; 0x10c + 10a: c0 98 cbi 0x18, 0 ; 24 + 10c: c2 9a sbi 0x18, 2 ; 24 + 10e: 99 0f add r25, r25 + 110: 81 50 subi r24, 0x01 ; 1 + 112: b1 f7 brne .-20 ; 0x100 + 114: d0 df rcall .-96 ; 0xb6 + 116: 18 2b or r17, r24 + 118: b8 9a sbi 0x17, 0 ; 23 + 11a: ec 16 cp r14, r28 + 11c: fd 06 cpc r15, r29 + 11e: 71 f7 brne .-36 ; 0xfc + 120: c3 df rcall .-122 ; 0xa8 + 122: 81 2f mov r24, r17 + 124: df 91 pop r29 + 126: cf 91 pop r28 + 128: 1f 91 pop r17 + 12a: 0f 91 pop r16 + 12c: ff 90 pop r15 + 12e: ef 90 pop r14 + 130: 08 95 ret + +00000132 <_rtc_write>: + 132: cf 93 push r28 + 134: df 93 push r29 + 136: 00 d0 rcall .+0 ; 0x138 <_rtc_write+0x6> + 138: cd b7 in r28, 0x3d ; 61 + 13a: dd 27 eor r29, r29 + 13c: 89 83 std Y+1, r24 ; 0x01 + 13e: 6a 83 std Y+2, r22 ; 0x02 + 140: 62 e0 ldi r22, 0x02 ; 2 + 142: ce 01 movw r24, r28 + 144: 01 96 adiw r24, 0x01 ; 1 + 146: c1 df rcall .-126 ; 0xca + 148: ce 5f subi r28, 0xFE ; 254 + 14a: cd bf out 0x3d, r28 ; 61 + 14c: df 91 pop r29 + 14e: cf 91 pop r28 + 150: 08 95 ret + +00000152 : + 152: 0f 93 push r16 + 154: 1f 93 push r17 + 156: cf 93 push r28 + 158: 6c e3 ldi r22, 0x3C ; 60 + 15a: 70 e0 ldi r23, 0x00 ; 0 + 15c: 14 d1 rcall .+552 ; 0x386 <__udivmodhi4> + 15e: 8b 01 movw r16, r22 + 160: ca e0 ldi r28, 0x0A ; 10 + 162: 6c 2f mov r22, r28 + 164: 04 d1 rcall .+520 ; 0x36e <__udivmodqi4> + 166: 68 2f mov r22, r24 + 168: 62 95 swap r22 + 16a: 60 7f andi r22, 0xF0 ; 240 + 16c: 69 2b or r22, r25 + 16e: 88 e0 ldi r24, 0x08 ; 8 + 170: e0 df rcall .-64 ; 0x132 <_rtc_write> + 172: c8 01 movw r24, r16 + 174: 6c e0 ldi r22, 0x0C ; 12 + 176: 70 e0 ldi r23, 0x00 ; 0 + 178: 06 d1 rcall .+524 ; 0x386 <__udivmodhi4> + 17a: 8f 5f subi r24, 0xFF ; 255 + 17c: 6c 2f mov r22, r28 + 17e: f7 d0 rcall .+494 ; 0x36e <__udivmodqi4> + 180: 90 64 ori r25, 0x40 ; 64 + 182: 68 2f mov r22, r24 + 184: 62 95 swap r22 + 186: 60 7f andi r22, 0xF0 ; 240 + 188: 69 2b or r22, r25 + 18a: 89 e0 ldi r24, 0x09 ; 9 + 18c: cf 91 pop r28 + 18e: 1f 91 pop r17 + 190: 0f 91 pop r16 + 192: cf cf rjmp .-98 ; 0x132 <_rtc_write> + +00000194 <_rtc_read>: + 194: 1f 93 push r17 + 196: cf 93 push r28 + 198: df 93 push r29 + 19a: 1f 92 push r1 + 19c: cd b7 in r28, 0x3d ; 61 + 19e: dd 27 eor r29, r29 + 1a0: 89 83 std Y+1, r24 ; 0x01 + 1a2: 61 e0 ldi r22, 0x01 ; 1 + 1a4: ce 01 movw r24, r28 + 1a6: 01 96 adiw r24, 0x01 ; 1 + 1a8: 90 df rcall .-224 ; 0xca + 1aa: 46 df rcall .-372 ; 0x38 + 1ac: c2 98 cbi 0x18, 2 ; 24 + 1ae: c0 9a sbi 0x18, 0 ; 24 + 1b0: c2 9a sbi 0x18, 2 ; 24 + 1b2: 81 df rcall .-254 ; 0xb6 + 1b4: c2 98 cbi 0x18, 2 ; 24 + 1b6: 88 e0 ldi r24, 0x08 ; 8 + 1b8: 10 e0 ldi r17, 0x00 ; 0 + 1ba: c2 9a sbi 0x18, 2 ; 24 + 1bc: 11 0f add r17, r17 + 1be: b0 99 sbic 0x16, 0 ; 22 + 1c0: 11 60 ori r17, 0x01 ; 1 + 1c2: c2 98 cbi 0x18, 2 ; 24 + 1c4: 81 50 subi r24, 0x01 ; 1 + 1c6: c9 f7 brne .-14 ; 0x1ba <_rtc_read+0x26> + 1c8: b8 9a sbi 0x17, 0 ; 23 + 1ca: c0 9a sbi 0x18, 0 ; 24 + 1cc: c2 9a sbi 0x18, 2 ; 24 + 1ce: 00 00 nop + 1d0: 00 00 nop + 1d2: c2 98 cbi 0x18, 2 ; 24 + 1d4: 69 df rcall .-302 ; 0xa8 + 1d6: 81 2f mov r24, r17 + 1d8: 0f 90 pop r0 + 1da: df 91 pop r29 + 1dc: cf 91 pop r28 + 1de: 1f 91 pop r17 + 1e0: 08 95 ret + +000001e2 : + 1e2: 8f e0 ldi r24, 0x0F ; 15 + 1e4: d7 df rcall .-82 ; 0x194 <_rtc_read> + 1e6: 68 2f mov r22, r24 + 1e8: 6d 7f andi r22, 0xFD ; 253 + 1ea: 8f e0 ldi r24, 0x0F ; 15 + 1ec: a2 cf rjmp .-188 ; 0x132 <_rtc_write> + +000001ee : + 1ee: cf 93 push r28 + 1f0: 81 e0 ldi r24, 0x01 ; 1 + 1f2: d0 df rcall .-96 ; 0x194 <_rtc_read> + 1f4: c8 2f mov r28, r24 + 1f6: 82 e0 ldi r24, 0x02 ; 2 + 1f8: cd df rcall .-102 ; 0x194 <_rtc_read> + 1fa: 68 2f mov r22, r24 + 1fc: 8c 2f mov r24, r28 + 1fe: cf 91 pop r28 + 200: 29 cf rjmp .-430 ; 0x54 <_rtc_decode> + +00000202 <__vector_1>: + 202: 1f 92 push r1 + 204: 0f 92 push r0 + 206: 0f b6 in r0, 0x3f ; 63 + 208: 0f 92 push r0 + 20a: 11 24 eor r1, r1 + 20c: 0f 90 pop r0 + 20e: 0f be out 0x3f, r0 ; 63 + 210: 0f 90 pop r0 + 212: 1f 90 pop r1 + 214: 18 95 reti + +00000216
: + 216: 87 e0 ldi r24, 0x07 ; 7 + 218: 88 bb out 0x18, r24 ; 24 + 21a: 8d e1 ldi r24, 0x1D ; 29 + 21c: 87 bb out 0x17, r24 ; 23 + 21e: 80 e2 ldi r24, 0x20 ; 32 + 220: 85 bf out 0x35, r24 ; 53 + 222: 80 e4 ldi r24, 0x40 ; 64 + 224: 8b bf out 0x3b, r24 ; 59 + 226: 8f e0 ldi r24, 0x0F ; 15 + 228: b5 df rcall .-150 ; 0x194 <_rtc_read> + 22a: 87 fd sbrc r24, 7 + 22c: 11 c0 rjmp .+34 ; 0x250 + 22e: 85 b7 in r24, 0x35 ; 53 + 230: 87 7e andi r24, 0xE7 ; 231 + 232: 80 61 ori r24, 0x10 ; 16 + 234: 85 bf out 0x35, r24 ; 53 + 236: 85 b7 in r24, 0x35 ; 53 + 238: 80 62 ori r24, 0x20 ; 32 + 23a: 85 bf out 0x35, r24 ; 53 + 23c: 80 ed ldi r24, 0xD0 ; 208 + 23e: e8 2e mov r14, r24 + 240: 82 e0 ldi r24, 0x02 ; 2 + 242: f8 2e mov r15, r24 + 244: 9c e3 ldi r25, 0x3C ; 60 + 246: c9 2e mov r12, r25 + 248: d1 2c mov r13, r1 + 24a: 2a e0 ldi r18, 0x0A ; 10 + 24c: b2 2e mov r11, r18 + 24e: 0b c0 rjmp .+22 ; 0x266 + 250: c0 e6 ldi r28, 0x60 ; 96 + 252: d0 e0 ldi r29, 0x00 ; 0 + 254: 69 81 ldd r22, Y+1 ; 0x01 + 256: 88 81 ld r24, Y + 258: 6c df rcall .-296 ; 0x132 <_rtc_write> + 25a: 22 96 adiw r28, 0x02 ; 2 + 25c: 20 e0 ldi r18, 0x00 ; 0 + 25e: c6 37 cpi r28, 0x76 ; 118 + 260: d2 07 cpc r29, r18 + 262: c1 f7 brne .-16 ; 0x254 + 264: e4 cf rjmp .-56 ; 0x22e + 266: f8 94 cli + 268: bc df rcall .-136 ; 0x1e2 + 26a: 85 ef ldi r24, 0xF5 ; 245 + 26c: 91 e0 ldi r25, 0x01 ; 1 + 26e: 06 c0 rjmp .+12 ; 0x27c + 270: b1 99 sbic 0x16, 1 ; 22 + 272: 5e c0 rjmp .+188 ; 0x330 + 274: 2a e2 ldi r18, 0x2A ; 42 + 276: 2a 95 dec r18 + 278: f1 f7 brne .-4 ; 0x276 + 27a: 00 c0 rjmp .+0 ; 0x27c + 27c: 01 97 sbiw r24, 0x01 ; 1 + 27e: c1 f7 brne .-16 ; 0x270 + 280: 54 c0 rjmp .+168 ; 0x32a + 282: ce 01 movw r24, r28 + 284: 01 96 adiw r24, 0x01 ; 1 + 286: b7 01 movw r22, r14 + 288: 7e d0 rcall .+252 ; 0x386 <__udivmodhi4> + 28a: ec 01 movw r28, r24 + 28c: aa df rcall .-172 ; 0x1e2 + 28e: ce 01 movw r24, r28 + 290: b6 01 movw r22, r12 + 292: 79 d0 rcall .+242 ; 0x386 <__udivmodhi4> + 294: 16 2f mov r17, r22 + 296: 6b 2d mov r22, r11 + 298: 6a d0 rcall .+212 ; 0x36e <__udivmodqi4> + 29a: 68 2f mov r22, r24 + 29c: 62 95 swap r22 + 29e: 60 7f andi r22, 0xF0 ; 240 + 2a0: 69 2b or r22, r25 + 2a2: 81 e0 ldi r24, 0x01 ; 1 + 2a4: 46 df rcall .-372 ; 0x132 <_rtc_write> + 2a6: 81 e0 ldi r24, 0x01 ; 1 + 2a8: 81 0f add r24, r17 + 2aa: 6b 2d mov r22, r11 + 2ac: 60 d0 rcall .+192 ; 0x36e <__udivmodqi4> + 2ae: 90 64 ori r25, 0x40 ; 64 + 2b0: 68 2f mov r22, r24 + 2b2: 62 95 swap r22 + 2b4: 60 7f andi r22, 0xF0 ; 240 + 2b6: 69 2b or r22, r25 + 2b8: 82 e0 ldi r24, 0x02 ; 2 + 2ba: 3b df rcall .-394 ; 0x132 <_rtc_write> + 2bc: ce 01 movw r24, r28 + 2be: 49 df rcall .-366 ; 0x152 + 2c0: c0 ff sbrs r28, 0 + 2c2: 02 c0 rjmp .+4 ; 0x2c8 + 2c4: ee de rcall .-548 ; 0xa2 + 2c6: 01 c0 rjmp .+2 ; 0x2ca + 2c8: e9 de rcall .-558 ; 0x9c + 2ca: 8f e7 ldi r24, 0x7F ; 127 + 2cc: 9e e3 ldi r25, 0x3E ; 62 + 2ce: 01 97 sbiw r24, 0x01 ; 1 + 2d0: f1 f7 brne .-4 ; 0x2ce + 2d2: 00 c0 rjmp .+0 ; 0x2d4 + 2d4: 00 00 nop + 2d6: b1 9b sbis 0x16, 1 ; 22 + 2d8: d4 cf rjmp .-88 ; 0x282 + 2da: 1f c0 rjmp .+62 ; 0x31a + 2dc: 80 53 subi r24, 0x30 ; 48 + 2de: 9d 4f sbci r25, 0xFD ; 253 + 2e0: 8c 01 movw r16, r24 + 2e2: 0c 1b sub r16, r28 + 2e4: 1d 0b sbc r17, r29 + 2e6: 81 2c mov r8, r1 + 2e8: 91 2c mov r9, r1 + 2ea: 14 c0 rjmp .+40 ; 0x314 + 2ec: ce 01 movw r24, r28 + 2ee: 01 96 adiw r24, 0x01 ; 1 + 2f0: b7 01 movw r22, r14 + 2f2: 49 d0 rcall .+146 ; 0x386 <__udivmodhi4> + 2f4: ec 01 movw r28, r24 + 2f6: 2d df rcall .-422 ; 0x152 + 2f8: c0 ff sbrs r28, 0 + 2fa: 02 c0 rjmp .+4 ; 0x300 + 2fc: d2 de rcall .-604 ; 0xa2 + 2fe: 01 c0 rjmp .+2 ; 0x302 + 300: cd de rcall .-614 ; 0x9c + 302: 8f e7 ldi r24, 0x7F ; 127 + 304: 9e e3 ldi r25, 0x3E ; 62 + 306: 01 97 sbiw r24, 0x01 ; 1 + 308: f1 f7 brne .-4 ; 0x306 + 30a: 00 c0 rjmp .+0 ; 0x30c + 30c: 00 00 nop + 30e: 9f ef ldi r25, 0xFF ; 255 + 310: 89 1a sub r8, r25 + 312: 99 0a sbc r9, r25 + 314: 08 15 cp r16, r8 + 316: 19 05 cpc r17, r9 + 318: 49 f7 brne .-46 ; 0x2ec + 31a: 88 b3 in r24, 0x18 ; 24 + 31c: 87 7e andi r24, 0xE7 ; 231 + 31e: 88 bb out 0x18, r24 ; 24 + 320: 78 94 sei + 322: b1 9b sbis 0x16, 1 ; 22 + 324: a0 cf rjmp .-192 ; 0x266 + 326: 88 95 sleep + 328: 9e cf rjmp .-196 ; 0x266 + 32a: 61 df rcall .-318 ; 0x1ee + 32c: ec 01 movw r28, r24 + 32e: d3 cf rjmp .-90 ; 0x2d6 + 330: 88 e0 ldi r24, 0x08 ; 8 + 332: 30 df rcall .-416 ; 0x194 <_rtc_read> + 334: c8 2f mov r28, r24 + 336: 89 e0 ldi r24, 0x09 ; 9 + 338: 2d df rcall .-422 ; 0x194 <_rtc_read> + 33a: 68 2f mov r22, r24 + 33c: 8c 2f mov r24, r28 + 33e: 8a de rcall .-748 ; 0x54 <_rtc_decode> + 340: ec 01 movw r28, r24 + 342: 55 df rcall .-342 ; 0x1ee + 344: 8c 17 cp r24, r28 + 346: 9d 07 cpc r25, r29 + 348: 58 f6 brcc .-106 ; 0x2e0 + 34a: c8 cf rjmp .-112 ; 0x2dc + +0000034c <__mulhi3>: + 34c: 00 24 eor r0, r0 + 34e: 55 27 eor r21, r21 + 350: 04 c0 rjmp .+8 ; 0x35a <__mulhi3+0xe> + 352: 08 0e add r0, r24 + 354: 59 1f adc r21, r25 + 356: 88 0f add r24, r24 + 358: 99 1f adc r25, r25 + 35a: 00 97 sbiw r24, 0x00 ; 0 + 35c: 29 f0 breq .+10 ; 0x368 <__mulhi3+0x1c> + 35e: 76 95 lsr r23 + 360: 67 95 ror r22 + 362: b8 f3 brcs .-18 ; 0x352 <__mulhi3+0x6> + 364: 71 05 cpc r23, r1 + 366: b9 f7 brne .-18 ; 0x356 <__mulhi3+0xa> + 368: 80 2d mov r24, r0 + 36a: 95 2f mov r25, r21 + 36c: 08 95 ret + +0000036e <__udivmodqi4>: + 36e: 99 1b sub r25, r25 + 370: 79 e0 ldi r23, 0x09 ; 9 + 372: 04 c0 rjmp .+8 ; 0x37c <__udivmodqi4_ep> + +00000374 <__udivmodqi4_loop>: + 374: 99 1f adc r25, r25 + 376: 96 17 cp r25, r22 + 378: 08 f0 brcs .+2 ; 0x37c <__udivmodqi4_ep> + 37a: 96 1b sub r25, r22 + +0000037c <__udivmodqi4_ep>: + 37c: 88 1f adc r24, r24 + 37e: 7a 95 dec r23 + 380: c9 f7 brne .-14 ; 0x374 <__udivmodqi4_loop> + 382: 80 95 com r24 + 384: 08 95 ret + +00000386 <__udivmodhi4>: + 386: aa 1b sub r26, r26 + 388: bb 1b sub r27, r27 + 38a: 51 e1 ldi r21, 0x11 ; 17 + 38c: 07 c0 rjmp .+14 ; 0x39c <__udivmodhi4_ep> + +0000038e <__udivmodhi4_loop>: + 38e: aa 1f adc r26, r26 + 390: bb 1f adc r27, r27 + 392: a6 17 cp r26, r22 + 394: b7 07 cpc r27, r23 + 396: 10 f0 brcs .+4 ; 0x39c <__udivmodhi4_ep> + 398: a6 1b sub r26, r22 + 39a: b7 0b sbc r27, r23 + +0000039c <__udivmodhi4_ep>: + 39c: 88 1f adc r24, r24 + 39e: 99 1f adc r25, r25 + 3a0: 5a 95 dec r21 + 3a2: a9 f7 brne .-22 ; 0x38e <__udivmodhi4_loop> + 3a4: 80 95 com r24 + 3a6: 90 95 com r25 + 3a8: bc 01 movw r22, r24 + 3aa: cd 01 movw r24, r26 + 3ac: 08 95 ret + +000003ae <_exit>: + 3ae: f8 94 cli + +000003b0 <__stop_program>: + 3b0: ff cf rjmp .-2 ; 0x3b0 <__stop_program> + +Disassembly of section .data: + +00800060 <__data_start>: + 800060: 00 00 nop + 800062: 01 00 .word 0x0001 ; ???? + 800064: 02 52 subi r16, 0x22 ; 34 + 800066: 07 00 .word 0x0007 ; ???? + 800068: 08 00 .word 0x0008 ; ???? + 80006a: 09 52 subi r16, 0x29 ; 41 + 80006c: 0b 80 ldd r0, Y+3 ; 0x03 + 80006e: 0c d2 rcall .+1048 ; 0x800488 <__data_end+0x412> + 800070: 0d 81 ldd r16, Y+5 ; 0x05 + 800072: 0e 06 cpc r0, r30 + 800074: 0f 00 .word 0x000f ; ???? diff --git a/attiny13/src/i2c.c b/attiny13/src/i2c.c new file mode 100644 index 0000000..b01c9ed --- /dev/null +++ b/attiny13/src/i2c.c @@ -0,0 +1,152 @@ +#include "i2c.h" +#include + +static inline void nop() { + __asm__ volatile("nop"); +} + +uint8_t i2c_ddr_setup(void) { + return (1 << DDB0) | (1 << DDB2); +} + +uint8_t i2c_port_setup(void) { + // B0 as SDA, B2 as SCL. + return (1 << PB0) | (1 << PB2); +} + +#define scl_high() \ + { PORTB |= (1 << PB2); } +#define scl_low() \ + { PORTB &= ~(1 << PB2); } +#define sda_input() \ + { \ + DDRB &= ~(1 << DDB0); \ + PORTB |= (1 << PB0); \ + } +#define sda_output() \ + { DDRB |= (1 << DDB0); } +#define sda_high() \ + { PORTB |= (1 << PB0); } +#define sda_low() \ + { PORTB &= ~(1 << PB0); } +#define is_sda_high() (PINB & (1 << PINB0)) + +static uint8_t i2c_read_ack() { + uint8_t retval = 0; + scl_low(); + sda_input(); + scl_high(); + nop(); + nop(); + if (is_sda_high()) { // Error. + retval = 1; + } + scl_low(); + return retval; +} + +static void i2c_write_addr(uint8_t addr) { + sda_low(); + + for (uint8_t i = 0; i < 7; i++) { + scl_low(); + if (addr & (1 << 6)) { + sda_high(); + } else { + sda_low(); + } + scl_high(); + addr <<= 1; + } +} + +static void i2c_finish() { + sda_low(); + scl_high(); + nop(); + nop(); + nop(); + sda_high(); +} + +uint8_t i2c_write(uint8_t addr, uint8_t* buff, uint8_t size) { + uint8_t retval = 0; + + i2c_write_addr(addr); + + { + // Write bit + scl_low(); + sda_low(); + nop(); + nop(); + scl_high(); + } + + retval |= i2c_read_ack(); + sda_output(); + + for (uint8_t j = 0; j < size; j++) { + uint8_t cmd = buff[j]; + for (uint8_t i = 0; i < 8; i++) { + scl_low(); + if (cmd & (1 << 7)) { + sda_high(); + } else { + sda_low(); + } + scl_high(); + cmd <<= 1; + } + + retval |= i2c_read_ack(); + sda_output(); + } + + i2c_finish(); + + return retval; +} + +uint8_t i2c_read(uint8_t addr, uint8_t* buff, uint8_t size) { + uint8_t retval = 0; + + i2c_write_addr(addr); + + { + // Read bit + scl_low(); + sda_high(); + scl_high(); + } + + retval |= i2c_read_ack(); + + scl_low(); + for (uint8_t j = 0; j < size; j++) { + uint8_t* byte = &buff[j]; + *byte = 0; + for (uint8_t i = 0; i < 8; i++) { + scl_high(); + *byte <<= 1; + if (is_sda_high()) { + *byte |= 1; + } + scl_low(); + } + + { + // Write ACK + sda_output(); + sda_high(); + scl_high(); + nop(); + nop(); + scl_low(); + } + } + + i2c_finish(); + + return retval; +} diff --git a/attiny13/src/main.c b/attiny13/src/main.c new file mode 100644 index 0000000..8b292dc --- /dev/null +++ b/attiny13/src/main.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include + +#include "i2c.h" +#include "motor.h" +#include "rtc.h" + +#ifdef TEST +#include "avr_mcu_section.h" +AVR_MCU(F_CPU, "attiny13"); +// AVR_MCU_VCD_FILE("main.vcd", 1000); +// AVR_MCU_EXTERNAL_PORT_PULL('B', (1 << 0), 1); +// AVR_MCU_EXTERNAL_PORT_PULL('B', (1 << 1), 0xFFF); + +// const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = { +// {AVR_MCU_VCD_SYMBOL("SDA_DIR"), .mask = (1 << 0), .what = (void*)&DDRB}, +// {AVR_MCU_VCD_SYMBOL("SDA_IN"), .mask = (1 << 0), .what = (void*)&PINB}, +// {AVR_MCU_VCD_SYMBOL("SDA_OUT"), .mask = (1 << 0), .what = (void*)&PORTB}, +// {AVR_MCU_VCD_SYMBOL("SCL"), .mask = (1 << 2), .what = (void*)&PORTB}, +// {AVR_MCU_VCD_SYMBOL("INT"), .mask = (1 << 1), .what = (void*)&PINB}, +// {AVR_MCU_VCD_SYMBOL("MOTOR_A"), .mask = (1 << 3), .what = (void*)&PORTB}, +// {AVR_MCU_VCD_SYMBOL("MOTOR_B"), .mask = (1 << 4), .what = (void*)&PORTB}, +// }; +#endif + +#define IS_INT_PIN_HIGH (PINB & (1 << PB1)) + +static void setup() { + // Input pin B1 with pull-up + PORTB = (1 << PB1) | motor_port_setup() | i2c_port_setup(); + DDRB = motor_ddr_setup() | i2c_ddr_setup(); + + // Pin PB1 interrupt. + MCUCR = (1 << PCIE); // 1 -> 0 triggers. + GIMSK = (1 << INT0); // Interrupt on. + + if (rtc_lost_power()) { + rtc_reset(); + } +} + +static void motor_tick(uint16_t time) { + if (time % 2) { + motor_a(); + } else { + motor_b(); + } + _delay_ms(500); +} + +static uint8_t is_manual_tick() { + uint16_t milliseconds = 0; + while (milliseconds++ < 500) { + if (IS_INT_PIN_HIGH) { + return 0; + } + _delay_us(1000); + } + return 1; +} + +static void rtc_tick() { + const uint16_t last_set_time = rtc_get_alarm1(); + const uint16_t current_time = rtc_get_time(); + uint16_t lack_minutes; + if (last_set_time <= current_time) { + lack_minutes = current_time - last_set_time; + } else { + lack_minutes = current_time + 12 * 60 - last_set_time; + } + + uint16_t time = last_set_time; + for (int i = 0; i < lack_minutes; i++) { + time = ((time + 1) % 720); + rtc_set_alarm1(time); + motor_tick(time); + } + motor_off(); +} + +static void manual_tick() { + uint16_t time = rtc_get_time(); + while (!IS_INT_PIN_HIGH) { + time = ((time + 1) % 720); + rtc_clear_alarm2(); + rtc_set_time(time); + rtc_set_alarm1(time); + motor_tick(time); + } + motor_off(); +} + +static void loop() { + rtc_clear_alarm2(); + if (is_manual_tick()) { + manual_tick(); + } else { + rtc_tick(); + } +} + +ISR(INT0_vect) {} + +int main() { + setup(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_enable(); + + for (;;) { + cli(); + loop(); + sei(); + if (IS_INT_PIN_HIGH) { + sleep_cpu(); + } + } + return 0; +} diff --git a/attiny13/src/motor.c b/attiny13/src/motor.c new file mode 100644 index 0000000..bad063b --- /dev/null +++ b/attiny13/src/motor.c @@ -0,0 +1,24 @@ +#include "motor.h" +#include + +uint8_t motor_ddr_setup(void) { + return (1 << DDB3) | (1 << DDB4); +} + +uint8_t motor_port_setup(void) { + return 0; +} + +void motor_a(void) { + PORTB &= ~(1 << PB3); + PORTB |= (1 << PB4); +} + +void motor_b(void) { + PORTB &= ~(1 << PB4); + PORTB |= (1 << PB3); +} + +void motor_off(void) { + PORTB &= ~((1 << PB3) | (1 << PB4)); +} \ No newline at end of file diff --git a/attiny13/src/rtc.c b/attiny13/src/rtc.c new file mode 100644 index 0000000..8b4042e --- /dev/null +++ b/attiny13/src/rtc.c @@ -0,0 +1,88 @@ +#include "rtc.h" +#include "rtc_internal.h" +#include "i2c.h" + +const uint8_t RESET_DATA[][2] = { + // set time to 12:00:00AM (12h mode because of clock face). + {TIME_SECONDS_ADDR, _rtc_60_encode(0)}, + {TIME_MINUTES_ADDR, _rtc_60_encode(0)}, + {TIME_HOURS_ADDR, _rtc_12_encode(12)}, + + // set alarm1 {as last time) to 12:00:00AM + {ALARM1_SECONDS_ADDR, _rtc_60_encode(0)}, + {ALARM1_MINUTES_ADDR, _rtc_60_encode(0)}, + {ALARM1_HOURS_ADDR, _rtc_12_encode(12)}, + + // set alarm2 to 12:01PM + ALARM every minute + {ALARM2_MINUTES_ADDR, ALARM_FLAG | _rtc_60_encode(0)}, + {ALARM2_HOURS_ADDR, ALARM_FLAG | _rtc_12_encode(12)}, + {ALARM2_DAYS_ADDR, ALARM_FLAG | 1}, + + {CONTROL_ADDR, 0b00000110}, // Set INT pin + set alarm2. + {STATUS_ADDR, 0b00000000}, // Reset oscillator stop flag. +}; + +static void _rtc_write(uint8_t addr, uint8_t data) { + uint8_t buff[] = {addr, data}; + i2c_write(RTC_ADDR, buff, 2); +} + +static uint8_t _rtc_read(uint8_t addr) { + uint8_t data; + i2c_write(RTC_ADDR, &addr, 1); + i2c_read(RTC_ADDR, &data, 1); + return data; +} + +/// @return minutes from 0 to 719. +static uint16_t _rtc_decode(uint8_t raw_minutes, uint8_t raw_hours) { + uint16_t minutes = _rtc_60_decode(raw_minutes); + uint16_t hours = _rtc_12_decode(raw_hours); + return ((hours - 1) % 12) * 60 + (minutes % 60); +} + +void rtc_reset(void) { + uint8_t i; + for (i = 0; i < sizeof(RESET_DATA) / sizeof(RESET_DATA[0]); i++) { + _rtc_write(RESET_DATA[i][0], RESET_DATA[i][1]); + } +} + +uint8_t rtc_lost_power(void) { + uint8_t status = _rtc_read(STATUS_ADDR); + return status & RTC_STATUS_FLAG; +} + +uint16_t rtc_get_time(void) { + uint16_t minutes = _rtc_read(TIME_MINUTES_ADDR); + uint16_t hours = _rtc_read(TIME_HOURS_ADDR); + return _rtc_decode(minutes, hours); +} + +uint16_t rtc_get_alarm1(void) { + uint16_t minutes = _rtc_read(ALARM1_MINUTES_ADDR); + uint16_t hours = _rtc_read(ALARM1_HOURS_ADDR); + return _rtc_decode(minutes, hours); +} + +static inline uint8_t _time_to_minutes(uint16_t time) { + return time % 60; +} + +static inline uint8_t _time_to_hours(uint16_t time) { + return (((time / 60) % 12) + 1); +} + +void rtc_set_time(uint16_t time) { + _rtc_write(TIME_MINUTES_ADDR, _rtc_60_encode(_time_to_minutes(time))); + _rtc_write(TIME_HOURS_ADDR, _rtc_12_encode(_time_to_hours(time))); +} + +void rtc_set_alarm1(uint16_t time) { + _rtc_write(ALARM1_MINUTES_ADDR, _rtc_60_encode(_time_to_minutes(time))); + _rtc_write(ALARM1_HOURS_ADDR, _rtc_12_encode(_time_to_hours(time))); +} + +void rtc_clear_alarm2(void) { + _rtc_write(STATUS_ADDR, _rtc_read(STATUS_ADDR) & ~0b10); +} \ No newline at end of file diff --git a/attiny13/test/test.c b/attiny13/test/test.c new file mode 100644 index 0000000..a8ceffc --- /dev/null +++ b/attiny13/test/test.c @@ -0,0 +1,258 @@ +#include +#include +#include + +#include "avr_ioport.h" +#include "sim_avr.h" +#include "sim_elf.h" +#include "sim_time.h" + +#include "rtc_internal.h" + +#define PORTB AVR_IOCTL_IOPORT_GETIRQ('B') +#define GETPORT(ind) avr_io_getirq(avr, PORTB, ind) + +typedef struct { + int bitcount; + uint8_t addr; + uint8_t data[8]; + uint8_t size; + uint8_t last_reg; + char addr_readed; + char readwrite; + char start; + uint8_t request[256]; + uint8_t response[256]; +} twi_data_t; + +typedef struct { + char name; + int count; +} motor_t; + +avr_t* avr = NULL; +avr_irq_t* irq = NULL; +motor_t motor_a = {'A', 0}; +motor_t motor_b = {'B', 0}; +twi_data_t twi_data = {0}; + +static void motor_hook(struct avr_irq_t* irq, uint32_t value, void* param) { + motor_t* motor = param; + if (!value) { + return; + } + motor->count++; + // printf("MOTOR %c %d\n", motor->name, motor->count); +} + +static void sda_input(uint8_t v) { + avr_ioport_external_t io_ext; + io_ext.name = 'B'; + io_ext.mask = (1 << 0); + io_ext.value = v ? 1 : 0; + avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL('B'), &io_ext); +} + +static void int_input(uint8_t v) { + avr_ioport_external_t io_ext; + io_ext.name = 'B'; + io_ext.mask = (1 << 1); + io_ext.value = v ? 1 << 1 : 0; + avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL('B'), &io_ext); +} + +static void sda_hook(struct avr_irq_t* irq, uint32_t sda_value, void* param) { + static uint32_t prev_sda_value = 1; + twi_data_t* twi = param; + avr_irq_t* scl_irq = avr_io_getirq(avr, PORTB, IOPORT_IRQ_PIN2); + char scl_value = scl_irq->value ? 1 : 0; + if (scl_value) { + if (twi->start && prev_sda_value && !sda_value) { + twi->start = 0; + twi->addr = 0; + twi->size = 0; + twi->readwrite = 0; + twi->addr_readed = 0; + twi->bitcount = 0; + for (int i = 0; i < 8; i++) { + twi->data[i] = 0; + } + sda_input(1); + } + if (!twi->start && !prev_sda_value && sda_value) { + // printf("ADDR %02x DATA ", twi->addr); + // for (int i = 0; i < twi->size; i++) { + // printf("%02x", twi->data[i]); + // } + // printf("; %c\n", twi->readwrite ? 'R' : 'W'); + + if (!twi->readwrite && twi->size == 1) { + twi->last_reg = twi->data[0]; + } + if (!twi->readwrite && twi->size == 2) { + twi->response[twi->data[0]] = twi->data[1]; + } + twi->start = 1; + } + } + prev_sda_value = sda_value; +} + +static void scl_hook(struct avr_irq_t* irq, uint32_t scl_value, void* param) { + twi_data_t* twi = param; + avr_irq_t* sda_irq = avr_io_getirq(avr, PORTB, IOPORT_IRQ_PIN0); + if (twi->start) { + return; + } + if (!scl_value) { + if (!twi->readwrite && twi->bitcount == 8) { + sda_input(0); + } else if (twi->readwrite && twi->bitcount < 8) { + uint8_t data = twi->request[twi->last_reg]; + uint8_t mask = 1 << (7 - twi->bitcount); + sda_input(data & mask); + } + } else { + char value = sda_irq->value ? 1 : 0; + if (twi->start && value) { + return; + } + if (!twi->addr_readed) { // Addr + switch (twi->bitcount) { + case 0 ... 6: { + twi->addr = (twi->addr << 1) | value; + twi->bitcount++; + } break; + case 7: { + twi->readwrite = value; + twi->bitcount++; + } break; + case 8: { // ACK + twi->addr_readed = 1; + twi->bitcount = 0; + } break; + } + } else if (!twi->readwrite) { // Write + switch (twi->bitcount) { + case 0 ... 7: { + uint8_t* data = &twi->data[twi->size]; + *data = (*data << 1) | value; + twi->bitcount++; + } break; + case 8: { // ACK + twi->size++; + twi->bitcount = 0; + } break; + } + } else { // Read + switch (twi->bitcount) { + case 0 ... 7: { + uint8_t* data = &twi->data[twi->size]; + *data = (*data << 1) | value; + twi->bitcount++; + } break; + case 8: { // ACK + sda_input(1); + twi->size++; + twi->bitcount = 0; + } break; + } + } + } +} + +char is_evil(int state) { + return (state == cpu_Done) || (state == cpu_Crashed); +} + +int main(int argc, char* argv[]) { + if (argc < 6) { + return 1; + } + elf_firmware_t f = {{0}}; + const char* fname = "pkp_test.o"; + + // printf("Firmware pathname is %s\n", fname); + elf_read_firmware(fname, &f); + + // printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu); + + avr = avr_make_mcu_by_name(f.mmcu); + if (!avr) { + fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu); + exit(1); + } + avr_init(avr); + avr_load_firmware(avr, &f); + + int current_time_h = atoi(argv[1]); + int current_time_m = atoi(argv[2]); + int last_time_h = atoi(argv[3]); + int last_time_m = atoi(argv[4]); + int motor_ticks = atoi(argv[5]); + + printf("Args: %02d:%02d %02d:%02d %d\n", current_time_h, current_time_m, + last_time_h, last_time_m, motor_ticks); + + twi_data.start = 1; + + avr_irq_t* sda_irq = GETPORT(IOPORT_IRQ_PIN0); + avr_irq_t* int_irq = GETPORT(IOPORT_IRQ_PIN1); + + // Pullups + avr_raise_irq(int_irq, 1); + avr_raise_irq(sda_irq, 1); + avr_irq_register_notify(GETPORT(IOPORT_IRQ_PIN0), sda_hook, &twi_data); + avr_irq_register_notify(GETPORT(IOPORT_IRQ_PIN2), scl_hook, &twi_data); + avr_irq_register_notify(GETPORT(IOPORT_IRQ_PIN3), motor_hook, &motor_a); + avr_irq_register_notify(GETPORT(IOPORT_IRQ_PIN4), motor_hook, &motor_b); + + twi_data.request[STATUS_ADDR] = 1 << 7; + // twi_data.request[0x0F] = 0; + twi_data.request[TIME_MINUTES_ADDR] = _rtc_60_encode(current_time_m); + twi_data.request[TIME_HOURS_ADDR] = _rtc_12_encode(current_time_h); + twi_data.request[ALARM1_MINUTES_ADDR] = _rtc_60_encode(last_time_m); + twi_data.request[ALARM1_HOURS_ADDR] = _rtc_12_encode(last_time_h); + + int state; + state = cpu_Running; + while (state != cpu_Sleeping) { + if (is_evil(state)) { + return 0; + } + state = avr_run(avr); + } + + printf("Motor A ticks: %d\n", motor_a.count); + printf("Motor B ticks: %d\n", motor_b.count); + printf("Total ticks: %d\n", motor_a.count + motor_b.count); + if (motor_a.count + motor_b.count == motor_ticks) { + printf("Test passed!\n"); + return 0; + } else { + printf("Test failed!\n"); + return 1; + } + + // printf("---\n"); + // twi_data.request[0x01] = 0; + // twi_data.request[0x02] = 1 << 6 | 3; + // twi_data.request[0x08] = 0; + // twi_data.request[0x09] = 1 << 6 | 2; + + // avr_cycle_count_t deadline = avr->cycle + avr_usec_to_cycles(avr, 10000l); + // avr_raise_irq(int_irq, 0); + // state = cpu_Running; + // while (state != cpu_Sleeping) { + // if (avr->cycle < deadline) { + // int_input(0); + // } else { + // int_input(1); + // } + + // if (is_evil(state)) { + // return 0; + // } + // state = avr_run(avr); + // } +} \ No newline at end of file From 7d69662b9911bdbcb3e72cf9b30878ca6d560177 Mon Sep 17 00:00:00 2001 From: Firemark Date: Wed, 4 Dec 2024 19:58:29 +0100 Subject: [PATCH 9/9] Add queue system, fix hours problem --- zegar_pkp/rtc.h | 6 +-- zegar_pkp/zegar_pkp.ino | 98 +++++++++++++++++++++++++++-------------- 2 files changed, 68 insertions(+), 36 deletions(-) diff --git a/zegar_pkp/rtc.h b/zegar_pkp/rtc.h index a7b524f..3bea86e 100644 --- a/zegar_pkp/rtc.h +++ b/zegar_pkp/rtc.h @@ -22,7 +22,7 @@ class _Rtc { _write(ALARM1_MINUTES_ADDR, _minutes_encode(0)); _write(ALARM1_HOURS_ADDR, _hours_encode(12)); } - { // set alarm2 to 12:01PM + ALARM every second + { // set alarm2 to 12:01PM + ALARM every minute _write(ALARM2_MINUTES_ADDR, ALARM_FLAG | _minutes_encode(0)); _write(ALARM2_HOURS_ADDR, ALARM_FLAG | _hours_encode(12)); _write(ALARM2_DAYS_ADDR, ALARM_FLAG | 1); @@ -61,7 +61,7 @@ class _Rtc { } void set_hours(byte hours) { - _write(TIME_HOURS_ADDR, _seconds_encode(hours)); + _write(TIME_HOURS_ADDR, _hours_encode(hours)); } void set_alarm1_seconds(byte seconds) { @@ -73,7 +73,7 @@ class _Rtc { } void set_alarm1_hours(byte hours) { - _write(ALARM1_HOURS_ADDR, _seconds_encode(hours)); + _write(ALARM1_HOURS_ADDR, _hours_encode(hours)); } void clear_alarm1() { _write(STATUS_ADDR, get_status() & ~0b01); } diff --git a/zegar_pkp/zegar_pkp.ino b/zegar_pkp/zegar_pkp.ino index e5e2226..88b9bed 100644 --- a/zegar_pkp/zegar_pkp.ino +++ b/zegar_pkp/zegar_pkp.ino @@ -11,9 +11,12 @@ #define TICK 500L #define CLOCK_DEBUG 0 +#define QUEUE_SIZE 32 enum class Event { WAIT = 0, ALARM = 1, CHANGE_TIME = 2, SYNC = 3 }; -static Event global_event = Event::WAIT; +static volatile Event _events[QUEUE_SIZE] = { Event::WAIT }; +static volatile byte _read_counter = 0; +static volatile byte _write_counter = 0; void setup() { pinMode(PIN_ALARM, INPUT_PULLUP); @@ -29,10 +32,10 @@ void setup() { if (Rtc.get_status() & (1 << RTC_STATUS_FLAG_OSF)) { // When RTC lost the power. Rtc.reset(); - global_event = Event::WAIT; + push_event(Event::WAIT); } else { // When the microcontroller was turned off but RTC was working. Rtc.clear_alarm2(); - global_event = Event::SYNC; + push_event(Event::SYNC); } #if CLOCK_DEBUG @@ -90,11 +93,18 @@ inline void set_alarm1_in_rtc(const Time &t) { Rtc.set_alarm1_hours(t.hours()); } -inline Event manage_event(Event event) { +inline void motor_tick() { + #if CLOCK_DEBUG + Serial.println("TICK"); + #endif + Motor.tick(); +} + +inline void manage_event(Event event) { switch (event) { case Event::CHANGE_TIME: { while (digitalRead(PIN_BTN) == LOW) { - Motor.tick(); + motor_tick(); Time new_time = get_time_from_rtc(); new_time.increment_minute(); @@ -106,7 +116,6 @@ inline Event manage_event(Event event) { } Motor.turn_off(); Rtc.clear_alarm2(); - return Event::WAIT; } break; case Event::ALARM: case Event::SYNC: { @@ -123,47 +132,49 @@ inline Event manage_event(Event event) { lack_minutes = current_total_minutes + 12 * 60 - last_set_total_minutes; } + #if CLOCK_DEBUG + Serial.print("Alarm1 minutes: "); Serial.println(last_set_total_minutes); + Serial.print("Current minutes: "); Serial.println(current_total_minutes); + Serial.print("Lack minutes: "); Serial.println(lack_minutes); + #endif + for (int i = 0; i < lack_minutes; i++) { - if (digitalRead(PIN_BTN_TURN_ON) == HIGH) { - Motor.tick(); - } - last_set_time.increment_minute(); - set_alarm1_in_rtc(last_set_time); + motor_tick(); delay_tick(); } Motor.turn_off(); + + set_alarm1_in_rtc(current_time); Rtc.clear_alarm2(); - return Event::WAIT; - } break; - default: { - return Event::WAIT; } break; + default: break; } } void loop() { + noInterrupts(); + Event event = _events[_read_counter]; + interrupts(); #if CLOCK_DEBUG static unsigned int iii = 0; static unsigned char iiii = 0; - static Event prev_event = global_event; - if (global_event != prev_event || (iii++ == 0 && (iiii++ & 0b111) == 0)) { - prev_event = global_event; + if (iii++ == 0 && (iiii++ & 0b111) == 0) { Serial.print("event: "); - switch (global_event) { + switch (event) { case Event::WAIT: - Serial.print("WAIT "); + Serial.print("WAIT "); break; case Event::ALARM: - Serial.print("ALARM "); + Serial.print("ALARM "); break; case Event::CHANGE_TIME: - Serial.print("CHANGE_TIME"); + Serial.print("CHANGE"); break; case Event::SYNC: - Serial.print("SYNC "); + Serial.print("SYNC "); break; default: - Serial.print("??? "); + Serial.print("??? "); break; } Serial.print(" time: "); @@ -175,22 +186,43 @@ void loop() { print_byte(Rtc.get_status()); Serial.print(" control: "); print_byte(Rtc.get_control()); + Serial.print(" int: "); + Serial.print(digitalRead(PIN_ALARM)); Serial.print('\n'); delayMicroseconds(10000L); } + if (event == Event::WAIT) { + return; + } #else - LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + if (event == Event::WAIT) { + LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); + return; + } #endif - global_event = manage_event(global_event); + manage_event(event); + #if CLOCK_DEBUG + Serial.print("Read Counter: "); Serial.println(_read_counter); + #endif + noInterrupts(); + _events[_read_counter] = Event::WAIT; + _read_counter = (_read_counter + 1) % QUEUE_SIZE; + interrupts(); } -inline void int_change_event(Event event) { - if (global_event >= event) { - return; - } - global_event = event; +inline volatile void push_event(Event event) { +#if CLOCK_DEBUG + Serial.print("Write Counter: "); Serial.println(_write_counter); +#endif + _events[_write_counter] = event; + _write_counter = (_write_counter + 1) % QUEUE_SIZE; } -void alarm() { int_change_event(Event::ALARM); } +void volatile alarm() { +#if CLOCK_DEBUG + Serial.println("ALARM!"); +#endif + push_event(Event::ALARM); +} -void change_time() { int_change_event(Event::CHANGE_TIME); } +void volatile change_time() { push_event(Event::CHANGE_TIME); }