// Header file includes
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <Wire.h>
#include <RTClib.h>
// Define the number of devices we have in the chain and the hardware interface
#define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
#define MAX_DEVICES 4 // Define the number of displays connected
#define CLK_PIN 13 // CLK or SCK
#define DATA_PIN 11 // DATA or MOSI
#define CS_PIN 10 // CS or SS
#define SPEED_TIME 75 // Speed of the transition
#define PAUSE_TIME 0
#define MAX_MESG 20
// RTC object
RTC_DS3231 rtc;
// Global variables
char szTime[9]; // hh:mm:ss\0
char szDate[20]; // Day dd-mmm-yyyy
char szMesg[MAX_MESG + 1] = "";
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);
char* daysOfTheWeek[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
// Function to get time as string
void getTime(char *psz, bool f = true)
{
DateTime now = rtc.now();
sprintf(psz, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
}
// Function to get date as string
void getDate(char *psz)
{
DateTime now = rtc.now();
sprintf(psz, "%s %02d-%s-%04d", daysOfTheWeek[now.dayOfTheWeek()], now.day(), mon2str(now.month()), now.year());
}
// Get a label for month from PROGMEM into a char array
char* mon2str(uint8_t mon)
{
static char buf[4];
static const char* str[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
strncpy(buf, str[mon - 1], 3);
buf[3] = '\0';
return buf;
}
void setup(void)
{
Wire.begin();
rtc.begin();
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
P.begin();
P.setInvert(false);
P.setZone(0, MAX_DEVICES - 4, MAX_DEVICES - 1);
P.displayZoneText(0, szMesg, PA_CENTER, SPEED_TIME, PAUSE_TIME, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
}
void loop(void)
{
static uint32_t lastTime = 0; // Memory (ms)
static uint8_t display = 0; // Current display mode
P.displayAnimate();
// Get current time in milliseconds
uint32_t currentTime = millis();
if (P.getZoneStatus(0))
{
if (currentTime - lastTime >= 5000) // Change display every 5 seconds
{
lastTime = currentTime;
switch (display)
{
case 0: // Show time
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
getTime(szMesg);
break;
case 1: // Show date
P.setTextEffect(0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
getDate(szMesg);
break;
}
display = (display + 1) % 2; // Toggle between 0 and 1 (time and date)
P.displayReset(0); // Reset zone zero
}
}
}