Adding graphical hint to CosaWIO demo; show analog value as a bar.

--- examples/Wireless/CosaWIO/CosaWIO.ino
+++ examples/Wireless/CosaWIO/CosaWIO.ino
@@ -58,40 +58,45 @@
   Watchdog::begin();
   RTC::begin();
   rf.begin();
-  trace << PSTR("\fWIO: connected");
-  wio.flush();
+  trace << PSTR("\fWIO: connected") << flush;
   SLEEP(2);
+}
+
+void bar(uint16_t value, uint8_t pos, uint16_t max)
+{
+  uint16_t div = (value * pos) / max;
+  uint16_t rem = ((value * pos) % max) * 4 / max;
+  for (uint8_t i = 0; i < div; i++) trace << (char) 4;
+  if (rem != 0) trace << (char) (rem - 1);
 }

 void loop()
 {
   // Print analog pins
-  for (uint8_t pin = 0; pin < 8;) {
-    trace << clear;
-    trace << 'A' << pin << PSTR(": ");
-    trace << AnalogPin::sample(pin++) << endl;
-    trace << 'A' << pin << PSTR(": ");
-    trace << AnalogPin::sample(pin++);
-    wio.flush();
-    SLEEP(2);
+  for (uint8_t pin = 0; pin < 8; pin++) {
+    uint16_t sample = AnalogPin::sample(pin);
+    trace << clear << 'A' << pin << PSTR(": ") << sample << endl;
+    bar(sample, 16, 1023);
+    trace << flush;
+    SLEEP(1);
   }

   // Print bandgap voltage
-  trace << clear;
-  trace << PSTR("VCC: ") << AnalogPin::bandgap() << PSTR(" mV");
-  wio.flush();
+  uint16_t vcc = AnalogPin::bandgap();
+  trace << clear << PSTR("VCC: ") << vcc << PSTR(" mV") << endl;
+  bar(vcc, 16, 5500);
+  trace << flush;
   SLEEP(2);

   // Print digital pins
-  trace << clear;
-  trace << PSTR("D0-7:  ");
+  trace << clear << PSTR("D0-7:  ");
   for (uint8_t pin = 0; pin < 8; pin++)
     trace << InputPin::read(pin);
   trace << endl;
   trace << PSTR("D8-16: ");
   for (uint8_t pin = 8; pin < 16; pin++)
     trace << InputPin::read(pin);
-  wio.flush();
+  trace << flush;
   SLEEP(2);

   // Print statistics
@@ -100,7 +105,7 @@
   trace << PSTR("TN: ") << rf.get_trans() << endl;
   trace << PSTR("ER: ") << rf.get_retrans();
   trace << PSTR(",") << rf.get_drops();
-  wio.flush();
+  trace << flush;
   SLEEP(2);
 #endif
 }


fix temperature, should be targetting 150

--- Thermostat/Thermostat.ino
+++ Thermostat/Thermostat.ino
@@ -16,8 +16,8 @@
 const byte temperatureSensorPin = 8;

 // keep the temperature between these values
-const int lowTemp = 138;
-const int highTemp = 142;
+const int lowTemp = 148;
+const int highTemp = 152;

 volatile float temperatureInF;


Update DumpInfo.ino

Update DumpInfo.ino

Added pin layouts for ATMEGA32U4-based Arduinos in comment; code unchanged


Longer delay to warm up the machine

Longer delay to warm up the machine

--- arduino.ino
+++ arduino.ino
@@ -43,7 +43,7 @@
     digitalWrite(PIN_POWER, LOW);
     delay(PUSH_BTN_DELAY);
     digitalWrite(PIN_POWER, HIGH);
-    delay(10000);
+    delay(40000);
     if(is_short_ordered) {
       Serial.println("Start a short coffee");
       digitalWrite(PIN_MAKE_SHORT, LOW);
@@ -57,6 +57,9 @@
     }
     Serial.println("Wait for the coffee to be ready");
     delay(30000);
+    Serial.println("Shut down");
+    digitalWrite(PIN_POWER, LOW);
+    delay(PUSH_BTN_DELAY);
+    digitalWrite(PIN_POWER, HIGH);
   }
 }
-


Copy strings into songs array

Copy strings into songs array

--- ableton-midi-foot-controller.ino
+++ ableton-midi-foot-controller.ino
@@ -16,6 +16,8 @@

 #define SYSEX_BUFFER_SIZE 100
 char sysexBuffer[SYSEX_BUFFER_SIZE];
+
+#define MAX_ROW_LENGTH 16

 // LEDs
 const byte ledPin = 13;
@@ -101,7 +103,7 @@
 const byte SONG_OFFSET = 10;

 const byte numberOfSongs = 30;
-char* songs[numberOfSongs];
+char songs[numberOfSongs][MAX_ROW_LENGTH + 1];

 const byte CONTROL_OFFSET = SONG_OFFSET + numberOfSongs + 1;

@@ -189,6 +191,7 @@
   if (mode != SONG_MODE) {
     return;
   }
+  sysexBuffer[0] = (char)0;

   strcpy(sysexBuffer, messageOriginal);
   char* strings;
@@ -258,6 +261,7 @@
 }

 void handleSongConfiguration(char* messageOriginal) {
+  sysexBuffer[0] = (char)0;
   strcpy(sysexBuffer, messageOriginal);
   char* strings;
   strings = strtok(sysexBuffer, "|");
@@ -279,7 +283,13 @@
   Serial.println(strings);
 #endif

-  songs[index] = strings;
+  strncpy(songs[index], strings, MAX_ROW_LENGTH);
+  byte lengthOfName = strlen(strings);
+  if (lengthOfName < MAX_ROW_LENGTH) {
+    songs[index][lengthOfName] = (char)0;
+  } else {
+    songs[index][MAX_ROW_LENGTH] = (char)0;
+  }
 }

 byte getConfigurationType(char* messageOriginal) {


Use 2-9 to set the speed for one full rotation

--- sketch_drive_rod.ino
+++ sketch_drive_rod.ino
@@ -1,27 +1,64 @@
 #include <SoftwareSerial.h>
-#include <comm.h>
 #include <Arduino.h>

-const int x_step = 2;
-const int x_dir = 5;
-const int disable = 8;
+const int X_STEP_PIN = 2;
+const int X_DIR_PIN = 5;
+const int DISABLE_PIN = 8;

-//const int steps_per_rotation = 200 * 4;
-const int steps_per_rotation = 40;
+/*
+  With all 3 jumpers in the driver is configured to run at 1/16 microstepping
+*/
+const int STEPS_PER_ROTATION = 200 * 16;

-int hold_high = 300;
-int hold_low = 700;
-int t;
+int step_time = 500;
+int is_active;

 void setup() {
-  pinMode(x_step, OUTPUT);
-  pinMode(x_dir, OUTPUT);
-  pinMode(disable, OUTPUT);
+  pinMode(X_STEP_PIN, OUTPUT);
+  pinMode(X_DIR_PIN, OUTPUT);
+  pinMode(DISABLE_PIN, OUTPUT);
   Serial.begin(57600);
   Serial.println("RoboFoos Ready!");
-  //send: 07766544444517654444460776654444451765444444670776654444451765444446077665444445176544444467
-  //digitalWrite(x_dir, HIGH);
-  t = 0;
+  digitalWrite(X_DIR_PIN, HIGH);
+  is_active = 0;
+}
+
+void go(int steps, int dir) {
+  if(dir <= 0) {
+    digitalWrite(X_DIR_PIN, LOW);
+  } else {
+    digitalWrite(X_DIR_PIN, HIGH);
+  }
+
+  for (int i = 0; i < steps; i++){
+    int hold_time = step_time;
+    if(i==0 || i == steps-1){
+      hold_time = 800;
+    } else if (i == 1 || i == steps-2) {
+      hold_time = 750;
+    } else if (i == 2 || i == steps-3) {
+      hold_time = 600;
+    } else if (i == 3 || i == steps-4) {
+      hold_time = 500;
+    } else if (i == 4 || i == steps-5) {
+      hold_time = 400;
+    } else if (i == 5 || i == steps-6) {
+      hold_time = 300;
+    } else if (i == 6 || i == steps-7) {
+      hold_time = 200;
+    } else if (i == 7 || i == steps-8) {
+      hold_time = 100;
+    } else if (i == 8 || i == steps-9) {
+      hold_time = 70;
+    } else if (i == 9 || i == steps-10) {
+      hold_time = 50;
+    }
+    digitalWrite(X_STEP_PIN, HIGH);
+    delayMicroseconds(20);
+    digitalWrite(X_STEP_PIN, LOW);
+    delayMicroseconds((hold_time)-20);
+  }
+  //digitalWrite(DISABLE_PIN, HIGH);
 }

 void loop() {
@@ -31,34 +68,22 @@
     Serial.print("N is ");
     Serial.println(n);
     if(n == 0) {
-      digitalWrite(x_dir, HIGH);
-    } else if(n==1){
-      digitalWrite(x_dir, LOW);
-    } else if(n==2){
-      delay(1000);
-    } else if(3 < n && n <= 9) {
-      //hold_high = n * 100;
-      hold_low = n * 100;
-      t+=1;
+      is_active = 0;
+    }
+    else if(1 < n && n <= 9) {
+      step_time = n * 30;
+      is_active = 1;
     }
     Serial.print("Running with ");
-    Serial.println(hold_low);
+    Serial.println(step_time);
   }
-  if(t > 0) {
-
-    digitalWrite(disable, LOW);
-    //digitalWrite(x_dir, HIGH);
-
-    for (int i = 0; i < steps_per_rotation; i++){
-      digitalWrite(x_step, HIGH);
-      delayMicroseconds(hold_high);
-      digitalWrite(x_step, LOW);
-      delayMicroseconds(hold_low);
-    }
-    //digitalWrite(disable, HIGH);
-
-    t -= 1;
+  if(is_active > 0) {
+    digitalWrite(DISABLE_PIN, LOW);
+      go(STEPS_PER_ROTATION, 0);
+      go(STEPS_PER_ROTATION, 1);
+    digitalWrite(DISABLE_PIN, HIGH);
   } else {
-    digitalWrite(disable, HIGH);
+    digitalWrite(DISABLE_PIN, HIGH);
   }
 }
+


Gestion reconnexions Cloud

Gestion reconnexions Cloud

Redéclaration des variables cloud exposées en cas de perte de connexion
au cloud.

--- Logiciel/remora/remora.ino
+++ Logiciel/remora/remora.ino
@@ -19,6 +19,51 @@
 // ==================
 // status global de l'application
 uint16_t status = 0;
+
+// Nombre de deconexion cloud detectée
+int cloud_disconnect = 0;
+
+/* ======================================================================
+Function: spark_expose_cloud
+Purpose : declare et expose les variables et fonctions cloud
+Input   :
+Output  : -
+Comments: -
+====================================================================== */
+void spark_expose_cloud(void)
+{
+  Serial.println("spark_expose_cloud()");
+
+  #ifdef MOD_TELEINFO
+    // Déclaration des variables "cloud" pour la téléinfo
+    // je ne sais pas si les fonction cloud sont persistentes
+    // c'est à dire en cas de deconnexion/reconnexion du wifi
+    // si elles sont perdues ou pas, à tester
+    Spark.variable("papp", &mypApp, INT);
+    Spark.variable("iinst", &myiInst, INT);
+    Spark.variable("isousc", &myisousc, INT);
+    Spark.variable("indexhc", &myindexHC, INT);
+    Spark.variable("indexhp", &myindexHP, INT);
+    Spark.variable("periode", &myPeriode, STRING); // Période tarifaire en cours (string)
+    Spark.variable("iperiode", (ptec_e *)&ptec, INT); // Période tarifaire en cours (numerique)
+  #endif
+
+  // Déclaration des fonction "cloud"
+  Spark.function("fp",    fp);
+  Spark.function("setfp", setfp);
+  Spark.function("relais",relais);
+
+  // Déclaration des variables "cloud"
+  Spark.variable("nbdelest", &nbDelestage, INT);
+  Spark.variable("disconnect", &cloud_disconnect, INT);
+  Spark.variable("etatfp", &etatFP, STRING);
+
+  // relais pas disponible sur les carte 1.0
+  #ifndef REMORA_BOARD_V10
+    Spark.variable("etatrelais", &etatrelais, INT);
+  #endif
+}
+

 /* ======================================================================
 Function: setup
@@ -131,18 +176,8 @@
   // Hors gel, désactivation des fils pilotes
   delestage();

-  // Déclaration des fonction "cloud"
-  Spark.function("fp", fpControl);
-  Spark.function("setfp", setFP);
-  Spark.function("relais", relais);
-
-  // Déclaration des variables "cloud"
-  Spark.variable("nbdelest", &nbDelestage, INT);
-  Spark.variable("etatfp", &etatFP, STRING);
-  // relais pas disponible sur les carte 1.0
-  #ifndef REMORA_BOARD_V10
-    Spark.variable("etatrelais", &etatrelais, INT);
-  #endif
+  // Rendre à dispo nos API
+  spark_expose_cloud();

   // On etteint la LED embarqué du core
   RGB.color( 0, 0, 0);
@@ -161,6 +196,8 @@
 {
   static bool refreshDisplay   = false;
   static uint8_t lastsec = Time.second();
+  static bool lastcloudstate = Spark.connected();
+  bool currentcloudstate ;

   // Par defaut on rafraichit à minima toutes les secondes
   if (Time.second() != lastsec )
@@ -193,6 +230,27 @@
   // çà c'est fait
   refreshDisplay = false;

-  // on laisse un peu de temps au système
-  delay(20);
+  // recupération de l'état de connexion au cloud spark
+  currentcloudstate = Spark.connected();
+
+  // La connexion cloud vient de chager d'état ?
+  if (lastcloudstate != currentcloudstate)
+  {
+    // Mise à jour de l'état
+    lastcloudstate=currentcloudstate;
+
+    // on vient de se reconnecter ?
+    if (currentcloudstate)
+    {
+      // on pubie à nouveau nos affaires et led verte
+      spark_expose_cloud();
+      RGB.color( 0, 255, 0);
+    }
+    else
+    {
+      // on compte la deconnexion led rouge
+      cloud_disconnect++;
+      RGB.color( 255, 0, 0);
+    }
+  }
 }


Added some comments.

Added some comments.

--- Drones/Drones.ino
+++ Drones/Drones.ino
@@ -131,10 +131,10 @@
     Serial.println(gpsSerial.read());
     Serial.println("Waiting for buffer to be filled");*/

-  gpsbuffer = dynamic_array_serial(gpsSerial, MAX_BUFFER_SIZE , '$', '*');
+  gpsbuffer = dynamic_array_serial(gpsSerial, MAX_BUFFER_SIZE , '$', '*');//TTry to read data from gpsSerial
   //Serial.println("Succeed in loading buffer with data");
   //Serial.println(array_length);
-  for (int i; i < array_length - 1; i++) {
+  for (int i; i < array_length - 1; i++) {//Print all data in gpsbuffer
     Serial.print(gpsbuffer[i]);
   }
   Serial.println();
@@ -143,7 +143,7 @@
   //if(gpstime== NULL) Serial.println("NULL");
   //Serial.println();
   array_length = 1;
-  free(gpsbuffer);
+  free(gpsbuffer);//Free memory that given to temp containter
   delay(1000);//Waiting for bytes to fill IO buffer
 }
 char* dynamic_array_serial(SoftwareSerial src, int max_length, char start_char, char terminator) {
@@ -180,9 +180,9 @@
             //Serial.println("End listening");
             //Serial.println(result[0]);
             if(string_pattern_checker(result,GPS_START_PATTERN)){
-            return result;
-          }
-          else return NULL;
+              return result;
+            }
+            else return NULL;//Not the data we want? Return NULL!
           }
           else {
             result[i] = max_array[i];
@@ -194,7 +194,7 @@
       }
     }
   }
