#include <Arduino.h>
#include <RTClib.h>
#include <AlarmTone.h>
#include "main.h"
#if defined(extEEPROM)
#include "Eeprom24Cxx.h"
static Eeprom24C eeprom(extEEPROM, extEEPROM_ADDRESS);
#else
#include <EEPROM.h>
#endif
#if defined(DS3231)
RTC_DS3231 rtc;
#elif defined(DS1307)
RTC_DS1307 rtc;
#else
#error define RTC chip is required.
#endif
AlarmTone alarmTone;
enum ClockMode { MODE_TIME, MODE_ALARM, MODE_SET, MODE_CAL_1, MODE_CAL_2 };
uint8_t mode = 0;
uint8_t select = 0;
uint8_t calib_hour_max = 240;
uint8_t calib_hour_min = 10;
uint8_t calib_min_max = 240;
uint8_t calib_min_min = 10;
uint8_t alarm_hour = 0;
uint8_t alarm_min = 0;
boolean alarm_state = 0;
uint8_t counter = 0;
int8_t rotation_accumulator;
uint8_t hour, minute;
uint8_t flag;
void readEncoder() {
int dtValue = digitalRead(ENCODER_DT);
if (dtValue == HIGH) {
counter++; // Clockwise
rotation_accumulator = 1;
}
if (dtValue == LOW) {
counter--; // Counterclockwise
rotation_accumulator = -1;
}
}
void initModePos() { pinMode(POS_MODE, INPUT); }
uint8_t getModePos() {
// update mode if value not change for 3s
return map(analogRead(POS_MODE), 0, 1023, 0, 4);
}
// Get the counter value, disabling interrupts.
// This make sure readEncoder() doesn't change the value
// while we're reading it.
int getCounter() {
int result;
noInterrupts();
result = counter;
interrupts();
return result;
}
void resetCounter() {
cli(); // noInterrupts
counter = 0;
sei(); // interrupts
}
void initVoltMeter() {
pinMode(HOUR_VOLT, OUTPUT);
pinMode(MIN_VOLT, OUTPUT);
/* scanning */
displayHour(13); //set hour=13 to check AM_PM_LED also
displayMin(59);
delay(1000);
displayHour(0);
displayMin(0);
}
void initAmPmLed() {
pinMode(AM_PM_LED, OUTPUT);
}
void turnOnAmPmLed() { digitalWrite(AM_PM_LED, HIGH); }
void turnOffAmPmLed() { digitalWrite(AM_PM_LED, LOW); }
void initAlarmSW() { pinMode(IS_ALARM_SW, INPUT_PULLUP); }
void processAlarmState() {
if (1 == digitalRead(IS_ALARM_SW)) {
alarm_state = ALARM_ON;
turnOnAmPmLed();
} else {
alarm_state = ALARM_OFF;
turnOffAmPmLed();
}
}
void initAlarmLed() {
pinMode(IS_ALARM_LED, OUTPUT);
digitalWrite(IS_ALARM_LED, HIGH);
delay(1000);
digitalWrite(IS_ALARM_LED, LOW);
}
void displayHour(uint8_t _hour) {
analogWrite(HOUR_VOLT, map(_hour, 0, 12, calib_hour_min, calib_hour_max));
if (_hour > 12) {
digitalWrite(AM_PM_LED, HIGH); // turn on Led
} else {
digitalWrite(AM_PM_LED, LOW); // turn off Led
}
}
void displayMin(uint8_t _min) {
analogWrite(MIN_VOLT, map(_min, 0, 60, calib_min_min, calib_min_max));
}
void modeAlarm() {
static uint8_t holder;
if (digitalRead(ENCODER_SW) == LOW) {
select++;
}
if (select == 1) {
flag = MODE_ALARM;
Serial.print("Setting Alarm HOUR: ");
holder = rotation_accumulator + alarm_hour;
if (holder >= 24) {
holder = 0;
}
if (holder < 0) {
holder = 24;
}
alarm_hour = holder;
Serial.println(alarm_hour);
} else if (select == 2) {
flag = MODE_ALARM;
Serial.print("Setting Alarm MIN: ");
holder = rotation_accumulator + alarm_min;
if (holder >= 60) {
holder = 0;
}
if (holder < 0) {
holder = 59;
}
alarm_min = holder;
Serial.println(alarm_min);
} else {
// TODO: display alarm time
select = 0; // reset select if press ENCODER_SW
counter = 0;
}
}
void modeCal_1() {
static uint8_t holder;
if (digitalRead(ENCODER_SW) == LOW) {
select++;
}
if (select == 0) {
Serial.print("Calib Max-Hour voltage: ");
holder = rotation_accumulator + calib_hour_max;
if (holder > 255) {
holder = 255;
}
if (holder < 0) {
holder = 0;
}
calib_hour_max = holder;
Serial.println(calib_hour_max);
} else if (select == 1) {
Serial.print("Calib Max-Minute voltage: ");
holder = rotation_accumulator + calib_hour_min;
if (holder > 255) {
holder = 255;
}
if (holder < 0) {
holder = 0;
}
calib_hour_min = holder;
Serial.println(calib_hour_min);
} else {
select = 0; // reset select if press ENCODER_SW
counter = 0;
}
}
void modeCal_2() {
static uint8_t holder;
if (digitalRead(ENCODER_SW) == LOW) {
select++;
}
if (select == 0) {
Serial.print("Calib Max-Hour voltage: ");
holder = rotation_accumulator + calib_min_max;
calib_min_max = holder;
Serial.println(calib_min_max);
} else if (select == 1) {
Serial.print("Calib Max-Minute voltage: ");
holder = rotation_accumulator + calib_min_min;
calib_min_min = holder;
Serial.println(calib_min_min);
} else {
select = 0; // reset select if press ENCODER_SW
counter = 0;
}
if (holder > 255) {
holder = 255;
}
if (holder < 0) {
holder = 0;
}
}
void modeSetting() {
static uint8_t holder;
if (digitalRead(ENCODER_SW) == LOW) {
select++;
}
if (select == 0) {
flag = MODE_SET;
Serial.print("Setting HOUR: ");
holder = rotation_accumulator + hour;
if (holder >= 24) {
holder = 0;
}
if (holder < 0) {
holder = 23;
}
hour = holder;
Serial.println(hour);
} else if (select == 1) {
flag = MODE_SET;
Serial.print("Setting MIN: ");
holder = rotation_accumulator + minute;
if (holder >= 60) {
holder = 0;
}
if (holder < 0) {
holder = 59;
}
minute = holder;
Serial.println(minute);
} else {
select = 0; // reset select if press ENCODER_SW
counter = 0;
}
}
void saveData(uint8_t ADDRESS, uint8_t data) {
#if defined(extEEPROM)
eeprom.write_1_byte(ADDRESS, data);
#else
EEPROM.write(ADDRESS, data);
#endif
}
uint8_t getSavedData(uint8_t ADDRESS) {
#if defined(extEEPROM)
return eeprom.write_1_byte(ADDRESS);
#else
return EEPROM.read(ADDRESS);
#endif
}
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.print("Couldn't find RTC");
while (1)
;
}
#ifdef DS1307
if (!rtc.isrunning()) {
Serial.print("RTC is NOT running!");
Serial.println();
}
#endif
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
/* Get saved data from eeprom */
if (getSavedData(EEPROM_SAVED) != 0x30) {
Serial.print("Data not saved!, write data to EEPROM");
saveData(EEPROM_SAVED, 0x30);
saveData(EEPROM_CALIB_HOUR_MAX_ADDRESS, calib_hour_max);
saveData(EEPROM_CALIB_HOUR_MIN_ADDRESS, calib_hour_min);
saveData(EEPROM_CALIB_MIN_MAX_ADDRESS, calib_min_max);
saveData(EEPROM_CALIB_MIN_MIN_ADDRESS, calib_min_max);
saveData(EEPROM_ALARM_HOUR_ADDRESS, alarm_hour);
saveData(EEPROM_ALARM_MINUTE_ADDRESS, alarm_min);
} else {
Serial.print("Get init data");
calib_hour_max = getSavedData(EEPROM_CALIB_HOUR_MAX_ADDRESS);
calib_hour_min = getSavedData(EEPROM_CALIB_HOUR_MIN_ADDRESS);
calib_min_max = getSavedData(EEPROM_CALIB_MIN_MAX_ADDRESS);
calib_min_min = getSavedData(EEPROM_CALIB_MIN_MIN_ADDRESS);
alarm_hour = getSavedData(EEPROM_ALARM_HOUR_ADDRESS);
alarm_min = getSavedData(EEPROM_ALARM_MINUTE_ADDRESS);
}
initModePos();
initVoltMeter();
initAmPmLed();
initAlarmLed();
// alarmTone.begin(ALARM_TONE);
// Initialize encoder pins
pinMode(ENCODER_CLK, INPUT);
pinMode(ENCODER_DT, INPUT);
pinMode(ENCODER_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, FALLING);
}
void loop() {
mode = getModePos();
if (mode == MODE_TIME) {
DateTime now = rtc.now();
if (flag == MODE_SET) {
DateTime _now =
DateTime(now.year(), now.month(), now.day(), hour, minute, 0);
rtc.adjust(_now);
flag = MODE_TIME;
Serial.println("Update time! Done!");
}
hour = now.hour();
minute = now.minute();
processAlarmState();
Serial.println("Display Mode");
displayHour(now.hour());
displayMin(now.minute());
Serial.print(hour);
Serial.print(" ");
Serial.println(minute);
delay(500);
} else if (mode == MODE_ALARM) {
Serial.println("Setting Alarm Mode");
modeAlarm();
} else if (mode == MODE_SET) {
Serial.println("Setting time");
modeSetting();
} else if (mode == MODE_CAL_1) {
Serial.println("CAL 1 Mode");
modeCal_1();
} else if (mode == MODE_CAL_1) {
Serial.println("CAL 2 Mode");
modeCal_2();
}
rotation_accumulator = 0;
// delay(1000);
if (digitalRead(ENCODER_SW) == LOW) {
resetCounter();
}
}