#include <Wire.h>
#include <LiquidCrystal.h>
// LCD pins
const int lcdRS = PB0;
const int lcdEN = PB1;
const int lcdD4 = PB10;
const int lcdD5 = PB11;
const int lcdD6 = PA8;
const int lcdD7 = PA9;
LiquidCrystal lcd(lcdRS, lcdEN, lcdD4, lcdD5, lcdD6, lcdD7);
// MAX7219 pins
#define DIN_PIN PA7
#define CLK_PIN PA6
#define CS_PIN PA5
// Pushbutton and LEDs pins
#define BTN1_PIN PB0
#define BTN2_PIN PB1
#define LED1_PIN PB10
#define LED2_PIN PB11
unsigned long previousMillis = 0;
const unsigned long interval = 1000; // 1 second
int seconds = 0;
int minutes = 49;
int hours = 21;
int dayOfMonth = 9;
int month = 8;
int year = 2025;
int weekdays = 6; // Saturday
unsigned long patternStartMillis = 0;
bool patternActive = false;
const unsigned long patternDuration = 5000; // total pattern active duration (5 sec)
// 8x8 font for digits 0-9 (simple) - not used here but kept if needed later
const byte digits[10][8] = {
{0x3C,0x66,0x6E,0x7E,0x76,0x66,0x3C,0x00}, //0
{0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00}, //1
{0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, //2
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, //3
{0x0C,0x1C,0x3C,0x6C,0x7E,0x0C,0x1E,0x00}, //4
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, //5
{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, //6
{0x7E,0x06,0x0C,0x18,0x18,0x18,0x18,0x00}, //7
{0x3C,0x66,0x3C,0x66,0x66,0x66,0x3C,0x00}, //8
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00} //9
};
void spiTransfer(byte data) {
for (int i = 7; i >= 0; i--) {
digitalWrite(CLK_PIN, LOW);
digitalWrite(DIN_PIN, (data & (1 << i)) ? HIGH : LOW);
digitalWrite(CLK_PIN, HIGH);
}
}
void max7219Write(byte address, byte data) {
digitalWrite(CS_PIN, LOW);
for (int i = 0; i < 4; i++) {
spiTransfer(address);
spiTransfer(data);
}
digitalWrite(CS_PIN, HIGH);
}
void max7219Init() {
pinMode(DIN_PIN, OUTPUT);
pinMode(CLK_PIN, OUTPUT);
pinMode(CS_PIN, OUTPUT);
max7219Write(0x0C, 0x01); // Shutdown: Normal operation
max7219Write(0x09, 0x00); // Decode mode: none (raw data)
max7219Write(0x0B, 0x07); // Scan limit: all digits
max7219Write(0x0A, 0x08); // Intensity: medium
max7219Write(0x0F, 0x00); // Display test: off
clearMatrix();
}
void clearMatrix() {
for (byte i = 1; i <= 8; i++) {
max7219Write(i, 0);
}
}
void showPattern() {
for (byte i = 1; i <= 8; i++) {
max7219Write(i, 0xFF);
}
}
void setup() {
Serial.begin(115200);
Wire.begin(PB7, PB6);
pinMode(BTN1_PIN, INPUT_PULLUP);
pinMode(BTN2_PIN, INPUT_PULLUP);
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
lcd.begin(16, 2);
lcd.print("Starting...");
max7219Init();
delay(2000);
lcd.clear();
}
void loop() {
unsigned long currentMillis = millis();
// Update time every second
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
seconds++;
if (seconds >= 60) {
seconds = 0;
minutes++;
}
if (minutes >= 60) {
minutes = 0;
hours++;
}
if (hours >= 24) {
hours = 0;
dayOfMonth++;
weekdays++;
if (weekdays > 7) weekdays = 1;
// skipping month/year update for simplicity
}
}
bool btn1Pressed = (digitalRead(BTN1_PIN) == LOW);
bool btn2Pressed = (digitalRead(BTN2_PIN) == LOW);
// If BTN1 pressed: show pattern
if (btn1Pressed && !patternActive) {
patternActive = true;
patternStartMillis = currentMillis;
digitalWrite(LED1_PIN, HIGH);
digitalWrite(LED2_PIN, LOW);
lcd.clear(); // clear LCD when pattern starts
}
// If BTN2 pressed: clear pattern immediately
if (btn2Pressed && patternActive) {
patternActive = false;
clearMatrix();
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, HIGH);
delay(200); // brief LED indication
digitalWrite(LED2_PIN, LOW);
}
if (patternActive) {
if (currentMillis - patternStartMillis < patternDuration) {
showPattern(); // Keep showing the pattern continuously
} else {
// pattern time ended, clear pattern & deactivate
patternActive = false;
clearMatrix();
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, LOW);
}
} else {
clearMatrix(); // keep matrix blank if no pattern
}
// Show time/date on LCD only if pattern not active
if (!patternActive) {
lcd.setCursor(0, 0);
lcd.print("Time: ");
if (hours < 10) lcd.print('0');
lcd.print(hours);
lcd.print(':');
if (minutes < 10) lcd.print('0');
lcd.print(minutes);
lcd.print(':');
if (seconds < 10) lcd.print('0');
lcd.print(seconds);
lcd.setCursor(0, 1);
lcd.print("Date: ");
if (dayOfMonth < 10) lcd.print('0');
lcd.print(dayOfMonth);
lcd.print('/');
if (month < 10) lcd.print('0');
lcd.print(month);
lcd.print('/');
lcd.print(year);
}
delay(50);
}