-  else return NULL;
+  else return NULL;//Src has no data waiting to read? Return NULL!
 }

 boolean string_pattern_checker(char* string, char* pattern){
@@ -211,14 +211,14 @@
   while(src[counter]!=start_char) counter++;//Wait until find the start_char
   counter++;//Can remove this line by using advanced approach?
   if(src[counter]==NULL) return NULL;//Counldn't find the start_char? Return NULL!
-  while(src[counter]!=terminator){
+  while(src[counter]!=terminator){//Fill the acceptable chars into temp containter
     temp[array_length]=src[counter];
     counter++;
     array_length++;
   }
   if(array_length==0) return NULL;//Can remove this line by using advanced approach?
-  char* result=(char*)malloc(sizeof(char) * array_length);
+  char* result=(char*)malloc(sizeof(char) * array_length);//Initialize result pointer
   for(int i=0;i<array_length;i++) result[i]=temp[i];
-  free(temp);
+  free(temp);//Free memory spend by temp containter
   return result;
 }


add comment

add comment

--- arduino-neopixel.ino
+++ arduino-neopixel.ino
@@ -1,4 +1,7 @@
 #include <Adafruit_NeoPixel.h>
+
+// Arduino Nano v2.x, v3.x
+
 #define TOTAL_PIXELS 99

 // common settings :::::::::


revert bad fix

revert bad fix

--- sms_thermo/sms_thermo.ino
+++ sms_thermo/sms_thermo.ino
@@ -24,13 +24,9 @@
 int last_message_hour;

 int monPeriod1Len = 600;                              // 10 minutes
-float dataPeriod1[4][600];
-
 int monPeriod2Len = 36000;                             // 60 minutes
-float dataPeriod2[4][60];
-
 int monPeriod3Len = 21600;                            // 12 hours
-float dataPeriod3[4][36];
+

 long count_t1,        count_t2,       count_t3;
 long startOfPeriod1,  startOfPeriod2, startOfPeriod3;
@@ -330,11 +326,6 @@
     count_t1 = 1;
   }

-    tt1m[i] = tt1m[i] + sensors.getTempC(thermalSensor[i]);
-    tt1m_avg[i] = round(tt1m[i] / count_t1);
-
-
-
   if (now() - startOfPeriod2 <= monPeriod2Len)
   {
     count_t2++;
@@ -348,9 +339,6 @@
     }
   }

-    tt2m[i] = tt2m[i] + sensors.getTempC(thermalSensor[i]);
-    tt2m_avg[i] = round(tt2m[i] / count_t2);
-

   if (now() - startOfPeriod3 <= monPeriod3Len)
   {
@@ -364,14 +352,18 @@
       tt3m[i] = 0;
     }
   }
+
   for (int i = 0; i < sizeof(thermalSensor) / sizeof(DeviceAddress); i++)
   {
+
+    tt1m[i] = tt1m[i] + sensors.getTempC(thermalSensor[i]);
+    tt1m_avg[i] = round(tt1m[i] / count_t1);
+
+    tt2m[i] = tt2m[i] + sensors.getTempC(thermalSensor[i]);
+    tt2m_avg[i] = round(tt2m[i] / count_t2);

     tt3m[i] = tt3m[i] + sensors.getTempC(thermalSensor[i]);
     tt3m_avg[i] = round(tt3m[i] / count_t3);
-
-
-

     if (debug) {
       Serial.print("TEMP"); Serial.print(i); Serial.print(":");


fixed wrong pin assignment

fixed wrong pin assignment

--- main_controller/joystick.ino
+++ main_controller/joystick.ino
@@ -62,7 +62,7 @@
 LightButton lb4("gear", &kc1, 7, &lc2, 1);
 LightButton lb5("switch_right", &kc5, 6);
 LightButton lb6("switch_left", &kc5, 7);
-LightButton lb7("lights", &kc2, 7, NULL, 0);
+LightButton lb7("lights", &kc2, 0, NULL, 0);
 LightButton lb8("brakes", &kc1, 0, NULL, 0);

 #define NUM_ANALOG_BUTTONS 7


Moved reset_reason values to flash.

Moved reset_reason values to flash.

--- loggertask.ino
+++ loggertask.ino
@@ -74,22 +74,22 @@
 {
   switch ( reason)
   {
-    case 1 : return "POWERON_RESET"; break;         /**<1, Vbat power on reset*/
-    case 3 : return "SW_RESET"; break;              /**<3, Software reset digital core*/
-    case 4 : return "OWDT_RESET"; break;            /**<4, Legacy watch dog reset digital core*/
-    case 5 : return "DEEPSLEEP_RESET"; break;       /**<5, Deep Sleep reset digital core*/
-    case 6 : return "SDIO_RESET"; break;            /**<6, Reset by SLC module, reset digital core*/
-    case 7 : return "TG0WDT_SYS_RESET"; break;      /**<7, Timer Group0 Watch dog reset digital core*/
-    case 8 : return "TG1WDT_SYS_RESET"; break;      /**<8, Timer Group1 Watch dog reset digital core*/
-    case 9 : return "RTCWDT_SYS_RESET"; break;      /**<9, RTC Watch dog Reset digital core*/
-    case 10 : return "INTRUSION_RESET"; break;      /**<10, Instrusion tested to reset CPU*/
-    case 11 : return "TGWDT_CPU_RESET"; break;      /**<11, Time Group reset CPU*/
-    case 12 : return "SW_CPU_RESET"; break;         /**<12, Software reset CPU*/
-    case 13 : return "RTCWDT_CPU_RESET"; break;     /**<13, RTC Watch dog Reset CPU*/
-    case 14 : return "EXT_CPU_RESET"; break;        /**<14, for APP CPU, reseted by PRO CPU*/
-    case 15 : return "RTCWDT_BROWN_OUT_RESET"; break; /**<15, Reset when the vdd voltage is not stable*/
-    case 16 : return "RTCWDT_RTC_RESET"; break;     /**<16, RTC Watch dog reset digital core and rtc module*/
-    default : return "NO_MEAN";
+    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");
   }
 }


Version 4.0b - 31st August 2021

Version 4.0b - 31st August 2021

Fixes #48

--- ulisp.ino
+++ ulisp.ino
@@ -1,5 +1,5 @@
-/* uLisp AVR Version 4.0a - www.ulisp.com
-   David Johnson-Davies - www.technoblogy.com - 9th July 2021
+/* uLisp AVR Version 4.0b - www.ulisp.com
+   David Johnson-Davies - www.technoblogy.com - 31st August 2021

    Licensed under the MIT license: https://opensource.org/licenses/MIT
 */
@@ -55,7 +55,7 @@

 #elif defined(__AVR_ATmega1284P__)
   #include "optiboot.h"
-  #define WORKSPACESIZE (2816-SDSIZE)     /* Objects (4*bytes) */
+  #define WORKSPACESIZE (2944-SDSIZE)     /* Objects (4*bytes) */
 //  #define EEPROMSIZE 4096                 /* Bytes */
   #define FLASHWRITESIZE 16384            /* Bytes */
   #define CODESIZE 96                     /* Bytes <= 256 */
@@ -765,7 +765,7 @@
   file.close();
   if (autorun != NULL) {
     loadimage(NULL);
-    apply(0, autorun, NULL, NULL);
+    apply(NIL, autorun, NULL, NULL);
   }
 #elif defined(FLASHWRITESIZE)
   uint32_t addr = 0;
@@ -1700,7 +1700,7 @@
       #if defined(CPU_ATmega4809)
       if (sname == sym(ppspecial[i])) { special = 1; break; }
       #else
-      if (sname == sym(pgm_read_byte(&ppspecial[i]))) { special = 1; break; }
+      if (sname == sym((builtin_t)pgm_read_byte(&ppspecial[i]))) { special = 1; break; }
       #endif
     }
   }
@@ -3466,7 +3466,7 @@
       superprint(cons(bsymbol(DEFCODE), cons(var, cdr(val))), 0, pfun);
     #endif
     } else {
-      superprint(cons(bsymbol(DEFVAR), cons(var, cons(quote(val), NULL))), 0, pserial);
+      superprint(cons(bsymbol(DEFVAR), cons(var, cons(quote(val), NULL))), 0, pfun);
     }
     pln(pfun);
     testescape();
@@ -4340,7 +4340,7 @@
   #if defined(CPU_ATmega4809)
   PGM_P s = lookup_table[name].string;
   #else
-  PGM_P s = pgm_read_word(&lookup_table[name].string);
+  PGM_P s = (char*)pgm_read_word(&lookup_table[name].string);
   #endif
   while (1) {
     #if defined(CPU_ATmega4809)


SSH key test?

SSH key test?

--- chicken_door_timer_v2.ino
+++ chicken_door_timer_v2.ino
@@ -9,7 +9,6 @@
  *  Requires Button.h, TimeLord.h, RTClib.h (Adafruit), and included encoder.h
  */

-// TODO: if door didn't close/open properly, get it to try again a few times.
 // TODO: thoroughly read through code to ensure it's all good.k
 #include <avr/sleep.h>
 #include <avr/power.h>


Removed Geiger VariPass features.

Removed Geiger VariPass features.

--- Alicorn.ino
+++ Alicorn.ino
@@ -336,9 +336,9 @@
         digitalWrite(PIN_RELAY_GEIG, HIGH);

     if (settings.gasSensor)
+        digitalWrite(PIN_RELAY_GAS, HIGH);
+    else
         digitalWrite(PIN_RELAY_GAS, LOW);
-    else
-        digitalWrite(PIN_RELAY_GAS, HIGH);
 }

 void drawScreen(String top, String bot) {
@@ -1133,8 +1133,6 @@
             varipassWriteFloat(KEY1, ID_GAS,     average.gas         / average.gasCount,         &result);
         varipassWriteFloat(KEY1, ID_MAGNITUDE,   average.magnitude   / average.magnitudeCount,   &result);
         varipassWriteFloat(KEY1, ID_INCLINATION, average.inclination / average.inclinationCount, &result);
-        varipassWriteInt  (KEY1, ID_CPM,  data.cpm,  &result);
-        varipassWriteFloat(KEY1, ID_DOSE, data.dose, &result);
     }
     resetAverage();
 }


