To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
If screen is scrambled switch pin D13 and D11.
-RR

Use EXP 3 Header!
-RR
#include <Arduino.h>
#include <U8g2lib.h>
#include <EEPROM.h>
// ================= LCD =================
const uint8_t PIN_LCD_CS = 10; // CS/RS
U8G2_ST7920_128X64_1_HW_SPI u8g2(U8G2_R0, PIN_LCD_CS, U8X8_PIN_NONE);
// ================= ENCODER =================
const uint8_t PIN_ENC_A = 2;
const uint8_t PIN_ENC_B = 3;
const uint8_t PIN_ENC_BTN = 4;
// If your encoder changes 2 numbers per click, set this to 2.
// If it changes 1 per click, leave at 4.
const int8_t TRANSITIONS_PER_DETENT = 4;
// ================= UI TIMING =================
const uint16_t LONG_MS = 700;
const uint16_t DEBOUNCE_MS = 25;
// ================= EEPROM =================
const int EEPROM_SIG_ADDR = 0;
const int EEPROM_TIME_ADDR = 1; // uint32_t (4 bytes)
const int EEPROM_CHIME_ADDR = EEPROM_TIME_ADDR + 4; // uint8_t
const int EEPROM_VOL_ADDR = EEPROM_CHIME_ADDR + 1; // uint8_t
const uint8_t EEPROM_SIG = 0xA5; // marker that EEPROM has valid data
// ================= BUZZER =================
const uint8_t PIN_BUZZER = 8;
// Chime settings (editable, saved)
bool chime_enabled = true;
uint8_t chime_volume_percent = 18; // editable 0..100 (0 = silent)
// ================= CLOCK CORE =================
uint32_t clock_sec = 0;
uint32_t last_tick_ms = 0;
// ================= SET MODE FIELDS =================
bool set_mode = false;
uint8_t edit_hour12 = 12; // 1..12
uint8_t edit_min = 0; // 0..59
uint8_t edit_sec = 0; // 0..59 (frozen in SET)
bool edit_pm = false; // false=AM, true=PM
bool edit_chime_enabled = true;
uint8_t edit_volume_percent = 18;
enum Sel : uint8_t { SEL_HOUR, SEL_MIN, SEL_AMPM, SEL_CHIME, SEL_VOL, SEL_TEST };
Sel sel = SEL_HOUR;
uint32_t saved_banner_until_ms = 0;
// Track last hour we chimed so we only do it once per hour
int8_t last_chimed_h24 = -1;
// ================= ENCODER ISR =================
volatile int16_t enc_delta = 0;
volatile uint8_t enc_prev = 0;
static const int8_t ENC_TAB[16] = {
0, -1, 1, 0,
1, 0, 0, -1,
-1, 0, 0, 1,
0, 1, -1, 0
};
void enc_isr() {
uint8_t a = digitalRead(PIN_ENC_A) ? 1 : 0;
uint8_t b = digitalRead(PIN_ENC_B) ? 1 : 0;
uint8_t cur = (a << 1) | b;
uint8_t idx = (enc_prev << 2) | cur;
enc_prev = cur;
enc_delta += ENC_TAB[idx];
}
// ================= BUTTON =================
bool btn_last_raw = true;
bool btn_stable = true;
uint32_t btn_change_ms = 0;
uint32_t btn_down_ms = 0;
bool long_fired = false;
static void poll_button(bool &short_press, bool &long_press) {
short_press = false;
long_press = false;
bool raw = digitalRead(PIN_ENC_BTN); // HIGH idle, LOW pressed
uint32_t now = millis();
if (raw != btn_last_raw) {
btn_last_raw = raw;
btn_change_ms = now;
}
if ((now - btn_change_ms) > DEBOUNCE_MS) {
if (btn_stable != raw) {
btn_stable = raw;
if (btn_stable == LOW) {
btn_down_ms = now;
long_fired = false;
} else {
if (!long_fired) short_press = true;
}
}
}
if (btn_stable == LOW && !long_fired && (now - btn_down_ms) >= LONG_MS) {
long_fired = true;
long_press = true;
}
}
// ================= HELPERS =================
static uint32_t wrap_day(uint32_t sec) { return sec % 86400UL; }
static void sec_to_hms(uint32_t sec, uint8_t &h24, uint8_t &m, uint8_t &s) {
sec = wrap_day(sec);
h24 = sec / 3600UL;
m = (sec / 60UL) % 60UL;
s ...
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates