#include <Arduino.h>
namespace MsTimer2 {
extern unsigned long msecs;
extern void (*func)();
extern volatile unsigned long count;
extern volatile char overflowing;
extern volatile unsigned int tcnt2;
void set(unsigned long ms, void (*f)());
void start();
void stop();
void _overflow();
}
unsigned long MsTimer2::msecs;
void (*MsTimer2::func)();
volatile unsigned long MsTimer2::count;
volatile char MsTimer2::overflowing;
volatile unsigned int MsTimer2::tcnt2;
#if defined(__arm__) && defined(TEENSYDUINO)
static IntervalTimer itimer;
#endif
void MsTimer2::set(unsigned long ms, void (*f)()) {
float prescaler = 0.0;
if (ms == 0)
msecs = 1;
else
msecs = ms;
func = f;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2);
TIMSK2 &= ~(1<<OCIE2A);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2B |= (1<<CS21);
TCCR2B &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2B |= ((1<<CS22) | (1<<CS20));
TCCR2B &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
ASSR &= ~(1<<AS2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2 |= ((1<<CS22) && (1<<CS20));
TCCR2 &= ~(1<<CS21);
prescaler = 128.0;
}
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= ((1<<CS21) | (1<<CS20));
TCCR2 &= ~(1<<CS22);
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 256
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 256.0;
}
#elif defined (__AVR_ATmega32U4__)
TCCR4B = 0;
TCCR4A = 0;
TCCR4C = 0;
TCCR4D = 0;
TCCR4E = 0;
if (F_CPU >= 16000000L) {
TCCR4B = (1<<CS43) | (1<<PSR4);
prescaler = 128.0;
} else if (F_CPU >= 8000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 64.0;
} else if (F_CPU >= 4000000L) {
TCCR4B = (1<<CS42) | (1<<CS41) | (1<<PSR4);
prescaler = 32.0;
} else if (F_CPU >= 2000000L) {
TCCR4B = (1<<CS42) | (1<<CS40) | (1<<PSR4);
prescaler = 16.0;
} else if (F_CPU >= 1000000L) {
TCCR4B = (1<<CS42) | (1<<PSR4);
prescaler = 8.0;
} else if (F_CPU >= 500000L) {
TCCR4B = (1<<CS41) | (1<<CS40) | (1<<PSR4);
prescaler = 4.0;
} else {
TCCR4B = (1<<CS41) | (1<<PSR4);
prescaler = 2.0;
}
tcnt2 = (int)((float)F_CPU * 0.001 / prescaler) - 1;
OCR4C = tcnt2;
return;
#elif defined(__arm__) && defined(TEENSYDUINO)
// nothing needed here
#else
#error Unsupported CPU type
#endif
tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler);
}
void MsTimer2::start() {
count = 0;
overflowing = 0;
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIFR4 = (1<<TOV4);
TCNT4 = 0;
TIMSK4 = (1<<TOIE4);
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.begin(MsTimer2::_overflow, 1000);
#endif
}
void MsTimer2::stop() {
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TIMSK2 &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
#elif defined (__AVR_ATmega32U4__)
TIMSK4 = 0;
#elif defined(__arm__) && defined(TEENSYDUINO)
itimer.end();
#endif
}
void MsTimer2::_overflow() {
count += 1;
if (count >= msecs && !overflowing) {
overflowing = 1;
count = count - msecs; // subtract ms to catch missed overflows
// set to 0 if you don't want this.
(*func)();
overflowing = 0;
}
}
#if defined (__AVR__)
#if defined (__AVR_ATmega32U4__)
ISR(TIMER4_OVF_vect) {
#else
ISR(TIMER2_OVF_vect) {
#endif
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
TCNT2 = MsTimer2::tcnt2;
#elif defined (__AVR_ATmega128__)
TCNT2 = MsTimer2::tcnt2;
#elif defined (__AVR_ATmega8__)
TCNT2 = MsTimer2::tcnt2;
#elif defined (__AVR_ATmega32U4__)
// not necessary on 32u4's high speed timer4
#endif
MsTimer2::_overflow();
}
#endif // AVR
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Servo.h>
#define CHOOSE_CLK 2
#define CHOOSE_DT 3
#define CHANGE_CLK 4
#define CHANGE_DT 5
#define CHOOSE_SW 6
#define CHANGE_SW 13
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
int hour, mins, secs, mode;
String Now[3] {"hour", "minute", "second"};
inline bool isChooseCW()
{return digitalRead(CHOOSE_CLK) == LOW && digitalRead(CHOOSE_DT) == HIGH; }
inline bool isChooseCCW()
{return digitalRead(CHOOSE_CLK) == HIGH && digitalRead(CHOOSE_DT) == LOW; }
inline bool isChangeCW()
{return digitalRead(CHANGE_CLK) == LOW && digitalRead(CHANGE_DT) == HIGH; }
inline bool isChangeCCW()
{return digitalRead(CHANGE_CLK) == HIGH && digitalRead(CHANGE_DT) == LOW; }
void changeClk(const int wise) {
if (mode == 0) {
hour = (hour + 24 + wise) % 24;
}
else if (mode == 1) {
mins = (mins + 60 + wise) % 60;
}
else {
secs = (secs + 60 + wise) % 60;
}
}
void showSpalshScreen() {
lcd.print("LiuLuoSong");
lcd.setCursor(2, 1);
lcd.print("20232241391");
delay(1000);
lcd.clear();
}
void updateTime() {
++secs;
mins += secs >= 60;
hour += mins >= 60;
hour %= 24;
mins %= 60;
secs %= 60;
lcd.clear();
lcd.print((hour < 10 ? "0" : "") + String(hour) + ":" + (mins < 10 ? "0" : "") + String(mins) + ":" + (secs < 10 ? "0" : "") + String(secs));
lcd.setCursor(2, 1);
lcd.print("Now:" + Now[mode]);
}
void setup() {
Serial.begin(115200);
pinMode(CHOOSE_SW, INPUT_PULLUP);
pinMode(CHANGE_SW, INPUT_PULLUP);
lcd.begin(16, 2);
showSpalshScreen();
MsTimer2::set(1000, updateTime);
hour = mins = secs = mode = 0;
MsTimer2::start();
}
void loop() {
bool ifDelay = 0;
if (isChooseCW()) {
++mode;
mode %= 3;
ifDelay = 1;
}
else if (isChooseCCW()) {
mode = (mode + 2) % 3;
ifDelay = 1;
}
if (isChangeCW()) {
changeClk(1);
ifDelay = 1;
}
else if (isChangeCCW()) {
changeClk(-1);
ifDelay = 1;
}
if (ifDelay) {
delay(4);
}
}