#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <ArduinoTrace.h>
#include <TimerOne.h>
#include <ezButton.h>
#include <Wire.h>
#include <SPI.h>
#include "image.h"
#include "Time.h"
char timeString[6]; //para HH:MM\0
bool buzzerAllowed = HIGH;
bool buzzerState = LOW;
unsigned char halfsecond = 0;
unsigned char ClockPoint = 1;
unsigned char alarmMode = 0;
unsigned char Update = 0;
unsigned long pm1 = 0;
unsigned long pm2 = 0;
#define allowBuzzerPin 8
#define alarmSetBtnPin 4
#define timeSetBtnPin 5
#define minuteBtnPin 7
#define hourBtnPin 6
#define buzzerPin 9
#define CLK 2
#define DIO 3
#define OFF 0
#define ON 1
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
ezButton alarmSetBtn(alarmSetBtnPin);
ezButton timeSetBtn(timeSetBtnPin);
ezButton minuteBtn(minuteBtnPin);
ezButton hourBtn(hourBtnPin);
Time currentTime;
Time alarmTime;
void setup()
{
currentTime.hour = 12;
alarmTime.hour = 12;
currentTime.minute = 0;
alarmTime.minute = 1;
currentTime.second = 0;
alarmTime.second = 0;
Serial.begin(115200);
pinMode(buzzerPin, OUTPUT);
pinMode(hourBtnPin, INPUT_PULLUP);
pinMode(minuteBtnPin, INPUT_PULLUP);
pinMode(timeSetBtnPin, INPUT_PULLUP);
pinMode(alarmSetBtnPin, INPUT_PULLUP);
pinMode(allowBuzzerPin, INPUT_PULLUP);
hourBtn.setDebounceTime(50);
minuteBtn.setDebounceTime(50);
timeSetBtn.setDebounceTime(50);
alarmSetBtn.setDebounceTime(50);
Timer1.initialize(500000);
Timer1.attachInterrupt(TimingISR);
// inicializar y limpiar el display.
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
// limpiar el buffer.
display.clearDisplay();
// Display bitmap.
display.drawBitmap(0, 0, image, 128, 64, WHITE);
display.display();
delay(2000);
// limpiar el buffer.
display.clearDisplay();
}
void loop()
{
alarmSetBtn.loop();
timeSetBtn.loop();
hourBtn.loop();
minuteBtn.loop();
if(alarmMode == ON) incrementTime(&alarmTime);
else incrementTime(¤tTime);
if(Update == ON)
{
if(alarmMode == ON) TimeUpdate(alarmTime);
else TimeUpdate(currentTime);
}
if(currentTime == alarmTime){
activateAlarm();
}else{
noTone(buzzerPin);
}
buzzerAllowed = digitalRead((allowBuzzerPin));
showTimeOnOLED(timeString, SCREEN_HEIGHT - 40, 3);
display.fillRect(20, 0, 88, 10, BLACK);
if (buzzerAllowed == HIGH) centerPrint("Alarma:ON", 2, 1, WHITE);
else centerPrint("Alarma:OFF", 2, 1, WHITE);
}
void incrementTime(Time *time)
{
enum {s0,s1,s2,s3};
static int state = s0;
switch(state)
{
case s0:
if(timeSetBtn.getState() == LOW || alarmSetBtn.getState() == LOW)
{
state = s1;
if(alarmSetBtn.getState() == LOW) alarmMode = ON;
}
break;
case s1:
if((timeSetBtn.getState() == LOW && alarmMode == OFF) ||
(alarmSetBtn.getState() == LOW && alarmMode == ON))
{
if(hourBtn.getState() == LOW)
{
if (time->hour < 23) time->hour++;
else time->hour = 0;
pm1 = millis();
state = s2;
}
if(minuteBtn.getState() == LOW)
{
if (time->minute < 59) time->minute++;
else time->minute = 0;
pm1 = millis();
state = s2;
}
}
else
{
state = s0;
if(alarmSetBtn.getState() == HIGH && alarmMode == ON) alarmMode = OFF;
}
break;
case s2:
if((timeSetBtn.getState() == LOW && alarmMode == OFF) ||
(alarmSetBtn.getState() == LOW && alarmMode == ON))
{
if((millis() - pm1) > 800)
{
pm1 = millis();
state = s3;
}
if(minuteBtn.getState() == HIGH && hourBtn.getState() == HIGH)
{
state = s1;
}
}
else
{
state = s0;
if(alarmSetBtn.getState() == HIGH && alarmMode == ON) alarmMode = OFF;
}
break;
case s3:
if((timeSetBtn.getState() == LOW && alarmMode == OFF) ||
(alarmSetBtn.getState() == LOW && alarmMode == ON))
{
if(hourBtn.getState() == LOW)
{
if((millis() - pm1) > 250)
{
pm1 = millis();
if (time->hour < 23) time->hour++;
else time->hour = 0;
}
}
if(minuteBtn.getState() == LOW)
{
if((millis() - pm1) > 250)
{
pm1 = millis();
if (time->minute < 59) time->minute++;
else time->minute = 0;
}
}
if(minuteBtn.getState() == HIGH && hourBtn.getState() == HIGH)
{
state = s1;
}
}
else
{
state = s0;
if(alarmSetBtn.getState() == HIGH && alarmMode == ON) alarmMode = OFF;
}
break;
}
}
void TimingISR()
{
Update = ON;
halfsecond ++;
if(halfsecond == 2){
currentTime.second ++;
if(currentTime.second == 60)
{
currentTime.minute ++;
if(currentTime.minute == 60)
{
currentTime.hour ++;
if(currentTime.hour == 24) currentTime.hour = 0;
currentTime.minute = 0;
}
currentTime.second = 0;
}
halfsecond = 0;
}
ClockPoint = (~ClockPoint) & 0x01;
}
void TimeUpdate(Time newTime)
{
uint16_t color;
if(ClockPoint) color = WHITE;
else color = BLACK;
sprintf(timeString, "%02d %02d", newTime.hour, newTime.minute);
centerPrint(":", SCREEN_HEIGHT - 40, 3, color);
Update = OFF;
}
void activateAlarm()
{
if(buzzerAllowed == HIGH)
{
if((millis()-pm2) >= 1000)
{
pm2=millis();
if (buzzerState==HIGH)
{
noTone(buzzerPin);
buzzerState=LOW;
}
else
{
tone(buzzerPin, 262, 250);
buzzerState=HIGH;
}
}
}
else
{
noTone(buzzerPin);
}
}
void showTimeOnOLED(char timeString[], int y, int size)
{
display.fillRect(16, 17, 40, 30, BLACK);
display.fillRect(70, 17, 40, 30, BLACK);
centerPrint(timeString, y, size, WHITE);
}
void centerPrint(char *text, int y, int size, uint16_t color)
{
display.setTextSize(size);
display.setTextColor(color);
display.setCursor(SCREEN_WIDTH/2 - ((strlen(text))*6*size)/2, y);
display.print(text);
display.display();
}