// =======================================================================
// CHANGE YOUR CONFIG HERE:
// =======================================================================
#define ESP32 // ESP8266 or ESP32
#define DEBUG //uncomment for debugging
char ssid[30] = "Wokwi-GUEST"; // SSID of local network //Julian
char pwd[30] = ""; // Password on network
int tmz = 1, dst = 1, ofs = 0, clm = 1, lzr = 1, rot = 0;
int brightness = 0, light = 0;
// =============================DEFINE DISPLAY==============================
#define MAX_DIGITS 30
#define NUM_MAX 3
// number of 8x8 LED DISPLAYS
#define SCROLL_SPEED 60/NUM_MAX
// =============================DEFINE BRIGHTNESS===========================
// board AirM2M_CORE_ESP32C3: Y6(450,1000); Y5(50,1100); Y4 (50,1500)
// R6(10,40)/(45,200); G6(1,60); R4(28,150); G4(45,200)
#define DARKNESS 50
#define LIGHTNESS 1100
#define MAXIMUM_BRIGHTNESS 11 // 0-15, or "brightness" (recommended for red display)
// default "brightness", 15 is maximum,
// comment for night,dim,bright mode, 0 for night,dim,day mode
// =============================DEFINE PINS===========================
//#define PHOTORES_PIN A0 // A0 uncomment if there is photoresistor
//#define RED_LED_PIN 5 // D1 uncomment if there is red led for time unset
//#define GREEN_LED_PIN 16 // D0 uncomment if there is green led for connection
//#define BLUE_LED_PIN 16 // D0 uncomment if there is internal blue led for connection
//#define ESP_LED_PIN 2 // D4 use if there is no other led for connection
//#define USER_PIN 9
/* odkomentarisati za satove lemnjene po starom
#define DIN_PIN 13 // D7
#define CS_PIN 0 // D3
#define CLK_PIN 14 // D5
#undef USER_PIN // */
/* for WeMos D1 R1 mini
#define DIN_PIN 2 // D4
#define CS_PIN 0 // D3
#define CLK_PIN 4 // D2
#undef ESP_LED_PIN
#undef USER_PIN // */
/* for NodeMCU V3 - board NodeMCU 0.9 (ESP-12 module)
#define DIN_PIN 14 // D5
#define CS_PIN 12 // D6
#define CLK_PIN 13 // D7 */
/* for luatos ESP32C3-CORE - board AirM2M_CORE_ESP32C3
#define DIN_PIN 8
#define CS_PIN 4
#define CLK_PIN 5 // */
/* for ESP32 SuperMini - board AirM2M_CORE_ESP32C3
#define DIN_PIN 7
#define CS_PIN 6
#define CLK_PIN 5 // */
/* for ESP32S3 Dev Module
#define DIN_PIN 14 // D5
#define CS_PIN 12 // D6
#define CLK_PIN 13 // D7 */
// for ESP32 DevKitC V4 // also for Wokwi
#define DIN_PIN 10 // D3
#define CS_PIN 9 // D2
#define CLK_PIN 13
#define USER_PIN 0 // */
// =======================================================================
// END OF CONFIG
// =======================================================================
#include <EEPROM.h>
#include "debug.h"
#include "fonts.h"
static uint8_t * cfont=dig4x8; //use clock font
static uint8_t * sfont=dig4x7s; //use seconds font
uint8_t dotbyte=B00100100; //use seconds font
uint8_t pdw=4; //digit width in pixels
uint8_t psw=4; //second digit width in pixels
uint8_t ppw=1; //point width in pixels
bool m12h = false, mSec =false, m2Dot = true;
int8_t pxx=0; //shift everithing to right
uint8_t pxd=1; //points around dots
uint8_t pxe=1; //extra point between digits
int8_t pxs=1; //aditional shift seconts to the right
short int digPos[6]; //={pxx, pxx+pdw+pxe, pxx+2*pdw+ppw+2*pxd+pxe, pxx+3*pdw+ppw+2*pxd+2*pxe, pxx+4*pdw+(1+(NUM_MAX>4))*ppw+(3+(NUM_MAX>4))*pxd+2*pxe+pxs, pxx+5*pdw+(1+(NUM_MAX>4))*ppw+(3+(NUM_MAX>4))*pxd+3*pxe+pxs};
int day, month, year, dayOfWeek;
int summerTime = 0;
String date;
bool Dural=false;
bool cnected=false;
bool ipset=false;
bool tset=false;
bool dset=false;
int dots = 0;
bool nowifi=true;
bool noserial=true;
bool isdark=false;
bool islight=false;
int APmode=false;
int updCnt = 0;
int h,m,s,ls,lm,r;
int br,stp=0;
String TimeAtUpdate = "29 APR 1972 22:07:47 GMT";
#define SIGNATURE "ESP_Clock"
char host[30] = SIGNATURE;
#include "max7219.h"
// =======================================================================
void SetIntesity(int br1,bool dim){
#ifdef PHOTORES_PIN
if (!isdark && (br1<1) && tset) return; else if (isdark && (br1>0) && tset) return;
#endif
int br2=(br1+2)/3-1;
#if NUM_MAX==3
if (mSec&&!m2Dot){
if (br2<0) br2=0;
if (rot){
sendCmd(0,CMD_INTENSITY,br1); sendCmd(1,CMD_INTENSITY,br1); sendCmd(2,CMD_INTENSITY,br2);
}else{
sendCmd(2,CMD_INTENSITY,br1); sendCmd(1,CMD_INTENSITY,br1); sendCmd(0,CMD_INTENSITY,br2);
}
}else sendCmdAll(CMD_INTENSITY,br1);
#elif NUM_MAX==6
if (mSec&&!m2Dot){
if (br2<0) br2=0;
if (rot){
for (int i = 0; i<4; i++) sendCmd(i,CMD_INTENSITY,br1);
for (int i = 4; i<NUM_MAX; i++) sendCmd(i,CMD_INTENSITY,br2);
//if (br1>0){ sendCmd(4,CMD_INTENSITY,(br2-1)*2/3+1);sendCmd(5,CMD_INTENSITY,(br2-1)*2/3+1); } // Za novi Kijin
//if ((br1<15)&&(br1>0)) sendCmd(1,CMD_INTENSITY,br1+1); //Za stari Kijin
}else{
for (int i = 0; i<2; i++) sendCmd(i,CMD_INTENSITY,br2);
for (int i = 2; i<NUM_MAX; i++) sendCmd(i,CMD_INTENSITY,br1);
//if (br1>0){ sendCmd(4,CMD_INTENSITY,(br1-1)*2/3+1);sendCmd(5,CMD_INTENSITY,(br1-1)*2/3+1); } // Za novi Kijin
//if ((br1<15)&&(br1>0)) sendCmd(1,CMD_INTENSITY,br2+1); //Za stari Kijin
}
}else{
br2=br1;
sendCmdAll(CMD_INTENSITY,br1);
//if (br1>0){ sendCmd(4,CMD_INTENSITY,(br1-1)*2/3+1);sendCmd(5,CMD_INTENSITY,(br1-1)*2/3+1); } // Za novi Kijin
//if ((br1<15)&&(br1>0)) sendCmd(1,CMD_INTENSITY,br1+1); //Za stari Kijin
}
#else
sendCmdAll(CMD_INTENSITY,br1);
#endif*/
//DEBUG_PRINTLN(String(light)+" "+String(brightness)+":"+String(br1)+","+String(dim));
}
// =======================================================================
void SetBrightness(int brightness){
#define L_VALUES 4
static int l_index=0;
static int l_sum=0;
static int l_val[L_VALUES];
// sendCmdAll(CMD_INTENSITY,brightness);
if (stp==0) {
#ifdef PHOTORES_PIN
delay(5);
light = analogRead(PHOTORES_PIN);
l_sum = l_sum - l_val[l_index] + light; l_val[l_index] = light; l_index = (l_index+1) % L_VALUES; light = (light + l_sum / L_VALUES)/2;
#if ((defined(MAXIMUM_BRIGHTNESS)) && (MAXIMUM_BRIGHTNESS==0))
bool dim=(tset ? (h<6)||(h>19)||!islight : s&1 );
#elif MAXIMUM_BRIGHTNESS
bool dim=(tset ? 0 : s&1 );
#else
bool dim=(tset ? !islight : s&1 );
#endif
if ((light<DARKNESS) && tset){
//DEBUG_PRINT(String(dim)+" - ");
br=0;
SetIntesity(br,dim);
return;
}
/*
#if ((defined(MAXIMUM_BRIGHTNESS)) && (MAXIMUM_BRIGHTNESS==0))
if ((light>LIGHTNESS) && tset){
dim=(tset ? 1 : s&1 );
DEBUG_PRINT(String(dim)+" ");
DEBUG_PRINT("+ ");
SetIntesity(brightness,dim);
return;
}
#endif
*/
#else
bool dim=(tset ? (h<6)||(h>19) : s&1 );
#endif
#if defined(PHOTORES_PIN) && defined(MAXIMUM_BRIGHTNESS)
if (MAXIMUM_BRIGHTNESS>0){
//DEBUG_PRINT(String(dim)+" V "+String(MAXIMUM_BRIGHTNESS)+" ");
br=(tset? (float)(light-DARKNESS)*brightness/(LIGHTNESS-DARKNESS)+1: (dim? (brightness+1)/3 : brightness));
if (br<0) br=0;
if (MAXIMUM_BRIGHTNESS<brightness){
if (br>MAXIMUM_BRIGHTNESS) br=MAXIMUM_BRIGHTNESS;
}else if (br>brightness) br=brightness;
}else{
//DEBUG_PRINT(String(dim)+" S "+String(MAXIMUM_BRIGHTNESS)+" ");
br=(dim? (brightness+1)/3 : brightness);
}
#else
#if defined(MAXIMUM_BRIGHTNESS)
//DEBUG_PRINT(String(dim)+" C "+String(MAXIMUM_BRIGHTNESS)+" ");
#else
//DEBUG_PRINT(String(dim)+" C ? ");
#endif
br=(dim? (brightness+1)/3 : brightness);
#endif
SetIntesity(br,dim);
}
stp=(stp+1)&7;
}
// =======================================================================
void SetDarkness(){
#ifdef PHOTORES_PIN
if (isdark && (light>DARKNESS+DARKNESS/16)) {
isdark=false;
// if (mSec&&!m2Dot) if (rot){ sendCmd(0,CMD_SHUTDOWN,1); sendCmd(1,CMD_SHUTDOWN,1); } else { sendCmd(4,CMD_SHUTDOWN,1); sendCmd(5,CMD_SHUTDOWN,1); }
}
else if (!isdark && (light<DARKNESS)) {
isdark=true;
// if (mSec&&!m2Dot) if (rot){ sendCmd(0,CMD_SHUTDOWN,0); sendCmd(1,CMD_SHUTDOWN,0); } else { sendCmd(4,CMD_SHUTDOWN,0); sendCmd(5,CMD_SHUTDOWN,0); }
}
if (!islight && (light>LIGHTNESS)) {
islight=true;
}
else if (islight && (light<LIGHTNESS-(LIGHTNESS-DARKNESS)/16)) {
islight=false;
}
#endif
#ifdef GREEN_LED_PIN
if (dset||(tset && s&1)){
#ifdef PHOTORES_PIN
if (isdark) analogWrite(GREEN_LED_PIN, 230);
else
#endif
digitalWrite(GREEN_LED_PIN, LOW);
}else
digitalWrite(GREEN_LED_PIN, HIGH);
#endif
if (cnected){
#ifdef ESP_LED_PIN
#ifdef BLUE_LED_PIN
analogWrite(ESP_LED_PIN, 233);
#else
analogWrite(ESP_LED_PIN, 250);
#endif
#endif
#ifdef BLUE_LED_PIN
if (dset||(tset && s&1)) analogWrite(BLUE_LED_PIN, 250);
else analogWrite(BLUE_LED_PIN, 1000);
#endif
#ifdef RED_LED_PIN
if (!tset){
#ifdef PHOTORES_PIN
if (isdark) analogWrite(RED_LED_PIN, 250);
else
#endif
analogWrite(RED_LED_PIN, 200);
} else digitalWrite(RED_LED_PIN, HIGH);
#endif
} else {
#ifdef ESP_LED_PIN
analogWrite(ESP_LED_PIN, 1000);
#endif
#ifdef BLUE_LED_PIN
if (tset && s&1) analogWrite(BLUE_LED_PIN, 250);
else analogWrite(BLUE_LED_PIN, 1000);
#endif
#ifdef RED_LED_PIN
#ifdef PHOTORES_PIN
if (isdark) analogWrite(RED_LED_PIN, 250);
else
#endif
analogWrite(RED_LED_PIN, 200);
#endif
}
}
// =======================================================================
#include "handlers.h"
uint8_t macAddr[6];
IPAddress ap_local_IP(192,168,4,1);
IPAddress ap_gateway(192,168,4,1);
IPAddress ap_subnet(255,255,255,0);
IPAddress dns1(8, 8, 8, 8); //Google Public DNS
IPAddress dns2(1, 1, 1, 1); //Cloudflare’s consumer DNS
// =======================================================================
void setClockMode(int clm){
pxd=1;
pxe=1;
pxs=0;
#if NUM_MAX<4
m2Dot=false;
if (clm>3) mSec=true; else mSec=false;
if (clm&1) m12h=false; else m12h=true;
if (clm<2){
// cfont= ((uint8_t *) &dig4x7); dotbyte=B00110110; pxx=0; pdw=4; ppw=2; pxd=1; pxe=2;
cfont= ((uint8_t *) &dig4x7);
if (m12h&&!lzr){
dotbyte=B00010100; pxx=-1; pxe=2; pdw=4; ppw=1; pxd=2;
}else{
dotbyte=B00110110; pxx=1; pdw=4; ppw=2; pxd=1;
}
}else if (clm<4){
cfont= ((uint8_t *) &dig4x8);
if (m12h) {
dotbyte=B00100100; pxx=-1; pxe=2; pdw=4; ppw=1; pxd=2;
}else{
dotbyte=B01100110; pxx=1; pdw=4; ppw=2; pxd=1;
}
}else if (clm<6){
cfont= ((uint8_t *) &dig3x7); sfont= ((uint8_t *) &dig3x5s);
dotbyte=B00010100; pxx=-1; pdw=3; pxe=1; ppw=1; pxd=1; psw=3; pxs=-1;
}else if (clm<8){
cfont= ((uint8_t *) &dig3x5); sfont= ((uint8_t *) &dig3x5);
dotbyte=0; pxx=-1; pdw=3; pxe=1; ppw=0; pxd=1; psw=3; pxs=0;
}else{
cfont= ((uint8_t *) &dig3x7); sfont= ((uint8_t *) &dig3x7);
dotbyte=0; pxx=-1; pdw=3; pxe=1; ppw=0; pxd=1; psw=3; pxs=0;
//if (clm<5) {pxs=1;}
}
#elif NUM_MAX<5
psw=4;
if (clm<2){
cfont= ((uint8_t *) &dig5x7);
dotbyte=B00110110; pxx=1; pxd=2; pxe=2; pdw=5; ppw=2;
}else if (clm<4){
cfont= ((uint8_t *) &dig6x8); sfont= ((uint8_t *) &dig6x8);
dotbyte=B01100110; pxx=1; pxd=1; pdw=6; ppw=2;
}else if (clm<6){
cfont= ((uint8_t *) &dig4x8); sfont= ((uint8_t *) &dig4x7s);
dotbyte=B01000010; pdw=4; ppw=1;
if (clm<5) {pxx=-1; pxs=1;} else pxx=0;
}else if (clm<8){
cfont= ((uint8_t *) &dig4x7); sfont= ((uint8_t *) &dig4x7);
dotbyte=B00100010; pxx=-1; pdw=4; ppw=1;
} else {
cfont= ((uint8_t *) &dig4x8); sfont= ((uint8_t *) &dig4x8);
dotbyte=B00100100; pxx=-1; pdw=4; ppw=1;
}
if (clm>3) mSec=true; else mSec=false;
if (clm>5) m2Dot=true; else m2Dot=false;
if (clm&1) m12h=false; else m12h=true;
#elif NUM_MAX<6
pxx=0; pdw=5; psw=5;
if (clm<2) { cfont= ((uint8_t *) &dig5x7); dotbyte=B00100010; ppw=1; pdw=5;}
else if (clm<4) { cfont= ((uint8_t *) &dig5x7); dotbyte=B00110110; pxx=4; ppw=2; pdw=5; pxx=4; pxe=2; pxd=3; }
else if (clm>7) { cfont= ((uint8_t *) &dig6x8); dotbyte=B01100110; ppw=2; pdw=6; pxx=2; pxe=2; pxd=3; }
else { cfont= ((uint8_t *) &dig5x8); dotbyte=B01000010; ppw=1; pdw=5; }
if (clm<2) { sfont= ((uint8_t *) &dig5x7); pxx=1; psw=5; pxs=0; }
else if ((clm>3)&&(clm<6)) { sfont= ((uint8_t *) &dig4x7s); dotbyte=B01100110; ppw=2; psw=4; pxs=2;}
else if (clm>7) { pxx=2; psw=5; pxs=0; }
else if (clm>5) { sfont= ((uint8_t *) &dig5x8); pxx=1; psw=5; pxs=0; }
if ((clm==2)||(clm==3)||(clm==8)||(clm==9)) mSec=false; else mSec=true;
if ((clm==0)||(clm==1)||(clm==6)||(clm==7)) m2Dot=true; else m2Dot=false;
if ((clm%2)==0) m12h=true; else m12h=false;
#else
pxx=0; pdw=5; ppw=2;
if (clm<2) { cfont= ((uint8_t *) &dig5x7); dotbyte=B00110110; pdw=5; } else { cfont= ((uint8_t *) &dig6x8); dotbyte=B01100110; pdw=6; }
if (clm<4) { sfont= ((uint8_t *) &dig5x7); pxx=(clm<2 ? 0 : 6); pxe=2; pxd=(clm<2 ? 2 : 3); psw=5; pxs=0; }
else if (clm<6) { sfont= ((uint8_t *) &dig5x7s); psw=5; pxs=3;}
else { sfont= ((uint8_t *) &dig6x8); psw=6; pxs=1; }
if (clm>7) { cfont= ((uint8_t *) &dig7x8); pdw=7; pxx=3; pxe=3; pxd=3; }
if ((clm==2)||(clm==3)||(clm==8)||(clm==9)) mSec=false; else mSec=true;
if ((clm==0)||(clm==1)||(clm==6)||(clm==7)) m2Dot=true; else m2Dot=false;
if ((clm%2)==0) m12h=true; else m12h=false;
#endif
digPos[0]=pxx;
digPos[1]=digPos[0]+pdw+pxe;
digPos[2]=digPos[1]+pdw+ppw+2*pxd;
digPos[3]=digPos[2]+pdw+pxe;
digPos[4]=digPos[3]+pdw+ppw*m2Dot+2*pxd+pxs;
digPos[5]=digPos[4]+psw+pxe;
SetBrightness(brightness);
}
void SerialPrintLocalTime(){
DEBUG_PRINTLN(String("Local time: ")+(h/10)+""+(h%10)+":"+(m/10)+""+(m%10)+":"+(s/10)+""+(s%10));
}
const char hex[17]="0123456789ABCDEF";
bool probeAP(const char* ssid, const char* pwd){
bool timeout=false;
DEBUG_PRINT(String("Probing: ") +ssid+", "+pwd);
int n = WiFi.scanNetworks();
//DEBUG_PRINTLN();DEBUG_PRINT(nowifi);
for (int i = 0; (i<n) ; ++i){
//DEBUG_PRINTLN();DEBUG_PRINT(WiFi.SSID(i));
if (WiFi.SSID(i) == ssid) {
nowifi=false;
printStringWithShift((String(ipset?" Probing ":" Connecting ")+ssid).c_str(),SCROLL_SPEED);
WiFi.begin(ssid, pwd);
for (int i=30; ((WiFi.status() != WL_CONNECTED) && (i>0)); i--) { DEBUG_PRINT(" ."); delay(1000); }
DEBUG_PRINTLN("");
if (WiFi.status() == WL_CONNECTED){
if (!ipset){
printStringWithShift((String(" MyIP: ")+WiFi.localIP().toString()).c_str(),SCROLL_SPEED);
WiFi.setAutoReconnect(true);
delay(1000);
ipset=true;
}
return(true);
}else{
DEBUG_PRINTLN("Timeout!\n");
printStringWithShift(" Timeout!",SCROLL_SPEED);
delay(1000);
timeout=true;
}
}
}
if (!timeout) DEBUG_PRINTLN(", NO WiFi!\n");
printStringWithShift(" No WiFi!",SCROLL_SPEED);
return(false);
}
#include "html.h"
// =============================DEFINE VARS==============================
byte dig[MAX_DIGITS]={0};
byte digold[MAX_DIGITS]={0};
byte digtrans[MAX_DIGITS]={0};
long dotTime = 0;
long clkTime = 0;
int dx=0;
int dy=0;
byte del=0;
long localEpoc = 0;
long localMillisAtUpdate = 0;
long ms;
// =======================================================================
void setup() {
delay(500);
#ifdef USER_PIN
pinMode(USER_PIN, INPUT_PULLUP);
#endif
#ifdef RED_LED_PIN
pinMode(RED_LED_PIN, OUTPUT);
#endif
#ifdef BLUE_LED_PIN
pinMode(BLUE_LED_PIN, OUTPUT);
analogWrite(BLUE_LED_PIN, 1000);
#endif
#ifdef ESP_LED_PIN
pinMode(ESP_LED_PIN, OUTPUT);
analogWrite(ESP_LED_PIN, 1000);
#endif
#ifdef GREEN_LED_PIN
pinMode(GREEN_LED_PIN, OUTPUT);
digitalWrite(GREEN_LED_PIN, HIGH);
#endif
if (noserial){
EEPROM.begin(512);
read_string(30,0).toCharArray(host,30);
brightness = read_string(30,96).toInt();
rot = read_string(30,288).toInt();
#ifdef DEBUG
Serial.begin(9600);
#endif
noserial=false;
initMAX7219();
sendCmdAll(CMD_SHUTDOWN,1);
SetDarkness();
SetBrightness(brightness);
printStringWithShift(" ESP_Clock!",SCROLL_SPEED);
}
// WiFi.printDiag(Serial);
delay(500);
WiFi.softAPdisconnect (true);
WiFi.persistent(false);
DEBUG_PRINTLN(String("\n\nBooting!\nSignature: ")+host+".");
WiFi.macAddress(macAddr);
if (!String(host).startsWith("ESP_")){
write_to_Memory(String(ssid), String(pwd), String(brightness), String(clm), String(tmz), String(dst), String(ofs), String(lzr), String(rot));
DEBUG_PRINTLN("Initial SSID and pasword!");
}
else{ read_string(30,32).toCharArray(ssid,30); read_string(30,64).toCharArray(pwd,30); clm = read_string(30,128).toInt(); tmz = read_string(30,160).toInt(); dst = read_string(30,192).toInt(); ofs = read_string(30,224).toInt(); lzr = read_string(30,256).toInt();}
DEBUG_PRINTF("MAC: %02X:%02X:%02X:%02X:%02X:%02X\n\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
#ifdef DEBUG
SerialPrintLocalTime();
#endif
SetBrightness(brightness);
String(String("ESP_")+hex[macAddr[3]/16]+hex[macAddr[3]%16]+hex[macAddr[4]/16]+hex[macAddr[4]%16]+hex[macAddr[5]/16]+hex[macAddr[5]%16]).toCharArray(host,30);
//if (String(host)==String("ESP_D55D47")) String("ESP_FE394A").toCharArray(host,30); //Maki
//if (String(host)==String("ESP_F794DC")) String("FaryLink_F794DC").toCharArray(host,30); //Moj
//probeAP(ssid,pwd);
//if (WiFi.status() != WL_CONNECTED){
if (!probeAP(ssid,pwd)){
WiFi.mode(WIFI_AP);
APmode=true;
WiFi.softAPConfig(ap_local_IP, ap_gateway, ap_subnet);
DEBUG_PRINTLN((String("Setting soft-AP ... ")+host).c_str());
WiFi.softAP(host);
delay(1000);
printStringWithShift((String(" Starting AP: ")+host).c_str(), SCROLL_SPEED);
delay(1000);
DEBUG_PRINT("Soft-AP IP address = ");DEBUG_PRINTLN(WiFi.softAPIP());
DEBUG_PRINTLN("HTTP server started");
printStringWithShift((String(" MyIP: ")+WiFi.softAPIP().toString()).c_str(), SCROLL_SPEED);
delay(2000);
}
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
setClockMode(clm);
delay(1000);
WiFi.setSleep(false);
// isdark=false; sendCmdAll(CMD_SHUTDOWN,1);
for(int i=0; i<6; i++) dig[i]=11;
String SSID=String(ssid);
SSID.toUpperCase();
Dural=SSID.startsWith("DURAL");
}
// =======================================================================
void loop()
{
ms=millis();
updateTime();
// SetBrigthness(brightness);
if(updCnt<=0) {
if (cnected && tset) updCnt = 180; // every 180 minutes
else updCnt = 1; //try every minute
// printStringWithShift(" Setting Time...",SCROLL_SPEED);
getTime();
clkTime = millis();
}else if (ms-clkTime > 60000 && dots) {
// printStringWithShift(date.c_str(),SCROLL_SPEED); delay(2000);
updCnt--;
clkTime = millis();
}else if (ls!=s){
del=0;
dots=0;
dotTime = ms;
r=1;
ls=s;
showAnimClock();
refreshAll();
dots=0;
SetDarkness();
// DEBUG_PRINTLN(light);
}else if ((r<10)&&(ms-dotTime >= r*40)){
showAnimClock();
if((ms-dotTime >500) && !dots){
for(int i=0; i<ppw; i++) setCol(digPos[2]-ppw-pxd+i,dotbyte);
if (m2Dot) for(int i=0; i<ppw; i++) setCol(digPos[4]-ppw-pxd+i,dotbyte);
dots=1;
}
refreshAll();
r++;
}else if ((ms-dotTime >500) && !dots){
for(int i=0; i<ppw; i++) setCol(digPos[2]-ppw-pxd+i,dotbyte);
if (m2Dot) for(int i=0; i<ppw; i++) setCol(digPos[4]-ppw-pxd+i,dotbyte);
refreshAll();
dots=1;
}else SetBrightness(brightness);
#ifdef USER_PIN
if (digitalRead(USER_PIN)==LOW){
//for(int i=0; i<6; i++) dig[i]=11;
//printStringWithShift((String(" MyIP: ")+WiFi.localIP().toString()).c_str(), SCROLL_SPEED); delay(3000);
clm=++clm % 10;
setClockMode(clm);
delay(500);
}
#endif
server.handleClient();//Checks for web server activity
}
// =======================================================================
void showSimpleClock()
{
dx=dy=0;
#if NUM_MAX<5
int H=((m12h||((clm>5)&&(h>19))) ? (h+11)%12+1 : h);
showDigit((lzr&&!((clm>5)||(clm==4)) ? H/10 : (H<10? 10 : H/10)), digPos[0], cfont);
#else
int H=(m12h ? (h+11)%12+1 : h);
showDigit((lzr ? H/10 : (H<10? 10 : H/10)), digPos[0], cfont);
#endif
showDigit(H%10, digPos[1], cfont);
showDigit(m/10, digPos[2], cfont);
showDigit(m%10, digPos[3], cfont);
if (mSec){
showDigit(s/10, digPos[4], sfont);
showDigit(s%10, digPos[5], sfont);
}
}
// =======================================================================
void showAnimClock()
{
int digHt = 10;
int num = 6; //NUM_MAX;
int i;
if(del==0) {
del = digHt;
for(i=0; i<num; i++) digold[i] = dig[i];
#if NUM_MAX<5
int H=((m12h||((clm>5)&&(h>19))) ? (h+11)%12+1 : h);
dig[0] = (lzr&&!((clm>5)||(clm==4)) ? H/10 : (H<10? 10 : H/10));
#else
int H=(m12h ? (h+11)%12+1 : h);
// dig[0] = (lzr ? H/10 : (H<10? 10 : H/10));
dig[0] = (lzr ? H/10 : (H<10? (isdark&&mSec&&!m2Dot? 0 : 10) : H/10));
#endif
dig[1] = H % 10;
dig[2] = m/10;
dig[3] = m%10;
if (mSec){
dig[4] = (isdark&&mSec&&!m2Dot? 10 : s/10);
dig[5] = (isdark&&mSec&&!m2Dot? 10 : s%10);
}
for(i=0; i<num; i++) digtrans[i] = (dig[i]==digold[i]) ? 0 : digHt-1;
} else
del--;
clr();
for(i=0; i<num; i++) {
if(digtrans[i]==0) {
dy=0;
if (i<4) showDigit(dig[i], digPos[i], cfont);
else if (mSec) showDigit(dig[i], digPos[i], sfont);
} else {
dy = digHt-digtrans[i];
if (i<4) showDigit(digold[i], digPos[i], cfont);
else if (mSec) showDigit(digold[i], digPos[i], sfont);
dy = -digtrans[i];
if (i<4) showDigit(dig[i], digPos[i], cfont);
else if (mSec) showDigit(dig[i], digPos[i], sfont);
digtrans[i]--;
}
}
dy=0;
}
// =======================================================================
void showDigit(char ch, int col, const uint8_t *data)
{
if(dy<-8 | dy>8) return;
int len = pgm_read_byte(data);
int w = pgm_read_byte(data + 1 + ch * len);
col += dx;
for (int i = 0; i < w; i++)
if(col+i>=0 && col+i<8*NUM_MAX) {
byte v = pgm_read_byte(data + 1 + ch * len + 1 + i);
if(!dy) scr[col + i] = v; else scr[col + i] |= dy>0 ? v>>dy : v<<-dy;
}
}
// =======================================================================
void setCol(int col, byte v)
{
if(dy<-8 | dy>8) return;
col += dx;
if(col>=0 && col<8*NUM_MAX)
if(!dy) scr[col] = v; else scr[col] |= dy>0 ? v>>dy : v<<-dy;
}
// =======================================================================
int showChar(char ch, const uint8_t *data)
{
int len = pgm_read_byte(data);
int i,w = pgm_read_byte(data + 1 + ch * len);
for (i = 0; i < w; i++)
scr[NUM_MAX*8 + i] = pgm_read_byte(data + 1 + ch * len + 1 + i);
// scr[NUM_MAX*8 + i] = 0;
return w;
}
// =======================================================================
void printCharWithShift(unsigned char c, int shiftDelay) {
c -= 32;
int w = showChar(c, font);
for (int i=0; i<w+1; i++) {
delay(shiftDelay);
scrollLeft();
refreshAll();
}
}
// =======================================================================
void printStringWithShift(const char* s, int shiftDelay){
while (*s) {
printCharWithShift(*s, shiftDelay);
s++;
}
}
// =======================================================================
void getTime()
{
DEBUG_PRINTLN();
#ifdef DEBUG
SerialPrintLocalTime();
#endif
DEBUG_PRINT("Getting data ...");
if (!cnected) {
DEBUG_PRINTLN("No connection");
int clients=WiFi.softAPgetStationNum();
if (clients!=0) DEBUG_PRINTLN(String("Connected clients: ") + clients + "\n");
else { DEBUG_PRINTLN(); setup(); }
return;
}
dset=false;
if (!client.connect("www.google.com", 80)) {
DEBUG_PRINTLN("connection to google failed");
//WiFi.begin(ssid, pdw);
updCnt = 1; // reconnect every 5 minutes
return;
}
client.print(String("GET / HTTP/1.1\r\n") +
String("Host: www.google.com\r\n") +
String("Connection: close\r\n\r\n"));
int repeatCounter = 0;
while (!(client.connected() && client.available()) && repeatCounter < 40) {
delay(500);
DEBUG_PRINT(".");
repeatCounter++;
}
String line,mmmm;
client.setNoDelay(false);
while(client.connected() && client.available() && !dset) {
line = client.readStringUntil('\n');
// DEBUG_PRINTLN(line);
line.toUpperCase();
if (line.startsWith("DATE: ")) {
date = line.substring(6, 22);
date.toUpperCase();
// decodeDate(date);
h = line.substring(23, 25).toInt();
m = line.substring(26, 28).toInt();
s = line.substring(29, 31).toInt();
day = line.substring(11, 13).toInt();
year = line.substring(18, 22).toInt();
mmmm = line.substring(14, 17);
if (mmmm=="JAN") month=1;
else if (mmmm=="FEB") month=2;
else if (mmmm=="MAR") month=3;
else if (mmmm=="APR") month=4;
else if (mmmm=="MAY") month=5;
else if (mmmm=="JUN") month=6;
else if (mmmm=="JUL") month=7;
else if (mmmm=="AUG") month=8;
else if (mmmm=="SEP") month=9;
else if (mmmm=="OCT") month=10;
else if (mmmm=="NOV") month=11;
else if (mmmm=="DEC") month=12;
else month=0;
DEBUG_PRINTLN("Date: "+date+" "+(h/10)+(h%10)+":"+(m/10)+(m%10)+":"+(s/10)+(s%10)+" OK!");
summerTime = checkSummerTime();
if(h+tmz+summerTime>23) {
if(++day>31) { day=1; month++; }; // needs better patch
if(++dayOfWeek>7) dayOfWeek=1;
}
TimeAtUpdate = line.substring(11, 31);
localMillisAtUpdate = millis();
localEpoc = (h * 60 * 60 + m * 60 + s);
tset=true;
dset=true;
}
}
client.stop();
}
// =======================================================================
int checkSummerTime()
{
if (!dst) return 0;
if(month>3 && month<10) return 1;
if(month==3 && day>=31-(((5*year/4)+4)%7) ) return 1;
if(month==10 && day<31-(((5*year/4)+1)%7) ) return 1;
return 0;
}
// =======================================================================
void updateTime()
{
long epoch = long(86400L + 60 * ofs + localEpoc + round((millis() - localMillisAtUpdate) / 1000) + 3600 * (tmz+checkSummerTime())) % 86400L;
h = (epoch / 3600) % 24;
m = (epoch % 3600) / 60;
s = epoch % 60;
/*
if (dural){
int h3 = (epoch / 3600) % 24;
long epoch3 = epoch % 10800;
switch ((h3 % 12) /3) {
case 0: epoch = h3 / 3 * 10800 + epoch3 * 61 / 60; break;
case 1: epoch = h3 / 3 * 10800 + 180 + epoch3 * 59 / 60; break;
case 2: epoch = h3 / 3 * 10800 + epoch3 * 59 / 60; break;
case 3: epoch = h3 / 3 * 10800 - 180 + epoch3 * 61 / 60; break;
}
}
*/
h = (epoch / 3600) % 24;
m = (epoch % 3600) / 60;
s = epoch % 60;
}
// =======================================================================