// Learn about the ESP32 WiFi simulation in
// https://docs.wokwi.com/guides/esp32-wifi
#include <Wire.h>
#include <WiFi.h>
#include <Fsm.h>
#include <JC_Button.h>
#include <DS3232RTC.h>
#include <LiquidCrystal_I2C.h>
#define BUTTON_PIN_UP 18
#define BUTTON_PIN_DOWN 5
#define BUTTON_PIN_MENU_SELECT 19
#define BUTTON_PIN_BACK 4
#define SQW_PIN 23
#define DEBOUNCE_MS 20
#define PULLUP true
#define INVERT false
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 16, 2);
DS3232RTC RTC;
/*
Symbols
*/
byte bell_symbol[8] = {
B00100,
B01110,
B01110,
B01110,
B01110,
B11111,
B00000,
B00100
};
/*
States of FSM
*/
enum STATES
{
MAIN,
MENU_SET_ALARM,
MENU_SET_TIME,
MENU_SET_DATE,
SET_HOUR,
SET_MINUTE,
SET_DAY,
SET_MONTH,
SET_YEAR,
SET_ALARM_HOUR,
SET_ALARM_MINUTE,
SET_ALARM_ON_OFF,
ALARM_TIME,
// Otherwise, it times out after 5 seconds, discards the changes and returns to displaying the time
};
STATES state = MAIN;
enum BUTTONS
{
BUTTON_LEFT,
BUTTON_RIGHT,
BUTTON_UP,
BUTTON_DOWN,
BUTTON_OK,
BUTTON_BACK
};
int Hour;
int Minute;
int Second;
/*
Transition callback functions
*/
void on_page_exit();
void on_main_page_enter();
void main_page_on_state();
void on_set_time_page_enter();
void set_time_page_on_state();
boolean is_button_prassed(Button button);
void check_button();
void get_time();
void display_time();
byte decToBcd(byte val);
byte bcdToDec(byte val);
void display_position(int digits);
/*
Initialize push buttons
*/
Button buttonSelect(BUTTON_PIN_MENU_SELECT, DEBOUNCE_MS, PULLUP, INVERT);
/*
Initialize states of fsm
*/
State state_main_page(&on_main_page_enter,
&main_page_on_state,
&on_page_exit);
State state_set_time_page(&on_set_time_page_enter,
&set_time_page_on_state,
&on_page_exit);
Fsm fsm(&state_main_page);
void spinner() {
static int8_t counter = 0;
const char* glyphs = "\xa1\xa5\xdb";
LCD.setCursor(15, 1);
LCD.print(glyphs[counter++]);
if (counter == strlen(glyphs)) {
counter = 0;
}
}
void setup() {
Serial.begin(115200);
LCD.init();
LCD.backlight();
LCD.setCursor(0, 0);
LCD.print("Connecting to ");
LCD.setCursor(0, 1);
LCD.print("WiFi ");
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
spinner();
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
fsm.add_transition(&state_main_page, &state_set_time_page, BUTTON_OK, NULL);
setSyncProvider(RTC.get);
setSyncInterval(5);
RTC.squareWave(DS3232RTC::SQWAVE_NONE);
LCD.createChar(1, bell_symbol);
LCD.clear();
}
void loop() {
fsm.run_machine();
delay(100);
}
void get_time() {
Wire.beginTransmission(0x68);
Wire.write(0); //set register to zero
Wire.endTransmission();
Wire.requestFrom(0x68, 3);// 3 bytes (sec, min, hour)
Second = bcdToDec(Wire.read() & 0x7f);
Minute = bcdToDec(Wire.read());
Hour = bcdToDec(Wire.read() & 0x3f);
}
void display_time() {
get_time();
LCD.setCursor(0, 0);
display_position(Hour);
LCD.print(":");
display_position(Minute);
LCD.print(":");
display_position(Second);
}
void on_page_exit() {
LCD.clear();
}
void on_main_page_enter() {
LCD.write(1);
LCD.print("Welcome");
delay(1000);
}
void main_page_on_state() {
display_time();
boolean isPressed = is_button_prassed(buttonSelect);
if (isPressed) {
fsm.trigger(BUTTON_OK);
}
}
void on_set_time_page_enter() {
LCD.setCursor(0, 0);
LCD.print("setTime");
delay(300);
}
void set_time_page_on_state() {
boolean isPressed = is_button_prassed(buttonSelect);
if (isPressed) {
fsm.trigger(BUTTON_OK);
}
}
boolean is_button_prassed(Button button) {
button.read();
return button.isPressed();
}
byte decToBcd(byte val) {
return ( (val / 10 * 16) + (val % 10) );
}
byte bcdToDec(byte val) {
return ( (val / 16 * 10) + (val % 16) );
}
void display_position(int digits) {
if (digits < 10)
LCD.print("0");
LCD.print(digits);
}