Update Serre_menuLCD.ino

Update Serre_menuLCD.ino

Fixed the random sunTime values

--- Serre_menuLCD.ino
+++ Serre_menuLCD.ino
@@ -14,14 +14,21 @@
 #define DS18B20
 //define SHT1X

-//Select your ouput pins
+#define NBROLLUPS 1
+#define NBHEATERS 1
+#define NBFANS 1
+#define NBPROGRAMS 5
+
+//Select your input pins
 #define LCDKEYPAD A0
 #define MENU_PIN 2
-const byte SAFETY_SWITCH[2] = {2,3};
-const byte ROLLUP_OPEN[1] = {4};
-const byte ROLLUP_CLOSE[1] = {5};
-const byte CHAUFFAGE[2] = {6,8}; // relais fournaise2
-const byte FAN[2] = {7,9}; // relais fournaise2
+const byte SAFETY_SWITCH[NBROLLUPS] = {3};
+
+//Select your output pins
+const byte ROLLUP_OPEN[NBROLLUPS] = {4};
+const byte ROLLUP_CLOSE[NBROLLUPS] = {5};
+const byte CHAUFFAGE[NBHEATERS] = {6};
+const byte FAN[NBFANS] = {7};

 //*********************OBJETS************************
 //---------------------LCD-----------------
@@ -53,21 +60,24 @@
 //*********************VARIABLES GLOBALES*************
 //nombre d'items activés
 const int nbPrograms = 5;              //Nombre de programmes de température
-boolean rollups[1];
-boolean heaters[1];
-boolean fans[1];
-boolean fanSafety[sizeof(fans)];
-boolean rollupSafety[sizeof(rollups)];
+boolean rollups[NBROLLUPS] = {};
+boolean heaters[NBHEATERS] = {};
+boolean fans[NBFANS] = {};
+boolean fanSafety[NBFANS] = {};
+boolean rollupSafety[NBROLLUPS] = {};

 //Sonde de température
 boolean failedSensor = false;

 //Poisition des Rollups
-volatile byte incrementCounter[sizeof(rollups)];               //positionnement des rollups
-boolean firstOpening[sizeof(rollups)];
+volatile byte incrementCounter[NBROLLUPS] = {};               //positionnement des rollups
+boolean firstOpening[NBROLLUPS] = {};

 //Programmes horaire
-byte sunTime[6];                      //données de l'horloge
+byte sunTime[6] = {};                      //données de l'horloge
+byte sunRise[3] = {};
+byte sunSet[3] = {};
+byte P[nbPrograms][3] = {};
 byte program;                         //Programme en cour
 byte lastProgram;                    //Dernier programme en cour

@@ -93,7 +103,7 @@
 int menu = 0;
 //#items/menu
 byte Nbitems = 6;
-char* menuitems[10];
+char* menuitems[10] = {};
 int yr; byte mt; byte dy; byte hr; byte mn; byte sc;
 byte nr; byte inc; unsigned int rot; unsigned int p; int mod; byte hys; boolean sfty;
 byte typ; byte tt;
@@ -113,17 +123,16 @@
   initLCD(20,4);
   initTimeLord();

-  defineProgram(1, SR, 0, -30, 20);
-  defineProgram(2, SR, 0, 20, 21);
-  defineProgram(3, CLOCK, 11, 10, 22);
-  defineProgram(4, SS, 0, -60, 28);
-  defineProgram(5, SS, 0, -2, 18);
-
-  defineRollup(1, 5, 1, 1, 0, 1, false);
-  defineFan(1, 2, 1, false);
-  defineHeater(1, -3, 1);
-  defineHeater(2, -5, 1);
-  defineRamping(5);
+  //defineProgram(1, SR, 0, -30, 20);
+  //defineProgram(2, SR, 0, 20, 21);
+  //defineProgram(3, CLOCK, 11, 10, 22);
+  //defineProgram(4, SS, 0, -60, 28);
+  //defineProgram(5, SS, 0, -2, 18);
+
+  //defineRollup(1, 5, 1, 1, 0, 1, false);
+  //defineFan(1, 2, 1, false);
+  //defineHeater(1, -3, 1);
+  //defineRamping(5);

   initVariables();
   initOutputs();
@@ -131,11 +140,9 @@
   initRollupOutput(1, ROLLUP_OPEN[0], ROLLUP_CLOSE[0], LOW);
   initFanOutput(1,FAN[0], LOW);
   initHeaterOutput(1,CHAUFFAGE[0], LOW);
-  initHeaterOutput(2,CHAUFFAGE[1], LOW);

   pinMode(LCDKEYPAD, INPUT_PULLUP);
   pinMode(SAFETY_SWITCH[0], INPUT_PULLUP);
-  pinMode(SAFETY_SWITCH[1], INPUT_PULLUP);
   pinMode(MENU_PIN, INPUT_PULLUP);
   //Affichage LCD
   lcdDisplay();
@@ -163,10 +170,10 @@
     startRamping();
     //Protocoles spéciaux (pré-jour/pré-nuit) [VIDE]
     specialPrograms();
+    //Affichage LCD
+    lcdDisplay();
     //Activation des relais
     relayLogic();
-    //Affichage LCD
-    lcdDisplay();
     //Pause entre chaque cycle
     delay(sleeptime);
   }