adjust examples to esp32

adjust examples to esp32

--- examples/ScheduleFromInterrupt/ScheduleFromInterrupt.ino
+++ examples/ScheduleFromInterrupt/ScheduleFromInterrupt.ino
@@ -1,7 +1,12 @@
 #include <DeepSleepScheduler.h>

+#ifdef ESP32
+#define INTERRUPT_PIN 4
+#define LED_PIN 2
+#else
 #define INTERRUPT_PIN 2
 #define LED_PIN 13
+#endif

 void ledOn() {
   digitalWrite(LED_PIN, HIGH);
@@ -17,6 +22,11 @@
 }

 void setup() {
+#ifdef ESP32
+  // wake up using ext0 (4 low)
+  esp_sleep_enable_ext0_wakeup(GPIO_NUM_4, LOW);
+#endif
+
   pinMode(INTERRUPT_PIN, INPUT_PULLUP);
   attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isrInterruptPin, FALLING);
   pinMode(LED_PIN, OUTPUT);


Loop to read out serial buffer

Loop to read out serial buffer

--- arduino/mearm.ino
+++ arduino/mearm.ino
@@ -76,7 +76,7 @@

 void loop() {
   int dt = millis() - t0;
-  if (Serial.available())
+  while (Serial.available())
     controller.parseChar(Serial.read());
   controller.update(dt * 0.001);
   t0 += dt;


Update todo list

Update todo list

--- moros/moros.ino
+++ moros/moros.ino
@@ -3,7 +3,6 @@
 * time setting - P1
 * case - P1
 * display tenths of a second - P2
-* have graphical representation of flag P3
 *
 */


add some delay to the loop to avoid button bouncing

--- ksp-gegi-microusb/ksp-gegi-microusb.ino
+++ ksp-gegi-microusb/ksp-gegi-microusb.ino
@@ -498,4 +498,6 @@
   if (testMode) {
 	  handleTestMode();
   }
-}
+  delay(20);
+}
+


update

update

--- examples/mqtttest.ino
+++ examples/mqtttest.ino
@@ -1,41 +0,0 @@
-#include "MQTT.h"
-
-void callback(char* topic, byte* payload, unsigned int length);
-MQTT client("server_name", 1883, callback);
-
-// recieve message
-void callback(char* topic, byte* payload, unsigned int length) {
-    char p[length + 1];
-    memcpy(p, payload, length);
-    p[length] = NULL;
-    String message(p);
-
-    if (message.equals("RED"))
-        RGB.color(255, 0, 0);
-    else if (message.equals("GREEN"))
-        RGB.color(0, 255, 0);
-    else if (message.equals("BLUE"))
-        RGB.color(0, 0, 255);
-    else
-        RGB.color(255, 255, 255);
-    delay(1000);
-}
-
-
-void setup() {
-    RGB.control(true);
-
-    // connect to the server
-    client.connect("sparkclient");
-
-    // publish/subscribe
-    if (client.isConnected()) {
-        client.publish("outTopic","hello world");
-        client.subscribe("inTopic");
-    }
-}
-
-void loop() {
-    if (client.isConnected())
-        client.loop();
-}


Simplified card registration.

Simplified card registration.

--- Arduino/arduino-yun-lockitron-nfc/arduino-yun-lockitron-nfc.ino
+++ Arduino/arduino-yun-lockitron-nfc/arduino-yun-lockitron-nfc.ino
@@ -14,29 +14,29 @@
     files in https://github.com/devalfrz/arduino-lockitron-nfc).

     Buttons: (buttons are set to have a pullup resistor so they ar inverted)
-      - SLOT_SELECT: Selects a memory slot. STATUS_LED will blink n times depending
-          on the slot that has been selected.
-
-      - MEMORY_BUTTON: If it's pressed for 3 seconds while a card is read,
-          it will either override the selected slot or delete the card if it
-          was already registered.
-
       - LOCK_UNLOCK: This button will lock or unlock the system depending on its
           previous state.

+      - SAVE_CARD: If it's pressed for 3 seconds while a card is read,
+          it will either save the current card and blink 3 times or delete the
+          card and blink one time for 2 seconds.
+
+      - RESET_MEMORY: Keep this button pressed and this will clear all cards in
+          memory.
+

 */
 /**************************************************************************/

 /**** INPUTS/OUTPUTS ****/
 // Adafruit PN532 breakout board:
-#define PN532_SCK  22
-#define PN532_MOSI 21
-#define PN532_SS   20
-#define PN532_MISO 23
+#define PN532_SCK  A4
+#define PN532_MOSI A3
+#define PN532_SS   A2
+#define PN532_MISO A5
 // Buttons
-#define SLOT_SELECT 10
-#define MEMORY_BUTTON 9
+#define RESET_MEMORY 10
+#define SAVE_CARD 9
 #define STATUS_LED 13
 #define UNLOCKED 12
 #define LOCKED 11
@@ -48,7 +48,7 @@
 #define LOCK_UNLOCK 8

 /**** Other definitions ****/
-#define TOTAL_SLOTS 4 // Arbitrary number of slots available
+#define TOTAL_SLOTS 64 // Arbitrary number of slots available (depends on the memory of your chip)
 #define SLOT_SIZE 4
 #define OPEN 0
 #define CLOSE 1
