#include "RTClib.h"
#include "U8glib.h"
#include <Wire.h>
#include <Adafruit_SSD1306.h>
RTC_DS1307 rtc; // create an instance of the Real Time Clock
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire); // create an instance of the OLED display
DateTime now = rtc.now(); //get the current time
int clockCenterX=32;
int clockCenterY=32;
int modeToggle = 0;
boolean stateStopwatch;
unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedMillis;
void setup() {
Serial.begin(115200);
//check rtc connection
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
attachInterrupt(1, modeChange, RISING);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
display.display();
// Clear the buffer.
display.clearDisplay();
display.display();
}
void modeChange(){
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
// If interrupts come faster than 200ms, assume it's a bounce and ignore
if (interrupt_time - last_interrupt_time > 200)
{
if (modeToggle != 1) {
modeToggle = 1;
stateStopwatch = true;
startMillis = millis();
} else if (modeToggle == 1 && stateStopwatch == false) {
modeToggle = 0;
} else if (modeToggle == 1 && stateStopwatch == true) {
stateStopwatch = false;
}
}
last_interrupt_time = interrupt_time;
}
void drawDigital() {
String timeStr;
if (now.minute() >= 10)
timeStr = String(now.hour()) + ":" + String(now.minute());
else
timeStr = String(now.hour()) + ":0" + String(now.minute());
// text display tests
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(67,25);
display.print(timeStr);
display.setCursor(0,0);
}
void drawMark(int h)
{
float x1, y1, x2, y2;
h=h*30;
h=h+270;
x1=29*cos(h*0.0175);
y1=29*sin(h*0.0175);
x2=26*cos(h*0.0175);
y2=26*sin(h*0.0175);
display.drawLine(x1+clockCenterX, y1+clockCenterY, x2+clockCenterX, y2+clockCenterY, SSD1306_WHITE);
}
void drawMin(int m)
{
float x1, y1, x2, y2, x3, y3, x4, y4;
m=m*6;
m=m+270;
x1=25*cos(m*0.0175);
y1=25*sin(m*0.0175);
x2=3*cos(m*0.0175);
y2=3*sin(m*0.0175);
x3=10*cos((m+8)*0.0175);
y3=10*sin((m+8)*0.0175);
x4=10*cos((m-8)*0.0175);
y4=10*sin((m-8)*0.0175);
display.drawLine(x1+clockCenterX, y1+clockCenterY, x3+clockCenterX, y3+clockCenterY, SSD1306_WHITE);
display.drawLine(x3+clockCenterX, y3+clockCenterY, x2+clockCenterX, y2+clockCenterY, SSD1306_WHITE);
display.drawLine(x2+clockCenterX, y2+clockCenterY, x4+clockCenterX, y4+clockCenterY, SSD1306_WHITE);
display.drawLine(x4+clockCenterX, y4+clockCenterY, x1+clockCenterX, y1+clockCenterY, SSD1306_WHITE);
}
void drawHour(int h, int m)
{
float x1, y1, x2, y2, x3, y3, x4, y4;
h=(h*30)+(m/2);
h=h+270;
x1=20*cos(h*0.0175);
y1=20*sin(h*0.0175);
x2=3*cos(h*0.0175);
y2=3*sin(h*0.0175);
x3=8*cos((h+12)*0.0175);
y3=8*sin((h+12)*0.0175);
x4=8*cos((h-12)*0.0175);
y4=8*sin((h-12)*0.0175);
display.drawLine(x1+clockCenterX, y1+clockCenterY, x3+clockCenterX, y3+clockCenterY, SSD1306_WHITE);
display.drawLine(x3+clockCenterX, y3+clockCenterY, x2+clockCenterX, y2+clockCenterY, SSD1306_WHITE);
display.drawLine(x2+clockCenterX, y2+clockCenterY, x4+clockCenterX, y4+clockCenterY, SSD1306_WHITE);
display.drawLine(x4+clockCenterX, y4+clockCenterY, x1+clockCenterX, y1+clockCenterY, SSD1306_WHITE);
}
void drawClockFace() {
// Draw Clockface
for (int i=0; i<2; i++)
{
display.drawCircle(clockCenterX, clockCenterY, 31-i, SSD1306_WHITE);
}
for (int i=0; i<3; i++)
{
display.drawCircle(clockCenterX, clockCenterY, i, SSD1306_WHITE);
}
// Draw a small mark for every hour
for (int i=0; i<12; i++)
{
drawMark(i);
}
}
void drawAnalog() {
drawClockFace();
drawMin(now.minute());
drawHour(now.hour(), now.minute());
}
void drawStopwatch(){
// text display tests
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10,24);
if (stateStopwatch) {
//elapsedMillis = getStopwatch();
currentMillis = millis();
elapsedMillis = (currentMillis - startMillis);
unsigned long durMS = (elapsedMillis%1000); //Milliseconds
unsigned long durSS = (elapsedMillis/1000)%60; //Seconds
unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
unsigned long durHH = (elapsedMillis/(3600000)%24); //Hours
String timeStr = String(durHH) + ":" + String(durMM) + ":" + String(durSS) + ":" + String(durMS);
display.print(timeStr);
} else {
unsigned long durMS = (elapsedMillis%1000); //Milliseconds
unsigned long durSS = (elapsedMillis/1000)%60; //Seconds
unsigned long durMM = (elapsedMillis/(60000))%60; //Minutes
unsigned long durHH = (elapsedMillis/(3600000)%24); //Hours
String timeStr = String(durHH) + ":" + String(durMM) + ":" + String(durSS) + ":" + String(durMS);
display.print(timeStr);
}
display.setCursor(0,0);
}
void loop() {
display.clearDisplay();
if (modeToggle == 0) {
now = rtc.now();
drawDigital();
drawAnalog();
} else if (modeToggle == 1) {
drawStopwatch();
}
display.display();
}
/*
Continuing from Pass Plus Task 1 for designing digital clock with few features. Connect
to a push button. You can use the hardware/timer interrupt to detect the button if needed. If the
button is pressed, it will convert to a stopwatch or back to be digital clock. While as stopwatch,
the same button is used to start/stop the stopwatch (Require demonstration)
*/