Matrix Clock
#include <LedControl.h>
/*H*******************************************************
Name:		ArduinoMatrixClock.ino
Created:	12.06.2018  20:56:49 
Author:	mylms.cz
From: https://abidcg.blogspot.com/2019/05/hello-weMtrxome-to-abid-cg-creator-blog.html
https://www.mylms.cz/text-arduino-hod iny-s-maticovym-displejem/
5V = common for all modules, 5V supply connected via 1N4148
********************************************************/
#include <EEPROM.h>
#include <Wire.h>
#include <LedControl.h>

//************************* DEFINES ************************************
#define  NBRDEVS   4
#define DS3231_I2C_ADDRESS 0x68                        // DS3231 MODULE ADDR
#define  BTN1    D2                                 // (SET INTERNAL_PULLUP)
#define  BTN2    D3                                 // (SET INTERNAL_PULLUP)
#define  MTXDIN  D4                               // MATRIX DISPLAY, pin DIN
#define  MTXCLK  D5                               // MATRIX DISPLAY, pin CLK
#define  MTXCS   D6                                // MATRIX DISPLAY, Pin CS
#define  RTCSDA  A4                                   // RTC MODULE, PIN SDA
#define  RTCCLK  A5                                   // RTC MODULE, PIN SCL

//************************* PROTOTYPES ************************************
void GetButton(); 
void WriteTime(); 
void Intro(); 
void DrawSymbol( byte adr, byte symbol, byte offset ); 
byte ByteRevers( byte in ); 
void SetRtc( byte Sec, byte Min, byte Hr, byte Dow, byte Dom, byte Mon
	, byte Yr); 
void GetRtc(); 
byte decToBcd( byte val ); 
byte bcdToDec( byte val ); 
void SerialComm();

//************************* VARIABLES ************************************
LedControl Mtrx = LedControl( 4, 5,6, NBRDIVS);//DIN, CLK, CS, DISPLAY COUNT
byte Bright = 0;
bool ShowDots;
byte Sec, Min, Hr, Dow, Dom, Mon, Yr;
unsigned long CurrTim;
unsigned long DsplTim;     	                                      // DRAWING
bool LstInp1;                                      // LAST STATE OF #1 INPUT
bool lastInput2;                                   // LAST STATE OF #2 INPUT
bool CurrInp1;                                   // ACTUAL STATE OF INPUT #1
bool CurrInp2;                                   // ACTUAL STATE OF INPUT #2
byte State;