@@ -84,8 +84,8 @@

 void setup(void) {
-  pinMode(MEMORY_BUTTON,INPUT_PULLUP);
-  pinMode(SLOT_SELECT,INPUT_PULLUP);
+  pinMode(SAVE_CARD,INPUT_PULLUP);
+  pinMode(RESET_MEMORY,INPUT_PULLUP);
   pinMode(STATUS_LED,OUTPUT);
   pinMode(LOCKED,OUTPUT);
   pinMode(UNLOCKED,OUTPUT);
@@ -131,6 +131,7 @@
 void loop(void) {
   uint8_t success;
   uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
+  int tmp_addr;
   uint8_t uidLength;    // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
   int i,j;
   boolean save_delete = 0;
@@ -143,7 +144,7 @@
   // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
   success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength,100);

-  save_delete = (success && !digitalRead(MEMORY_BUTTON)) ? 1 : 0;
+  save_delete = (success && !digitalRead(SAVE_CARD)) ? 1 : 0;

   if (success) {
     digitalWrite(STATUS_LED,HIGH);
@@ -157,30 +158,31 @@
     nfc.PrintHex(uid, uidLength);
     Serial.println("");
     #endif
-    for(i=0;i<TOTAL_SLOTS;i++){ //Check all memory slots
-      if(check_card(uid,i))
-        access_granted = 1;
-    }
+    memory_slot = check_card(uid);
+    access_granted = (memory_slot == -1) ? 0 : 1;
+
     if(save_delete){
       access_granted = 0; //Reset Access
       #ifdef DEBUG
       Serial.println("Continue pressing to save or delete card");
       #endif
       delay(3000);
-      if(!digitalRead(MEMORY_BUTTON)){
-        if(save_delete_card(uid,memory_slot)){
+      if(!digitalRead(SAVE_CARD)){
+        if(memory_slot == -1){
+          memory_slot = save_card(uid);
           #ifdef DEBUG
           Serial.print("Save Card Slot: ");
-          Serial.println(memory_slot);
+          Serial.println(memory_slot+1);
+          blink_n_times(memory_slot+1,STATUS_LED,250);
+          delay(1000);
           #endif
-          blink_n_times(memory_slot+1,STATUS_LED);
+          blink_n_times(3,STATUS_LED,100);
         }else{
+          delete_card(memory_slot);
           #ifdef DEBUG
-          Serial.println("Delete Card");
+          Serial.println("Card deleted!");
           #endif
-          digitalWrite(STATUS_LED,HIGH);
-          delay(2000);
-          digitalWrite(STATUS_LED,LOW);
+          blink_n_times(1,STATUS_LED,2000);
         }
       }
     }
@@ -194,12 +196,9 @@
       state = lock(!state);
       digitalWrite(STATUS_LED,LOW);
       delay(100);
-
-      for(i=0;i<TOTAL_SLOTS;i++){ // Usefull to know the slot in which the card
-                                  //  is saved :)
-        if(check_card(uid,i))
-          blink_n_times(i+1,STATUS_LED);
-      }
+      #ifdef DEBUG
+        if(check_card(uid)) blink_n_times(i+1,STATUS_LED,250);
+      #endif
     }else{
       #ifdef DEBUG
       Serial.println("Access Denied");
@@ -231,74 +230,88 @@
   }

-
-  if(!digitalRead(SLOT_SELECT)){// Select memory slot
-    while(!digitalRead(SLOT_SELECT));
-    memory_slot = (memory_slot < TOTAL_SLOTS - 1) ? memory_slot + 1 : 0;
-    #ifdef DEBUG
-    Serial.print("Slot selected: ");
-    Serial.println(memory_slot);
-    #endif
-    blink_n_times(memory_slot+1,STATUS_LED);
-  }
   if(!digitalRead(LOCK_UNLOCK)){// Select slot
     state = lock(!state);
   }
-}
-
-boolean save_delete_card(uint8_t *uid,int addr){
+  if(!digitalRead(RESET_MEMORY)){// Select slot
+    digitalWrite(STATUS_LED,HIGH);
+    delay(5000);
+    digitalWrite(STATUS_LED,LOW);
+    if(!digitalRead(RESET_MEMORY)){
+      clear_memory();
+      blink_n_times(4,STATUS_LED,100);
+      delay(1000);
+    }
+  }
+}
+
+int check_card(uint8_t *uid){
+  /*
+   *  Checks if card is saved, returns the address of the card if it saved
+   *  or -1 if it is not found.
+   */
+  int i,j;
+  int memory_offset;
+
+  for(i=0;i<TOTAL_SLOTS;i++){
+    memory_offset = i*SLOT_SIZE;
+    for(j=0;j<SLOT_SIZE;j++){
+      if(EEPROM.read(memory_offset+j)!=uid[j]) break;
+    }
+    if(j==SLOT_SIZE){
+      return i;
+    }
+  }
+  return -1;
+}
+int save_card(uint8_t *uid){
+  /*
+   *  Saves card to empty slot
+   */
+  uint8_t blank_card[] = {0,0,0,0};
+  int card_addr = check_card(uid);// Search card
+  int i, new_addr, memory_offset;
+  if(card_addr == -1){
+    new_addr = check_card(blank_card);// Search for a empty slot
+    if(new_addr != -1){
+      memory_offset = SLOT_SIZE*new_addr;
+      for(i=0;i<SLOT_SIZE;i++){
+        EEPROM.write(memory_offset+i,uid[i]);
+      }
+    }
+    return new_addr;
+  }
+  return -1;// Already saved
+
+}
+int delete_card(int addr){
+  /*
+   *  Deletes card from memory slot (addr)
+   */
+  int memory_offset = SLOT_SIZE*addr;
+  int i;
+
+  for(i=0;i<SLOT_SIZE;i++){
+    EEPROM.write(memory_offset+i,0);
+  }
+}
+void clear_memory(void){
+  int i;
+  int total = TOTAL_SLOTS*SLOT_SIZE;
+  for(i=0;i<total;i++){
+    EEPROM.write(i,0);
+  }
+}
+void blink_n_times(int n,int led_pin,int blink_interval){
   /*
-   * If card doesn't exist in any slot, then it is saved in "addr",
-   *   else it is deleted from memory.
-   */
-  int i;
-  int j;
-  int memory_offset = SLOT_SIZE*addr;
-  boolean save = 1;
-
-  for(i=0;i<TOTAL_SLOTS;i++){ //Check if card is saved in any slot
-    if(check_card(uid,i)){
-      save = 0; //Delete if found
-    }
-  }
-  if(save){
-    for(i=0;i<SLOT_SIZE;i++){
-      EEPROM.write(memory_offset+i,uid[i]);
-    }
-    return(1);
-  }else{
-    for(i=0;i<TOTAL_SLOTS;i++){ //Delete card from all slots
-      if(check_card(uid,i)){
-        memory_offset = SLOT_SIZE*i;
-        for(j=0;j<SLOT_SIZE;j++){
-          EEPROM.write(memory_offset+j,0);
-        }
-      }
-    }
-    return(0);
-  }
-}
-boolean check_card(uint8_t *uid,int addr){
-  /*
-   *  Checks if card (uid) is contained in the designed address (addr)
-   */
-  int i;
-  int memory_offset = SLOT_SIZE*addr;
-  for(i=0;i<SLOT_SIZE;i++){
-    if(EEPROM.read(memory_offset+i)!=uid[i]) return 0;
-  }
-  return 1;
-}
-void blink_n_times(int n,int led_pin){
-  /*
-   * Blink n times
+   * Blink led_pin n times for blink_interval
    */
   int i;
   for(i=0;i<n;i++){
     digitalWrite(led_pin,HIGH);
-    delay(250);
+    delay(blink_interval);
     digitalWrite(led_pin,LOW);
-    delay(250);
+    delay(blink_interval);
   }
 }


Update BB-UNIT.ino

Update BB-UNIT.ino

--- Firmware/BB-UNIT/BB-UNIT.ino
+++ Firmware/BB-UNIT/BB-UNIT.ino
@@ -342,7 +342,7 @@
     if (remote.available()) // IF RF24 ---> radio.available()
     {
     	char msg[64] = {0};
-    	radio.read(&msg, sizeof(msg));
+    	radio.readBytesUntil('\n', msg, sizeof msg);
     	newData = true;
     }


Update comments

Update comments

--- Arduino/v0.2.0_no_conditioning/v0.2.0_no_conditioning.ino
+++ Arduino/v0.2.0_no_conditioning/v0.2.0_no_conditioning.ino
@@ -4,9 +4,9 @@
  *
  *  2015 Rob Seward
  *
- *  Captures random data from Z1FFER v0.2.0 and conditions it using AES-CBC-MAC
- *
- *  Requires Rhys Weatherley's crypto library: https://github.com/rweather/arduinolibs
+ *  Sends raw random data to the host as fast as possible.
+ *  Baud rate is 230400
+ *
  */

 void setup()
@@ -16,7 +16,6 @@
   DDRB = B00000000;
   delay(1000);
 }
-

 void loop() {
   static byte currentByte = 0x00;


Show SampleTime with GetConfig Add SampleTime to Help menu

--- XV_Lidar_Controller.ino
+++ XV_Lidar_Controller.ino
@@ -402,6 +402,7 @@
   Serial.println("  SetKp");
   Serial.println("  SetKi");
   Serial.println("  SetKp");
+  Serial.println("  SetSampleTime");
   Serial.println("  ShowRPM");
   Serial.println("  HideRPM");
   Serial.println("  MotorOff");
@@ -428,6 +429,8 @@
   Serial.println(xv_config.Ki);
   Serial.print("PID Kd: ");
   Serial.println(xv_config.Kd);
+  Serial.print("SampleTime: ");
+  Serial.println(xv_config.sample_time);

   Serial.print("Motor Enable: ");
   Serial.println(xv_config.motor_enable);


Minor non-critical updates of the IR MQTT example code. (#334)

* Minor non-critical updates of the IR MQTT example code.
* Try to limit locking up when MQTT connection is down.
* IP and MQTT server information display on main html page.
* Add a crude timestamp to debug messages sent to the serial port.
* More code comments.
* Improve some MQTT status messages.

* Zero pad debug output.

--- examples/IRMQTTServer/IRMQTTServer.ino
+++ examples/IRMQTTServer/IRMQTTServer.ino
@@ -117,10 +117,10 @@
 // --------------------------------------------------------------------
 // * * * IMPORTANT * * *
 // You must change <PubSubClient.h> to have the following value.
-// #define MQTT_MAX_PACKET_SIZE 400
+// #define MQTT_MAX_PACKET_SIZE 512
 // --------------------------------------------------------------------
 #include <PubSubClient.h>
-#endif
+#endif  // MQTT_ENABLE
 #include <algorithm>
 #include <string>

@@ -140,7 +140,7 @@
 #define MQTTprefix "ir_server"
 #define MQTTack MQTTprefix "/sent"  // Topic we send back acknowledgements on
 #define MQTTcommand MQTTprefix "/send"  // Topic we get new commands from.
-#endif
+#endif  // MQTT_ENABLE

 // HTML arguments we will parse for IR code information.
 #define argType "type"
@@ -168,13 +168,14 @@
 // Create a unique MQTT client id.
 const char* mqtt_clientid = String(MQTTprefix +
                                    String(ESP.getChipId(), HEX)).c_str();
-#endif
+#endif  // MQTT_ENABLE

 // Debug messages get sent to the serial port.
 void debug(String str) {
 #ifdef DEBUG
-  Serial.println(str);
-#endif
+  uint32_t now = millis();
+  Serial.printf("%07u.%03u: %s\n", now / 1000, now % 1000, str.c_str());
+#endif  // DEBUG
 }

 // Root web page with example usage etc.
@@ -183,6 +184,15 @@
     "<title>IR MQTT server</title>"
     ""
     "
ESP8266 IR MQTT Server
"
+    "

"
+    "
Connection details
"
+    "
IP address: " + WiFi.localIP().toString() + "
"
+#ifdef MQTT_ENABLE
+    "
MQTT server: " MQTT_SERVER ":" + String(MQTT_PORT) + " ("+
+    (mqtt_client.connected() ? "Connected" : "Disconnected") + ")
"
+    "Command topic: " MQTTcommand "
"
+    "Acknowledgements topic: " MQTTack "
"
+#endif  // MQTT_ENABLE
     "

"
     "
Hardcoded examples
"
     "
<a href=\"ir?code=38000,1,69,341,171,21,64,21,64,21,21,21,21,21,21,21,"
@@ -567,7 +577,7 @@

   wifiManager.setTimeout(300);  // Time out after 5 mins.
   if (!wifiManager.autoConnect()) {
-    debug("Failed to connect and hit timeout.");
+    debug("Wifi failed to connect and hit timeout.");
     delay(3000);
     // Reboot. A.k.a. "Have you tried turning it Off and On again?"
     ESP.reset();
@@ -582,7 +592,7 @@

   #ifdef DEBUG
   Serial.begin(115200);
-  #endif
+  #endif  // DEBUG

   setup_wifi();

@@ -617,14 +627,14 @@
         if (!Update.begin(maxSketchSpace)) {  // start with max available size
 #ifdef DEBUG
           Update.printError(Serial);
-#endif
+#endif  // DEBUG
         }
       } else if (upload.status == UPLOAD_FILE_WRITE) {
         if (Update.write(upload.buf, upload.currentSize) !=
             upload.currentSize) {
 #ifdef DEBUG
           Update.printError(Serial);
-#endif
+#endif  // DEBUG
         }
       } else if (upload.status == UPLOAD_FILE_END) {
         if (Update.end(true)) {  // true to set the size to the current progress
@@ -652,11 +662,13 @@
 }

 bool reconnect() {
-  // Loop until we're reconnected
-  while (!mqtt_client.connected()) {
+  // Loop a few times or until we're reconnected
+  uint16_t tries = 1;
+  while (!mqtt_client.connected() && tries <= 3) {
     int connected = false;
     // Attempt to connect
-    debug("Attempting MQTT connection ... ");
+    debug("Attempting MQTT connection to " MQTT_SERVER ":" + String(MQTT_PORT) +
+          "... ");
     if (mqtt_user && mqtt_password)
       connected = mqtt_client.connect(mqtt_clientid, mqtt_user, mqtt_password);
     else
@@ -665,18 +677,19 @@
     // Once connected, publish an announcement...
       mqtt_client.publish(MQTTack, "Connected");
       debug("connected.");
-    // Subscribing to topic(s)
-    subscribing(MQTTcommand);
+      // Subscribing to topic(s)
+      subscribing(MQTTcommand);
     } else {
       debug("failed, rc=" + String(mqtt_client.state()) +
-            " try again in a bit.");
+            " Try again in a bit.");
       // Wait for a bit before retrying
-      delay(MQTT_RECONNECT_TIME);
+      delay(tries << 7);  // Linear increasing back-off (x128)
     }
+    tries++;
   }
   return mqtt_client.connected();
 }
-#endif
+#endif  // MQTT_ENABLE

 void loop(void) {
   server.handleClient();
@@ -685,6 +698,7 @@
   // MQTT client connection management
   if (!mqtt_client.connected()) {
     uint32_t now = millis();
+    // Reconnect if it's longer than MQTT_RECONNECT_TIME since we last tried.
     if (now - lastReconnectAttempt > MQTT_RECONNECT_TIME) {
       lastReconnectAttempt = now;
       debug("client mqtt not connected, trying to connect");
@@ -703,7 +717,7 @@
     // MQTT loop
     mqtt_client.loop();
   }
-#endif
+#endif  // MQTT_ENABLE
   delay(100);
 }

@@ -877,7 +891,7 @@
       debug(code_str);
       debug("Repeats: " + String(repeat));
       // Confirm what we were asked to send was sent.
-  #ifdef MQTT_ENABLE
+#ifdef MQTT_ENABLE
       if (ir_type == PRONTO && repeat > 0)
         mqtt_client.publish(MQTTack, (String(ir_type) + ",R" +
                                       String(repeat) + "," +
@@ -885,7 +899,7 @@
       else
         mqtt_client.publish(MQTTack, (String(ir_type) + "," +
                                       String(code_str)).c_str());
-  #endif
+#endif  // MQTT_ENABLE
       break;
     default:
       debug("Code: 0x" + uint64ToString(code, 16));
@@ -897,7 +911,7 @@
                                     uint64ToString(code, 16)
                                     + "," + String(bits) + "," +
                                     String(repeat)).c_str());
-#endif
+#endif  // MQTT_ENABLE
   }
 }

@@ -965,4 +979,4 @@
   // Free the memory
   free(payload_copy);
 }
-#endif
+#endif  // MQTT_ENABLE


Resume on powerup

Resume on powerup

--- UbarCDC.ino
+++ UbarCDC.ino
@@ -38,6 +38,7 @@
   Serial.begin(9600);
   cdc_setup();
   bt_setup();
+  onResume();
   DEBUG("[UCDC] started\n");
 }


Remove unused handleByte function

Remove unused handleByte function

--- inverted-pendulum.ino
+++ inverted-pendulum.ino
@@ -183,54 +183,6 @@
   Serial.println(s);
 }

-void handleByte(byte b)
-{
-  Serial.print((char)b);
-
-  if (b == '-')
-    cmd = "-";
-
-  // kp
-  else if (b == 'p') // increase kp
-    kp += 0.01;
-  else if (b == 'l') // decrease kp
-    kp -= 0.01;
-
-  // ki
-  else if (b == 'i') // increase ki
-    ki += 0.1;
-  else if (b == 'k') // decrease ki
-    ki -= 0.1;
-
-  // kd
-  else if (b == 'd') // increase kd
-    kd += 0.001;
-  else if (b == 'c') // decrease kd
-    kd -= 0.001;
-
-  else if (b == '.')
-    cmd += b;
-  else if (isDigit(b))
-  {
-    byte digit = b - 48;
-    cmd += digit;
-  }
-  else if (b == '\r' || b == '\n')
-  {
-    // Assume here that cmd is a signed track x setpoint value in encoder units.
-    // Convert to a fraction in [-1,1] for PID input
-    float setpoint = cmd.toFloat()/xMax;
-    cartPid.setpoint = constrain(setpoint, cartPid.minOutput, cartPid.maxOutput);
-    cmd = "";
-  }
-  else
-  {
-    cartPid.setPID(kp, ki, kd);
-    Serial.println();
-    printStatus(cartPid);
-  }
-}
-
 // string -> callback "dictionary"
 Command cmdlist[] =
 {


Update max30205demo.ino

Update max30205demo.ino

--- examples/max30205demo/max30205demo.ino
+++ examples/max30205demo/max30205demo.ino
@@ -26,7 +26,7 @@
 	Serial.begin(9600);
 	Serial.println("ClosedCube MAX30205 Arduino Demo");

-	max30205.begin(0x48);
+	max30205.begin(0x90);
 }

 void loop()


Display button press feedback via the status LED also

--- Arduino_Firmware/Arduino_Firmware.ino
+++ Arduino_Firmware/Arduino_Firmware.ino
@@ -29,7 +29,7 @@
 #define DEBUG 1

 // SENSOR ID. Each sensor must have a unique ID, which is used to determine which reading comes from which part of the building.
-#define SENSOR_ID 7
+#define SENSOR_ID 3

 // Time delay between sensor readings (in seconds)
 unsigned int sensor_period = 20;