@@ -191,20 +198,19 @@

 void initOutputs(){
   //Activation des items
-  for (int x = 0; x < sizeof(rollups);x++){
+  for (int x = 0; x < NBROLLUPS;x++){
     rollups[x] = true;
     firstOpening[x] = true;
     rollupSafety[x] = rollupSafetyE(x);
     if (rollupSafety[x] == true) {
         attachInterrupt(digitalPinToInterrupt(SAFETY_SWITCH[0]), endOfTheRun0, FALLING);
-        attachInterrupt(digitalPinToInterrupt(SAFETY_SWITCH[1]), endOfTheRun1, FALLING);
-    }
-  }
-  for (int x = 0; x < sizeof(fans);x++){
+    }
+  }
+  for (int x = 0; x < NBFANS;x++){
     fans[x] = true;
     fanSafety[x] = fanSafetyE(x);
   }
-  for (int x = 0; x < sizeof(heaters);x++){
+  for (int x = 0; x < NBHEATERS;x++){
     heaters[x] = true;
   }
 }
@@ -212,14 +218,7 @@
 void endOfTheRun0(){
   incrementCounter[0] = incrementsE(0);
 }
-void endOfTheRun1(){
-  byte x;
-  switch(sizeof(rollups)){
-    case 1 : x = 0;
-    case 2 : x = 1;
-  }
-  incrementCounter[x] = incrementsE(x);
-}
+

 void initVariables(){
   //Première lecture d'horloge pour définir le lever et coucher du soleil
@@ -244,12 +243,66 @@
 }

 void selectProgram(){
-  //Définition des variables locales
-  int P[nbPrograms][3];
-  byte sunRise[3];
-  byte sunSet[3];
-
   //Exécution du programme
+  setSunrise();
+  setSunset();
+  getDateAndTime();
+  setPrograms();
+  selectActualProgram();
+}
+
+void setPrograms(){
+  int PInt[nbPrograms][3] = {};
+  for(byte x = 0; x < nbPrograms; x++){
+    //Serial.println(x);Serial.println (programType[x]);
+    if (programsE(x) == SR){
+      PInt[x][HEURE] = sunRise[HEURE];
+      PInt[x][MINUTE] = sunRise[MINUTE] + srmodE(x);
+      convertDecimalToTime(&PInt[x][HEURE], &PInt[x][MINUTE]);
+      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
+    }
+    else if (programsE(x) == CLOCK){
+      PInt[x][HEURE] = PROGRAM_TIME(x, HEURE);
+      P[x][MINUTE] = PROGRAM_TIME(x, MINUTE);
+      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
+    }
+
+    else if (programsE(x) == SS){
+      PInt[x][HEURE] = sunSet[HEURE];
+      PInt[x][MINUTE] = sunSet[MINUTE] + ssmodE(x);
+      convertDecimalToTime(&PInt[x][HEURE], &PInt[x][MINUTE]);
+      //Serial.print(" Program ");Serial.print(x); Serial.print(" : "); Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
+    }
+  }
+  //Convert to byte
+  for(byte x = 0; x < nbPrograms; x++){
+      for(byte y = 0; y < 3; y++){
+        P[x][y] = (byte)PInt[x][y];
+      }
+  }
+}
+
+
+
+void selectActualProgram(){
+  //Sélectionne le programme en cour
+    //Serial.print ("Heure actuelle ");Serial.print(" : ");Serial.print(sunTime[HEURE] );Serial.print(" : ");Serial.println(sunTime[MINUTE]);
+    for (byte y = 0; y < (nbPrograms-1); y++){
+    //Serial.print ("Programme "); Serial.print(y+1);Serial.print(" : ");Serial.print(P[y][HEURE]);Serial.print(" : ");Serial.println(P[y][MINUTE]);
+      if (((sunTime[HEURE] == P[y][HEURE])  && (sunTime[MINUTE] >= P[y][MINUTE]))||((sunTime[HEURE] > P[y][HEURE]) && (sunTime[HEURE] < P[y+1][HEURE]))||((sunTime[HEURE] == P[y+1][HEURE])  && (sunTime[MINUTE] < P[y+1][MINUTE]))){
+          program = y+1;
+          //Serial.println("YES!");
+        }
+    }
+    //  Serial.print ("Programme ");Serial.print(nbPrograms);Serial.print(" : ");Serial.print(P[nbPrograms-1][HEURE]);Serial.print(" : ");Serial.println(P[nbPrograms-1][MINUTE]);
+    if (((sunTime[HEURE] == P[nbPrograms-1][HEURE])  && (sunTime[MINUTE] >= P[nbPrograms-1][MINUTE]))||(sunTime[HEURE] > P[nbPrograms-1][HEURE])||(sunTime[HEURE] < P[0][HEURE])||((sunTime[HEURE] == P[0][HEURE])  && (sunTime[MINUTE] < P[0][MINUTE]))){
+      program = nbPrograms;
+    //Serial.println("YES!");
+    }
+}
+
+
+void setSunrise(){
   //Définit l'heure du lever et coucher du soleil
   myLord.SunRise(sunTime); ///On détermine l'heure du lever du soleil
   myLord.DST(sunTime);//ajuster l'heure du lever en fonction du changement d'heure
@@ -257,50 +310,16 @@
   sunRise[MINUTE] = sunTime[MINUTE];
   //Serial.print("lever du soleil :");Serial.print(sunRise[HEURE]);  Serial.print(":");  Serial.println(sunRise[MINUTE]);

+}
+
+void setSunset(){
   /* Sunset: */
   myLord.SunSet(sunTime); // Computes Sun Set. Prints:
   myLord.DST(sunTime);
   sunSet[HEURE] = sunTime[HEURE];
   sunSet[MINUTE] = sunTime[MINUTE];
   //Serial.print("coucher du soleil :");  Serial.print(sunSet[HEURE]);  Serial.print(":");  Serial.println(sunSet[MINUTE]);
-  getDateAndTime();
-  //Ajuste l'heure des programmes en fonction du lever et du coucher du soleil
-  for(byte x = 0; x < nbPrograms; x++){
-    //Serial.println(x);Serial.println (programType[x]);
-    if (programsE(x) == SR){
-      P[x][HEURE] = sunRise[HEURE];
-      P[x][MINUTE] = sunRise[MINUTE] + srmodE(x);
-      convertDecimalToTime(&P[x][HEURE], &P[x][MINUTE]);
-      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-    }
-    else if (programsE(x) == CLOCK){
-      P[x][HEURE] = PROGRAM_TIME(x, HEURE);
-      P[x][MINUTE] = PROGRAM_TIME(x, MINUTE);
-      //Serial.print(" Program ");Serial.print(x);Serial.print(" : ");Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-    }
-
-    else if (programsE(x) == SS){
-      P[x][HEURE] = sunSet[HEURE];
-      P[x][MINUTE] = sunSet[MINUTE] + ssmodE(x);
-      convertDecimalToTime(&P[x][HEURE], &P[x][MINUTE]);
-      //Serial.print(" Program ");Serial.print(x); Serial.print(" : "); Serial.print(P[x][HEURE]);Serial.print(" : ");Serial.println(P[x][MINUTE]);
-
-    //Sélectionne le programme en cour
-    //Serial.print ("Heure actuelle ");Serial.print(" : ");Serial.print(sunTime[HEURE] );Serial.print(" : ");Serial.println(sunTime[MINUTE]);
-    for (byte y = 0; y < (nbPrograms-1); y++){
-    //Serial.print ("Programme "); Serial.print(y+1);Serial.print(" : ");Serial.print(P[y][HEURE]);Serial.print(" : ");Serial.println(P[y][MINUTE]);
-      if (((sunTime[HEURE] == P[y][HEURE])  && (sunTime[MINUTE] >= P[y][MINUTE]))||((sunTime[HEURE] > P[y][HEURE]) && (sunTime[HEURE] < P[y+1][HEURE]))||((sunTime[HEURE] == P[y+1][HEURE])  && (sunTime[MINUTE] < P[y+1][MINUTE]))){
-          program = y+1;
-          //Serial.println("YES!");
-        }
-      }
-      //  Serial.print ("Programme ");Serial.print(nbPrograms);Serial.print(" : ");Serial.print(P[nbPrograms-1][HEURE]);Serial.print(" : ");Serial.println(P[nbPrograms-1][MINUTE]);
-      if (((sunTime[HEURE] == P[nbPrograms-1][HEURE])  && (sunTime[MINUTE] >= P[nbPrograms-1][MINUTE]))||(sunTime[HEURE] > P[nbPrograms-1][HEURE])||(sunTime[HEURE] < P[0][HEURE])||((sunTime[HEURE] == P[0][HEURE])  && (sunTime[MINUTE] < P[0][MINUTE]))){
-        program = nbPrograms;
-      //Serial.println("YES!");
-      }
-    }
-  }
+
 }

 void setTempCible(){
@@ -400,63 +419,65 @@

 void specialPrograms(){}

+float tempRollup(byte index){
+  return tempCible +rmodE(index);
+}         //Température d'activation des rollups (max.2)
+float tempHeater(byte index){
+  return tempCible + hmodE(index);
+}         //Température d'activation des fournaises (max.2)
+
+float tempFan(byte index){
+    return tempCible + vmodE(index);
+}         //Température d'activation des fans (max.2)
+
+
 void relayLogic(){                     //Température cible
-
-  float tempRollup[sizeof(rollups)];         //Température d'activation des rollups (max.2)
-  float tempHeater[sizeof(heaters)];         //Température d'activation des fournaises (max.2)
-  float tempFan[sizeof(fans)];                //Température d'activation des fans (max.2)
-
-  for(byte x = 0; x < sizeof(rollups); x++){
-    tempRollup[x] = tempCible + rmodE(x);
-  }
-  for(byte x = 0; x < sizeof(heaters); x++){
-    tempHeater[x] = tempCible + hmodE(x);
-  }
-  for(byte x = 0; x < sizeof(rollups); x++){
-    tempFan[x] = tempCible + vmodE(x);
-  }
-
   //Exécution du programme
   lcd.noBlink();
   //Programme d'ouverture/fermeture des rollups
-  for(byte x = 0; x < sizeof(rollups); x++){
+  for(byte x = 0; x < NBROLLUPS; x++){
     if (rollups[x] == true){
-      if (greenhouseTemperature() < (tempRollup[x] - rhystE(x))) {
+      if (greenhouseTemperature() < (tempRollup(x) - rhystE(x))) {
         closeSides(x);
-      } else if (greenhouseTemperature() > tempRollup[x]) {
+      } else if (greenhouseTemperature() > tempRollup(x)) {
         openSides(x);
       }
     }
   }

   //Programme fournaise
-  for(byte x = 0; x < sizeof(heaters); x++){
+  for(byte x = 0; x < NBHEATERS; x++){
     if (heaters[x] == true){

-      if ((greenhouseTemperature() < tempHeater[x])&&(incrementCounter[0] == 0)) {
+      if ((greenhouseTemperature() < tempHeater(x))&&(incrementCounter[0] == 0)) {
         digitalWrite(CHAUFFAGE[x], ON);
-      } else if ((greenhouseTemperature() > (tempHeater[x] + hhystE(x)))||(incrementCounter[0] != 0)) {
+      } else if ((greenhouseTemperature() > (tempHeater(x) + hhystE(x)))||(incrementCounter[0] != 0)) {
         digitalWrite(CHAUFFAGE[x], OFF);
       }
     }
   }

   //Programme ventilation forcée
-  for(byte x = 0; x < sizeof(fans); x++){
+  for(byte x = 0; x < NBFANS; x++){
     if (fans[x] == true){
       if (fanSafety[x] == true){
-        if (greenhouseTemperature() > tempFan[x]&&(digitalRead(SAFETY_SWITCH[0]) == OFF)){
+        Serial.println(fanSafety[x]);
+        if (greenhouseTemperature() > tempFan(x)&&(digitalRead(SAFETY_SWITCH[0]) == OFF)){
+          Serial.println(digitalRead(SAFETY_SWITCH[0]));
           digitalWrite(FAN[x], ON);
         }
-        else if ((greenhouseTemperature() < (tempFan[x] - vhystE(x)))||(digitalRead(SAFETY_SWITCH[0]) == ON)) {
+        else if ((greenhouseTemperature() < (tempFan(x) - vhystE(x)))||(digitalRead(SAFETY_SWITCH[0]) == ON)) {
+          Serial.println(digitalRead(SAFETY_SWITCH[0]));
           digitalWrite(FAN[x], OFF);
         }
       }
       else if (fanSafety[x] == false){
-        if (greenhouseTemperature() > tempFan[x]){
+        if (greenhouseTemperature() > tempFan(x)){
+                    Serial.println(digitalRead(SAFETY_SWITCH[0]));
           digitalWrite(FAN[x], ON);
         }
-        else if (greenhouseTemperature() < (tempFan[x] - vhystE(x))) {
+        else if (greenhouseTemperature() < (tempFan(x) - vhystE(x))) {
+                  Serial.println(digitalRead(SAFETY_SWITCH[0]));
           digitalWrite(FAN[x], OFF);
         }
       }
@@ -687,6 +708,34 @@
   lcd.setCursor(0, 0);
   lcd.print("**ROBOT-SERRE**V.1**");
 }
+
+void programPrintM(byte index){
+    lcd.noBlink();
+    clearPrintTitle();
+    lcd.setCursor(0, 1);lcd.print(F("Type: "));
+      switch(programsE(index)){
+        case SR: lcd.print(F("SUNRISE"));break;
+        case CLOCK: lcd.print(F("MANUAL"));break;
+        case SS: lcd.print(F("SUNSET"));break;
+      }
+    lcd.setCursor(0, 2);lcd.print(F("HD: "));lcdPrintDigits(P[index][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index][MINUTE]);
+    lcd.setCursor(9, 2);lcd.print(F("| HF: "));lcdPrintDigits(P[index+1][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index+1][MINUTE]);
+    lcd.setCursor(0, 3);lcd.print(F("Temp. cible: "));lcd.print(targetTempE(index));lcd.print(F("C"));
+}
+void programPrintE(byte index){
+    lcd.noBlink();
+    clearPrintTitle();
+    lcd.setCursor(0, 1);lcd.print(F("Type: "));
+      switch(programsE(index)){
+        case SR: lcd.print(F("SUNRISE"));break;
+        case CLOCK: lcd.print(F("MANUAL"));break;
+        case SS: lcd.print(F("SUNSET"));break;
+      }
+    lcd.setCursor(0, 2);lcd.print(F("HD: "));lcdPrintDigits(P[index][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[index][MINUTE]);
+    lcd.setCursor(9, 2);lcd.print(F("| HF: "));lcdPrintDigits(P[0][HEURE]);lcd.print(F(":"));lcdPrintDigits(P[0][MINUTE]);
+    lcd.setCursor(0, 3);lcd.print(F("Temp. cible: "));lcd.print(targetTempE(index));lcd.print(F("C"));
+}
+
 //-----------------DISPLAY-------------------------
 //Scrollingmenu(Nbitems, Item1, item2, item3, item4, item5, Item6, item7, item8, item9, item10, currentMenuItem); //leave variable "Itemx" blank if it doesnt exist
 //Scrollingnumbers(Nbitems, currentMenuItem, starting number, multiplicator);
@@ -705,36 +754,36 @@
     case 1311: Scrollingnumbers("SEC**",62, currentMenuItem, 0, 1); break;

     case 2: Scrollingmenu("ROLL*", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 21: Scrollingmenu("ITEM*",(sizeof(rollups)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 22: Scrollingmenu("ITEM*",(sizeof(rollups)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 21: Scrollingmenu("ITEM*",(NBROLLUPS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 22: Scrollingmenu("ITEM*",(NBROLLUPS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
     case 221: Scrollingnumbers("INCR*",11, currentMenuItem, 1, 1); break;
-    case 2211: Scrollingnumbers("ROTA*", 61, currentMenuItem, 2, 2); break;
-    case 22111: Scrollingmenu("PAUSE", 10, "5", "15", "20", "30", "45", "60", "75", "90", "120", "back", currentMenuItem); break;
-    case 221111: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 2211111: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 22111111: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 222: Scrollingnumbers("ROTA*", 61, currentMenuItem, 2, 2); break;
+    case 223: Scrollingmenu("PAUSE", 10, "5", "15", "20", "30", "45", "60", "75", "90", "120", "back", currentMenuItem); break;
+    case 224: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
+    case 225: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
+    case 226: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;

     case 3: Scrollingmenu("FANS*", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 31: Scrollingmenu("ITEM*",(sizeof(fans)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 32: Scrollingmenu("ITEM*",(sizeof(fans)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 31: Scrollingmenu("ITEM*",(NBFANS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 32: Scrollingmenu("ITEM*",(NBFANS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
     case 321: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 3211: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 32111: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 322: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
+    case 323: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;

     case 4: Scrollingmenu("HEATR", 3, "Parameters", "setParameters", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 41: Scrollingmenu("ITEM*",(sizeof(heaters)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
-    case 42: Scrollingmenu("ITEM*",(sizeof(heaters)+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
+    case 41: Scrollingmenu("ITEM*",(NBHEATERS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
+    case 42: Scrollingmenu("ITEM*",(NBHEATERS+1),"1", "2", "back", "", "", "", "",  "", "", "", currentMenuItem);break;
     case 421: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 4211: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
+    case 422: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;

     case 5: Scrollingmenu("PROG*", 3, "Timezones", "setTimezones", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
     case 51: Scrollingnumbers("TIMZ*",(nbPrograms+1),currentMenuItem, 1, 1);break;
     case 52: Scrollingnumbers("TIMZ*",(nbPrograms+1),currentMenuItem, 1, 1);break;
     case 521: Scrollingmenu("ITEM*", 3,"SR", "MANUAL", "SS", "", "", "", "",  "", "", "", currentMenuItem);break;
-    case 5211: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
-    case 52111: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
-    case 5212: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
-    case 521111: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;
+    case 5221: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
+    case 5222: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
+    case 523: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
+    case 524: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;

   }
 }
@@ -750,6 +799,9 @@
 }

 void selectMenu(int x, int y) {
+
+  int P[nbPrograms][3];
+
   switch (x) {
     //------------------------------SelectrootMenu-------------------------------------
     //"Temperature/humidex","Date/time","Rollups","Ventilation","Chauffage"
@@ -929,64 +981,64 @@
     case 221 :
       if (y < Nbitems) {
         inc = y;
-        switchmenu(2211);
+        switchmenu(222);
       }
       else {
         switchmenu(2);
       }
       break;
-    //-------------------------------SelectMenu2211-----------------------------------------
+    //-------------------------------SelectMenu222-----------------------------------------
     //SET ROTATION TIME
-    case 2211 :
+    case 222 :
       if (y < Nbitems) {
         rot = y*2;
-        switchmenu(22111);
+        switchmenu(223);
       }
       else {
         switchmenu(2);
       }
       break;
-      //-------------------------------SelectMenu22111-----------------------------------------
+      //-------------------------------SelectMenu223-----------------------------------------
       //SET PAUSE TIME
-      case 22111 :
+      case 223 :
         switch (y) {
-          case 1: p = 5; switchmenu(221111);break;
-          case 2: p = 15; switchmenu(221111); break;
-          case 3: p = 20; switchmenu(221111); break;
-          case 4: p = 30; switchmenu(221111); break;
-          case 5: p = 45; switchmenu(221111); break;
-          case 6: p = 60; switchmenu(221111); break;
-          case 7: p = 75; switchmenu(221111); break;
-          case 8: p = 90; switchmenu(221111); break;
-          case 9: p = 120; switchmenu(221111); break;
+          case 1: p = 5; switchmenu(224);break;
+          case 2: p = 15; switchmenu(224); break;
+          case 3: p = 20; switchmenu(224); break;
+          case 4: p = 30; switchmenu(224); break;
+          case 5: p = 45; switchmenu(224); break;
+          case 6: p = 60; switchmenu(224); break;
+          case 7: p = 75; switchmenu(224); break;
+          case 8: p = 90; switchmenu(224); break;
+          case 9: p = 120; switchmenu(224); break;
           case 10: switchmenu(2); break;
           }
         break;
-      //-------------------------------SelectMenu221111-----------------------------------------
+      //-------------------------------SelectMenu224-----------------------------------------
       //SET MODIFICATOR
-      case 221111 :
+      case 224 :
         if (y < Nbitems) {
           mod = y-11;
-          switchmenu(2211111);
+          switchmenu(225);
         }
         else {
           switchmenu(2);
         }
       break;
-      //-------------------------------SelectMenu221111-----------------------------------------
+      //-------------------------------SelectMenu224-----------------------------------------
       //SET HYSTERESIS
-      case 2211111 :
+      case 225 :
         if (y < Nbitems) {
           hys = y;
-          switchmenu(22111111);
+          switchmenu(226);
         }
         else {
           switchmenu(2);
         }
       break;
-      //-------------------------------SelectMenu221111-----------------------------------------
+      //-------------------------------SelectMenu224-----------------------------------------
       //SET SAFETY AND UPDATE EEPROM
-      case 22111111 :
+      case 226 :
         switch (y){
           case 1: sfty = true;defineRollup(nr,inc,rot,p,mod,hys,sfty); switchmenu(2);break;
           case 2: sfty = false;defineRollup(nr,inc,rot,p,mod,hys,sfty); switchmenu(2);break;
@@ -995,11 +1047,11 @@
       break;
     //-------------------------------SelectMenu31-----------------------------------------
   /*  case 3: Scrollingmenu("FANS*", 3, "Program", "setProgram", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 31: Scrollingnumbers("#****",(sizeof(fans)+1), currentMenuItem, 1, 1); break;
-    case 32: Scrollingnumbers("#****", (sizeof(fans)+1), currentMenuItem, 1, 1); break;
+    case 31: Scrollingnumbers("#****",(NBFANS+1), currentMenuItem, 1, 1); break;
+    case 32: Scrollingnumbers("#****", (NBFANS+1), currentMenuItem, 1, 1); break;
     case 321: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 3211: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
-    case 32111: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
+    case 322: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
+    case 323: Scrollingmenu("SAFTY", 3, "Oui", "Non", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
 */

 //-------------------------------SelectMenu3-----------------------------------------
@@ -1009,8 +1061,7 @@
     case 1:
       switchmenu(31); break;
     case 2:
-      if (sizeof(rollups) == 2){switchmenu(32);}
-      else{switchmenu(0);}
+      switchmenu(32);
       break;
     case 3: switchmenu(0); break;
   }
@@ -1055,26 +1106,26 @@
     case 321 :
       if (y < Nbitems) {
         mod = y-11;
-        switchmenu(3211);
+        switchmenu(322);
       }
       else {
         switchmenu(2);
       }
       break;
-    //-------------------------------SelectMenu3211-----------------------------------------
+    //-------------------------------SelectMenu322-----------------------------------------
     //SET HYSTERESIS
-    case 3211 :
+    case 322 :
       if (y < Nbitems) {
         hys = y;
-        switchmenu(32111);
+        switchmenu(323);
       }
       else {
         switchmenu(2);
       }
       break;
-      //-------------------------------SelectMenu321111-----------------------------------------
+      //-------------------------------SelectMenu3231-----------------------------------------
       //SET SAFETY AND UPDATE EEPROM
-      case 32111 :
+      case 323 :
         switch (y){
           case 1: sfty = true;defineFan(nr,mod,hys,sfty); switchmenu(3);break;
           case 2: sfty = false;defineFan(nr,mod,hys,sfty); switchmenu(3);break;
@@ -1083,10 +1134,10 @@
       break;

 /*  case 4: Scrollingmenu("HEATR", 3, "Program", "setProgram", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-    case 41: Scrollingnumbers("ITEM*",(sizeof(fans)+1), currentMenuItem, 1, 1); break;
-    case 42: Scrollingnumbers("ITEM*", (sizeof(fans)+1), currentMenuItem, 1, 1); break;
+    case 41: Scrollingnumbers("ITEM*",(NBFANS+1), currentMenuItem, 1, 1); break;
+    case 42: Scrollingnumbers("ITEM*", (NBFANS+1), currentMenuItem, 1, 1); break;
     case 421: Scrollingnumbers("MOD**", 22, currentMenuItem, -10, 1); break;
-    case 4211: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
+    case 422: Scrollingnumbers("HYST*", 6, currentMenuItem, 1, 1); break;
 */

 //-------------------------------SelectMenu4-----------------------------------------
@@ -1096,7 +1147,7 @@
     case 1:
       switchmenu(41); break;
     case 2:
-      if (sizeof(fans) == 2){switchmenu(42);}
+      if (NBFANS == 2){switchmenu(42);}
       else{switchmenu(0);}
       break;
     case 3: switchmenu(0); break;
@@ -1140,15 +1191,15 @@
     case 421 :
       if (y < Nbitems) {
         mod = y-11;
-        switchmenu(4211);
+        switchmenu(422);
       }
       else {
         switchmenu(4);
       }
       break;
-    //-------------------------------SelectMenu4211-----------------------------------------
+    //-------------------------------SelectMenu422-----------------------------------------
     //SET HYSTERESIS
-    case 4211 :
+    case 422 :
       if (y < Nbitems) {
         hys = y;
         defineHeater(nr,mod,hys);
@@ -1160,13 +1211,13 @@
       break;
       /*
       case 5: Scrollingmenu("PROG*", 3, "Timezones", "setTimezones", "back", "", "", "", "",  "", "", "", currentMenuItem); break;
-      case 51: Scrollingnumbers("TIMZ*",(sizeof(nbPrograms)+1),currentMenuItem, 1, 1);break;
-      case 52: Scrollingnumbers("TIMZ*",(sizeof(nbPrograms)+1),currentMenuItem, 1, 1);break;
+      case 51: Scrollingnumbers("TIMZ*",(NBPROGRAMS+1),currentMenuItem, 1, 1);break;
+      case 52: Scrollingnumbers("TIMZ*",(NBPROGRAMS+1),currentMenuItem, 1, 1);break;
       case 521: Scrollingmenu("ITEM*", 3,"SR", "MANUAL", "SS", "", "", "", "",  "", "", "", currentMenuItem);break;
-      case 5211: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
-      case 52111: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
-      case 5212: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
-      case 521111: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;
+      case 5221: Scrollingnumbers("HOUR*",25, currentMenuItem, 1, 1); break;
+      case 523: Scrollingnumbers("MIN***",62, currentMenuItem, 0 , 1); break;
+      case 5222: Scrollingnumbers("MOD***",122, currentMenuItem, -60 , 1); break;
+      case 524: Scrollingnumbers("TEMP", 42, currentMenuItem, 0, 1);break;
 */
       //-------------------------------SelectMenu5-----------------------------------------
       //État, setProgram
@@ -1175,19 +1226,19 @@
           case 1:
             switchmenu(51); break;
           case 2:
-            if (sizeof(nbPrograms) >= 2){switchmenu(52);}
+            if (NBPROGRAMS >= 2){switchmenu(52);}
             else{switchmenu(0);}
             break;
           case 3:
-            if (sizeof(nbPrograms) >= 3){switchmenu(52);}
+            if (NBPROGRAMS >= 3){switchmenu(52);}
             else{switchmenu(0);}
             break;
           case 4:
-            if (sizeof(nbPrograms) >= 4){switchmenu(52);}
+            if (NBPROGRAMS >= 4){switchmenu(52);}
             else{switchmenu(0);}
             break;
           case 5:
-            if (sizeof(nbPrograms) >= 5){switchmenu(52);}
+            if (NBPROGRAMS >= 5){switchmenu(52);}
             else{switchmenu(0);}
             break;
           case 6: switchmenu(0); break;
@@ -1195,41 +1246,60 @@
       break;

       //-------------------------------SelectMenu41-----------------------------------------
-    //PROGRAMME DES TIMEZONES
-    case 51 :
-        switch(y){
-          case 1 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1);
-          lcd.setCursor(0, 2);
-          break;
-          case 2 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1);
-          lcd.setCursor(0, 2);
-          case 3 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1);
-          lcd.setCursor(0, 2);
-          case 4 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1);
-          lcd.setCursor(0, 2);
-          case 5 :
-          lcd.noBlink();
-          clearPrintTitle();
-          lcd.setCursor(0, 1);
-          lcd.setCursor(0, 2);
-          break;
-          case 6 :
-          switchmenu(5);
-          break;
-        }
-      break;
+
+      //PROGRAMME DES TIMEZONES
+      case 51 :
+          switch(y){
+            case 1 :
+              if (nbPrograms > 1){
+                programPrintM(0);
+              }
+              else if(nbPrograms == 1){
+                programPrintE(0);
+              }
+              else{switchmenu(5);}
+            break;
+            case 2 :
+              if (nbPrograms > 2){
+                programPrintM(1);
+              }
+              else if(nbPrograms == 2){
+                programPrintE(1);
+              }
+              else{switchmenu(5);}
+            break;
+            case 3 :
+              if (nbPrograms > 3){
+                programPrintM(2);
+              }
+              else if(nbPrograms == 3){
+                programPrintE(2);
+              }
+              else{switchmenu(5);}
+            break;
+            case 4 :
+              if (nbPrograms > 4){
+                programPrintM(3);
+              }
+              else if(nbPrograms == 4){
+                programPrintE(3);
+              }
+              else{switchmenu(5);}
+            break;
+            case 5 :
+              if (nbPrograms > 5){
+                programPrintM(4);
+              }
+              else if(nbPrograms == 5){
+                programPrintE(4);
+              }
+              else{switchmenu(5);}
+            break;
+            case 6 :
+              switchmenu(5);
+            break;
+          }
+        break;
     //-------------------------------SelectMenu52-----------------------------------------
     //SET TIMEZONES PROGRAM
     case 52 :
@@ -1245,62 +1315,59 @@
     //SET TYPE
     case 521 :
       switch(y){
-        case 1:typ = SR;switchmenu(5212);break;
-        case 2:typ = CLOCK;switchmenu(5211);break;
-        case 3:typ = SS;switchmenu(5212);break;
+        case 1:typ = SR;switchmenu(5222);break;
+        case 2:typ = CLOCK;switchmenu(5221);break;
+        case 3:typ = SS;switchmenu(5222);break;
         case 4:switchmenu(5);break;
       }
       break;
-    //-------------------------------SelectMenu5211-----------------------------------------
+    //-------------------------------SelectMenu5221-----------------------------------------
     //SET HOUR
-    case 5211 :
-      t = rtc.getTime();
-      sunTime[HEURE] = t.hour;
-      myLord.DST(sunTime);
-        if ((t.hour != sunTime[HEURE]) && (y < Nbitems)) {
-        hr = y-1;
-        switchmenu(52111);
-      }
-      else if ((t.hour == sunTime[HEURE]) && (y < Nbitems)) {
+    case 5221 :
+      if (y < Nbitems) {
         hr = y;
-        switchmenu(52111);
+        switchmenu(523);
       }
       else{
         switchmenu(5);
       }
       break;
-    //-------------------------------SelectMenu52111-----------------------------------------
+    //-------------------------------SelectMenu523-----------------------------------------
     //SET MINUTES
-    case 52111 :
+    case 523 :
       if (y < Nbitems) {
         mn = y - 1;
-        switchmenu(521111);
+        switchmenu(524);
       }
       else {
         switchmenu(5);
       }
       break;
-    //-------------------------------SelectMenu5212-----------------------------------------
+    //-------------------------------SelectMenu5222-----------------------------------------
     //SET MOD
-    case 5212 :
+    case 5222 :
       if (y < Nbitems) {
         mod = y-60;
-        switchmenu(521111);
+        switchmenu(524);
       }
       else {
         switchmenu(5);
       }
     break;
-    //-------------------------------SelectMenu521111-----------------------------------------
+    //-------------------------------SelectMenu524-----------------------------------------
     //SET TEMP CIBLE AND UPDATE EEPROM
-    case 521111 :
+    case 524 :
       if (y < Nbitems) {
         tt = y-1;
         if (typ == CLOCK){
           defineProgram(nr,typ,hr,mn,tt);
+          setPrograms();
+            switchmenu(5);
         }
         else{
           defineProgram(nr,typ,0,mod,tt);
+          setPrograms();
+            switchmenu(5);
         }
       }
       else {


Removed INFINITY since this code is using 1000 as infinite

--- utils/arduino_astar/arduino_astar.ino
+++ utils/arduino_astar/arduino_astar.ino
@@ -85,7 +85,7 @@
   /* Setando todo o grid para 1000, isso irá auxiliar no momento da execução do A* */
   for (i = 0; i < m; i++) {
     for (j = 0; j < m; j++) {
-      grid[i][j] = INT_MAX;
+      grid[i][j] = 1000;
     }
   }


main: preliminary support for config file

--- src/main.ino
+++ src/main.ino
@@ -3,6 +3,8 @@
 #include "Pcd8544.h"
 #include "Expander.h"
 #include "Dht.h"
+#include "ArduinoJson.h"
+#include "FS.h"

 #ifdef ESP8266
 #include <Wire.h>
@@ -15,6 +17,12 @@
 #include <ArduinoOTA.h>
 #include "wifi_sta_pass.h"
 #endif
+
+static struct configuration {
+    char *wifi_ssid;
+    char *wifi_pass;
+    char *banner;
+} config;

 static const int PM25_NORM=25;
 static const int PM10_NORM=40;
@@ -34,6 +42,7 @@
 #endif

 dht::Dht dht22(14);
+StaticJsonBuffer<200> jsonBuffer;

 static bool set_press;

@@ -81,9 +90,54 @@
     display.print("%");
 }

+bool load_config(void)
+{
+    char buf[1024];
+
+    memset(&config, 0, sizeof(config));
+
+    File file = SPIFFS.open("/config.json", "r");
+    if (!file) {
+        return false;
+    }
+
+    size_t size = file.size();
+    if (size > sizeof(buf)) {
+        return false;
+    }
+
+    file.readBytes(buf, size);
+
+    StaticJsonBuffer<200> json_buf;
+
+    JsonObject& json = json_buf.parseObject(buf);
+
+    if (!json.success()) {
+        return false;
+    }
+
+    const char *tmp = json["wifi_ssid"];
+    if (tmp) {
+        config.wifi_ssid = strdup(tmp);
+    }
+
+    tmp = json["wifi_pass"];
+    if (tmp) {
+        config.wifi_pass = strdup(tmp);
+    }
+
+    tmp = json["banner"];
+    if (tmp) {
+        config.banner = strdup(tmp);
+    } else {
+        config.banner = strdup("");
+    }
+}
+
 void setup()
 {
     bool clear = true;
+    char *banner;

 #ifdef ESP8266
     expand.begin();
@@ -100,11 +154,20 @@

     display.begin();
     dht22.begin();
+
+    SPIFFS.begin();
+
+    if (!load_config()) {
+        banner = strdup("NO CONFIG");
+    } else {
+        banner = config.banner;
+    }

     if (clear) {
         display.clear();
         display.setCursor(0,0);
         display.println("Hello");
+        display.println(banner);
     }

 #ifdef ESP8266


Update pid.ino

Update pid.ino

--- code/pid.ino
+++ code/pid.ino
@@ -11,8 +11,6 @@
   Setpoint = 127;
   myPID.SetOutputLimits(120, 255);
   myPID.SetMode(AUTOMATIC);
-  //
-  Serial.println("PID Iniciado\n");
 }

 int PID_loop(float angulo) {
@@ -24,8 +22,6 @@

   Input > 127 ? Input = Input - (2*(Input-127)): Input = Input;

- // Serial.print("\tInput: ");
-  //Serial.print(Input);
   myPID.Compute();
   Serial.print("\nPID: ");
   Serial.print(Output);


Message making using strings

Message making using strings

--- hacks/rf_temp_link/rf_temp_link.ino
+++ hacks/rf_temp_link/rf_temp_link.ino
@@ -34,6 +34,9 @@
 OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices
 DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
 DeviceAddress firstThermometer = { 0x28, 0xFF, 0xAD, 0x82, 0x61, 0x15, 0x02, 0xE8 }; // Assign the addresses of your 1-Wire temp sensors.
+String messageString = "";
+int messageId = 0;
+float tempC = -127.00; //-127.00 is the error temp

 void setup() {
   // initialize the LED pin as an output:
@@ -65,21 +68,25 @@
       // Get and print temperature
       Serial.println("Getting temperatures...");
       sensors.requestTemperatures();
-      float tempC = sensors.getTempC(firstThermometer);
+      tempC = sensors.getTempC(firstThermometer);
       if (tempC == -127.00) {
-        Serial.print("Error getting temperature");
-      } else {
-        Serial.print("C: ");
-        Serial.print(tempC);
+        Serial.println("Error getting temperature");
       }
-      Serial.print("\n\r");

-      // Send temperature message
-      char temperatureMessage[6];
-      dtostrf(tempC, 6, 2, temperatureMessage);
-      driver.send((uint8_t *)temperatureMessage, strlen(temperatureMessage));
+      // Make and send message
+      messageString = "Id: ";
+      messageString = messageString + String(messageId, DEC);
+      messageString = messageString + " Temp: ";
+      messageString = messageString + String(tempC, 2);
+      int str_len = messageString.length()+1;
+      char messageStringChar[str_len];
+      messageString.toCharArray(messageStringChar, str_len);
+      Serial.println(messageStringChar);
+      driver.send((uint8_t *)messageStringChar, strlen(messageStringChar));
       driver.waitPacketSent();
-
+      messageString = "";
+      messageId = messageId + 1;
+
       // Provide feedback that message sent
       Serial.println("Message sent!");
       digitalWrite(LED_PIN_TX, HIGH);


'Rysk' ver 0.03

'Rysk' ver 0.03

:jp: Japanese letters
:one: Display score larger
:clock12: Timer
:bulb: LED control

--- rysk/rysk.ino
+++ rysk/rysk.ino
@@ -10,31 +10,119 @@
 #define FPS             60
 #define APP_TITLE       "RYSK"
 #define APP_CODE        "OBN-Y00"
-#define APP_VERSION     "0.02"
+#define APP_VERSION     "0.03"
 #define APP_RELEASED    "NOVEMBER 2019"

-#define COOKIES     8
-#define ANIM_MAX    16
-
-#define PL_SIZE     4
-#define CK_SIZE     2
-#define SCALE       64
-#define WIDTH_S     (WIDTH * SCALE)
-#define HEIGHT_S    (HEIGHT * SCALE)
-#define PL_SIZE_S   (PL_SIZE * SCALE)
-#define CK_SIZE_S   (CK_SIZE * SCALE)
-#define HIT_DIFF_S  PL_SIZE_S
-#define NEW_DIFF_S  (PL_SIZE_S * 4)
+#define COOKIES         8
+#define ANIM_MAX        16
+
+#define PL_SIZE         4
+#define CK_SIZE         2
+#define SCALE           64
+#define WIDTH_S         (WIDTH * SCALE)
+#define HEIGHT_S        (HEIGHT * SCALE)
+#define PL_SIZE_S       (PL_SIZE * SCALE)
+#define CK_SIZE_S       (CK_SIZE * SCALE)
+#define HIT_DIFF_S      PL_SIZE_S
+#define NEW_DIFF_S      (PL_SIZE_S * 4)
+
+#define GAME_DURATION   (FPS * 60)
+
+#define IMG_TITLE_W     128
+#define IMG_TITLE_H     16
+#define IMG_START1_W    48
+#define IMG_START1_H    16
+#define IMG_START2_W    32
+#define IMG_START2_H    16
+#define IMG_OVER_W      64
+#define IMG_OVER_H      16
+#define IMG_FIGURE_W    8
+#define IMG_FIGURE_H    12
+#define IMG_TEN_W       12
+#define IMG_TEN_H       8
+#define CLOCK_R         9
+#define CLOCK_X         (WIDTH - (CLOCK_R + 1))
+#define CLOCK_Y         (HEIGHT - (CLOCK_R + 1))
+#define LED_LEVEL_START 16
+#define LED_VALUE(r, g, b)  ((r) * 25 + (g) * 5 + (b))
+
+enum {
+    ALIGN_LEFT = 0,
+    ALIGN_CENTER,
+    ALIGN_RIGHT,
+};
+
+/*  Typedefs  */
+
+typedef struct {
+    int16_t x, y;
+    int8_t  vx, vy;
+} COOKIE_T;

 /*  Functions  */

-void initialize(void);
-void update(void);
-void movePlayer(void);
-void newCookie(uint8_t idx);
-void draw(void);
+static void initialize(void);
+static void update(void);
+static void initGame(void);
+static void updateGame(void);
+static void movePlayer(void);
+static void moveCookie(COOKIE_T *pCookie);
+static void newCookie(COOKIE_T *pCookie);
+static bool isInRange(COOKIE_T *pCookie, int16_t range);
+
+static void draw(void);
+static void drawObject(int16_t x, int16_t y, uint8_t size, const uint8_t *bitmap);
+static void drawStatus(void);
+static int  drawFigure(int16_t x, int16_t y, int value, uint8_t align);
+static void drawClock(int16_t x, int16_t y, uint8_t r, uint8_t sec);

 /*  Variables  */
+
+PROGMEM static const uint8_t imgTitle[256] = { // 128x16
+    0x00, 0xF8, 0xFC, 0x00, 0x00, 0x00, 0x98, 0x98, 0x98, 0xF8, 0xF8, 0xDA, 0xC4, 0x0D, 0x0B, 0x06,
+    0x00, 0x60, 0x60, 0xE0, 0xF0, 0xFC, 0x3C, 0x30, 0x30, 0xA0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x10, 0x90, 0xF0, 0xF8, 0x9E, 0x9E, 0x98, 0x18, 0x88, 0x80, 0x80, 0x00, 0x00, 0x00,
+    0x00, 0x60, 0x60, 0x60, 0xFE, 0xFC, 0x30, 0x30, 0x30, 0x00, 0x08, 0x18, 0x38, 0x30, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x10, 0x98, 0xD8, 0x78, 0x38, 0x18, 0x18, 0x08, 0x00, 0x00,
+    0x40, 0xC0, 0x60, 0xF8, 0xFC, 0x64, 0x80, 0xC0, 0x60, 0x30, 0x30, 0x30, 0xF0, 0xC0, 0x00, 0x00,
+    0x00, 0x7F, 0x7F, 0x38, 0x00, 0x30, 0x79, 0x49, 0x49, 0x7F, 0x3F, 0x30, 0x30, 0x60, 0x00, 0x00,
+    0x00, 0x60, 0x7C, 0x1F, 0x07, 0x00, 0x00, 0x33, 0x31, 0x61, 0x61, 0x61, 0x61, 0x41, 0x00, 0x00,
+    0x00, 0x70, 0x3E, 0x1F, 0x0F, 0x06, 0x1F, 0x7F, 0x70, 0x60, 0x60, 0x70, 0x38, 0x1C, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x21, 0x79, 0x7C, 0x66, 0x6F, 0x6F, 0x63, 0x61, 0x61, 0x01, 0x00, 0x00, 0x00,
+    0x00, 0x38, 0x7C, 0x4C, 0xFF, 0x7F, 0x02, 0x03, 0x43, 0x43, 0x63, 0x63, 0x7E, 0x3C, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0E, 0x3F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x70, 0x38, 0x0C, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0x38, 0x60, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00,
+    0x10, 0x38, 0x1E, 0xFF, 0xFF, 0x01, 0x01, 0x30, 0x78, 0x68, 0x68, 0x78, 0x3F, 0x3F, 0x60, 0x00
+};
+
+PROGMEM static const uint8_t imgStart1[96] = { // 48x16
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFC, 0x60, 0x60, 0x30, 0x20, 0x00, 0x00, 0x00,
+    0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+    0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xE0, 0xC0, 0x80, 0x00, 0x00,
+    0x00, 0x30, 0x78, 0x68, 0x4C, 0x6C, 0x68, 0x7F, 0x1F, 0x18, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00,
+    0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+    0x00, 0x03, 0x0F, 0x3C, 0x70, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00
+};
+
+PROGMEM static const uint8_t imgStart2[64] = { // 32x16
+    0x00, 0x00, 0x00, 0x1C, 0x7C, 0xF0, 0x80, 0xC0, 0xE0, 0x60, 0x70, 0x30, 0x0C, 0x1A, 0x06, 0x04,
+    0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x3E, 0x7F, 0x63, 0x61, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x70, 0x3E, 0x1F, 0x0F, 0x06, 0x1F, 0x7F, 0x70, 0x60, 0x60, 0x70, 0x38, 0x1C, 0x00, 0x00
+};
+
+PROGMEM static const uint8_t imgOver[128] = { // 64x16
+    0x00, 0x60, 0x60, 0x60, 0xFE, 0xFC, 0x30, 0x30, 0x30, 0x00, 0x08, 0x18, 0x38, 0x30, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x10, 0x30, 0xB0, 0xB0, 0xB0, 0xFE, 0xFE, 0x90, 0x98, 0x10, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xE0, 0xC0, 0x80, 0x00, 0x00,
+    0x00, 0x38, 0x7C, 0x4C, 0xFF, 0x7F, 0x02, 0x03, 0x43, 0x43, 0x63, 0x63, 0x7E, 0x3C, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x0E, 0x3F, 0x7F, 0x60, 0x60, 0x60, 0x60, 0x70, 0x38, 0x0C, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x30, 0x79, 0x59, 0xD9, 0x59, 0x7F, 0x3F, 0x31, 0x31, 0x61, 0x40, 0x00, 0x00, 0x00,
+    0x00, 0x03, 0x0F, 0x3C, 0x70, 0x3C, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00
+};

 PROGMEM static const uint8_t imgPlayer[9][8] = { // 8x8 x9
     { 0xFE, 0xF2, 0xDE, 0xDE, 0xF2, 0xFE, 0xFE, 0xFE },
@@ -45,23 +133,63 @@
     { 0xFE, 0xFE, 0xFE, 0xE2, 0xBE, 0xBE, 0xE2, 0xFE },
     { 0xFE, 0xC6, 0xBE, 0xBE, 0xC6, 0xFE, 0xFE, 0xFE },
     { 0xFE, 0xFE, 0xC6, 0xBE, 0xBE, 0xC6, 0xFE, 0xFE },
-    { 0xFE, 0xFE, 0xFE, 0xC6, 0xBE, 0xBE, 0xC6, 0xFE },
+    { 0xFE, 0xFE, 0xFE, 0xC6, 0xBE, 0xBE, 0xC6, 0xFE }
+};
+
+PROGMEM static const uint8_t imgCookie[4] = { // 4x4
+    0x06, 0x09, 0x09, 0x06
+};
+
+PROGMEM static const uint8_t imgFigures[10][16] = { // 8x12 x10
+    { 0x78, 0xFC, 0xFE, 0x86, 0xFE, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00 },
+    { 0x8C, 0x8C, 0xFE, 0xFE, 0xFE, 0x86, 0x80, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00 },
+    { 0x0C, 0x86, 0xE6, 0xFE, 0xBE, 0xDC, 0xC0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x00 },
+    { 0x04, 0x26, 0x36, 0x3E, 0xFE, 0xF4, 0xE0, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00 },
+    { 0xE0, 0xF0, 0xD8, 0xFC, 0xFE, 0xFE, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x00, 0x00 },
+    { 0x38, 0x3E, 0x36, 0x76, 0xF6, 0xE6, 0xE6, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00 },
+    { 0x78, 0xFE, 0xFF, 0x9F, 0xF8, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00 },
+    { 0x0E, 0x0E, 0x06, 0xC6, 0xF6, 0x7E, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x03, 0x00, 0x00, 0x00 },
+    { 0xEE, 0xFF, 0x3F, 0x7D, 0xF9, 0xFF, 0xE6, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00 },
+    { 0x3C, 0x7E, 0x7E, 0xE6, 0xFE, 0xFC, 0x7C, 0x00, 0x00, 0x02, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00 }
+};
+
+PROGMEM static const uint8_t imgTen[12] = { // 12x8
+    0x08, 0x08, 0x68, 0x98, 0x08, 0x00, 0xC0, 0x70, 0x28, 0xC0, 0x80, 0x00
+};
+
+PROGMEM static const byte soundStart[] = {
+    0x90, 0x44, 0x00, 0x7D, 0x90, 0x43, 0x00, 0x7D, 0x90, 0x42, 0x00, 0x7D, 0x90, 0x41, 0x00, 0x7D,
+    0x90, 0x40, 0x00, 0x7D, 0x90, 0x41, 0x00, 0x7D, 0x90, 0x42, 0x00, 0x7D, 0x90, 0x43, 0x00, 0x7D,
+    0x90, 0x60, 0x00, 0x14, 0x90, 0x41, 0x00, 0x14, 0x90, 0x5B, 0x00, 0x14, 0x90, 0x56, 0x00, 0x14,
+    0x90, 0x51, 0x00, 0x14, 0x90, 0x4C, 0x00, 0x14, 0x90, 0x47, 0x00, 0x14, 0x90, 0x3C, 0x00, 0x14,
+    0x80, 0xF0
 };

 PROGMEM static const byte soundStep[] = {
-    0x90, 60, 0, 10, 0x80, 0xF0
+    0x90, 0x3C, 0x00, 0x0A, 0x80, 0xF0
 };

 PROGMEM static const byte soundCapture[] = {
-    0x90, 80, 0, 20, 0x90, 84, 0, 40, 0x90, 88, 0, 40, 0x80, 0xF0
+    0x90, 0x50, 0x00, 0x14, 0x90, 0x54, 0x00, 0x28, 0x90, 0x58, 0x00, 0x28, 0x80, 0xF0
+};
+
+PROGMEM static const byte soundOver[] = {
+    0x90, 0x37, 0x00, 0xC8, 0x90, 0x35, 0x00, 0xC8, 0x90, 0x37, 0x00, 0xC8, 0x90, 0x35, 0x00, 0xC8,
+    0x90, 0x32, 0x01, 0xF4, 0x80, 0xF0
+};
+
+PROGMEM static const uint8_t ledValues[] = {
+    LED_VALUE(2, 2, 2), LED_VALUE(4, 0, 0), LED_VALUE(0, 0, 4), LED_VALUE(3, 3, 0), LED_VALUE(0, 4, 0),
+    LED_VALUE(3, 1, 1), LED_VALUE(2, 1, 0), LED_VALUE(2, 0, 3), LED_VALUE(1, 3, 0), LED_VALUE(0, 2, 2)
 };

 MyArduboy   arduboy;
-int16_t     px, py;
-int16_t     cx[COOKIES], cy[COOKIES];
-int8_t      cvx[COOKIES], cvy[COOKIES];
-uint16_t    score;
-uint8_t     pc, pa;
+bool        isPlaying;
+int16_t     playerX, playerY;
+uint8_t     playerChr, playerAnim;
+COOKIE_T    cookie[COOKIES];
+int16_t     score, gameTime;
+uint8_t     ledRed, ledGreen, ledBlue, ledLevel;

 /*  For Debugging  */

@@ -96,6 +224,8 @@
 #endif

 /*---------------------------------------------------------------------------*/
+/*                               Entry Points                                */
+/*---------------------------------------------------------------------------*/

 void setup()
 {
@@ -121,37 +251,74 @@
 }

 /*---------------------------------------------------------------------------*/
-
-void initialize(void)
-{
-    px = WIDTH_S / 2;
-    py = HEIGHT_S / 2;
-    pc = 4;
-    pa = 0;
-    for (uint8_t idx = 0; idx < COOKIES; idx++) {
-        newCookie(idx);
+/*                             Control Functions                             */
+/*---------------------------------------------------------------------------*/
+
+static void initialize(void)
+{
+    arduboy.setAudioEnabled(true);
+    arduboy.drawBitmap(0, 24, imgTitle, IMG_TITLE_W, IMG_TITLE_H, WHITE);
+    arduboy.setCursor(40, 58);
+    arduboy.print(F("RYSK " APP_VERSION));
+    isPlaying = false;
+}
+
+static void update(void)
+{
+    if (isPlaying) {
+        updateGame();
+    } else {
+        randomSeed(rand() ^ micros()); // Shuffle random
+        if (arduboy.buttonDown(A_BUTTON | B_BUTTON)) {
+            initGame();
+        }
+    }
+}
+
+static void initGame(void)
+{
+    isPlaying = true;
+    playerX = WIDTH_S / 2;
+    playerY = HEIGHT_S / 2;
+    playerChr = 4;
+    playerAnim = 0;
+    for (COOKIE_T *pCookie = cookie; pCookie < cookie + COOKIES; pCookie++) {
+        newCookie(pCookie);
     }
     score = 0;
-    arduboy.setAudioEnabled(true);
-}
-
-void update(void)
-{
-    movePlayer();
-    for (uint8_t idx = 0; idx < COOKIES; idx++) {
-        if (cx[idx] + cvx[idx] < CK_SIZE_S || cx[idx] + cvx[idx] >= WIDTH_S - CK_SIZE_S) cvx[idx] = -cvx[idx];
-        if (cy[idx] + cvy[idx] < CK_SIZE_S || cy[idx] + cvy[idx] >= HEIGHT_S - CK_SIZE_S) cvy[idx] = -cvy[idx];
-        cx[idx] += cvx[idx];
-        cy[idx] += cvy[idx];
-        if (abs(px - cx[idx]) < HIT_DIFF_S && abs(py - cy[idx]) < HIT_DIFF_S) {
-            score++;
-            arduboy.playScore2(soundCapture, 0);
-            newCookie(idx);
-        }
-    }
-}
-
-void movePlayer(void)
+    gameTime = GAME_DURATION + FPS * 2;
+    ledLevel = 0;
+    arduboy.playScore2(soundStart, 0);
+}
+
+static void updateGame(void)
+{
+    gameTime--;
+    if (ledLevel > 0) ledLevel--;
+    if (gameTime <= GAME_DURATION && gameTime >= 0) {
+        movePlayer();
+        for (COOKIE_T *pCookie = cookie; pCookie < cookie + COOKIES; pCookie++) {
+            moveCookie(pCookie);
+            if (isInRange(pCookie, HIT_DIFF_S)) {
+                score++;
+                arduboy.playScore2(soundCapture, 2);
+                newCookie(pCookie);
+                uint8_t ledValue = pgm_read_byte(ledValues + score % 10);
+                ledRed = ledValue / 25;
+                ledGreen = ledValue / 5 % 5;
+                ledBlue = ledValue % 5;
+                ledLevel = LED_LEVEL_START;
+            }
+        }
+        if (gameTime == 0) {
+            arduboy.playScore2(soundOver, 1);
+        }
+    } else if (gameTime <= -FPS) {
+        isPlaying = false;
+    }
+}
+
+static void movePlayer(void)
 {
     /*  Move  */
     int8_t vx = 0, vy = 0;
@@ -159,46 +326,99 @@
     if (arduboy.buttonPressed(RIGHT_BUTTON)) vx++;
     if (arduboy.buttonPressed(UP_BUTTON))    vy--;
     if (arduboy.buttonPressed(DOWN_BUTTON))  vy++;
-    pc = (vy + 1) * 3 + (vx + 1);
     int8_t vs = (vx != 0 && vy != 0) ? (SCALE * 3 / 8) : (SCALE / 2);
-    vx *= vs;
-    vy *= vs;
-    if (px + vx >= PL_SIZE_S && px + vx < WIDTH_S - PL_SIZE_S) px += vx;
-    if (py + vy >= PL_SIZE_S && py + vy < HEIGHT_S - PL_SIZE_S) py += vy;
+    int16_t dx = playerX + vx * vs;
+    int16_t dy = playerY + vy * vs;
+    if (dx >= PL_SIZE_S && dx < WIDTH_S - PL_SIZE_S) playerX = dx;
+    if (dy >= PL_SIZE_S && dy < HEIGHT_S - PL_SIZE_S) playerY = dy;

     /*  Animation  */
-    if (pc == 4) {
-        pa = 0;
+    playerChr = (vy + 1) * 3 + (vx + 1);
+    if (playerChr == 4) {
+        playerAnim = 0;
     } else {
-        if (++pa >= ANIM_MAX) {
-            arduboy.playScore2(soundStep, 1);
-            pa = 0;
-        }
-    }
-}
-
-void newCookie(uint8_t idx)
+        if (++playerAnim >= ANIM_MAX) {
+            arduboy.playScore2(soundStep, 3);
+            playerAnim = 0;
+        }
+    }
+}
+
+static void moveCookie(COOKIE_T *pCookie)
+{
+    int16_t dx = pCookie->x + pCookie->vx;
+    int16_t dy = pCookie->y + pCookie->vy;
+    if (dx < CK_SIZE_S || dx >= WIDTH_S - CK_SIZE_S) pCookie->vx = -pCookie->vx;
+    if (dy < CK_SIZE_S || dy >= HEIGHT_S - CK_SIZE_S) pCookie->vy = -pCookie->vy;
+    pCookie->x += pCookie->vx;
+    pCookie->y += pCookie->vy;
+}
+
+static void newCookie(COOKIE_T *pCookie)
 {
     do {
-        cx[idx] = random(CK_SIZE_S, WIDTH_S - CK_SIZE_S);
-        cy[idx] = random(CK_SIZE_S, HEIGHT_S - CK_SIZE_S);
-    } while (abs(px - cx[idx]) < NEW_DIFF_S && abs(py - cy[idx]) < NEW_DIFF_S);
+        pCookie->x = random(CK_SIZE_S, WIDTH_S - CK_SIZE_S);
+        pCookie->y = random(CK_SIZE_S, HEIGHT_S - CK_SIZE_S);
+    } while (isInRange(pCookie, NEW_DIFF_S));
     float d = random(2048) * PI / 1024.0;
-    cvx[idx] = (int8_t) (cos(d) * (float) SCALE);
-    cvy[idx] = (int8_t) (sin(d) * (float) SCALE);
-}
-
-void draw(void)
-{
+    pCookie->vx = (int8_t) (cos(d) * (float) SCALE);
+    pCookie->vy = (int8_t) (sin(d) * (float) SCALE);
+}
+
+static bool isInRange(COOKIE_T *pCookie, int16_t range)
+{
+    return (abs(playerX - pCookie->x) < range && abs(playerY - pCookie->y) < range);
+}
+
+/*---------------------------------------------------------------------------*/
+/*                              Draw Functions                               */
+/*---------------------------------------------------------------------------*/
+
+static void draw(void)
+{
+    if (!isPlaying) return;
     arduboy.clear();
-    arduboy.setCursor(0, 0);
-    arduboy.print(score);
-    int16_t dx = px / SCALE - PL_SIZE;
-    int16_t dy = py / SCALE - PL_SIZE - (pa >= ANIM_MAX / 2);
-    arduboy.drawBitmap(dx, dy, imgPlayer[pc], PL_SIZE * 2, PL_SIZE * 2, WHITE);
-    for (uint8_t idx = 0; idx < COOKIES; idx++) {
-        dx = cx[idx] / SCALE - CK_SIZE;
-        dy = cy[idx] / SCALE - CK_SIZE;
-        arduboy.drawRect2(dx, dy, CK_SIZE * 2, CK_SIZE * 2, WHITE);
-    }
-}
+    drawObject(playerX, playerY - (playerAnim >= ANIM_MAX / 2) * SCALE, PL_SIZE, imgPlayer[playerChr]);
+    for (COOKIE_T *pCookie = cookie; pCookie < cookie + COOKIES; pCookie++) {
+        drawObject(pCookie->x, pCookie->y, CK_SIZE, imgCookie);
+    }
+    drawStatus();
+    arduboy.setRGBled(ledRed * ledLevel, ledGreen * ledLevel, ledBlue * ledLevel);
+}
+
+static void drawObject(int16_t x, int16_t y, uint8_t size, const uint8_t *bitmap)
+{
+    arduboy.drawBitmap(x / SCALE - size, y / SCALE - size, bitmap, size * 2, size * 2, WHITE);
+}
+
+static void drawStatus(void)
+{
+    if (gameTime > GAME_DURATION + FPS) {
+        arduboy.drawBitmap((WIDTH - IMG_START1_W) / 2, 8, imgStart1, IMG_START1_W, IMG_START1_H, WHITE);
+    } else if (gameTime > GAME_DURATION) {
+        arduboy.drawBitmap((WIDTH - IMG_START2_W) / 2, 8, imgStart2, IMG_START2_W, IMG_START2_H, WHITE);
+    } else {
+        int dx = drawFigure(0, 0, score, ALIGN_LEFT);
+        arduboy.drawBitmap(dx, 0, imgTen, IMG_TEN_W, IMG_TEN_H, WHITE);
+        drawClock(CLOCK_X, CLOCK_Y, CLOCK_R, (gameTime > 0) ? (GAME_DURATION - gameTime) / FPS : 0);
+        if (gameTime <= 0) {
+            arduboy.drawBitmap((WIDTH - IMG_OVER_W) / 2, 48, imgOver, IMG_OVER_W, IMG_OVER_H, WHITE);
+        }
+    }
+}
+
+static int drawFigure(int16_t x, int16_t y, int value, uint8_t align)
+{
+    int k = (value > 9) ? drawFigure(x - align * 4, y, value / 10, align) : 0;
+    arduboy.drawBitmap(x + k, y, imgFigures[value % 10], IMG_FIGURE_W, IMG_FIGURE_H, WHITE);
+    return k + 8 - align * 4;
+}
+
+static void drawClock(int16_t x, int16_t y, uint8_t r, uint8_t sec)
+{
+    float d = sec * PI / 30.0;
+    int16_t vx = sin(d) * r;
+    int16_t vy = -cos(d) * r;
+    arduboy.drawLine(x, y, x + vx, y + vy, WHITE);
+    arduboy.drawCircle(x, y, r, WHITE);
+}


Cleaned up SpinMeRightRound Example.
Can now interpret Response Packets.

Signed-off-by: Cruz Monrreal II <663375bc5b4c6ed13a95cc63b2dd9f1e16363f4e@gmail.com>

--- examples/SpinMeRightRound/SpinMeRightRound.ino
+++ examples/SpinMeRightRound/SpinMeRightRound.ino
@@ -12,19 +12,15 @@
 SoftwareSerial bluetooth(2,3);
 Sphero sphero(bluetooth);

-
 void setup() {
   Serial.begin(115200);
   bluetooth.begin(9600);
-  delay(250);

   // Turn on Back LED
   sphero.setBackLED(0xFF);
-  delay(250);
 }

 // ♫♫♫ You Spin Me Right Round ♫♫♫
 void loop() {
-  sphero.rotateHeadingBy(45);
-  delay(3);
+  sphero.rotateHeadingBy(90);
 }


Lower resolution on the ripple visualization

--- examples/cymatic-curtains/cymatic-curtains.ino
+++ examples/cymatic-curtains/cymatic-curtains.ino
@@ -27,7 +27,7 @@
 LEDs leds3 = LEDs(&strip, 300, 150);
 LEDs leds4 = LEDs(&strip, 450, 150);

-Visualization* viz = new RippleVisualization(input, 150);
+Visualization* viz = new RippleVisualization(input, 60);
 CurtainAnimation* anim1 = new CurtainAnimation(viz, leds1);
 CurtainAnimation* anim2 = new CurtainAnimation(viz, leds2);
 CurtainAnimation* anim3 = new CurtainAnimation(viz, leds3);


Changed separator between files from '-' to '|' in 'api/files'.

Ran into problems testing the new web interface.
Minus sign '-' is too common in filenames and '|' is much rarer.
On linux almost anything except NUL is allowed.


Formatting

Formatting

--- trikebox/trikebox.ino
+++ trikebox/trikebox.ino
@@ -3,12 +3,15 @@
 #include <FastLED.h>
 #define LEDS_PER_ROW 72
 #define COLS_LEDs 72  // all of the following params need to be adjusted for screen size
+// (we actually use 12 rows. Don't know why this is 16)
 #define ROWS_LEDs 16 // LED_LAYOUT assumed 0 if ROWS_LEDs > 8
 #define LEDS_PER_STRIP (COLS_LEDs * (ROWS_LEDs / 8))
 #define LED_LAYOUT 0

-#define qsubd(x, b)  ((x>b)?255:0)  // Digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value.
-#define qsuba(x, b)  ((x>b)?x-b:0)  // Analog Unsigned subtraction macro. if result <0, then => 0
+// Digital unsigned subtraction macro. if result <0, then => 0. Otherwise, take on fixed value.
+#define qsubd(x, b) ((x>b)?255:0)
+// Analog Unsigned subtraction macro. if result <0, then => 0
+#define qsuba(x, b) ((x>b)?x-b:0)

 DMAMEM int displayMemory[LEDS_PER_STRIP*6];
 int drawingMemory[LEDS_PER_STRIP*6];


Remove RX hack

Remove RX hack

--- home-node/home-node.ino
+++ home-node/home-node.ino
@@ -1,3 +1,4 @@
+
 #define MAX_HANDLERS 8
 #define CONFIG_TOPIC_PREFIX "config/"

@@ -18,7 +19,7 @@
 char* configTopic;

 WiFiClient wifiClient;
-MQTTClient client(512); //(wifiClient);
+MQTTClient client(512); //max package size

 //The clientId generation was taken from https://github.com/marvinroger/homie-esp8266
 void clientIdSetup() {
@@ -51,9 +52,6 @@

   Serial.print("Connected, IP address: ");
   Serial.println(WiFi.localIP());
-
-  pinMode(RX, OUTPUT);
-  digitalWrite(RX, LOW);
 };

 void reconnect() {


Improving Vigenere example sketch; adding checksum to avoid compiler tricks.

--- examples/Sandbox/CosaVigenere/CosaVigenere.ino
+++ examples/Sandbox/CosaVigenere/CosaVigenere.ino
@@ -61,11 +61,13 @@
   TRACE(sizeof(sender));
   char c;
   const char* s = msg;
+  uint8_t sum = 0;
   uint32_t start = RTC::micros();
   while ((c = pgm_read_byte(s++)) != 0)
-    c = sender.encode(c);
+    sum += sender.encode(c);
   uint32_t us = RTC::micros() - start;
   uint16_t len = strlen_P(msg);
+  TRACE(sum);
   trace << len << PSTR(" bytes, ")
 	<< us << PSTR(" us (")
 	<< (us * 1000) / len << PSTR(" ns/byte)")
@@ -86,6 +88,3 @@
   while ((c = pgm_read_byte(s++)) != 0)
     trace << receiver.decode(sender.encode(c));
 }
-
-
-


Update ha_mqtt_binary_sensor_pir.ino

Update ha_mqtt_binary_sensor_pir.ino

--- ha_mqtt_binary_sensor_pir/ha_mqtt_binary_sensor_pir.ino
+++ ha_mqtt_binary_sensor_pir/ha_mqtt_binary_sensor_pir.ino
@@ -22,7 +22,7 @@
    Schematic :
     - https://learn.adafruit.com/pir-passive-infrared-proximity-motion-sensor/using-a-pir

-    TODO :
+   TODO :
     - Use the interrupts instead of constinously polling the sensor

    Samuel M. - 08.2016


AdafruitPWM, minor improvements and simplifications


DHCP settings read from EEPROM. They were written to EEPROM from hard coded strings, next step is to receive them via the config GUI.

--- mqttHA_Point/mqttHA_Point.ino
+++ mqttHA_Point/mqttHA_Point.ino
@@ -122,8 +122,20 @@
 }
 /////////////////////////////////////////////////////////////////////////////////////////////////////////
 bool wifiConnectDHCP(void) {
+//  String esubnet="";
+//  Serial.println("Reading EEPROM DHCP subnet");
+//  for (int i = 129; i < 133; ++i)
+//  {
+//    esubnet += char(EEPROM.read(i));
+//  }
+  IPAddress estaticIP(EEPROM.read(129),EEPROM.read(130),EEPROM.read(131),EEPROM.read(132));
+  IPAddress esubnet(EEPROM.read(133),EEPROM.read(134),EEPROM.read(135),EEPROM.read(136));
+  IPAddress egateway(EEPROM.read(137),EEPROM.read(138),EEPROM.read(139),EEPROM.read(140));
+  IPAddress edns(EEPROM.read(141),EEPROM.read(142),EEPROM.read(143),EEPROM.read(144));
+  Serial.print("subnet: ");
+  Serial.println(esubnet);
   WiFi.mode(WIFI_STA);
-  WiFi.config(staticIP, subnet, gateway, dns);
+  WiFi.config(estaticIP, esubnet, egateway, edns);
   int c = 0;
   if ( esid.length() > 1 ) {
         Serial.println("Trying to connect to wifi net..");
@@ -429,6 +441,53 @@
   digitalWrite(AP_LED, LOW);
   digitalWrite(SEARCH_LED, HIGH);
   digitalWrite(LED_BUILTIN, HIGH); //Turn off
+
+  char egIP[16] = "192.168.0.68";
+  char egsubnet[16] = "255.255.255.0";
+  char eggateway[16] = "192.168.0.1";
+  char egdns[16] = "8.8.8.8";
+  char *digits;
+
+  digits = strtok(egIP, ".");
+  int k = 129;
+  while(digits != NULL ) {
+      Serial.println(atoi(digits));
+      EEPROM.write(k,atoi(digits));
+      k++;
+      digits = strtok(NULL, ".");
+   }
+
+  digits = strtok(egsubnet, ".");
+  k = 133;
+  while(digits != NULL ) {
+      Serial.println(atoi(digits));
+      EEPROM.write(k,atoi(digits));
+      k++;
+      digits = strtok(NULL, ".");
+   }
+
+  digits = strtok(eggateway, ".");
+  k = 137;
+  while(digits != NULL ) {
+      Serial.println(atoi(digits));
+      EEPROM.write(k,atoi(digits));
+      k++;
+      digits = strtok(NULL, ".");
+   }
+
+  digits = strtok(egdns, ".");
+  k = 141;
+  while(digits != NULL ) {
+      Serial.println(atoi(digits));
+      EEPROM.write(k,atoi(digits));
+      k++;
+      digits = strtok(NULL, ".");
+   }
+//  for (int i = 129; i < 133; ++i)
+//  {
+//    Serial.println(EEPROM.read(i));
+//  }
+
   WiFi.begin();
   delay(1000);
   Serial.println("");


Added functions to simplify FumeHoodMonitor sketch

--- FumeHoodMonitor/ThingSpeak.ino
+++ FumeHoodMonitor/ThingSpeak.ino
@@ -4,15 +4,36 @@
 unsigned long ThingSpeakChannelID = CHANNELID;
 const char * ThingSpeakWriteAPIKey = WRITEAPIKEY;

-
+DateTime ThingSpeakTimer;
+const unsigned long thingSpeakPostingInterval = 30; // seconds between ThingSpeak posts

 void initializeThingSpeak() {
+  writeLCD("Starting ThingSpeak...");
   Serial.println("Starting ThingSpeak client");
   ThingSpeak.begin(client); // Start the ThingSpeak connection
+  ThingSpeakTimer = getRTCCurrentTime();
 }

 void postToThingSpeak(){
   ThingSpeak.writeFields(ThingSpeakChannelID, ThingSpeakWriteAPIKey);
+}
+
+void postDataToThingSpeak(float airTemp, float oilTemp, String flameStatus){
+  DateTime now = getRTCCurrentTime();
+  unsigned long timeSpan = now.unixtime() - ThingSpeakTimer.unixtime();
+  if (timeSpan >= thingSpeakPostingInterval) {
+    setThingSpeakField(1, airTemp);
+    setThingSpeakField(2,oilTemp);
+    setThingSpeakField(3,flameStatus);
+    setThingSpeakStatus(flameStatus);
+    postToThingSpeak();
+    ThingSpeakTimer = now;
+  }
+}
+
+void postThingSpeakStatus(String status){
+  setThingSpeakStatus(status);
+  postToThingSpeak();
 }

 void setThingSpeakStatus(String status){


Modified Code to add custom Sleep Functions

--- ATTinyRFSerialTest.ino
+++ ATTinyRFSerialTest.ino
@@ -1,22 +1,38 @@
 /*
-                 +-\/-+
-           VCC  1|    |14  GND
-      (D0) PB0  2|    |13  AREF (D10)
-      (D1) PB1  3|    |12  PA1 (D9)
-         RESET  4|    |11  PA2 (D8)
- INT0 (D2) PB2  5|    |10  PA3 (D7)
-  PWM (D3) PA7  6|    |9   PA4 (D6)
-  PWM (D4) PA6  7|    |8   PA5 (D5) PWM
-                 +----+
+       +-\/-+
+ VCC  1|    |14  GND
+ PB0  2|    |13  AREF
+ PB1  3|    |12  PA1
+ RST  4|    |11  PA2
+ PB2  5|    |10  PA3
+ PA7  6|    |9   PA4
+ PA6  7|    |8   PA5
+       +----+
+
+ Watchdog Timer Prescale Select
+
+ WDP3   WDP2 WDP1 WDP0   Number of WDT     Typical Time-out at Oscillator Cycles     VCC = 5.0V
+
+ 0    0    0      0             2K (2048) cycles       16 ms
+ 0    0    0      1             4K (4096) cycles       32 ms
+ 0    0    1      0             8K (8192) cycles       64 ms
+ 0    0    1      1            16K (16384) cycles      0.125 s
+ 0    1    0      0            32K (32768) cycles      0.25 s
+ 0    1    0      1            64K (65536) cycles      0.5 s
+ 0    1    1      0            128K (131072) cycles    1.0 s
+ 0    1    1      1            256K (262144) cycles    2.0 s
+ 1    0    0      0            512K (524288) cycles    4.0 s
+ 1    0    0      1            1024K (1048576) cycles  8.0 s
+
 */

+
+#include <avr/sleep.h>
+#include <avr/power.h>
+#include <avr/wdt.h>
 #include <stdlib.h>
 #include <util/delay.h>
 #include <JeeLib.h> // https://github.com/jcw/jeelib
-
-ISR(WDT_vect) {
-  Sleepy::watchdogEvent();
-} // interrupt handler for JeeLabs Sleepy power saving

 #define myNodeID 8     // RF12 node ID in the range 1-30
 #define network 210      // RF12 Network group
@@ -37,6 +53,7 @@
 //#define DEBUG

 int counter;
+volatile uint8_t watchdog_counter;

 typedef struct {
   int counter;
@@ -52,20 +69,21 @@
 #if defined(DEBUG)
   sinit();
 #endif
+
   rf12_initialize(myNodeID,freq,network); // Initialize RFM12 with settings defined above
   rf12_sleep(0);                          // Put the RFM12 to sleep
-
   PRR = bit(PRTIM1); // only keep timer 0 going
-
   ADCSRA &= ~ bit(ADEN);
   bitSet(PRR, PRADC); // Disable the ADC to save power
+  setup_watchdog(7);

 }

 void loop() {

+  sleep(30);
+
   counter++;
-
   temptx.counter = (counter); // Get temperature reading and convert to integer, reversed at receiving end
   temptx.supplyV = readVcc(); // Get supply voltage
   temptx.tmpC    = readTmpC();
@@ -77,9 +95,45 @@
 #endif

   rfwrite(); // Send data via RF
-
-  Sleepy::loseSomeTime(10000); //JeeLabs power save function: enter low power mode for 10 seconds (valid range 16-65000 ms)
-}
+}
+
+//--------------------------------------------------------------------------------------------------
+// Sleep Configuration
+//-------------------------------------------------------------------------------------------------
+// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
+// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
+void setup_watchdog(int sleepMode) {
+
+  byte sleepByte;
+  if (sleepMode > 9 ) sleepMode=9;
+  sleepByte = sleepMode & 7;
+  if (sleepMode > 7) sleepByte |= (1<<5);
+  sleepByte |= (1<<WDCE);
+
+  MCUSR &= ~(1 << WDRF);                           // reset status flag
+  WDTCSR |= (1 << WDCE) | (1 << WDE);              // enable configuration changes
+  WDTCSR = sleepByte;
+  WDTCSR |= (1 << WDIE);                           // enable interrupt mode
+
+}
+
+void sleep(uint8_t sleepTime) {
+
+  while(watchdog_counter++ < sleepTime) {
+    set_sleep_mode(SLEEP_MODE_PWR_DOWN);             // select the watchdog timer mode
+    sleep_enable();                                  // enable the sleep mode ready for use
+    sleep_mode();                                    // trigger the sleep
+    sleep_disable();                                 // prevent further sleeps
+  }
+  watchdog_counter = 0;
+
+}
+
+ISR(WDT_vect) {
+  watchdog_counter++;
+}
+
+

 // Wait a few milliseconds for proper ACK
 #ifdef USE_ACK
@@ -111,8 +165,7 @@
     if (acked) {
       return;
     }      // Return if ACK received
-
-    Sleepy::loseSomeTime(RETRY_PERIOD * 1000);     // If no ack received wait and try again
+    sleep(30);
   }
 #else
   rf12_sleep(-1);              // Wake up RF module
@@ -202,3 +255,10 @@

 #endif
 // Serial Functions End
+
+
+
+
+
+
+


Fix id code

Fix id code

Signed-off-by: Mark Knoop <f1b5a91d4d6ad523f2610114591c007e75d15084@markknoop.com>

--- src/sketch.ino
+++ src/sketch.ino
@@ -9,8 +9,8 @@
 #define alarmPin        3
 #define sensorPin      11
 #define ledPin         13
-#define idmsbPin       18
-#define idlsbPin       19
+#define idmsbPin       A0
+#define idlsbPin       A1

 // speeds
 #define pulseWidth      5 // microseconds
@@ -111,7 +111,7 @@
 }

 void defaults() {
-    id = digitalRead(idmsbPin) << digitalRead(idlsbPin);
+    id = (digitalRead(idmsbPin) * 2) + digitalRead(idlsbPin);
     halfTurns = 1;
     Duration = 500;
     midDuration = 500;


Adjust naming and logging in advance of supporting multiple consoles

--- teensy/teensy.ino
+++ teensy/teensy.ino
@@ -143,9 +143,8 @@
   return totalWritten;
 }

-static FatFile m64File;
-static bool m64OpenSuccess = false;
-static bool openM64(const String& path);
+static FatFile tasFile;
+static bool openTAS(const String& path);

 //static unsigned int progressPos = 0;
 static unsigned long numFrames = 0, curFrame = 0;
@@ -164,11 +163,11 @@
     return;
   }
   dir.rewind();
-  while (m64File.openNext(&dir)) {
+  while (tasFile.openNext(&dir)) {
     char name[256];
-    m64File.getName(name, sizeof(name));
+    tasFile.getName(name, sizeof(name));
     lockedPrintln("A:", name);
-    m64File.close();
+    tasFile.close();
   }
   dir.close();
 }
@@ -196,7 +195,6 @@

   // Initialize SD card
   if (!sd.begin()) {
-    m64OpenSuccess = false;
     Serial.println(F("E:SD initialization failed!"));
     return;
   }
@@ -208,19 +206,14 @@
   Serial.println(F("L:Initialization done."));
 }

-void logFrame()
-{
-  const unsigned char *dat = (const unsigned char*)(inputBuffer + bufferPos);
+void logFrame(const unsigned char *dat, size_t count, size_t num)
+{
   Serial.write("F:");
-  Serial.print(curFrame);
-  Serial.write(" ");
-  Serial.print(dat[0], HEX);
-  Serial.write(" ");
-  Serial.print(dat[1], HEX);
-  Serial.write(" ");
-  Serial.print(dat[2], HEX);
-  Serial.write(" ");
-  Serial.println(dat[3], HEX);
+  Serial.print(num);
+  for (size_t i = 0; i < count; i++) {
+    Serial.write(" ");
+    Serial.print(dat[i], HEX);
+  }
 }

 static bool setPinMode(const String& cmd)
@@ -302,7 +295,7 @@
 static void handleCommand(const String& cmd)
 {
   if (cmd.startsWith("M:")) {
-    openM64(cmd.substring(2));
+    openTAS(cmd.substring(2));
   } else if (cmd.startsWith("O:")) {
     //dummy
   } else if (cmd.startsWith("L:")) {
@@ -439,12 +432,12 @@
             // blast out the pre-assembled array in output_buffer
             n64_send(output_buffer, 4, 1);

+            logFrame(output_buffer, 4, curFrame + 1);
+
             if (!haveFrame)
               break;

             curFrame++;
-
-            logFrame();

             // update input buffer and make sure it doesn't take too long

@@ -574,7 +567,7 @@
     mainLoop();
 }

-static bool openM64(const String& path) {
+static bool openTAS(const String& path) {
     char signature[4];
     int version;

@@ -588,18 +581,18 @@

     Serial.flush();

-    if (m64File.isOpen())
-      m64File.close();
+    if (tasFile.isOpen())
+      tasFile.close();

     // Error check
-    if (!m64File.open(&sd, path.c_str(), O_READ)) {
+    if (!tasFile.open(&sd, path.c_str(), O_READ)) {
         Serial.println(F("E:Error in opening file"));
         return false;
     }

     // Open header
-    if (m64File.read(signature, 4) != 4 || m64File.read(&version, 4) != 4) {
-        m64File.close();
+    if (tasFile.read(signature, 4) != 4 || tasFile.read(&version, 4) != 4) {
+        tasFile.close();
         Serial.println(F("E:Failed to read signature"));
         return false;
     }
@@ -607,7 +600,7 @@
     // Validate file signature
     if (memcmp(signature, "M64\x1A", 4) != 0) {
         Serial.println(F("E:m64 signature invalid"));
-        m64File.close();
+        tasFile.close();
         return false;
     }

@@ -617,12 +610,12 @@

     Serial.flush();

-    m64File.seekSet(0x018);
+    tasFile.seekSet(0x018);

     // Open header
     uint32_t newNumFrames;
-    if (m64File.read(&newNumFrames, 4) != 4) {
-        m64File.close();
+    if (tasFile.read(&newNumFrames, 4) != 4) {
+        tasFile.close();
         Serial.println(F("E:Failed to read frame count"));
         return false;
     }
@@ -631,26 +624,26 @@
     switch(version) {
         case 1:
         case 2:
-            m64File.seekSet(0x200);
+            tasFile.seekSet(0x200);
             break;
         case 3:
-            m64File.seekSet(0x400);
+            tasFile.seekSet(0x400);
             break;
         default:
           // Unknown version
             Serial.println(F("E:unknown M64 version"));
-            m64File.close();
+            tasFile.close();
             return false;
     }

     // Final check
-    if (!m64File.available()) {
+    if (!tasFile.available()) {
         Serial.println(F("E:No input data found in file"));
-        m64File.close();
+        tasFile.close();
         return false;
     }

-    newNumFrames = min(newNumFrames, (m64File.fileSize() - m64File.curPosition()) / 4);
+    newNumFrames = min(newNumFrames, (tasFile.fileSize() - tasFile.curPosition()) / 4);

     Serial.write("N:");
     Serial.println(newNumFrames);
@@ -665,7 +658,6 @@
     }*/

     noInterrupts();
-    m64OpenSuccess = true;
     finished = false;
     initBuffers();
     curFrame = 0;
@@ -676,12 +668,12 @@
 }

 static void updateInputBuffer() {
-    if (finished || !m64File.isOpen())
+    if (finished || !tasFile.isOpen())
       return;

     // Check for file end
-    if (!m64File.available()) {
-        m64File.close();
+    if (!tasFile.available()) {
+        tasFile.close();
         return;
     }

@@ -692,7 +684,7 @@
     if ((availableSize < 512 && (writePos % 512) == 0) || !availableSize)
         return;

-    int readBytes = m64File.read(inputBuffer + writePos, availableSize);
+    int readBytes = tasFile.read(inputBuffer + writePos, availableSize);
     if (readBytes <= 0) {
       lockedPrintln(F("W:Failed to read next inputs from file. (This is recoverable)"));
       return;


Log FFat errors as errors instead of info messages.

Better string compare code.

--- aquacontrol32.ino
+++ aquacontrol32.ino
@@ -287,7 +287,7 @@
     tftBrightness = preferences.getFloat( "tftbrightness", tftBrightness );
     ledcWrite( TFT_BACKLIGHT_CHANNEL, map( tftBrightness, 0, 100, 0, TFT_BACKLIGHT_MAXPWM ) );

-    ( preferences.getString( "tftorientation", "normal" ) == "normal" ) ? tftOrientation = TFT_ORIENTATION_NORMAL : tftOrientation = TFT_ORIENTATION_UPSIDEDOWN;
+    ( preferences.getString( "tftorientation", "normal" ).equals( "normal" ) ) ? tftOrientation = TFT_ORIENTATION_NORMAL : tftOrientation = TFT_ORIENTATION_UPSIDEDOWN;
     tft.setRotation( tftOrientation );

     touch.begin();
@@ -312,7 +312,7 @@
   else {
     OLED.init();
     ESP_LOGI( TAG, "Found SSD1306 OLED on I2C at address 0x%x.", OLED_ADDRESS );
-    if ( preferences.getString( "oledorientation", "normal" ) == "upsidedown" ) {
+    if ( preferences.getString( "oledorientation", "normal" ).equals( "upsidedown" ) ) {
       oledOrientation = OLED_ORIENTATION_UPSIDEDOWN;
       OLED.flipScreenVertically();
     }
@@ -335,7 +335,7 @@

   /* check if a ffat partition is defined and halt the system if it is not defined*/
   if (!esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "ffat")) {
-    ESP_LOGI( TAG, "No FFat partition defined. Halting.\nCheck 'Tools>Partition Scheme' in the Arduino IDE and select a FFat partition." );
+    ESP_LOGE( TAG, "No FFat partition defined. Halting.\nCheck 'Tools>Partition Scheme' in the Arduino IDE and select a FFat partition." );
     const char * noffatStr = "No FFat found...";
     if ( xTftTaskHandle ) {
       tft.println( noffatStr );
@@ -363,7 +363,7 @@
     }
     ESP_LOGI( TAG, "%s", formatStr );
     if (!FFat.format( true, (char*)"ffat" ) || !FFat.begin()) {
-      ESP_LOGI( TAG, "FFat error while formatting. Halting." );
+      ESP_LOGE( TAG, "FFat error while formatting. Halting." );
       const char * errorffatStr = "FFat error.";
       if ( xTftTaskHandle ) {
         tft.println( errorffatStr );


Refactored reset_reason().

Refactored reset_reason().

--- loggertask.ino
+++ loggertask.ino
@@ -133,25 +133,27 @@
   return true;
 }

+const char * resetStr[] =
+{
+  "NO_MEAN",
+  "POWERON_RESET",
+  "SW_RESET",
+  "OWDT_RESET",
+  "DEEPSLEEP_RESET",
+  "SDIO_RESET",
+  "TG0WDT_SYS_RESET",
+  "TG1WDT_SYS_RESET",
+  "RTCWDT_SYS_RESET",
+  "INTRUSION_RESET",
+  "TGWDT_CPU_RESET",
+  "SW_CPU_RESET",
+  "RTCWDT_CPU_RESET",
+  "EXT_CPU_RESET",
+  "RTCWDT_BROWN_OUT_RESET",
+  "RTCWDT_RTC_RESET"
+};
+
 static inline __attribute__((always_inline)) const char * reset_reason( const RESET_REASON reason )
 {
-  switch ( reason)
-  {
-    case 1 : return PSTR("POWERON_RESET"); break;         /**<1, Vbat power on reset*/
-    case 3 : return PSTR("SW_RESET"); break;              /**<3, Software reset digital core*/
-    case 4 : return PSTR("OWDT_RESET"); break;            /**<4, Legacy watch dog reset digital core*/
-    case 5 : return PSTR("DEEPSLEEP_RESET"); break;       /**<5, Deep Sleep reset digital core*/
-    case 6 : return PSTR("SDIO_RESET"); break;            /**<6, Reset by SLC module, reset digital core*/
-    case 7 : return PSTR("TG0WDT_SYS_RESET"); break;      /**<7, Timer Group0 Watch dog reset digital core*/
-    case 8 : return PSTR("TG1WDT_SYS_RESET"); break;      /**<8, Timer Group1 Watch dog reset digital core*/
-    case 9 : return PSTR("RTCWDT_SYS_RESET"); break;      /**<9, RTC Watch dog Reset digital core*/
-    case 10 : return PSTR("INTRUSION_RESET"); break;      /**<10, Instrusion tested to reset CPU*/
-    case 11 : return PSTR("TGWDT_CPU_RESET"); break;      /**<11, Time Group reset CPU*/
-    case 12 : return PSTR("SW_CPU_RESET"); break;         /**<12, Software reset CPU*/
-    case 13 : return PSTR("RTCWDT_CPU_RESET"); break;     /**<13, RTC Watch dog Reset CPU*/
-    case 14 : return PSTR("EXT_CPU_RESET"); break;        /**<14, for APP CPU, reseted by PRO CPU*/
-    case 15 : return PSTR("RTCWDT_BROWN_OUT_RESET"); break; /**<15, Reset when the vdd voltage is not stable*/
-    case 16 : return PSTR("RTCWDT_RTC_RESET"); break;     /**<16, RTC Watch dog reset digital core and rtc module*/
-    default : return PSTR("NO_MEAN");
-  }
+  return resetStr[reason];
 }


Update particle_photon_to_ir.ino

Update particle_photon_to_ir.ino

--- Infrared/particle_photon_to_ir.ino
+++ Infrared/particle_photon_to_ir.ino
@@ -1,3 +1,27 @@
+/*
+
+ CheerLights IR Controller
+
+ CheerLights API -> Particle Photon -> IR Transmitter
+
+ This sketch gets the latest CheerLights color from ThingSpeak and
+ transmits the color code over infrared to control IR lights.
+
+ Parts:
+   * SleepyLights Robot (http://amzn.to/2l8FCjM)
+   * Particle Photon (http://amzn.to/2lTvsRe)
+   * IR LED
+   * 330Ω resistor
+   * Breadboard
+
+ Tutorial: http://nurseryhacks.com/nursery-robot-connected-cheerlights
+
+ Created: Feb 28, 2017 by Hans Scharler - http://nothans.com
+
+ To join the CheerLights project, visit http://www.cheerlights.com
+
+*/
+
 // This #include statement was automatically added by the Particle IDE.
 #include <ThingSpeak.h>


Update breakbeatsaw8.ino

Update breakbeatsaw8.ino

Corrected publish date.  (It's 2021 now!)

--- breakbeatsaw8.ino
+++ breakbeatsaw8.ino
@@ -14,7 +14,7 @@
 If no delay value is added on the end then the delay will be 0.

-Marc Miller, Feb 2020
+Marc Miller, Feb 2021
 ****************************************************************/

 #define USE_GET_MILLISECOND_TIMER 1  // needed for breakbeatsaw8


Clean up.

Clean up.

--- examples/LCD/CosaLCDclock/CosaLCDclock.ino
+++ examples/LCD/CosaLCDclock/CosaLCDclock.ino
@@ -33,10 +33,10 @@
 // HD44780::SR3W port;
 // HD44780::SR3WSPI port;
 // HD44780::SR4W port;
-// HD44780::ERM1602_5 port;
 // HD44780::MJKDZ port;
 // HD44780::GYIICLCD port;
 HD44780::DFRobot port;
+// HD44780::ERM1602_5 port;

 #if defined(__ARDUINO_MEGA__)
 #include "Cosa/TWI/Driver/ADXL345.hh"
@@ -70,12 +70,12 @@
 #ifdef RTC_SET_TIME
   time_t now;
   now.seconds = 0x00;
-  now.minutes = 0x50;
-  now.hours = 0x20;
+  now.minutes = 0x08;
+  now.hours = 0x00;
   now.day = 0x01;
-  now.date = 0x21;
-  now.month = 0x07;
-  now.year = 0x13;
+  now.date = 0x24;
+  now.month = 0x03;
+  now.year = 0x14;
   rtc.set_time(now);
 #endif


Changed to use DEG_TO_RAD

Changed to use DEG_TO_RAD

--- examples/LcdColumnGraph/LcdColumnGraph.ino
+++ examples/LcdColumnGraph/LcdColumnGraph.ino
@@ -29,7 +29,7 @@
     {
         int32_t phase = col * 24;
         lcdColumnGraph.setColumn(col);
-        lcdColumnGraph.value(int(8.0 * sin((angle+phase) * 3.141592654 / 180.0)));
+        lcdColumnGraph.value(int(8.0 * sin((angle+phase) * DEG_TO_RAD)));
     }
     angle = (angle + 5) % 360;
     delay(30);


code cleanups

code cleanups

--- thsens/thsens.ino
+++ thsens/thsens.ino
@@ -132,18 +132,6 @@
 #endif
 }

-
-// EuroChron / Tchibo
-//                /--------------------------- Channel, changes after every battery change
-//               /        / ------------------ Battery state 0 == Ok
-//              /        / /------------------ unknown
-//             /        / /  / --------------- forced send
-//            /        / /  /  / ------------- unknown
-//           /        / /  /  /     / -------- Humidity
-//          /        / /  /  /     /       / - neg Temp: if 1 then temp = temp - 2048
-//         /        / /  /  /     /       /  / Temp
-//         01100010 1 00 1  00000 0100011 0  00011011101
-// Bit     0        8 9  11 12    17      24 25        36
 static String generateEnvMessage(uint8_t deviceId, uint8_t channel, bool battOk, bool manualSend, uint8_t trend, float temperature, float humidity) {
   String message = "";
   // ID Part 1
@@ -180,10 +168,6 @@
 char txBuf[37];

 /*
-
- Bit-Stream: 1000 10 10 0 01 1 101111110000 11100011 1000
- IIII CC II B TT F tttttttttttt hhhhhhhh cccc
-
  I  Device Id
  C  Channel
  B  Battery low
@@ -193,7 +177,6 @@
  h  humidity
  c  checksum
  */
-
 static void sendEnv() {
   float temperature = dht.readTemperature();
   float humidity = dht.readHumidity();


Testing RFID integration

Testing RFID integration

--- module/module.ino
+++ module/module.ino
@@ -174,6 +174,9 @@
 			if (pollCounter == pollTimeout) {
 				soundFeedback(reject);
 				Serial.print(messages.cancel);
+				while(1) {
+					Serial.println(endTime);
+				}
 				return endTime;
 			}
 		}
@@ -218,7 +221,10 @@
 					// calculate elapsed time and push to ThingSpeak log
 					sendCount = (millis() - startTime)/1000;
 					Serial.print("Sending... Time: ");
-					Serial.println(sendCount);
+					while (1) {
+						Serial.println(sendCount);
+					}
+					//Serial.println(sendCount);
 					// Make sure logs are properly spaced out
 					if ( (millis() - lastSend) < sendInterval) {
 						delay(sendInterval);


fixed syntax errors

fixed syntax errors

--- module/module.ino
+++ module/module.ino
@@ -17,7 +17,7 @@
 char txrxbuffer[bufferSize];

 const int ledPin = 13;
-const int signalPin = 4
+const int signalPin = 4;
 const int debounce = 25;

 void setup() {
@@ -54,7 +54,7 @@
 		BCC = BCC ^ A[i];
 	}

-	return BCC
+	return BCC;
 }

 void MF_SNR(unsigned char DADD) {
@@ -85,15 +85,16 @@
 	int i = 0;
 	unsigned char timeByte0 = time & MSB;
 	unsigned char timeByte1 = (time >> 4) & MSB;
-	unsigned char timeByte2 = (time >> 8) & MSB:
+	unsigned char timeByte2 = (time >> 8) & MSB;
 	unsigned char timeByte3 = (time >> 12) & MSB;

 	unsigned char A[] = { 0x00, 0x1A, CMD_WRITE, 0x01, numBlocks, startAddress,
 						0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-						0xDD, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+						0xDD, 0xA1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
 						timeByte3, timeByte2, timeByte1, timeByte0 };
 	unsigned char BCC = checksum( A, sizeof(A)/sizeof(A[0]) );
 	unsigned char CMD[31];
+	unsigned char response[bufferSize];

 	CMD[0] = STX;
 	memcpy( CMD + 1, A, sizeof(A)/sizeof(A[0]) );


add pre-exploration

add pre-exploration


Delete sensorflare-relayboard.ino

Delete sensorflare-relayboard.ino

--- sensorflare-relayboard.ino
+++ sensorflare-relayboard.ino
@@ -1,25 +0,0 @@
-//Include the SensorFlare library
-#include "sensorflare.h"
-
-//Initialize objects from the library
-//One object of the class "DigitalOut" is initialized for
-//every digital output that will be remote control
-SensorFlare::DigitalOut outputPin1(D0);
-SensorFlare::DigitalOut outputPin2(D1);
-SensorFlare::DigitalOut outputPin3(D2);
-SensorFlare::DigitalOut outputPin4(D3);
-
-void setup() {
-
-// Call the begin() functions for every object of the classes "DigitalOut" and
-//"PWMout" to be wired up correct and available.
-    outputPin1.begin();
-    outputPin2.begin();
-    outputPin3.begin();
-    outputPin4.begin();
-
-}
-
-void loop() {
-
-}


git-svn-id: svn://192.168.1.10/public/Zimodem@14605 0d6f1817-ed0e-0410-87c9-987e46238f29

--- zimodem/zstream.ino
+++ zimodem/zstream.ino
@@ -68,6 +68,35 @@

 void ZStream::loop()
 {
+  WiFiServerNode *serv = servs;
+  while(serv != null)
+  {
+    WiFiClient newClient = serv->server->available();
+    if((newClient != null)&&(newClient.connected()))
+    {
+      int port=newClient.localPort();
+      String remoteIPStr = newClient.remoteIP().toString();
+      const char *remoteIP=remoteIPStr.c_str();
+      bool found=false;
+      WiFiClientNode *c=conns;
+      while(c!=null)
+      {
+        if((c->isConnected())
+        &&(c->port==port)
+        &&(strcmp(remoteIP,c->host)==0))
+          found=true;
+        c=c->next;
+      }
+      if(!found)
+      {
+        newClient.write("BUSY\r\n7\r\n");
+        newClient.flush();
+        newClient.stop();
+      }
+    }
+    serv=serv->next;
+  }
+
   if((current==null)||(!current->isConnected()))
   {
     if(!commandMode.suppressResponses)
@@ -117,7 +146,7 @@
   &&(current->client->available()>0))
   {
     int maxBytes=commandMode.packetSize; // watchdog'll get you if you're in here too long
-    while((current->client->available()>0)&&(--maxBytes > 0))
+    while(current->isConnected() && (current->client->available()>0)&&(--maxBytes > 0))
     {
       uint8_t c=current->client->read();
       if(telnet)