/*
"ard_clock" Arduino sketch by Marco Zonca 10/2023, version 1.00
Digital clock with 4 dot matrix displays, Arduino Nano ESP32, TTL level shifter,
GL5539 photoresistor for automatic brightness adj, WiFi internet connection for
NTP time updating, Arduino WebEditor, a few other components, USB C power,
DST daylight saving time correction for Central Europe, personalized font, BLE setup,
3 buttons and 1 led for manual time setup in case of no WiFi internet connection;
To set Wifi (Access Point Name and Password) and time zone (+2 or +1 hours vs. UTC)
enter Setup pressing the setup button and connect to the clock via Bluetooth
(i.e. using nRF Connect app); send new datas to the clock one at a time in Text format:
APN=thename<nl> PSW=password<nl> TZ=2<nl>; then disconnect Bluetooth connection,
press again setup button to save in the EEPROM internal memory and exit; with null APN the NTP
by the way of WiFi will not be checked, so you need a manual time setup using HH and MM buttons;
Used syncro-serial transmission, 3 digital pins (like SPI but slower speed);
Inspired by Eberhard Fahle and his LedControl library + examples code
for controlling matrix led display using MAX7219;
Approx. power consumption with full 256 leds on: level 0=75mA, 2=245mA, 6=525mA, 10=725mA;
brightness level is available from 0 to 15 but let keep it below 5 because
of current (mA) consumption considering USB powering;
*/
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
#include <WiFi.h>
#include <NTPClient.h>
#include <Time.h>
#include <EEPROM.h>
#include <ArduinoBLE.h>
const boolean isDebug = false; // set to "true" to activate debug on serial monitor
// if "true" the serial monitor MUST be available or
// the sketch does not run;
const byte BrightMin=0;
const byte BrightMed=2;
const byte BrightHigh=5;
const char poolUrl[] = "it.pool.ntp.org"; // NTP url server
const byte lightSens_pin = 23; // A6 (physical chip pin nr. 10)
const byte DATA_Pin = 10; // D10 (physical chip pin nr. 28)
const byte CLK_Pin = 9; // D9 (physical chip pin nr. 27)
const byte CS_Pin = 8; // D8 (physical chip pin nr. 26)
const byte LEDSetup_pin = 2; // D2 (physical chip pin nr. 20)
const byte butMinutes_pin = 3; // D3 (physical chip pin nr. 21)
const byte butHours_pin = 4; // D4 (physical chip pin nr. 22)
const byte butSetup_pin = 5; // D5 (physical chip pin nr. 23)
const byte Devices = 4; // how many matrixes of displays
const byte BIT_order = MSBFIRST; // LSBFIRST=0 MSBFIRST=1
const byte MAX_Devices = 8; // MAX Nr. of matrixes of display
const byte maxattempts = 10; // nr. of WiFi connection attempts
const unsigned long updateRate = 60 * (60 * 1000); // 60 minutes NTP update rate
const unsigned long blinkDotsRate = 1 * (1000); // 1 second clock dots blink rate
unsigned long prevMillis = 0;
unsigned long prevBlinkDots = 0;
byte Brightness = 10;
byte prevBrightness = 0;
boolean isUpdated = false;
boolean isDotsOn = false;
boolean isClockSetup = false;
byte T_prev_hours = 99;
byte T_prev_minutes = 99;
time_t epoch = 0;
byte status[64]; // =Max_Devices*8
byte spidata[16]; // =Max_Devices*2
int i=0;
String myStrValue = "";
String AValue = "";
int eeaddress=0;
int eedata_TimeZone=0;
char eedata_Wifi_AccessPoint[40]="";
char eedata_Wifi_Password[40]="";
// following data change reading the EEPROM
char ssid[40] = ""; // was to put your SSID WiFi access point here
char pass[40] = ""; // was put your PASSWORD WiFi access point here
long utcOffset = +2 * (60 * 60); // +- UTC offset +2 hours (see also Daylight saving)
// set numbers for display
byte matrix_09[10][7][6] =
{
{
{0,1,1,1,1,0}, // 0
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,0}
},
{
{0,0,0,0,1,0}, // 1
{0,0,0,1,1,0},
{0,0,1,0,1,0},
{0,1,0,0,1,0},
{0,0,0,0,1,0},
{0,0,0,0,1,0},
{0,0,1,1,1,1}
},
{
{0,1,1,1,1,0}, // 2
{0,0,0,0,0,1},
{0,0,0,0,0,1},
{0,1,1,1,1,0},
{1,0,0,0,0,0},
{1,0,0,0,0,0},
{1,1,1,1,1,1}
},
{
{1,1,1,1,1,0}, // 3
{0,0,0,0,0,1},
{0,0,0,0,0,1},
{0,1,1,1,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,1},
{1,1,1,1,1,0}
},
{
{1,0,0,0,0,1}, // 4
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{1,1,1,1,1,1},
{0,0,0,0,0,1},
{0,0,0,0,0,1},
{0,0,0,0,0,1}
},
{
{1,1,1,1,1,1}, // 5
{1,0,0,0,0,0},
{1,0,0,0,0,0},
{0,1,1,1,1,0},
{0,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,0}
},
{
{0,0,1,1,1,0}, // 6
{0,1,0,0,0,0},
{1,0,0,0,0,0},
{1,1,1,1,1,0},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,0}
},
{
{1,1,1,1,1,1}, // 7
{0,0,0,0,0,1},
{0,0,0,0,1,0},
{0,0,0,1,0,0},
{0,0,1,0,0,0},
{0,1,0,0,0,0},
{1,0,0,0,0,0}
},
{
{0,1,1,1,1,0}, // 8
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,0},
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,0}
},
{
{0,1,1,1,1,0}, // 9
{1,0,0,0,0,1},
{1,0,0,0,0,1},
{0,1,1,1,1,1},
{0,0,0,0,0,1},
{0,0,0,0,1,0},
{0,1,1,1,0,0}
}
};
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, poolUrl, utcOffset);
BLEService myStrService("19b10000-e8f2-537e-4f6c-d104768a1214");
BLEStringCharacteristic myStrCharacteristic("19b10000-e8f2-537e-4f6c-d104768a1214", BLERead | BLEWrite, 40);
void setup()
{
if (isDebug) {
Serial.begin(9600);
while (!Serial) {}
}
if (!EEPROM.begin(512)) {
if (isDebug) {Serial.println("failed to initialize EEPROM");}
}
if (!BLE.begin()) {
if (isDebug) {Serial.println("failed to initialize BLE");}
}
pinMode(LED_BUILTIN, OUTPUT);
pinMode(lightSens_pin, INPUT);
digitalWrite(LED_BUILTIN, LOW);
pinMode(butMinutes_pin, INPUT_PULLUP);
pinMode(butHours_pin, INPUT_PULLUP);
pinMode(butSetup_pin, INPUT_PULLUP);
pinMode(LEDSetup_pin, OUTPUT);
digitalWrite(LEDSetup_pin, LOW);
//-------------------------- display init
Brightness=readLightSensor();
prevBrightness=Brightness;
pinMode(DATA_Pin, OUTPUT);
pinMode(CLK_Pin, OUTPUT);
pinMode(CS_Pin, OUTPUT);
digitalWrite(CS_Pin,HIGH);
for(i=0;i<(MAX_Devices*8);i++)
{
status[i]=0x00;
}
for(i=0;i<Devices;i++)
{
spiTransfer(i,OP_DISPLAYTEST,0);
spiTransfer(i, OP_SCANLIMIT,7);
spiTransfer(i,OP_DECODEMODE,0);
clearDisplay(i);
spiShutdown(i,false);
setIntensity(i,Brightness);
}
//-------------------------- BLE init
myStrValue.reserve(40);
AValue.reserve(40);
BLE.setLocalName("Clock setup: TZ= APN= PSW=");
BLE.setAdvertisedService(myStrService);
myStrService.addCharacteristic(myStrCharacteristic);
BLE.addService(myStrService);
BLE.advertise();
if (isDebug) {Serial.println("BLE ready");}
//-------------------------- other init
setTime(967680000); // initial datetime: 31/08/2000 00:00:00 in epoch format
readEEPROM();
displayNumbers();
if (strcmp(ssid,"") != 0)
{
updateTime();
} else {
if (isDebug) {Serial.println("Empty SSID, no WiFi");}
}
}//setup()
void loop()
{
readButtons();
if (isClockSetup == false)
{
//------------------------------update display numbers
if (second(now()) == 0)
{
displayNumbers();
}
//------------------------------update NTP time
if (prevMillis > millis()) { prevMillis=millis(); } // manage millis() rollover
if ((((prevMillis + updateRate) <= millis()) && (second(now()) > 30) && (second(now()) < 40))
|| ((isUpdated==false) && (second(now()) > 30) && (second(now()) < 40))) // update NTP time
{
if (strcmp(ssid,"") != 0)
{
updateTime();
} else {
if (isDebug) {Serial.println("Empty SSID, no WiFi");}
}
}
//------------------------------update brightness and blinking dots
if (prevBlinkDots > millis()) { prevBlinkDots=millis(); } // manage millis() rollover
if ((prevBlinkDots + blinkDotsRate) <= millis())
{
Brightness=readLightSensor();
if (prevBrightness != Brightness)
{
for (int d=0;d<Devices;d++)
{
setIntensity(d,Brightness);
}
if (isDebug) {Serial.print("Brightness ");}
if (isDebug) {Serial.println(Brightness);}
prevBrightness=Brightness;
}
blinkDots();
}
}//if (isClockSetup == false)
if (isClockSetup == true)
{
BLEDevice central = BLE.central(); // Listen for BLE connect
if (central)
{
if (isDebug) {Serial.print("BLE Connected to: ");}
if (isDebug) {Serial.println(central.address());} // MAC address
while (central.connected()) // While is still connected
{
if (myStrCharacteristic.written()) // If the remote device wrote to the characteristic
{
myStrValue=String(myStrCharacteristic.value());
if (myStrValue.substring(0,3)=="TZ=")
{
AValue=myStrValue.substring(3);
eedata_TimeZone=AValue.toInt();
}
if (myStrValue.substring(0,4)=="PSW=")
{
AValue=myStrValue.substring(4);
AValue.toCharArray(eedata_Wifi_Password, AValue.length()+1);
}
if (myStrValue.substring(0,4)=="APN=")
{
AValue=myStrValue.substring(4);
AValue.toCharArray(eedata_Wifi_AccessPoint, AValue.length()+1);
}
if (isDebug)
{
Serial.print("BLE Received: ");
Serial.print(myStrValue);
Serial.print(" len=");
Serial.println(myStrValue.length());
}
if (isDebug)
{
Serial.print(" TZ=");
Serial.println(eedata_TimeZone);
Serial.print(" APN=");
Serial.print(eedata_Wifi_AccessPoint);
Serial.print(" len=");
Serial.println(strlen(eedata_Wifi_AccessPoint));
Serial.print(" PSW=");
Serial.print(eedata_Wifi_Password);
Serial.print(" len=");
Serial.println(strlen(eedata_Wifi_Password));
Serial.println("");
}
}
}
// When the central disconnects
if (isDebug) {Serial.print("BLE Disconnected: ");}
if (isDebug) {Serial.println(central.address());}
}
}//if (isClockSetup == true)
}//loop()
void readButtons()
{
if (isClockSetup == true)
{
isUpdated=false;
blinkDots();
if (digitalRead(butMinutes_pin) == LOW)
{
delay(250);
time_t NowTime=now();
NowTime = NowTime + 60;
setTime(NowTime); // set MPU time +1 minute
displayNumbers();
}
if (digitalRead(butHours_pin) == LOW)
{
delay(250);
time_t NowTime=now();
NowTime = NowTime + (60 * 60);
setTime(NowTime); // set MPU time +1 hour
displayNumbers();
}
if (digitalRead(butSetup_pin) == LOW)
{
digitalWrite(LEDSetup_pin, LOW);
// UPDATES after SETUP here...
updateEEPROM();
isClockSetup=false;
}
}else{
if (digitalRead(butSetup_pin) == LOW)
{
delay(1000);
if (digitalRead(butSetup_pin) == LOW)
{
digitalWrite(LEDSetup_pin, HIGH);
delay(1000);
isClockSetup=true;
}
}
}
}//readButtons()
void updateEEPROM()
{
bool isDataChanged=false;
if (utcOffset != (eedata_TimeZone * (60 * 60)))
{
eeaddress=101;
EEPROM.put(eeaddress,eedata_TimeZone);
delay(10);
utcOffset = (eedata_TimeZone * (60 * 60));
timeClient.setTimeOffset(utcOffset);
isDataChanged=true;
}
if (strcmp(ssid,eedata_Wifi_AccessPoint) != 0)
{
eeaddress=201;
EEPROM.put(eeaddress,eedata_Wifi_AccessPoint);
delay(10);
strcpy(ssid,eedata_Wifi_AccessPoint);
isDataChanged=true;
}
if (strcmp(pass,eedata_Wifi_Password) != 0)
{
eeaddress=301;
EEPROM.put(eeaddress,eedata_Wifi_Password);
delay(10);
strcpy(pass,eedata_Wifi_Password);
isDataChanged=true;
}
if (isDataChanged==true) {EEPROM.commit();}
if (isDebug && isDataChanged==true) {Serial.println("EEPROM updated");}
}
void readEEPROM()
{
eeaddress=101;
EEPROM.get(eeaddress,eedata_TimeZone);
eeaddress=201;
EEPROM.get(eeaddress,eedata_Wifi_AccessPoint);
eeaddress=301;
EEPROM.get(eeaddress,eedata_Wifi_Password);
if (isDebug)
{
Serial.print(" TZ=");
Serial.println(eedata_TimeZone);
Serial.print(" APN=");
Serial.print(eedata_Wifi_AccessPoint);
Serial.print(" len=");
Serial.println(strlen(eedata_Wifi_AccessPoint));
Serial.print(" PSW=");
Serial.print(eedata_Wifi_Password);
Serial.print(" len=");
Serial.println(strlen(eedata_Wifi_Password));
Serial.println("");
}
if (utcOffset != (eedata_TimeZone * (60 * 60)))
{
utcOffset = (eedata_TimeZone * (60 * 60));
timeClient.setTimeOffset(utcOffset);
}
strcpy(ssid,eedata_Wifi_AccessPoint);
strcpy(pass,eedata_Wifi_Password);
}//readEEPROM()
byte readLightSensor()
{
byte bright=0;
int ls=analogRead(lightSens_pin);
int n=map(ls,0,4095,0,255);
if ((n >= 0 ) && (n <= 100)) { bright=BrightMin; }
if ((n >= 101) && (n <= 220)) { bright=BrightMed; }
if ((n >= 221) && (n <= 255)) { bright=BrightHigh; } // max brightness is 15
return bright;
} //readLightSensor()
void blinkDots()
{
if (isUpdated==true) // dots blinking active
{
switch (isDotsOn)
{
case true:
setColumn(2,7,B00000000); // set off dots at right of display 2
setColumn(1,0,B00000000); // set off dots at left of display 1
//if (isDebug) {Serial.println("_");}
isDotsOn=false;
break;
case false:
setColumn(2,7,B01101100); // set ON dots at right of display 2
setColumn(1,0,B01101100); // set ON dots at left of display 1
//if (isDebug) {Serial.println(".");}
isDotsOn=true;
break;
}
}
else // dots steady, not blinking
{
setColumn(2,7,B01101100); // set ON dots at right of display 2
setColumn(1,0,B01101100); // set ON dots at left of display 1
//if (isDebug) {Serial.println(".");}
isDotsOn=true;
}
prevBlinkDots=millis();
}//blinkDots()
void updateTime()
{
isUpdated=false;
blinkDots();
byte attempts = 0;
while ((WiFi.status() != WL_CONNECTED) && (attempts < maxattempts) )
{
if (isDebug) {
Serial.print("Attempting to connect to '");
Serial.print(ssid);
Serial.println("'");
}
WiFi.begin(ssid, pass);
delay(4000);
if (isDebug) {
if (WiFi.status() == WL_NO_SHIELD) {Serial.println("* no shield available *");}
if (WiFi.status() == WL_IDLE_STATUS) {Serial.println("* idle *");}
if (WiFi.status() == WL_CONNECT_FAILED) {Serial.println("* failed *");}
if (WiFi.status() == WL_NO_SSID_AVAIL) {Serial.println("* no SSID available *");}
if (WiFi.status() == WL_CONNECTION_LOST) {Serial.println("* connection lost *");}
if (WiFi.status() == WL_CONNECTED) {Serial.println("* connected *");}
if (WiFi.status() == WL_DISCONNECTED) {Serial.println("* disconnected *");}
}
attempts++;
}
if (attempts < maxattempts)
{
if (isDebug)
{
Serial.print("Connected to '");
Serial.print(WiFi.SSID());
Serial.println("'");
}
digitalWrite(LED_BUILTIN, HIGH);
timeClient.update();
delay(4000);
if (timeClient.isTimeSet() == true)
{
isUpdated=true;
epoch = timeClient.getEpochTime();
if (isDebug) {
Serial.print("Formatted time is ");
Serial.println(timeClient.getFormattedTime());
}
setTime(epoch); // set MPU time
}
else
{
if (isDebug) {
Serial.print("* no time *");
}
}
while (WiFi.status() != WL_DISCONNECTED)
{
WiFi.disconnect();
delay(4000);
if (isDebug) {
if (WiFi.status() == WL_NO_SHIELD) {Serial.println("* no shield available *");}
if (WiFi.status() == WL_IDLE_STATUS) {Serial.println("* idle *");}
if (WiFi.status() == WL_CONNECT_FAILED) {Serial.println("* failed *");}
if (WiFi.status() == WL_NO_SSID_AVAIL) {Serial.println("* no SSID available *");}
if (WiFi.status() == WL_CONNECTION_LOST) {Serial.println("* connection lost *");}
if (WiFi.status() == WL_CONNECTED) {Serial.println("* connected *");}
if (WiFi.status() == WL_DISCONNECTED) {Serial.println("* disconnected *");}
}
}
if (isDebug) {
Serial.println("Disconnected.");
Serial.print("\n");
}
digitalWrite(LED_BUILTIN, LOW);
}
else
{
if (isDebug) {
Serial.print("Connection failed after ");
Serial.print(attempts);
Serial.println(" attempts.");
Serial.print("\n");
}
}
prevMillis=millis();
}//updateTime()
void displayNumbers()
{
time_t NowTime=now();
byte T_Hours=checkDaylightSaving(NowTime); // DST hour correction
byte T_Minutes=minute(NowTime);
if ((T_prev_hours != T_Hours) || (T_prev_minutes != T_Minutes)) {
byte col=0;
byte row=0;
byte disp=0;
byte rowval=0;
int hdeci=(int)(T_Hours/10);
int hunit=T_Hours-(hdeci*10);
int mdeci=(int)(T_Minutes/10);
int munit=T_Minutes-(mdeci*10);
int prev_hdeci=(int)(T_prev_hours/10);
int prev_hunit=T_prev_hours-(prev_hdeci*10);
int prev_mdeci=(int)(T_prev_minutes/10);
int prev_munit=T_prev_minutes-(prev_mdeci*10);
if (hdeci != prev_hdeci) // change 1st number
{
disp=3;
for (row=0;row<=6;row++) { // row 7 always off
rowval=0;
for (col=0;col<=5;col++) {
setLed(disp,row,col+1,matrix_09[hdeci][row][col]);
}
}
}
if (hunit != prev_hunit) // change 2nd number
{
disp=2;
for (row=0;row<=6;row++) { // row 7 always off
rowval=0;
for (col=0;col<=5;col++) {
setLed(disp,row,col,matrix_09[hunit][row][col]);
}
}
}
if (mdeci != prev_mdeci) // change 3th number
{
disp=1;
for (row=0;row<=6;row++) { // row 7 always off
rowval=0;
for (col=0;col<=5;col++) {
setLed(disp,row,col+2,matrix_09[mdeci][row][col]);
}
}
}
if (munit != prev_munit) // change 4th number
{
disp=0;
for (row=0;row<=6;row++) { // row 7 always off
rowval=0;
for (col=0;col<=5;col++) {
setLed(disp,row,col+1,matrix_09[munit][row][col]);
}
}
}
if (isDebug) {
Serial.print("Clock is ");
Serial.print(hdeci);
Serial.print(hunit);
Serial.print(":");
Serial.print(mdeci);
Serial.println(munit);
}
T_prev_hours=T_Hours;
T_prev_minutes=T_Minutes;
}
}//displayNumbers()
byte checkDaylightSaving(time_t unixTimeNow) // adjust actual hour with DST
{ // Daylight Saving Time (Central Europe Summer Time)
tmElements_t te; //Time elements structure
time_t unixTime03;
time_t unixTime10;
int d=0;
int x=0;
int c=0;
byte correctedHour=0;
// convert date and time into unix Summer (UTC+1) start Time, offset 1970
// last Sunday of March at 03:00
te.Hour = 3;
te.Minute = 0;
te.Second = 0;
te.Month = 3; //March
te.Year = (year(now()) - 1970);
for (x=25;x<=31;x++)
{
te.Day = x;
unixTime03 = makeTime(te);
d=(weekday(unixTime03) - 1); // converts day 1 of the week from sunday to monday
if (d==0) { d=7; }
if (d==7) { break; } // find the last sunday of March
}
// convert date and time into unix Standard (UTC+2) start time, offset 1970
// last Sunday of October at 03:00
te.Hour = 3;
te.Minute = 0;
te.Second = 0;
te.Month = 10; //October
te.Year = (year(now()) - 1970);
for (x=25;x<=31;x++)
{
te.Day = x;
unixTime10 = makeTime(te);
d=(weekday(unixTime10) - 1); // converts day 1 of the week from sunday to monday
if (d==0) { d=7; }
if (d==7) { break; } // find the last sunday of October
}
// compare the two dates with now()
if ((unixTimeNow < unixTime03) || (unixTimeNow >= unixTime10))
{
c=(hour(unixTimeNow)-1);
if (c == -1) {c = 23;}
} else {
c=(hour(unixTimeNow));
}
correctedHour=c;
return correctedHour;
}//checkDaylightSaving()
void setColumn(int addr, int col, byte value)
{
byte val;
for (int row=0;row<8;row++)
{
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}//setColumn()
void setRow(int addr, int row, byte value)
{
int offset;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}//setRow()
void setLed(int addr, int row, int column, boolean state)
{
int offset;
byte val=0x00;
offset=addr*8;
val=B10000000 >> column;
if (state)
{
status[offset+row]=status[offset+row]|val;
}else{
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}//setLed()
void setIntensity(int addr, int intensity)
{
if (intensity>=0 && intensity<16)
{
spiTransfer(addr, OP_INTENSITY, intensity);
}else{
spiTransfer(addr, OP_INTENSITY, 0);
}
}//setIntensity()
void spiShutdown(int addr, bool shut)
{
if (shut)
{
spiTransfer(addr, OP_SHUTDOWN, 0);
}else{
spiTransfer(addr, OP_SHUTDOWN ,1);
}
}//spiShutdown()
void clearDisplay(int addr)
{
int offset;
offset=addr*8;
for (int i=0;i<8;i++)
{
status[offset+i]=0;
spiTransfer(addr, i+1,status[offset+i]);
}
}//clearDisplay()
void spiTransfer(int addr, volatile byte opcode, volatile byte data) {
//Create an array with the data to shift out
int offset=addr*2;
int maxbytes=MAX_Devices*2;
for (int i=0;i<maxbytes;i++)
{
spidata[i]=(byte)0;
}
//put our device data into the array
spidata[offset+1]=opcode;
spidata[offset]=data;
//enable the line
digitalWrite(CS_Pin,LOW);
//Now shift out the data
for(int i=maxbytes;i>0;i--)
serialSyncroTX(DATA_Pin,CLK_Pin,BIT_order,spidata[i-1]);
//latch the data onto the display
digitalWrite(CS_Pin,HIGH);
}//spiTransfer()
void serialSyncroTX(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i=0;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST) {
digitalWrite(dataPin, !!(val & (1 << i)));
}else{
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
}
digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);
}
}//serialSyncroTX()
Comments