@@ -184,7 +184,7 @@
 {
   static unsigned long last_change = 0;
   unsigned long current_time = millis();
-  if ((current_time - last_change) < 1000) {
+  if (((current_time - last_change) < 2000) && (buttonStatus != NoButtons)) {
     // It has been too soon since the last change. Disallow this.
     return;
   }
@@ -283,8 +283,22 @@
       }
       break;
     case NodeOK:
-      // Solid green LED
-      ledRGB(0, 40, 0);
+      // Display the button status on this LED
+      switch (buttonStatus) {
+        case HappyDown:
+          ledRGB(0, 255, 0); // Bright green
+          break;
+        case IndifferentDown:
+          ledRGB(128, 128, 48); // Whitish green
+          break;
+        case SadDown:
+          ledRGB(255, 0, 0); // Red
+          break;
+        case NoButtons:
+          ledRGB(0, 1, 0); // Very faint green
+          break;
+      }
+
       break;
     case LossOfRadioContact:
       // Blinking red LED


reverted delays

reverted delays

--- frontdesk/module.wifi.ino
+++ frontdesk/module.wifi.ino
@@ -42,18 +42,16 @@
     String closeConnection = "AT+CIPCLOSE";

     WIFI.println(beginConnection);
-    //delay(waitForConnect);
-    delay(100);
+    delay(waitForConnect);

-    getStr += String(ID) + " HTTP/1.1\r\n";
+    getStr += String(ID) + " HTTP/1.1";

     cmd += getStr.length();

     WIFI.println(cmd);
-    //delay(waitForGET);
-    delay(500);
+    delay(waitForGET);

-    WIFI.print(getStr);
+    WIFI.println(getStr);
     delay(waitForFlush);

     WIFI.println(closeConnection);


removed unneccesary #include

removed unneccesary #include

--- GY521_self_tests/GY521_self_tests.ino
+++ GY521_self_tests/GY521_self_tests.ino
@@ -1,5 +1,4 @@
  #include <Wire.h>
- #include <MPU6050.h>

 const uint8_t MPU_addr=0x68;  // I2C address of the MPU-6050


Increased debounceTime parameter to ensure that only one status update is published

Dramatically increased the debounceTime (50 to 5000ms) to ensure that only the first switch change is registered as a status change and published.

--- GarHAge.ino
+++ GarHAge.ino
@@ -55,7 +55,7 @@
 int door2_lastStatusValue = 2;
 unsigned long door1_lastSwitchTime = 0;
 unsigned long door2_lastSwitchTime = 0;
-int debounceTime = 50;
+int debounceTime = 5000;

 WiFiClient espClient;
 PubSubClient client(espClient);


Siren sucked but disco twirl is great

Siren sucked but disco twirl is great

--- all/all.ino
+++ all/all.ino
@@ -1,49 +1,44 @@
-uint8_t wavebright = 255;                                     // You can change the brightness of the waves/bars rolling across the screen.
-#define qsubd(x, b)  ((x>b)?wavebright: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
+uint8_t wavebright = 255;                  // You can change the brightness of the waves/bars rolling across the screen.
+#define qsubd(x, b)  ((x>b)?wavebright: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

 #include "FastLED.h"
-#define LED_DT 7                                             // Data pin to connect to the strip.
-#define COLOR_ORDER GRB                                       // Are they RGB, GRB or what??
-#define LED_TYPE WS2812B                                       // Don't forget to change LEDS.addLeds
-#define NUM_LEDS 1500                                           // Number of LED's.
-struct CRGB leds[NUM_LEDS];                                   // Initialize our LED array.
-
-uint8_t max_bright = 255;                                      // Overall brightness definition. It can be changed on the fly.
-unsigned long previousMillis;                                 // Store last time the strip was updated.
-
-int hue = 50;                                       // Starting hue.
-
-// This variable is set the first run-through of every pattern. Use it for setup!
-bool firstRun = false;
-
-// Patterns
+#define LED_DT 7              // Data pin to connect to the strip.
+#define COLOR_ORDER GRB       // Are they RGB, GRB or what??
+#define LED_TYPE WS2812B      // Don't forget to change LEDS.addLeds
+#define NUM_LEDS 1500         // Number of LED's.
+struct CRGB leds[NUM_LEDS];   // Initialize our LED array.
+uint8_t max_bright = 255;     // Overall brightness definition. It can be changed on the fly.
+unsigned long previousMillis; // Store last time the strip was updated.
+int hue = 50;                 // Starting hue.
+bool firstTimeRunningThroughPattern = false;
+
 #define NIGHT_SPARKLES 1
 #define BEAUTIFUL_SPARKLES 2
-#define SINGLE_COLOR_SPARKLES 3
+#define DISCO_BARBER_2 3
 #define DISCO_BARBER_1 4
-#define DISCO_BARBER_2 5
+#define SINGLE_COLOR_SPARKLES 5
 #define WORMS 6
-#define NEW 7
-
-int maxPatternId = 6;
-int rotationInMillseconds = 2000; // 20 seconds for production
-
-
+#define PARTY 7
+//#define SIREN 8
+#define DISCO_TWIRL 8
+
+int maxPatternId = 8;
+int rotationInMillseconds = 20000; // 20 seconds for production
+
+// Either A)
+bool holdPattern = true;
+int patternId = DISCO_TWIRL;
+// OR B)
 //bool holdPattern = false;
-bool holdPattern = true;
-//int patternId = 2;
-int patternId = SINGLE_COLOR_SPARKLES;
-
-const int ledPin = 13;
-const int led = 13;
+//int patternId = NIGHT_SPARKLES;

 void setup() {
   delay(3000);
   Serial.begin(57600);
   LEDS.addLeds<LED_TYPE, LED_DT, COLOR_ORDER>(leds, NUM_LEDS);
   FastLED.setBrightness(max_bright);
-  set_max_power_in_volts_and_milliamps(5, 10000);
+  set_max_power_in_volts_and_milliamps(5, 12000);
   randomSeed(analogRead(0));
 }

@@ -76,23 +71,24 @@
   hue = hue + 1;
 }

+void beautifulSparkles() {
+  fadeToBlackBy(leds, NUM_LEDS, 200);
+  numberOfSparkles = upAndDownBy(numberOfSparkles, 1);
+  for (int i = 0; i < numberOfSparkles * 4; i++) {
+    int pos = random16(NUM_LEDS);
+    leds[pos] = CHSV(hue + (pos / 10), 240, 255);
+  }
+  hue += 10;
+}
+
 void sparkles() {
   fadeToBlackBy(leds, NUM_LEDS, 200);
   numberOfSparkles = upAndDownBy(numberOfSparkles, 1);
   for (int i = 0; i < numberOfSparkles * 4; i++) {
     int pos = random16(NUM_LEDS);
-    if (patternId == BEAUTIFUL_SPARKLES) {
-      leds[pos] = CHSV(hue + (pos / 10), 240, 255);
-    } else if (patternId == SINGLE_COLOR_SPARKLES) {
-      leds[pos] = CHSV(hue, 240, 255);
-    }
-  }
-
-  if (patternId == BEAUTIFUL_SPARKLES) {
-    hue += 10;
-  } else {
-    hue = hue + 1;
-  }
+    leds[pos] = CHSV(hue, 240, 255);
+  }
+  hue += 1;
 }

 uint8_t numberOfWorms = 3;
@@ -145,12 +141,87 @@
       leds[k] += CHSV(hue * -20 + k / 4, discoBarberSaturation, _brightness);                       // Then assign a hue to any that are bright enough.
     }
   }
