// Wall Clock 2019
// WallClock2_06 by Koji Ohashi @MaDA Lab
// 2019.09.05
#include <WiFi.h>
#include "time.h"
const char* ssid = "Your SSID";
const char* password = "Your Password";
const char* ntpServer = "ntp.nict.jp";
const long gmtOffset_sec = 9*3600;
const int daylightOffset_sec = 0;
int SecCount=300;
//------------------------------
hw_timer_t * timer = NULL;
volatile SemaphoreHandle_t timerSemaphore;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
//------------------------------
#include <FastLED.h>
#define DATA_PIN 16
#define WIDTH 32
#define HEIGHT 8
#define NUM_LEDS (WIDTH * HEIGHT)
CRGBArray<NUM_LEDS> leds;
int Pos[HEIGHT][WIDTH];
int imageArray[HEIGHT][WIDTH];
const int FontWidth=7;
const int FontHeight=8;
const int ColWidth=2;
byte CF_hue=0;
boolean End_Minute=false;
boolean DayTime=true;
int DAY_START=6;
int DAY_END=22;
int DAY_BRIGHTNESS=255;
int NIGHT_BRIGHTNESS=40;
int NIGHT_HUE=70;
byte ColonFont[FontHeight][ColWidth]={{0,0},{00,90},{00,90},{0,0},{0,0},{90,0},{90,0},{0,0}};
byte NumFont[10][FontHeight][FontWidth]={
//-0-
{{0,0,30,90,90,50,0},{0,30,90,30,50,90,40},{10,90,30,0,0,70,60},{40,80,0,0,0,60,60},
{60,70,0,0,0,80,30},{70,50,0,0,30,70,0},{50,80,30,40,80,40,0},{0,60,100,80,30,0,0}},
//-1-
{{0,0,0,60,80,70,0},{0,0,70,50,90,40,0},{0,40,00,60,70,20,0},{0,0,0,80,50,0,0},
{0,0,30,90,30,0,0},{0,0,40,90,20,0,0},{0,00,60,80,00,0,0},{00,80,90,70,50,0,0}},
//-2-
{{0,0,40,80,90,50,0},{0,40,90,30,40,90,20},{0,40,0,0,30,90,20},{0,0,0,30,80,50,0},
{0,00,70,90,30,0,0},{0,50,70,0,0,0,0},{30,90,70,40,40,20,0},{40,90,90,90,90,20,0}},
//-3-
{{0,0,30,90,90,40,0},{0,0,90,20,20,90,50},{0,0,0,0,20,90,40},{0,0,40,90,90,20,0},
{0,0,0,20,50,80,0},{0,20,0,0,40,90,20},{0,90,40,20,80,70,0},{0,50,90,90,70,0,0}},
//-4-
{{0,0,0,0,60,90,40},{0,0,0,50,90,90,30},{0,0,40,90,40,90,20},{0,40,80,0,60,60,0},
{30,80,50,20,80,40,20},{40,80,80,80,90,90,80},{0,0,0,60,90,30,0},{0,0,0,80,90,20,0}},
//-5-
{{0,00,70,90,90,90,70},{0,30,90,40,0,0,0},{0,60,60,90,90,20,0},{0,90,50,20,50,70,0},
{0,20,0,0,40,80,00},{20,0,0,0,50,70,0},{80,60,20,20,90,30,0},{30,70,90,90,30,0,0}},
//-6-
{{0,0,0,20,50,80,40},{0,0,20,70,70,30,0},{0,20,90,60,0,0,0},{0,60,70,90,90,20,0},
{30,90,60,20,40,90,20},{50,80,20,0,20,90,20},{30,90,40,0,50,60,0},{0,40,90,90,60,20,0}},
//-7-
{{00,90,90,90,90,90,50},{00,50,40,40,90,70,30},{0,0,0,60,80,20,0},{0,0,40,90,30,0,0},
{0,0,80,60,0,0,0},{0,60,80,0,0,0,0},{40,90,30,0,0,0,0},{60,70,0,0,0,0,0}},
//-8-
{{0,0,30,70,90,40,0},{0,20,90,30,20,90,40},{0,40,80,0,0,90,40},{0,00,90,90,90,40,0},
{0,50,70,20,40,80,0},{30,90,20,0,20,90,20},{30,80,30,20,40,80,0},{0,60,90,90,70,20,0}},
//-9-
{{0,0,50,90,90,60,0},{0,60,50,0,30,80,50},{20,90,20,0,0,60,70},{20,70,50,20,30,90,30},
{0,30,70,90,80,60,0},{0,0,0,70,70,20,0},{0,30,70,80,20,0,0},{20,90,70,0,0,0,0}}
};
void setup() {
Serial.begin(115200);
delay(500);
Serial.println("WallClock2_04 by Koji Ohashi @MaDA Lab");
//connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
//---------------
onTimerSetup();
//---------------
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
setPosArray();
clearDisplay();
delay(3000);
}
void loop(){
if (xSemaphoreTake(timerSemaphore, 0) == pdTRUE){
printLocalTime();
SecCount=SecCount+1;
}
if(SecCount>=300){
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.print("Updated to ");
printLocalTime();
SecCount=0;
}
if(DayTime){
if(End_Minute){
showImageArrayColorFlow();
} else {
showImageArray(CF_hue);
}
} else {
showImageArray(NIGHT_HUE);
}
}
void printLocalTime(){
struct tm timeInfo;
getLocalTime(&timeInfo);
int time_h=timeInfo.tm_hour;;
int time_m=timeInfo.tm_min;
int time_s=timeInfo.tm_sec;
End_Minute=(time_s>50);//colorChange
DayTime=(time_h>=DAY_START)&&(time_h<=DAY_END);//Day or Night
if(DayTime){
LEDS.setBrightness(DAY_BRIGHTNESS);
} else {
LEDS.setBrightness(NIGHT_BRIGHTNESS);
}
Serial.print(time_h);
Serial.print(":");
Serial.print(time_m);
Serial.print(":");
Serial.println(time_s);
int h1=time_h/10;
int h0=time_h%10;
int m1=time_m/10;
int m0=time_m%10;
setImageArray(h1,h0,m1,m0);
}
void showImageArrayColorFlow(){
for(int j=0;j<WIDTH;j++){
for(int i=0; i < HEIGHT; i++){
byte FontBrightness=imageArray[i][j];
int led_num=Pos[i][j];
leds[led_num] = CHSV(CF_hue,255,FontBrightness);
}
FastLED.show();
delay(100);
CF_hue=CF_hue+5;
}
}
void showImageArray(byte hue){
for(int j=0;j<WIDTH;j++){
for(int i=0; i < HEIGHT; i++){
byte FontBrightness=imageArray[i][j];
int led_num=Pos[i][j];
leds[led_num] = CHSV(hue,255,FontBrightness);
}
FastLED.show();
delay(1);
}
}
void setImageArray(int h1,int h0,int m1, int m0){
int PosH1=0;
int PosH0=7;
int PosCol=15;
int PosM1=17;
int PosM0=25;
for(int j=0;j<WIDTH;j++){
for(int i=0; i < HEIGHT; i++){
imageArray[i][j]=0;
}
}
//Hour1
if(h1>0){
for(int j=0;j<FontWidth;j++){
for(int i=0; i < FontHeight; i++){
imageArray[i][j+PosH1]=NumFont[h1][i][j];
}
}
}
//Hour0
for(int j=0;j<FontWidth;j++){
for(int i=0; i < FontHeight; i++){
imageArray[i][j+PosH0]=NumFont[h0][i][j];
}
}
//:
for(int j=0;j<ColWidth;j++){
for(int i=0; i < FontHeight; i++){
imageArray[i][j+PosCol]=ColonFont[i][j];
}
}
//Min1
for(int j=0;j<FontWidth;j++){
for(int i=0; i < FontHeight; i++){
imageArray[i][j+PosM1]=NumFont[m1][i][j];
}
}
//Min0
for(int j=0;j<FontWidth;j++){
for(int i=0; i < FontHeight; i++){
imageArray[i][j+PosM0]=NumFont[m0][i][j];
}
}
}
void setPosArray(){
for(int i=0; i < HEIGHT; i++){
for(int j=0; j < WIDTH; j++){
if(i%2==0){
Pos[i][j]=i*WIDTH+j;
} else{
Pos[i][j]=(i+1)*WIDTH-j-1;
}
}
}
}
void clearDisplay(){
for(int i=0;i<NUM_LEDS;i++){
leds[i] = CRGB::Black;
}
FastLED.show();
}
void IRAM_ATTR onTimer(){
portENTER_CRITICAL_ISR(&timerMux);
portEXIT_CRITICAL_ISR(&timerMux);
xSemaphoreGiveFromISR(timerSemaphore, NULL);//Give a semaphore that we can check in the loop
}
void onTimerSetup(){
timerSemaphore = xSemaphoreCreateBinary();
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);//Attach onTimer function to our timer.
timerAlarmWrite(timer, 1000000, true);//alarm 1sec interval
timerAlarmEnable(timer);//Start an alarm
}