/*F********************************************************************
*
**********************************************************************/
void 
setup() 
{
	Wire.begin();                                          // START I2C COMM
	Serial.begin( 9600 );
	pinMode( BTN1, INPUT_PULLUP);
	pinMode( BTN2, INPUT_PULLUP);
	Bright = EEPROM.read( 0 );           // LOAD LIGHT INTENSITY FROM EEPROM
	delay( 10 );
	for( byte address = 0; address < devices; address++) 
	{
		Mtrx.shutdown( address, false);	                      // POWERSAVING
		Mtrx.setIntensity( address, Bright );// SET LIGHT INTENS MIN: 0 MAX:15
		Mtrx.clearDisplay( address );                       // CLEAR DISPLAY
	}
	//INIT TIME SETTING
	// SetRtc( 15, 41, 8, 6, 30, 3, 18);  // sec, min, Hr, Dow, Dom, Mon, Yr
	//Intro();	//show LMS!
}
/*F********************************************************************
*
**********************************************************************/
void 
loop() 
{
	CurrInp1 = digitalRead( BTN1 );                    // STORE INPUT TO VAR
	CurrInp2 = digitalRead( BTN2 );
	switch( State ) 
	{
		case 0:
			CurrTim = millis();                          // SHOW ACTUAL TIME
			if( CurrTim - DsplTim >= 500) 
			{
				DsplTim = CurrTim;                           // "MULTASKING"
				GetRtc();		                          // GET ACTUAL TIME
				WriteTime();	      // WRITE ACTUAL TIME TO MATRIX DISPLAY
			}
			if( !CurrInp1 && !CurrInp2 ) 
			{
				delay( 20 );
				State = 1;                               // GO TO "pre" MENU
			}
			break;
		case 1:
			if( CurrInp1 && CurrInp2) 
			{
				delay( 20 );
				State = 2;                                     // GO TO MENU
				DrawSymbol( 1, 0, 0);                               // SPACE
				DrawSymbol( 0, 72 - 32, 0);                             // H
			}
			break;
		case 2:                                                    // MENU 1
			WriteTime();                                          // SET HRS
			if( CurrInp1 != LstInp1 ) 
			{                                        // CHANGE DETECTED BTN1
				delay( 20 );
				if( CurrInp1 ) 
				{
					delay( 20 );
					State = 3;                       // RISING EDGE DETECTED
					DrawSymbol( 3, 77 - 32, 0 );                        // M
					DrawSymbol( 2, 0, 0 );	                        // SPACE
				}
			}
			if( CurrInp2 != lastInput2 ) 
			{                                        // CHANGE DETECTED BTN2
				delay( 20 );
				if( CurrInp2 ) 
				{                                    // RISING EDGE DETECTED
					Hr++;                                          // ADD HR
					if( Hr > 23 ) 
						Hr = 0;
				}
			}
			break;
		case 3:                                                    // MENU 2
			WriteTime();                                         // SET Mins
			if( CurrInp1 != LstInp1 ) 
			{
				delay( 20 );
				// CHANGE DETECTED BTN1
				if( CurrInp1 ) 
				{ // RISING EDGE DETECTED
					State = 4;
					DrawSymbol( 3, 66 - 32, 0);                          // B
					DrawSymbol( 2, 0, 0);	//space
					DrawSymbol( 0, (Bright % 10) + 16, 1);// ACTUAL LIGHT INTENS
					DrawSymbol(1, (Bright / 10) + 16, 1);// ACTUAL LIGHT INTENS
				}
			}
			if( CurrInp2 != lastInput2) 
			{
				delay(20);
				if( CurrInp2 )                       // CHANGE DETECTED BTN2
				{                                    // RISING EDGE DETECTED
					Min++;                                         // ADD HR
					if( Min > 59 ) 
						Min = 0;
				}
			}
			break;
		case 4:                                                    // MENU 3
			if( CurrInp1 != LstInp1 )                      // SET BRIGHTNESS
			{                                        // CHANGE DETECTED BTN1
				delay(2 0 );
				if( CurrInp1 ) 
				{                                    // RISING EDGE DETECTED
					State = 5;
					DrawSymbol( 3, 83 - 32, 0 );                        // S
					DrawSymbol( 2, 116 - 32, 0 );                       // t
					DrawSymbol( 1, 114 - 32, 0 );                       // r
					DrawSymbol(0, 116 - 32, 0 );                        // t
				}
			}
			if( CurrInp2 != lastInput2 ) 
			{                                        // CHANGE DETECTED BTN2
				delay(20);
				if( CurrInp2) 
				{                                    // RISING EDGE DETECTED
					Bright++;                                      // ADD HR
					if( Bright > 15 ) 	
						Bright = 0;			
					DrawSymbol( 0, (Bright % 10) + 16, 1);// ACT LIGHT INTENS
					DrawSymbol( 1, (Bright / 10) + 16, 1);// ACT LIGHT INTENS
					                        // SET LIGHT INTENS MIN:0, MAX:15
					for( byte address = 0; address> offset;
		Mtrx.setRow( adr, i, dataRow );
	}
}
/*F********************************************************************
* FONT TURNING
**********************************************************************/
byte 
ByteRevers( byte in ) 
{
	byte  out;
	
	out = 0;
	if( in & 0x01 ) 
		out |= 0x80;
	if( in & 0x02 ) 
		out |= 0x40;
	if( in & 0x04 ) 
		out |= 0x20;
	if( in & 0x08 ) 
		out |= 0x10;
	if( in & 0x10 ) 
		out |= 0x08;
	if( in & 0x20 ) 
		out |= 0x04;
	if( in & 0x40 ) 
		out |= 0x02;
	if( in & 0x80 ) 
		out |= 0x01;
	return( out );
}
/*F********************************************************************
*  SET RTC
**********************************************************************/
void 
SetRtc( byte Sec, byte Min, byte Hr, byte Dow, byte Dom, byte Mon, byte Yr) 
{
	Wire.beginTransmission( DS3231_I2C_ADDRESS );
	Wire.write( 0 );                              // SET 0 TO FIRST REGISTER
	Wire.write( decToBcd( Sec ) );                                // SET Sec
	Wire.write( decToBcd( Min ) );                               // SET Mins 
	Wire.write( decToBcd( Hr ) );                                 // SET Hrs
	Wire.write( decToBcd( Dow ) );     // SET DAY OF WEEK (1=SU, 2=MO, 3=TU)
	Wire.write( decToBcd( Dom ) );                         // SET day of Mon
	Wire.write( decToBcd( Mon ) );                                // SET Mon
	Wire.write( decToBcd( Yr ) );                                  // SET Yr
	Wire.endTransmission();
}
/*F********************************************************************
* READ RTC
**********************************************************************/
void 
GetRtc() 
{
	Wire.beginTransmission( DS3231_I2C_ADDRESS );
	Wire.write( 0 );                                            // WRITE "0"
	Wire.endTransmission();
	Wire.requestFrom( DS3231_I2C_ADDRESS, 7 ); // REQUEST - 7 BYTES FROM RTC
	Sec = bcdToDec( Wire.read() & 0x7f );
	Min = bcdToDec( Wire.read() );
	Hr = bcdToDec( Wire.read() & 0x3f );
	Dow = bcdToDec( Wire.read() );
	Dom = bcdToDec( Wire.read() );
	Mon = bcdToDec( Wire.read() );
	Yr = bcdToDec(W ire.read() );
}
/*F********************************************************************
* CONVERSION Dec TO BCD 
**********************************************************************/
byte 
decToBcd( byte val ) 
{
	return( (val / 10 * 16) + (val % 10) );
}
/*F********************************************************************
* CONVERSION BCD TO Dec 
**********************************************************************/
byte 
bcdToDec( byte val ) 
{
	return( (val / 16 * 10) + (val % 16) );
}
/*F********************************************************************
* SERIAL COMMUNICATION WITH PC, SET TIME VIA PC
**********************************************************************/
void                       // FIRST LETTER - TYPE OF DATA, SEC LETTER - DATA
SerialComm()                      // (SPACE = 0, != 1, ETC, SEE ASCII TABLE)
{

	if( Serial.available() > 0 ) 
	{
		byte receivedCommand;
		receivedCommand = Serial.read();                // READ FIRST LETTER
		if( receivedCommand < 90 ) 
		{                        // RECEIVED DATA IS LESS THAN 90 (LETTER Z)
			delay( 10 );                              // WAIT FOR sEC LETTER
			byte receivedData;
			receivedData = Serial.read();
			receivedData -= 32;	//shift - 32 -> 32 = space
			switch( receivedCommand ) 
			{
				case 65:                                        // Yr 65 = A
					Yr = receivedData;
					Mtrx.setLed( 3, 7, 0, true );	     // SHOW SETTING DOT
					break;
				case 66:                                       // Mon 66 = B
					Mon = receivedData;
					Mtrx.setLed( 3, 7, 1, true );        // SHOW SETTING DOT
					break;
				case 67:                                       // Dom 67 = C
					Dom = receivedData;
					Mtrx.setLed( 3, 7, 2, true );        // SHOW SETTING DOT
					break;
				case 68:                                        // Hr 68 = D
					Hr = receivedData;
					Mtrx.setLed( 3, 7, 3, true );/        / SHOW SETTING DOT
					break;
				case 69:                                       // Min 69 = E
					Min = receivedData;
					Mtrx.setLed( 3, 7, 4, true );        // SHOW SETTING DOT
					break;
				case 70:                                       // Sec 70 = F
					Sec = receivedData;
					Mtrx.setLed( 3, 7, 5, true );        // SHOW SETTING DOT
					break;
				case 71:                                 // DAYOFwEEK 71 = G
				Dow = receivedData;
				Mtrx.setLed( 3, 7, 6, true );            // SHOW SETTING DOT
				break;
			}
			SetRtc( Sec, Min, Hr, Dow, Dom, Mon, Yr );
		} // spl�chnout buffer do hajzlu
		Serial.flush();
	}
}