- }
+}
+
+int partySeed;
+int partySeedDirection = true;
+
+void party() {
+  int partySeedLength = 200;
+  if (firstTimeRunningThroughPattern) {
+    partySeed = 0;
+  } else {
+    partySeed += partySeedDirection ? 20 : -20;
+    if (partySeed > NUM_LEDS - partySeedLength) {
+      partySeedDirection = false;
+    } else if (partySeed < 0) {
+      partySeedDirection = true;
+    }
+  }
+  EVERY_N_MILLISECONDS(500) {
+    hue += 33;
+  }
+  fadeToBlackBy(leds, NUM_LEDS, 120);
+  int brightness = 255;
+  int saturation = 200;
+  int pos = random(partySeed - partySeedLength, partySeed + partySeedLength);
+
+  for (int i = pos; i <= pos + 50; i++) {
+    brightness *= 0.97;
+    if (i < NUM_LEDS && i > 0) {
+      leds[i] = CHSV(hue, saturation, brightness);
+    }
+  }
+  brightness = 255;
+  saturation = 255;
+  for (int j = pos; j >= pos - 50; j--) {
+    brightness *= 0.97;
+    if (j < NUM_LEDS && j > 0) {
+      leds[j] = CHSV(hue, saturation, brightness);
+    }
+  }
+}
+
+uint8_t sirenHue = 0;                                          // Starting hue value.
+int8_t sirenRotation = 10;                                           // Hue rotation speed. Includes direction.
+uint8_t sirenDeltahue = 10;                                         // Hue change between pixels.
+bool sirenDirection = 0;                                             // I use a direction variable, so I can plug into inputs in a standar fashion.
+
+void siren() {
+  if (sirenDirection == 0) sirenHue += sirenRotation; else sirenHue -= sirenRotation; // I could use signed math, but 'thisdir' works with other routines.
+  sirenDeltahue = 1;
+  sirenRotation = 30;
+  fill_rainbow(leds, NUM_LEDS, sirenHue, sirenDeltahue);
+}
+
+uint8_t thishue = 0;                                          // You can change the starting hue value for the first wave.
+uint8_t thisrot = 0;                                          // You can change how quickly the hue rotates for this wave. Currently 0.
+uint8_t allsat = 255;                                         // I like 'em fully saturated with colour.
+bool thisdir = 0;                                             // You can change direction.
+int8_t thisspeed = 32;                                         // You can change the speed, and use negative values.
+uint8_t allfreq = 32;                                         // You can change the frequency, thus overall width of bars.
+int thisphase = 0;                                            // Phase change value gets calculated.
+uint8_t thiscutoff = 192;                                     // You can change the cutoff value to display this wave. Lower value = longer wave.
+int thisdelay = 20;                                           // You can change the delay. Also you can change the allspeed variable above.
+uint8_t bgclr = 0;                                            // A rotating background colour.
+uint8_t bgbri = 16;                                           // Don't go below 16.
+// End of resetvar() redefinitions.
+
+void discoTwirl() {
+  //  if (thisdir == 0) thisphase+=thisspeed; else thisphase-=thisspeed;          // You can change direction and speed individually.
+  thisphase += thisspeed;
+  thishue += thisrot;                                                         // Hue rotation is fun for thiswave.
+  for (int k=0; k<NUM_LEDS-1; k++) {
+    int thisbright = qsubd(cubicwave8((k*allfreq)+thisphase), thiscutoff);      // qsub sets a minimum value called thiscutoff. If < thiscutoff, then bright = 0. Otherwise, bright = 128 (as defined in qsub)..
+    leds[k] = CHSV(bgclr, 255, bgbri);
+    leds[k] += CHSV(thishue + k, allsat, thisbright);                               // Assigning hues and brightness to the led array.
+  }
+}

 void loop () {
   if (!holdPattern) {
     EVERY_N_MILLISECONDS(rotationInMillseconds) {
-      firstRun = true;
+      firstTimeRunningThroughPattern = true;
       patternId += 1;
       if (patternId > maxPatternId) {
         patternId = 1;
@@ -160,15 +231,23 @@

   if (patternId == NIGHT_SPARKLES) {
     nightSparkles();
-  } else if (patternId == BEAUTIFUL_SPARKLES || patternId == SINGLE_COLOR_SPARKLES) {
+  } else if (patternId == BEAUTIFUL_SPARKLES) {
+    beautifulSparkles();
+  } else if (patternId == SINGLE_COLOR_SPARKLES) {
     sparkles();
   } else if (patternId == DISCO_BARBER_1 || patternId == DISCO_BARBER_2) {
     discoBarber();
   } else if (patternId == WORMS) {
     worms();
-  }
-
-  firstRun = false;
+  } else if (patternId == PARTY) {
+    party();
+  } else if (patternId == SIREN) {
+    siren();
+  } else if (patternId == DISCO_TWIRL) {
+    discoTwirl();
+  }
+
+  firstTimeRunningThroughPattern = false;

   show_at_max_brightness_for_power();
 }


Added comments and tested.

Added comments and tested.

--- arduino/CounterCat/CounterCat.ino
+++ arduino/CounterCat/CounterCat.ino
@@ -1,8 +1,31 @@
-
+/////////////////////////////////////////////
+// CounterCat
+//
+// System Components:
+//   - 1x Parallax Passive Infrared Sensor
+//        http://parallax.com/product/555-28027
+//
+//   - 1x Beefcake Relay Board
+//        https://www.sparkfun.com/products/11042
+//
+//      uC   |  PIR
+//    -------|------
+//     D2 <<---- Out
+//     +5v|----- Vcc
+//     GND|----- Gnd
+//
+//     uC    |  Relay
+//    -------|---------
+//     +5v|----- Vcc
+//     GND|----- Gnd
+//     D3<<----- Cntrl
+//
+/////////////////////////////////////////////

 #define BLENDER_PIN 3
 #define SENSOR_PIN 2

+//Note that the PIR sensor needs at least 40 seconds to start up.
 #define WARM_UP_TIME_MS ((unsigned long) 41000)
 #define COOLDOWN_TIME_MS 5000
 #define ACTIVE_TIME_MS 2000
@@ -25,8 +48,6 @@
  "cooldown"
 };

-
-boolean warmedUp = false;

 unsigned long timerStart = 0;
 unsigned long now = 0;
@@ -52,11 +73,6 @@
 {
   now = millis();

-  //if (now % 1000 == 0)
-  //{
-  //   Serial.println("State = " + state2String[currentState]);
-  //}
-
    switch (currentState)
     {


Update CRE_Firmata.ino

Update CRE_Firmata.ino

Added new functionality.  Auto configure the connect HC-06 Bluetooth module on boot when Arduino A7 connected to GND.  Switched A0 and A1 back to inputs, these ports are now available on the robot for additional input sensors.  Added new tone functionality, included four example melodies built it.  Added three new images to the default display selection.  Added functions to allows the HC-06 Bluetooth module to be renamed from S4A.  Reduced the size of the text to say, text to scroll buffers to accommodate new functionality.  Memory now very squeezed, may optimise this at some point.

--- src/libraries/arduino/CRE_Firmata/CRE_Firmata.ino
+++ src/libraries/arduino/CRE_Firmata/CRE_Firmata.ino
@@ -22,9 +22,9 @@

 Last updated August 17th, 2017

-Creative Science Foundation Creative Robotix Educational Platform Modifications.
-
-Last updated May 15th, 2018
+Creative Science Foundation Creative Robotix Platform Modifications.
+
+Last updated June 18th, 2018

 Compile Notes:

@@ -32,13 +32,26 @@

 http://playground.arduino.cc/Code/NewPing

-https://github.com/wayoda/LedControl
-
-New Ping may conflict with the Tone function.  Edit the NewPing.h file
+New Ping conflicts with the Tone functions, edit the NewPing.h file
 and set the TIMMER_ENABLED setting to 'false'.  The header file can
 be found under the 'Arduino/libraries/NewPing' folder.

+https://github.com/wayoda/LedControl
+
 */
+
+
+// Edit this to rename your robot, you may also rename your robot via Firmata
+
+#define MY_ROBOTS_NAME		"Codee"
+
+
+// Edit this to give your robot a new pin number
+
+#define MY_ROBOTS_PIN		1234
+
+
+/* ----------------------------------------------------------------------------------------------------------------------------*/

 #include <Servo.h>
 #include <Wire.h>
@@ -65,10 +78,11 @@

 // CRE SYSEX Commands
 #define CRE_ULTRASOUND				0x08
-#define CRE_SAY						0x09
+#define CRE_AUDIO					0x09
 #define CRE_LED_DISPLAY				0x0A
 #define CRE_SWING_ARMS				0x0B
 #define CRE_LOOK_AROUND				0x0C
+#define CRE_HCO6_CMD				0x0D

 // CRE configuration
 #define CRE_DEFAULT_CONFIGURATION_INPUTS 0x000400 // each bit: 1 = pin in INPUT, 0 = anything else
@@ -107,11 +121,226 @@

 #define SPEAKER					13

-#define TEXT_TO_SAY_BUFFER_LEN	60
+#define TEXT_TO_SAY_BUFFER_LEN	30
+
+#define MELODY_TO_PLAY_BUFFER_LEN 40
+
+#define AUDIO_SAY			0
+#define AUDIO_MELODY_BLTIN	1
+#define AUDIO_MELODY_USR	2
+#define AUDIO_TONE			3
+
+#define NOTE_RST 0
+#define NOTE_B0  31
+#define NOTE_C1  33
+#define NOTE_CS1 35
+#define NOTE_D1  37
+#define NOTE_DS1 39
+#define NOTE_E1  41
+#define NOTE_F1  44
+#define NOTE_FS1 46
+#define NOTE_G1  49
+#define NOTE_GS1 52
+#define NOTE_A1  55
+#define NOTE_AS1 58
+#define NOTE_B1  62
+#define NOTE_C2  65
+#define NOTE_CS2 69
+#define NOTE_D2  73
+#define NOTE_DS2 78
+#define NOTE_E2  82
+#define NOTE_F2  87
+#define NOTE_FS2 93
+#define NOTE_G2  98
+#define NOTE_GS2 104
+#define NOTE_A2  110
+#define NOTE_AS2 117
+#define NOTE_B2  123
+#define NOTE_C3  131
+#define NOTE_CS3 139
+#define NOTE_D3  147
+#define NOTE_DS3 156
+#define NOTE_E3  165
+#define NOTE_F3  175
+#define NOTE_FS3 185
+#define NOTE_G3  196
+#define NOTE_GS3 208
+#define NOTE_A3  220
+#define NOTE_AS3 233
+#define NOTE_B3  247
+#define NOTE_C4  262
+#define NOTE_CS4 277
+#define NOTE_D4  294
+#define NOTE_DS4 311
+#define NOTE_E4  330
+#define NOTE_F4  349
+#define NOTE_FS4 370
+#define NOTE_G4  392
+#define NOTE_GS4 415
+#define NOTE_A4  440
+#define NOTE_AS4 466
+#define NOTE_B4  494
+#define NOTE_C5  523
+#define NOTE_CS5 554
+#define NOTE_D5  587
+#define NOTE_DS5 622
+#define NOTE_E5  659
+#define NOTE_F5  698
+#define NOTE_FS5 740
+#define NOTE_G5  784
+#define NOTE_GS5 831
+#define NOTE_A5  880
+#define NOTE_AS5 932
+#define NOTE_B5  988
+#define NOTE_C6  1047
+#define NOTE_CS6 1109
+#define NOTE_D6  1175
+#define NOTE_DS6 1245
+#define NOTE_E6  1319
+#define NOTE_F6  1397
+#define NOTE_FS6 1480
+#define NOTE_G6  1568
+#define NOTE_GS6 1661
+#define NOTE_A6  1760
+#define NOTE_AS6 1865
+#define NOTE_B6  1976
+#define NOTE_C7  2093
+#define NOTE_CS7 2217
+#define NOTE_D7  2349
+#define NOTE_DS7 2489
+#define NOTE_E7  2637
+#define NOTE_F7  2794
+#define NOTE_FS7 2960
+#define NOTE_G7  3136
+#define NOTE_GS7 3322
+#define NOTE_A7  3520
+#define NOTE_AS7 3729
+#define NOTE_B7  3951
+#define NOTE_C8  4186
+#define NOTE_CS8 4435
+#define NOTE_D8  4699
+#define NOTE_DS8 4978
+#define NOTE_P0	 0000
+
+#define AUDIO_MELODIES_BLTIN	4
+
+const static uint16_t AUDIO_MELODIES_NOTES[] PROGMEM = {
+	// Green Sleeves
+	19,
+	NOTE_FS3,
+	NOTE_A3, NOTE_B3,
+	NOTE_CS4, NOTE_D4, NOTE_CS4,
+	NOTE_B3, NOTE_GS3,
+	NOTE_E3, NOTE_FS3, NOTE_GS3,
+	NOTE_A3, NOTE_FS3,
+	NOTE_FS3, NOTE_F3, NOTE_FS3,
+	NOTE_GS3, NOTE_F3,
+	NOTE_CS3,
+	// Marry Had a Little Lamb
+	26,
+	NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3,
+	NOTE_E3, NOTE_E3, NOTE_E3,
+	NOTE_D3, NOTE_D3, NOTE_D3,
+	NOTE_E3, NOTE_G3, NOTE_G3,
+	NOTE_E3, NOTE_D3, NOTE_C3, NOTE_D3,
+	NOTE_E3, NOTE_E3, NOTE_E3, NOTE_E3,
+	NOTE_D3, NOTE_D3, NOTE_E3, NOTE_D3,
+	NOTE_C3,
+	// Happy Birthday
+	25,
+	NOTE_G3, NOTE_G3,
+	NOTE_A3, NOTE_G3, NOTE_C4,
+	NOTE_B3, NOTE_G3, NOTE_G3,
+	NOTE_A3, NOTE_G3, NOTE_D4,
+	NOTE_C4, NOTE_G3, NOTE_G3,
+	NOTE_G4, NOTE_E4, NOTE_C4,
+	NOTE_B3, NOTE_A3, NOTE_G4, NOTE_G4,
+	NOTE_E4, NOTE_C4, NOTE_D4,
+	NOTE_C4,
+	// Star Wars
+	40,
+	NOTE_A3, NOTE_A3, NOTE_A3,
+	NOTE_D4, NOTE_A4, NOTE_RST,
+	NOTE_G4, NOTE_FS4, NOTE_E4, NOTE_D5, NOTE_A4,
+	NOTE_G4, NOTE_FS4, NOTE_E4, NOTE_D5, NOTE_A4,
+	NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_E4, NOTE_RST, NOTE_A3, NOTE_A3, NOTE_A3,
+	NOTE_D4, NOTE_A4,
+	NOTE_G4, NOTE_FS4, NOTE_E4, NOTE_D5, NOTE_A4,
+	NOTE_G4, NOTE_FS4, NOTE_E4, NOTE_D5, NOTE_A4,
+	NOTE_G4, NOTE_FS4, NOTE_G4, NOTE_E4
+};
+
+const uint8_t AUDIO_MELODIES_NOTES_LEN = sizeof(AUDIO_MELODIES_NOTES) / sizeof(uint16_t);
+
+const static uint8_t AUDIO_MELODIES_DURATIONS[] PROGMEM = {
+	// Green Sleevs
+	19,
+	4,
+	2, 4,
+	3, 8, 4,
+	2, 4,
+	3, 8, 4,
+	2, 4,
+	3, 8, 4,
+	2, 4,
+	1,
+	// Mary Had a Little Lamb
+	26,
+	4, 4, 4, 4,
+	4, 4, 2,
+	4, 4, 2,
+	4, 4, 2,
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+	1,
+	// Happy Birthday
+	25,
+	8, 8,
+	4, 4, 4,
+	2, 8, 8,
+	4, 4, 4,
+	2, 8, 8,
+	4, 4, 4,
+	4, 4, 8, 8,
+	4, 4, 4,
+	2,
+	// Star Wars
+	40,
+	12, 12, 12,
+	2, 2, 8,
+	12, 12, 12, 2, 4,
+	12, 12, 12, 2, 4,
+	12, 12, 12, 2, 8, 12, 12, 12,
+	2, 2,
+	12, 12, 12, 2, 4,
+	12, 12, 12, 2, 4,
+	12, 12, 12, 2
+};
+
+const uint8_t AUDIO_MELODIES_DURATIONS_LEN = sizeof(AUDIO_MELODIES_DURATIONS) / sizeof(uint8_t);
+
+const static uint16_t NOTES[] PROGMEM = { // NOTE_P0 included to force a nice hash function
+	NOTE_A1, NOTE_AS1, NOTE_B1, NOTE_P0, NOTE_C1, NOTE_CS1, NOTE_D1, NOTE_DS1, NOTE_E1, NOTE_P0, NOTE_F1, NOTE_FS1, NOTE_G1, NOTE_GS1,	// Scale C1
+	NOTE_A2, NOTE_AS1, NOTE_B2, NOTE_P0, NOTE_C2, NOTE_CS2, NOTE_D2, NOTE_DS2, NOTE_E2, NOTE_P0, NOTE_F2, NOTE_FS2, NOTE_G2, NOTE_GS2,	// Scale C2
+	NOTE_A3, NOTE_AS1, NOTE_B3, NOTE_P0, NOTE_C3, NOTE_CS3, NOTE_D3, NOTE_DS3, NOTE_E3, NOTE_P0, NOTE_F3, NOTE_FS3, NOTE_G3, NOTE_GS3,	// Scale C3
+	NOTE_A4, NOTE_AS1, NOTE_B4, NOTE_P0, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_P0, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4,	// Scale C4
+	NOTE_A5, NOTE_AS1, NOTE_B5, NOTE_P0, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_P0, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5,	// Scale C5
+	NOTE_A6, NOTE_AS1, NOTE_B6, NOTE_P0, NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_P0, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6,	// Scale C6
+	NOTE_A7, NOTE_AS1, NOTE_B7, NOTE_P0, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_P0, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7,	// Scale C7
+	NOTE_P0, NOTE_P0, NOTE_P0, NOTE_P0, NOTE_C8, NOTE_CS8, NOTE_D1, NOTE_DS8															// Scale C8
+	};
+
+const uint8_t NOTES_LEN = sizeof(NOTES) / sizeof(uint16_t);

 // Bluetooth

-#define BLUETOOTH_RX_EN			12
+#define PIN_SETUP_HC06			21
+
+#define HC06_DATA_BUFFER_LEN	10
+
+#define HC06_CMD_SETNAME		1
+#define HC06_CMD_SETPIN			2

 // Local 8x8 display data

@@ -126,10 +355,13 @@
 	0x7e3c1805, 0x03070507,			// rock
 	0x1f3e7cf9, 0xf1070507,			// paper
 	0xd8f82027, 0x54570107,			// sissors
+	0x10387cfe, 0xfeee4400,			// Heart
+	0x060e0c08, 0x08281800,			// Quaver
+	0x066eecc8, 0x8898f000,			// Quaver x 2
 	0x00000000, 0x00000000			// blank
 };

-const uint8_t LED_DISPLAY_IMAGES_LEN = sizeof(LED_DISPLAY_IMAGES) / sizeof(uint32_t);
+const uint8_t LED_DISPLAY_IMAGES_LEN = sizeof(LED_DISPLAY_IMAGES) / sizeof(uint32_t) / 2;

 const static uint32_t LED_DISPLAY_DIGITS[][2] PROGMEM = {
 	0x0000e0a0, 0xa0a0e000,			// 0
@@ -144,7 +376,7 @@
 	0x00008080, 0xe0a0e000			// 9
 };

-const int LED_DIGITS_LEN = sizeof(LED_DISPLAY_DIGITS) / sizeof(uint32_t);
+const int LED_DIGITS_LEN = sizeof(LED_DISPLAY_DIGITS) / sizeof(uint32_t) / 2;

 const static uint32_t LED_DISPLAY_CHARACTERS[][2] PROGMEM = {
 	0x00000000, 0x00000000,
@@ -245,7 +477,7 @@
 	0x00000000, 0x00000000			// del
 };

-const int LED_DISPLAY_CHARACTERS_LEN = sizeof(LED_DISPLAY_CHARACTERS) / sizeof(uint32_t);
+const int LED_DISPLAY_CHARACTERS_LEN = sizeof(LED_DISPLAY_CHARACTERS) / sizeof(uint32_t) / 2;

 #define GETSCROLLROW(c, b)				((byte)((c >> (8*b)) & 0xFF))
 #define GETDISPLAYROW(c, b)				((byte)((c >> (8*(7-b)) & 0xFF)))
@@ -260,7 +492,10 @@
 #define LED_DISPLAY_ROCK				7
 #define LED_DISPLAY_PAPER				8
 #define LED_DISPLAY_SISSORS				9
-#define LED_DISPLAY_BLANK				10
+#define LED_DISPLAY_QUAVER				10
+#define LED_DISPLAY_QUAVERx2			11
+#define LED_DISPLAY_HEART				12
+#define LED_DISPLAY_BLANK				13

 #define LED_SET_IMAGE					1
 #define LED_SET_SCROLL_TEXT				2
@@ -269,7 +504,12 @@
 #define LED_SET_SET_PIXEL				5
 #define LED_SET_CLEAR					6

-#define TEXT_TO_SCROLL_BUFFER_LEN		60
+#define LED_DISPLAY_TYPE_IMAGES			0
+#define LED_DISPLAY_TYPE_DIGITS			1
+#define LED_DISPLAY_TYPE_ASCII			2
+
+
+#define TEXT_TO_SCROLL_BUFFER_LEN		30

 /*==============================================================================
 * GLOBAL VARIABLES
@@ -354,11 +594,20 @@
 boolean isHeadSwing = false;
 boolean isTextToScroll = false;
 boolean isTextToSay = false;
+boolean isMelodyToPlay = false;
+
+uint8_t ledDisplayImage = 0, ledDisplayDigits = 0, ledDisplayASCII = 0;
+
+uint8_t ledDisplayType = 0;

 uint8_t armSwingSpeed = 0, headSwingSpeed = 0;

 uint8_t textToScrollLen = 0;
 byte textToScrollBuffer[TEXT_TO_SCROLL_BUFFER_LEN];
+
+uint8_t	melodyToPlayLen = 0;
+uint16_t melodyToPlayNoteBuffer[MELODY_TO_PLAY_BUFFER_LEN];
+uint8_t melodyToPlayDurationBuffer[MELODY_TO_PLAY_BUFFER_LEN];

 unsigned long scrollInterval = 200;
 unsigned long armSwingInterval = 25;
@@ -367,6 +616,8 @@
 uint8_t textToSayLen = 0;
 byte textToSayBuffer[TEXT_TO_SAY_BUFFER_LEN];

+uint8_t hc06DataBuffer[HC06_DATA_BUFFER_LEN];
+
 /*==============================================================================
 * FUNCTIONS (CREATIVE ROBOTIX PLATFORM)
 *============================================================================*/
@@ -374,11 +625,6 @@
 void initCreativeRobotixPlatform() {
 	uint64_t character;

-	// Configure A0 and A1 as digital outputs
-
-	setPinModeCallback(14, OUTPUT);
-	setPinModeCallback(15, OUTPUT);
-
 	// Initialise the MAX72XX display

 	ledDisplay.shutdown(0, false);		// The MAX72XX is in power-saving mode on startup
@@ -386,21 +632,61 @@
 	ledDisplay.clearDisplay(0);			// and clear the display

 	// LED Display to neutral
-	character = pgm_read_dword(&(LED_DISPLAY_IMAGES[LED_DISPLAY_NEUTRAL][0])); // High
-	character = (character << 32) | pgm_read_dword(&(LED_DISPLAY_IMAGES[LED_DISPLAY_NEUTRAL][1])); // Low
-	setLEDisplay(character);
+
+	setLEDDisplayImage(LED_DISPLAY_NEUTRAL);

 	// Say hello, I'm active
 	sayDirect("Hello World!");

-	// If transistor in place, this will turn on the Blutooth serial RX, disabling USB Serial RX
-
-	BluetoothRX(true);
-
-	// LED display to smile
-	character = pgm_read_dword(&(LED_DISPLAY_IMAGES[LED_DISPLAY_SMILE][0])); // High
-	character = (character << 32) | pgm_read_dword(&(LED_DISPLAY_IMAGES[LED_DISPLAY_SMILE][1])); // Low
+	setLEDDisplayImage(LED_DISPLAY_SMILE);
+}
+
+
+void restoreLEDDisplay(void) {
+	switch (ledDisplayType) {
+	case LED_DISPLAY_TYPE_IMAGES:
+		setLEDDisplayImage(ledDisplayImage);
+		break;
+	case LED_DISPLAY_TYPE_DIGITS:
+		setLEDDisplayDigits(ledDisplayDigits);
+		break;
+	case LED_DISPLAY_TYPE_ASCII:
+		setLEDDisplayASCII(ledDisplayASCII);
+		break;
+	default:
+		break;
+	}
+}
+
+void setLEDDisplayImage(uint8_t image) {
+	uint64_t character;
+	character = pgm_read_dword(&(LED_DISPLAY_IMAGES[image][0])); // High
+	character = (character << 32) | pgm_read_dword(&(LED_DISPLAY_IMAGES[image][1])); // Low
 	setLEDisplay(character);
+	ledDisplayImage = image;
+	ledDisplayType = LED_DISPLAY_TYPE_IMAGES;
+}
+
+
+void setLEDDisplayDigits(uint8_t number) {
+	uint64_t digit_tens, digit_units;
+	digit_tens = pgm_read_dword(&(LED_DISPLAY_DIGITS[int(number/10)][0])); // High
+	digit_tens = (digit_tens << 32) | pgm_read_dword(&(LED_DISPLAY_DIGITS[int(number / 10)][1])); // Low
+	digit_units = pgm_read_dword(&(LED_DISPLAY_DIGITS[number - (int(number/10)*10)][0])); // High
+	digit_units = (digit_units << 32) | pgm_read_dword(&(LED_DISPLAY_DIGITS[number - (int(number / 10) * 10)][1])); // Low
+	setLEDisplay((digit_tens >> 4) | digit_units);
+	ledDisplayDigits = number;
+	ledDisplayType = LED_DISPLAY_TYPE_DIGITS;
+}
+
+
+void setLEDDisplayASCII(uint8_t ascii) {
+	uint64_t character;
+	character = pgm_read_dword(&(LED_DISPLAY_IMAGES[ascii][0])); // High
+	character = (character << 32) | pgm_read_dword(&(LED_DISPLAY_CHARACTERS[ascii][1])); // Low
+	setLEDisplay(character);
+	ledDisplayASCII = ascii;
+	ledDisplayType = LED_DISPLAY_TYPE_ASCII;
 }

 void setLEDisplay(const uint64_t character)
@@ -420,7 +706,7 @@
 	static unsigned long toneDuration;		// store current tone duration

 	l_currentMillis = millis();
-
+
 	if (character >= textToSayLen) { // All done, reset
 		isTextToSay = false;
 		character = 0;
@@ -443,13 +729,62 @@
 	}
 }

-void updateTextToScroll() {
+void updateMelodyToPlay() {
+	/* timer variables */
+	static uint8_t note = 0;
+	static boolean noteActive = false, notePause = false;
+	static unsigned long l_currentMillis;	// store the current value from millis()
+	static unsigned long l_previousMillis;	// for comparison with currentMillis
+	static unsigned long noteDuration;		// store current note duration
+	static unsigned long notePauseDuration;	// store current note duration
+
+	l_currentMillis = millis();
+
+	if (note >= melodyToPlayLen) { // All done, reset
+		isMelodyToPlay = false;
+		note = 0;
+		melodyToPlayLen = 0;
+	}
+	else { // Still have a character to say, have we finished the tone?
+		if (!noteActive) { // If no active note, play the next one
+			noteDuration = (1000 / melodyToPlayDurationBuffer[note]);
+			tone(SPEAKER, melodyToPlayNoteBuffer[note], noteDuration); // convert character to suitable frequency, currently arbitary, update?
+			noteActive = true;
+			l_previousMillis = l_currentMillis;
+		}
+		else { // update timmer and tone
+			if (!notePause) {
+				if ((l_currentMillis - l_previousMillis) > noteDuration) { // tone duration reached
+					notePauseDuration = noteDuration * 0.30; // 30% seems to work well
+					notePause = true;
+					l_previousMillis = l_currentMillis;
+				}
+			}
+			else {
+				if ((l_currentMillis - l_previousMillis) > notePauseDuration) {
+					noTone(SPEAKER);
+					notePause = false;
+					noteActive = false;
+					note++; // next note
+				}
+			}
+		}
+	}
+}
+
+void updateTextToScroll(boolean reset) {
 	static uint8_t character = 0, character_previous = 1, character_scroll = 0, cindex;
 	static unsigned long l_currentMillis;	// store the current value from millis()
 	static unsigned long l_previousMillis;	// for comparison with currentMillis
 	static uint64_t current_character = 0, screen = 0, column_update;

 	l_currentMillis = millis();
+
+	if (reset) {  // Reset the state
+		character = 0;
+		character_previous = 1, character_scroll = 0;
+		current_character = 0, screen = 0, column_update = 0;
+	}

 	if ((l_currentMillis - l_previousMillis) > scrollInterval) {
 		// update screen buffer
@@ -559,10 +894,105 @@
 	}
 }

-void BluetoothRX(bool active) {
-	// Controls the Bluetooth serial receive, when active USB receive is turned off.
-
-	setPinValueCallback(BLUETOOTH_RX_EN, active);
+boolean setHC06S4A(void) {
+	uint8_t i;
+	boolean btatcrlf = true;
+	String response, command;
+	unsigned long baudrate[] = { 57600, 9600, 1200, 2400, 4800, 19200, 38400, 115200 };
+
+	if (analogRead(PIN_SETUP_HC06) > 50) { // Nothing to do
+		return (false);
+	}
+
+	// Discover HC-06 current baudrate
+
+	uint8_t baudrates = sizeof(baudrate) / sizeof(baudrate[0]);
+
+	for (i = 0; i < baudrates; i++) {
+
+		// Try to connect
+		sayDirect("ATAT");
+		Serial.begin(baudrate[i]);
+
+		// Two types of firmwaire to deal with, types which require <CR><LF>, and types that do not
+
+		// Are we dealing with HC-05 type firmaware requiring <CR><LF>?
+
+		Serial.print("AT\r\n");
+		Serial.setTimeout(1000);
+		response = Serial.readString();
+
+		Serial.print("AT\r\n");			// TODO: Find out why this only works the second time, timming? Delays?
+		Serial.setTimeout(1000);
+		response = Serial.readString();
+
+		// Were we successful?
+
+		if (response.startsWith("OK")) {
+			break; // Yes, got it.
+		}
+
+		// Are we deadling with HC-06 firware with NO <CR><LF> needed?
+
+		Serial.print("AT");
+		Serial.setTimeout(1000);
+		response = Serial.readString();
+
+		Serial.print("AT");			// TODO: Find out why this only works the second time, timming? Delays?
+		Serial.setTimeout(1000);
+		response = Serial.readString();
+
+		// Were we successful?
+
+		if (response.startsWith("OK")) {
+			btatcrlf = false;
+			break; // Yes, got it.
+		}
+
+		Serial.end();
+	}
+
+	if (i == baudrates) { // Couldn't connect to the HC-06
+		while (1) { sayDirect("{}"); delay(100); }; // Sound the alarm...
+	}
+
+	// All good, let's congigure...
+
+	// Set Name
+	// TODO restrict name to 20 characters
+	(btatcrlf) ? command = (String)"AT+NAME" + (String)MY_ROBOTS_NAME + (String)"\r\n" : command = (String)"AT+NAME" + (String)MY_ROBOTS_NAME;
+	Serial.print(command);
+	Serial.setTimeout(3000);
+	delay(500);
+	sayDirect("OK");
+	// Set Pin
+
+	(btatcrlf) ? command = (String)"AT+PIN" + MY_ROBOTS_PIN + (String)"\r\n" : command = (String)"AT+PIN" + MY_ROBOTS_PIN;
+	Serial.print(command);
+	Serial.setTimeout(3000);
+	delay(500);
+	sayDirect("OK");
+
+	// Disable indications
+
+	(btatcrlf) ? command = (String)"AT+ENABLEIND0" + (String)"\r\n" : command = (String)"AT+ENABLEIND0";
+	Serial.print(command);
+	Serial.setTimeout(3000);
+	delay(500);
+	sayDirect("OK");
+
+	// Set S4A Baud rate
+
+	(btatcrlf) ? command = (String)"AT+BAUD7" + (String)"\r\n" : command = (String)"AT+BAUD7";
+
+	Serial.print(command);
+	Serial.setTimeout(3000);
+	delay(500);
+	sayDirect("OK");
+
+	Serial.end();
+
+	return(true); // setup complete
 }

 /*==============================================================================
@@ -942,7 +1372,7 @@
 	byte data;
 	int slaveRegister;
 	unsigned int delayTime;
-
+
 	switch (command) {
 	case I2C_REQUEST:
 		mode = argv[1] & I2C_READ_WRITE_MODE_MASK;
@@ -1056,7 +1486,7 @@
 		break;
 	case SERVO_CONFIG:
 		if (argc > 4) {
-
+
 			// these vars are here for clarity, they'll optimized away by the compiler
 			byte pin = argv[0];
 			int minPulse = argv[1] + (argv[2] << 7);
@@ -1161,8 +1591,12 @@
 		serialFeature.handleSysex(command, argc, argv);
 #endif
 		break;
+
+	/////////////////////////////////////////////////////
+	//////// CRE Cases
+	////////////////////////////////////////////////////
 	case CRE_ULTRASOUND:
-		{
+	{
 		// Ensure ultrasound pins have the correct sense
 		setPinModeCallback(HCSR04_TRIGGER, OUTPUT);
 		setPinModeCallback(HCSR04_ECHO, INPUT);
@@ -1173,71 +1607,116 @@
 		Firmata.write(STRING_DATA);
 		Serial.println((byte)range);  // Can we use Firmata.write(ULTRASOUND); Firmata.write(range);?
 		Firmata.write(END_SYSEX);
-		}
-		break;
-	case CRE_SAY:
-	{
-		uint8_t i = 0;
-		for (i; (i < argc) && (i < TEXT_TO_SAY_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
-			textToSayBuffer[i] = argv[i];
-		}
-		textToSayLen = i;
-		isTextToSay = true;
-	}
-		break;
+	}
+	break;
+	case CRE_AUDIO:
+		mode = argv[0];
+		switch (mode) {
+		case AUDIO_SAY:
+		{
+			uint8_t i = 1;
+			for (i; (i < argc) && (i < TEXT_TO_SAY_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
+				textToSayBuffer[i] = argv[i];
+			}
+			textToSayLen = i;
+			isTextToSay = true;
+		}
+		break;
+		case AUDIO_MELODY_BLTIN:
+		{
+
+			uint8_t melody = argv[1] % AUDIO_MELODIES_BLTIN;
+
+			uint8_t melody_record_start = 0;
+
+			for (uint8_t i = 0; i < melody; i++) {  // Work out melodies location
+				melody_record_start += pgm_read_word(&(AUDIO_MELODIES_NOTES[melody_record_start])) + 1; // melody record number_of_notes (+1);
+			}
+
+			melodyToPlayLen = pgm_read_word(&(AUDIO_MELODIES_NOTES[melody_record_start]));
+
+			for (uint8_t i = 0; i < melodyToPlayLen; i++) {
+				melodyToPlayNoteBuffer[i] = pgm_read_word(&(AUDIO_MELODIES_NOTES[melody_record_start + i + 1])); // offset the melody record start for first note in record
+				melodyToPlayDurationBuffer[i] = pgm_read_byte(&(AUDIO_MELODIES_DURATIONS[melody_record_start + i + 1]));
+			}
+
+			isMelodyToPlay = true;
+		}
+		break;
+		case AUDIO_MELODY_USR:
+		{
+			melodyToPlayLen = 0;
+			for (uint8_t i = 1; i < argc  && (melodyToPlayLen < MELODY_TO_PLAY_BUFFER_LEN); i += 3) { // each note have three bytes <freqency high byte, frequency low byte, duration> Silently drop notes > MAX_BUFFER
+
+				melodyToPlayNoteBuffer[melodyToPlayLen] = (argv[i] << 8) | argv[i + 1];
+				melodyToPlayDurationBuffer[melodyToPlayLen] = argv[i + 2];
+				melodyToPlayLen++;
+			}
+			isMelodyToPlay = true;
+		}
+		break;
+		case AUDIO_TONE:
+		{
+			melodyToPlayNoteBuffer[0] = (argv[1] << 8) | argv[2];
+			melodyToPlayDurationBuffer[0] = 1000 / ((argv[3] << 8) | argv[4]);
+			melodyToPlayLen = 1;
+			isMelodyToPlay = true;
+		}
+		break;
+		}
+	break;
 	case CRE_LED_DISPLAY:
 		mode = argv[0];
 		switch (mode) {
 		case LED_SET_IMAGE:
 			if (argv[1] < LED_DISPLAY_IMAGES_LEN) { // Stay silent if argv value greater than display images
-				uint64_t character;
-				character = pgm_read_dword(&(LED_DISPLAY_IMAGES[argv[1]][0])); // High
-				character = (character << 32) | pgm_read_dword(&(LED_DISPLAY_IMAGES[argv[1]][1])); // Low
-				setLEDisplay(character);
-			}
-			break;
+				setLEDDisplayImage(argv[1]);
+			}
+		break;
 		case LED_SET_SCROLL_TEXT:
 		{
-			for (uint8_t i = 1; (i < argc) && (i < TEXT_TO_SCROLL_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
-				textToScrollBuffer[i - 1] = argv[i];
-			}
-			textToScrollLen = argc - 1;
-			isTextToScroll = true;
-		}
-			break;
+			if (argv[1] == true) {
+				for (uint8_t i = 2; (i < argc) && (i < TEXT_TO_SCROLL_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
+					textToScrollBuffer[i - 2] = argv[i];
+				}
+				textToScrollLen = argc - 2;
+				updateTextToScroll(true);
+				isTextToScroll = true;
+			}
+			else {
+				isTextToScroll = false;
+				restoreLEDDisplay();
+			}
+
+		}
+		break;
 		case LED_SET_NUMBER:
-			// Construct a two digit number for display
-			if (argv[1] < LED_DIGITS_LEN && argv[2] < LED_DIGITS_LEN) {
-				uint64_t digit_tens, digit_units;
-				digit_tens = pgm_read_dword(&(LED_DISPLAY_DIGITS[argv[1]][0])); // High
-				digit_tens = (digit_tens << 32) | pgm_read_dword(&(LED_DISPLAY_DIGITS[argv[1]][1])); // Low
-				digit_units = pgm_read_dword(&(LED_DISPLAY_DIGITS[argv[2]][0])); // High
-				digit_units = (digit_units << 32) | pgm_read_dword(&(LED_DISPLAY_DIGITS[argv[2]][1])); // Low
-				setLEDisplay((digit_tens >> 4) | digit_units);
-			}
-			break;
+			if (argv[1] >= 0 && argv[1] < LED_DIGITS_LEN * 10) {
+				setLEDDisplayDigits(argv[1]);
+			}
+		break;
 		case LED_SET_ROW_DATA:
 		{
 			if ((argc - 1) == MAX72XX_WIDTH) {
-				uint64_t rowData = 0;
+				uint64_t rowData = 0;
 				for (uint8_t i = 1; i < argc; i++) {
 					rowData = (rowData << 8) | (argv[i] & 0xFF);
 				}
 				setLEDisplay(rowData);
 			}
 		}
-			break;
+		break;
 		case LED_SET_SET_PIXEL:
 			if (argv[1] < MAX72XX_WIDTH && argv[2] < MAX72XX_HEIGHT) {
 				ledDisplay.setLed(0, argv[1], argv[2], argv[3]);
 			}
-			break;
+		break;
 		case LED_SET_CLEAR:
 			isTextToScroll = false;
-			setLEDisplay(0x0);
-			break;
-		}
-		break;
+			setLEDDisplayImage(LED_DISPLAY_BLANK);
+		break;
+		}
+	break;
 	case CRE_SWING_ARMS:
 		if (argc == 2) {
 			if (argv[1] == true) {
@@ -1251,7 +1730,7 @@
 				stopArmsSwing();
 			}
 		}
-		break;
+	break;
 	case CRE_LOOK_AROUND:
 		if (argc == 2) {
 			if (argv[1] == true) {
@@ -1265,7 +1744,105 @@
 				stopHeadSwing();
 			}
 		}
-		break;
+	break;
+	case CRE_HCO6_CMD:
+	{
+			// Wait for S4A to disconnect from HC-06 and enter into AT mode
+
+			for (uint8_t i = 0; i < 4; i++) {
+				sayDirect("ok");
+				delay(1000);
+			}
+
+			// Type HC05 firmware
+			Serial.print("AT\r\n");
+			Serial.setTimeout(1000);
+			String responsecrlf = Serial.readString();
+
+			// Type HC06 firmware
+			Serial.print("AT");
+			Serial.setTimeout(1000);
+			String response = Serial.readString();
+
+			// Were we successful?
+
+			if (responsecrlf.startsWith("OK") || response.startsWith("OK")) {
+				mode = argv[0];
+
+				switch (mode) {
+				case HC06_CMD_SETNAME:
+				{
+					// Set Name
+
+					String hc06Command = "AT+NAME";  // Build command string
+
+					// Read data buffer
+					for (uint8_t i = 1; (i < argc) && (i < HC06_DATA_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
+						hc06Command += (char)argv[i];
+					}
+
+					// type HC05 firmware
+					if (responsecrlf.startsWith("OK")) {
+						hc06Command += (String)"\r\n";
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+					}
+
+					//type HC06 firmware
+					if (response.startsWith("OK")) {
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+					}
+
+					sayDirect("ok ok ok");
+				}
+				break;
+				case HC06_CMD_SETPIN:
+				{
+					String hc06Command = (String)"AT+PIN"; // Build command string
+
+					// Read data buffer
+					uint8_t i = 0;
+					for (i = 2; (i < argc) && (i < HC06_DATA_BUFFER_LEN); i++) { // Stay silent if text is longer than buffer
+						hc06Command += argv[i];
+					}
+
+					// type HC05 firmware
+					if (responsecrlf.startsWith("OK")) {
+						hc06Command += (String)"\r\n";
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+					}
+
+
+					//type HC06 firmware
+					if (response.startsWith("OK")) {
+						Serial.print(hc06Command);
+						Serial.setTimeout(3000);
+						delay(500);
+					}
+
+					sayDirect("ok ok ok");
+				}
+				break;
+				default:
+					sayDirect("{}{}{}{}{}{}{}{}{}"); // Signal Error
+				}
+			}
+			else {
+				sayDirect("{}{}{}{}{}{}{}{}{}"); // Signal Error
+			}
+	}
+	break;
 	}
 }

@@ -1337,6 +1914,9 @@

 void setup()
 {
+
+	setHC06S4A();  // setup HC06
+
 	Firmata.setFirmwareVersion(FIRMATA_FIRMWARE_MAJOR_VERSION, FIRMATA_FIRMWARE_MINOR_VERSION);

 	Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
@@ -1354,34 +1934,15 @@
 	// Firmata.begin(Serial1);
 	// However do not do this if you are using SERIAL_MESSAGE

-	Firmata.begin(57600);  // NOTE: change this back to 57600
+	Firmata.begin(57600);
 	while (!Serial) {
 		; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
 	}
-
+
 	systemResetCallback();  // reset to default config
-	// Firmata.printFirmwareVersion();
+
 	initCreativeRobotixPlatform(); // Initialise robot
 }
-
-//void staticReportVersionCallback(void * context) { if (context) { myFirmataPrintVersion(); } }
-
-/*
-void myFirmataPrintVersion(void)
-{
-static bool once = false;
-
-if (!once) {
-Firmata.printFirmwareVersion();
-}
-else {
-Firmata.write(REPORT_VERSION);
-Firmata.write(FIRMATA_PROTOCOL_MAJOR_VERSION);
-Firmata.write(FIRMATA_PROTOCOL_MINOR_VERSION);
-}
-}
-*/
-

 /*==============================================================================
 * LOOP()
@@ -1389,7 +1950,6 @@
 void loop()
 {
 	byte pin, analogPin;
-	static bool sendFirmwareVersion = false;

 	/* DIGITALREAD - as fast as possible, check for changes and output them to the
 	* FTDI buffer using Serial.print()  */
@@ -1398,7 +1958,6 @@
 	/* STREAMREAD - processing incoming messagse as soon as possible, while still
 	* checking digital inputs.  */
 	while (Firmata.available()) {
-		if (!sendFirmwareVersion) { Firmata.printFirmwareVersion(); sendFirmwareVersion = true; } /* Addresses Bluetooth connection issue */
 		Firmata.processInput();
 	}

@@ -1426,9 +1985,10 @@
 		// Do CRE updates ;

 		if (isTextToSay) updateTextToSay();
-		if (isTextToScroll) updateTextToScroll();
+		if (isTextToScroll) updateTextToScroll(false);
 		if (isArmsSwing) updateArmsSwing();
 		if (isHeadSwing) updateHeadSwing();
+		if (isMelodyToPlay) updateMelodyToPlay();
 	}

 #ifdef FIRMATA_SERIAL_FEATURE