Improvements and reordering

Improvements and reordering

--- staff/staff.ino
+++ staff/staff.ino
@@ -4,7 +4,7 @@
 #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 100         // Number of LED's.
+#define NUM_LEDS 1500         // Number of LED's.
 struct CRGB leds[NUM_LEDS];   // Initialize our LED array.
 uint8_t max_bright = 128;     // Overall brightness definition. It can be changed on the fly.
 unsigned long previousMillis; // Store last time the strip was updated.
@@ -13,29 +13,29 @@

 #define BEAUTIFUL_SPARKLES 1
 #define DISCO_BARBER_2 2
-#define DISCO_BARBER_1 3
-#define SINGLE_COLOR_SPARKLES 4
-#define WORMS 5
+#define SINGLE_COLOR_SPARKLES 3
+#define WORMS 4
+#define DISCO_BARBER_1 5
 #define PARTY 6
 #define DISCO_TWIRL 7
 #define NIGHT_SPARKLES 8

 int maxPatternId = 8;
-int rotationInMillseconds = 2000; // 20 seconds for production
+int rotationInMillseconds = 20000; // 20 seconds for production

 // Either A)
-bool holdPattern = true;
-int patternId = DISCO_TWIRL;
+//bool holdPattern = true;
+//int patternId = PARTY;
 // OR B)
-//bool holdPattern = false;
-//int patternId = BEAUTIFUL_SPARKLES;
+bool holdPattern = false;
+int patternId = BEAUTIFUL_SPARKLES;

 void setup() {
-  delay(1000);
+  delay(50);
   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, 3000);
+  set_max_power_in_volts_and_milliamps(5, 10000);
   randomSeed(analogRead(0));
 }

@@ -63,9 +63,9 @@
     leds[pos] = CHSV(hue, 180, 255);
   }
   for (int i = 0; i < numberOfSparkles * 4; i++) {
-    leds[random16(NUM_LEDS)] += CHSV(hue, 200, 20);
-  }
-  hue = hue + 1;
+    leds[random16(NUM_LEDS)] = CHSV(hue, 200, 20);
+  }
+  hue += 24;
 }

 void beautifulSparkles() {
@@ -144,7 +144,7 @@
 int partySeedDirection = true;

 void party() {
-  int partySeedLength = 200;
+  int partySeedLength = 800;
   if (firstTimeRunningThroughPattern) {
     partySeed = 0;
   } else {
@@ -158,7 +158,7 @@
   EVERY_N_MILLISECONDS(500) {
     hue += 33;
   }
-  fadeToBlackBy(leds, NUM_LEDS, 120);
+  fadeToBlackBy(leds, NUM_LEDS, 80);
   int brightness = 255;
   int saturation = 200;
   int pos = random(partySeed - partySeedLength, partySeed + partySeedLength);
@@ -182,8 +182,8 @@
 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.
+bool thisdir = 1;                                             // You can change direction.
+int8_t thisspeed = 48;                                         // 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 = 200;                                     // You can change the cutoff value to display this wave. Lower value = longer wave.
@@ -191,8 +191,15 @@
 void discoTwirl() {

   if (firstTimeRunningThroughPattern) {
-    allfreq = 32;
-    thiscutoff -= 240;
+    thishue = 0;                                          // You can change the starting hue value for the first wave.
+    thisrot = 0;                                          // You can change how quickly the hue rotates for this wave. Currently 0.
+    allsat = 255;                                         // I like 'em fully saturated with colour.
+    thisdir = 1;                                             // You can change direction.
+    thisspeed = 48;                                         // You can change the speed, and use negative values.
+    allfreq = 32;                                         // You can change the frequency, thus overall width of bars.
+    thisphase = 0;                                            // Phase change value gets calculated.
+    thiscutoff = 200;
+
   } else {
     EVERY_N_MILLISECONDS(1000) {
 //      allfreq += 1;
@@ -202,8 +209,8 @@
     }
   }

-  //  if (thisdir == 0) thisphase+=thisspeed; else thisphase-=thisspeed;          // You can change direction and speed individually.
-  thisphase += thisspeed;
+  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)..
@@ -239,8 +246,6 @@
     discoTwirl();
   }

-  delay(30);
-
   firstTimeRunningThroughPattern = false;

   show_at_max_brightness_for_power();


Tidying and removing patterns

Tidying and removing patterns

--- staff/staff.ino
+++ staff/staff.ino
@@ -1,6 +1,6 @@
 #include "FastLED.h"
 #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
+#define qsuba(x, b)  ((x>b)?x-b:0)  // Analog Unsigned subtraction macro. if result <0, then => 0
 #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
@@ -168,56 +168,12 @@
     }

     if (patternId == DISCO_BARBER_1) {
-      // original disco barber 1
-      // leds[k] += CHSV(hue+k/5, discoBarberSaturation, _brightness);                             // Then assign a hue to any that are bright enough.
       leds[k] += CHSV(hue * 10 + k / 2, discoBarberSaturation, _brightness);                             // Then assign a hue to any that are bright enough.
     } else {
       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 = 1500;
-//  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(100) {
-//    hue += 5;
-//  }
-//  fadeToBlackBy(leds, NUM_LEDS, 80);
-//  int brightness = 255;
-//  int saturation = 200;
-//  int pos;
-//
-//  for (int i = 0; i < 3; i++) {
-//    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 thishue = 0;                                          // You can change the starting hue value for the first wave.
 uint8_t thisrot = 18;                                          // You can change how quickly the hue rotates for this wave. Currently 0.
@@ -310,8 +266,6 @@
     discoBarber();
   } else if (patternId == WORMS) {
     worms();
-//  } else if (patternId == PARTY) {
-//    party();
   } else if (patternId == DISCO_TWIRL) {
     discoTwirl();
   } else if (patternId == DISCO_TWIRL_2) {


finalizing UI for alpha demonstrations

finalizing UI for alpha demonstrations

--- display/display.ino
+++ display/display.ino
@@ -56,10 +56,10 @@
 Button sp_button = Button(0,BOXSIZE,BOXSIZE,BOXSIZE,ILI9341_GREEN,true,&tft);
 Button temp_button = Button(0,BOXSIZE*2,BOXSIZE,BOXSIZE,ILI9341_BLUE,true,&tft);
 Button alarm_button = Button(260,200,BOXSIZE,BOXSIZE,ILI9341_RED,true,&tft);
-Button confirm_button = Button(0,200,BOXSIZE,BOXSIZE,ILI9341_LIGHTGREY,true,&tft);
+Button confirm_button = Button(0,200,BOXSIZE,BOXSIZE,ILI9341_GREEN,true,&tft);
 Button mode_button = Button(BOXSIZE*2,200,BOXSIZE,BOXSIZE,ILI9341_LIGHTGREY,true,&tft);
-Button cancel_button = Button(BOXSIZE*3,200,BOXSIZE,BOXSIZE,ILI9341_LIGHTGREY,true,&tft);
-Button default_button = Button(tft.height()-BOXSIZE,BOXSIZE,BOXSIZE-10,BOXSIZE,ILI9341_LIGHTGREY,true,&tft);
+Button cancel_button = Button(WIDTH-BOXSIZE,200,BOXSIZE,BOXSIZE,ILI9341_RED,true,&tft);
+Button default_button = Button(WIDTH-2*BOXSIZE-18,BOXSIZE,BOXSIZE,BOXSIZE-20,ILI9341_LIGHTGREY,true,&tft);
 // Create settings page buttons

 /*for ECGMin value*/
@@ -84,8 +84,8 @@
  */

  //Write labels
-char Title[] = "Texas Engineering World Health";
-char Version[] = "Patient Monitor v2.1";
+char Title[] = "FreePulse Patient Monitor";
+char Version[] = "Alpha Software v0.1";
 char ecgTitle[] = "ECG/HR (bpm)";
 char ecgLabel[] = "ECG";
 char sp02Title[] = "sp02 (%Sat.)";
@@ -143,8 +143,8 @@
  * product_title() - prints product name and version no.
  */
 void product_title(){
-  createHLabel(BOXSIZE + 20, 0, Title, 1, ILI9341_WHITE);
-  createHLabel(BOXSIZE + 40, 10, Version, 1, ILI9341_WHITE);
+  createHLabel(BOXSIZE + 35, 0, Title, 1, ILI9341_WHITE);
+  createHLabel(BOXSIZE + 45, 10, Version, 1, ILI9341_WHITE);

   /* create border */
   tft.drawFastVLine(BOXSIZE + 17, 0, 20, ILI9341_WHITE);
@@ -213,7 +213,7 @@

 void default_button_setup(void){
   default_button.draw();
-  createHLabel(tft.height() - BOXSIZE + 10, BOXSIZE + 17, defaultLabel, 1, ILI9341_BLACK);
+  createHLabel(WIDTH - BOXSIZE + 10, BOXSIZE + 17, defaultLabel, 1, ILI9341_BLACK);
 }

 void mode_button_setup(void){
@@ -223,13 +223,13 @@

 void cancel_button_setup(void){
   cancel_button.draw();
-  createHLabel(BOXSIZE*3 + 14, 217, cancelLabel, 1, ILI9341_BLACK);
+  createHLabel(WIDTH + 35, 217, cancelLabel, 1, ILI9341_BLACK);
 }

 void ECGSettings_setup(void){
   /* MINIMUM VALUE */
   tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
-  tft.setCursor(63, 55);
+  (DEFAULT_ECG_MIN + biasECGMin < 100) ? tft.setCursor(63,55) : tft.setCursor(56,55);
   tft.setTextSize(2);
   tft.setTextColor(ILI9341_BLACK);
   tft.printf("%d", DEFAULT_ECG_MIN);
@@ -242,7 +242,7 @@

   /* MAXIMUM VALUE */
   tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
-  tft.setCursor(63, 105);
+  (DEFAULT_ECG_MAX + biasECGMax < 100) ? tft.setCursor(63,105) : tft.setCursor(56,105);
   tft.setTextSize(2);
   tft.setTextColor(ILI9341_BLACK);
   tft.printf("%d", DEFAULT_ECG_MAX + biasECGMax);
@@ -315,7 +315,7 @@
   tft.println("Alarm Settings");
   confirm_button_setup();
   default_button_setup();
-  mode_button_setup();
+  //mode_button_setup();
   cancel_button_setup();
   tft.drawFastVLine(BOXSIZE, 200, 40, ILI9341_BLACK);
   tft.drawFastVLine(BOXSIZE*2, 200, 40, ILI9341_BLACK);
@@ -407,6 +407,12 @@
   if (currentMode == HOMESCREEN){
     MainScreenInit();
     stopAlarm();
+    int delay_touch_detection = 10000;
+    for (int i = 0; i < delay_touch_detection; i += 1) {
+        if (!ts.bufferEmpty()){
+            volatile TS_Point tossout = getFixedCoordinates();
+        }
+    }
     while (currentMode == HOMESCREEN){
   		if (display_count >= 10) {
     		ecg.display_signal();
@@ -448,52 +454,132 @@
   }
   /*alarm screen*/
   if (currentMode == ALARMSCREEN){
+    // Prevent double button presses between cancel and alarm settings
     SettingsScreenInit();
+    int tempECGMaxbias = biasECGMax;
+    int tempECGMinbias = biasECGMin;
+    int delay_touch_detection = 10000;
+    for (int i = 0; i < delay_touch_detection; i += 1) {
+        if (!ts.bufferEmpty()){
+            volatile TS_Point tossout = getFixedCoordinates();
+        }
+    }
     //throwAlarm();
     while(currentMode == ALARMSCREEN){
       TS_Point p = getFixedCoordinates();
+      int total_ecg_max = DEFAULT_ECG_MAX + tempECGMaxbias;
+      int total_ecg_min = DEFAULT_ECG_MIN + tempECGMinbias;
       if(ECGPlus.isTapped(p.x,p.y)){
-        biasECGMin += 1;
+        // Skip if you'll exceed the max value
+        if (total_ecg_min + 1 > total_ecg_max) { continue; }
+        tempECGMinbias += 1;
         /*for two digit numbers*/
-        if (DEFAULT_ECG_MIN + biasECGMin < 100){
+        if (DEFAULT_ECG_MIN + tempECGMinbias < 100){
           tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
           tft.setCursor(63, 55);
           tft.setTextSize(2);
           tft.setTextColor(ILI9341_BLACK);
-          tft.printf("%d", DEFAULT_ECG_MIN + biasECGMin);
+          tft.printf("%d", DEFAULT_ECG_MIN + tempECGMinbias);
           }
-        else if (DEFAULT_ECG_MIN + biasECGMin > 99){
+        else if (DEFAULT_ECG_MIN + tempECGMinbias > 99){
           /*for three digit numbers*/
           tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
           tft.setCursor(56, 55);
           tft.setTextSize(2);
           tft.setTextColor(ILI9341_BLACK);
-          tft.printf("%d", DEFAULT_ECG_MIN + biasECGMin);
+          tft.printf("%d", DEFAULT_ECG_MIN + tempECGMinbias);
         }
       }
       if(ECGMinus.isTapped(p.x,p.y)){
-        biasECGMin -= 1;
+        // Don't let the minimum go negative
+        if (total_ecg_min - 1 < 0) { continue; }
+        tempECGMinbias -= 1;
         /*for two digit numbers*/
-        if (DEFAULT_ECG_MIN + biasECGMin < 100){
+        if (DEFAULT_ECG_MIN + tempECGMinbias < 100){
           tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
           tft.setCursor(63, 55);
           tft.setTextSize(2);
           tft.setTextColor(ILI9341_BLACK);
-          tft.printf("%d", DEFAULT_ECG_MIN + biasECGMin);
+          tft.printf("%d", DEFAULT_ECG_MIN + tempECGMinbias);
           }
-        else if (DEFAULT_ECG_MIN + biasECGMin > 99){
+        else if (DEFAULT_ECG_MIN + tempECGMinbias > 99){
           /*for three digit numbers*/
           tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
           tft.setCursor(56, 55);
           tft.setTextSize(2);
           tft.setTextColor(ILI9341_BLACK);
-          tft.printf("%d", DEFAULT_ECG_MIN + biasECGMin);
-        }
-      }
-
-        if(confirm_button.isTapped(p.x,p.y)){
-            currentMode = HOMESCREEN;
-        }
+          tft.printf("%d", DEFAULT_ECG_MIN + tempECGMinbias);
+        }
+      }
+
+      if(ECGPlus1.isTapped(p.x,p.y)){
+        // Set reasonable upper limit on heartrate
+        if (total_ecg_max + 1 > 300) { continue; }
+        tempECGMaxbias += 1;
+        /*for two digit numbers*/
+        if (DEFAULT_ECG_MAX + tempECGMaxbias < 100){
+          tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(63, 105);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MAX + tempECGMaxbias);
+          }
+        else if (DEFAULT_ECG_MAX + tempECGMaxbias > 99){
+          /*for three digit numbers*/
+          tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(56, 105);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MAX + tempECGMaxbias);
+        }
+      }
+      if(ECGMinus1.isTapped(p.x,p.y)){
+        // Don't let the max go any lower than the min
+        if (total_ecg_max - 1 < total_ecg_min) { continue; }
+        tempECGMaxbias -= 1;
+        /*for two digit numbers*/
+        if (DEFAULT_ECG_MAX + tempECGMaxbias < 100){
+          tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(63, 105);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MAX + tempECGMaxbias);
+          }
+        else if (DEFAULT_ECG_MAX + tempECGMaxbias > 99){
+          /*for three digit numbers*/
+          tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(56, 105);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MAX + tempECGMaxbias);
+        }
+      }
+
+      // Reset alarm parameters to the default values
+      if (default_button.isTapped(p.x,p.y)) {
+        tempECGMaxbias = 0;
+          tft.fillRect(52, 100, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(63, 105);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MAX + tempECGMaxbias);
+        tempECGMinbias = 0;
+          tft.fillRect(52, 50, 45, 25, ILI9341_LIGHTGREY);
+          tft.setCursor(63, 55);
+          tft.setTextSize(2);
+          tft.setTextColor(ILI9341_BLACK);
+          tft.printf("%d", DEFAULT_ECG_MIN + tempECGMinbias);
+      }
+
+      if(confirm_button.isTapped(p.x,p.y)){
+        biasECGMax = tempECGMaxbias;
+        biasECGMin = tempECGMinbias;
+        currentMode = HOMESCREEN;
+      }
+
+      if (cancel_button.isTapped(p.x,p.y)) {
+        currentMode = HOMESCREEN;
+      }
     }
   }
 }


Buf fixes

Buf fixes

--- Battery_Tester/Battery_Tester.ino
+++ Battery_Tester/Battery_Tester.ino
@@ -324,8 +324,8 @@
 void startInStationMode(){
 		WiFi.mode(WIFI_STA);
 		delay(1);
-        char  ssid[33]  = "NobodySeenMeDoItNobodyCanProveAg";
-        char  password[64]  = "ThisIsTheNewKey17.d";
+        char  ssid[33]  = "AP_Name";
+        char  password[64]  = "AP_Password";
         struct  station_config  stationConf;
         stationConf.bssid_set = 0;            //need  not check MAC address of  AP
         os_memcpy(&stationConf.ssid,  ssid, 33);


More leds FTW 🎄

More leds FTW 🎄

--- lotree.ino
+++ lotree.ino
@@ -18,8 +18,9 @@
 #include "TheaterChaseAnimation.h"
 #include "ColorWipeAnimation.h"
 #include "RainbowAnimation.h"
+#include "SequenceAnimation.h"

-#define TOTAL_LEDS 180
+#define TOTAL_LEDS 450
 #define PIN 6


Actually did some of the things I said...and more.

Also changed how the color is selected. Changed from a heading to just
using the most "active" axis on the compass, and mapping it to numbers
corresponding to a hue.

--- InfinityGoggles.ino
+++ InfinityGoggles.ino
@@ -28,7 +28,7 @@
 Adafruit_Simple_AHRS ahrs(&lsm.getAccel(), &lsm.getMag());

 float pos = 6;  // Starting center position of pupil
-float increment = 2 * 3.14159 / 21; // distance between pixels in radians
+float increment = 2 * 3.14159 / NUM_PIXELS; // distance between pixels in radians
 float MomentumH = 0; // horizontal component of pupil rotational inertia
 float MomentumV = 0; // vertical component of pupil rotational inertia

@@ -42,7 +42,7 @@
 long nodStart = 0;
 long nodTime = 2000;

-bool antiGravity = true;  // The pendulum will anti-gravitate to the top.
+bool antiGravity = false;  // The pendulum will anti-gravitate to the top.
 bool mirroredEyes = false; // The left eye will mirror the right.

 const float halfWidth = 2; // half-width of pupil (in pixels)
@@ -72,13 +72,13 @@
 }

 void setup(void) {
-   Serial.begin(9600);
+//   Serial.begin(9600);
   FastLED.addLeds<APA102, DATAPIN_LEFT, CLOCKPIN_LEFT>(leftLense, NUM_LEDS);
   FastLED.addLeds<APA102, DATAPIN_RIGHT, CLOCKPIN_RIGHT>(rightLense, NUM_LEDS);

    // Try to initialise and warn if we couldn't detect the chip
   if (!lsm.begin()) {
-    Serial.println("Oops ... unable to initialize the LSM9DS0. Check your wiring!");
+//    Serial.println("Oops ... unable to initialize the LSM9DS0. Check your wiring!");
     while (1);
   }
   setupSensor();
@@ -90,18 +90,7 @@
    // Read the magnetometer and determine the compass heading:
    lsm.getEvent(&accel, &mag, &gyro, &temp);

-   sensors_vec_t   orientation;
-   ahrs.getOrientation(&orientation);
-
-   // Calculate the angle of the vector z,x from magnetic North
-//   float heading = atan2(mag.magnetic.x,mag.magnetic.z) * (180 / Pi);
-    float heading = orientation.heading;
-//    Serial.print("Heading");
-//    Serial.println(heading);
-   // Normalize to 0-360 for a compass heading
-   if (heading < 0) {
-      heading = 360 + heading;
-   }
+   CRGB color = selectColor(fabs(round(mag.magnetic.z*100)));

    // Check for mode change commands
 //   CheckForNods(lsm);
@@ -132,10 +121,7 @@

    // handle the wrap-arounds at the top
    while (round(pos) < 0) pos += NUM_LEDS;
-   while (round(pos) > 20) pos -= NUM_LEDS;
-
-   CRGB color = selectColor(heading);
-
+   while (round(pos) > NUM_LEDS - 1) pos -= NUM_LEDS;

    int lightOn[round(halfWidth*2 + 1)] = {0,1,2,3};
    int lightIndex = 0;
@@ -215,7 +201,7 @@

 // Reset to default
 void resetModes() {
-   antiGravity = true;
+   antiGravity = false;
    mirroredEyes = false;

    /// spin-up
@@ -249,11 +235,11 @@
 // utility function for feedback on mode changes.
 void spin(CRGB color, int count, int time) {
   for (int j = 0; j < count; j++) {
-    for (int i = 0; i < 21; i++) {
+    for (int i = 0; i < NUM_LEDS; i++) {
       rightLense[i] = color;
       leftLense[i] = color;
       FastLED.show();
-      delay(max(time / 21, 1));
+      delay(max(time / NUM_LEDS, 1));
       leftLense[i] = CRGB::Black;
       rightLense[i] = CRGB::Black;
       FastLED.show();


addition

addition

--- arduino/ws2812_controller_esp8266/ws2812_controller_esp8266.ino
+++ arduino/ws2812_controller_esp8266/ws2812_controller_esp8266.ino
@@ -25,7 +25,7 @@
 WiFiUDP port;

 // Network information
-// IP must match the IP in config.py
+// IP must match the IP in config.py in python folder
 IPAddress ip(192, 168, 0, 150);
 // Set gateway to your router's gateway
 IPAddress gateway(192, 168, 0, 1);


removed obsolete main.ino

removed obsolete main.ino

--- public/compiler/main.ino
+++ public/compiler/main.ino
@@ -1,58 +0,0 @@
-#include <Servo.h>
-
-Servo leftLeg;
-Servo rightLeg;
-void forward() {
-leftLeg.write(80);
-delay(250);
-rightLeg.write(40);
-delay(250);
-leftLeg.write(110);
-delay(250);
-rightLeg.write(60);
-delay(250);
-}
-
-void backward() {
-leftLeg.write(140);
-delay(250);
-rightLeg.write(90);
-delay(250);
-leftLeg.write(110);
-delay(250);
-rightLeg.write(60);
-delay(250);
-}
-
-void red() {
-analogWrite(9, 0);
-analogWrite(10, 255);
-analogWrite(11, 255);
-}
-
-void green() {
-analogWrite(9, 255);
-analogWrite(10, 0);
-analogWrite(11, 255);
-}
-
-void blue() {
-analogWrite(9, 255);
-analogWrite(10, 255);
-analogWrite(11, 0);
-}
-
-void setup() {
-leftLeg.attach(5);
-rightLeg.attach(6);
-leftLeg.write(110);
-rightLeg.write(40);
-}
-void loop() {
-  red();
-
-  backward();
-
-  delay(2000);
-
-}


port 13

port 13

--- birthdaysong/birthdaysong.ino
+++ birthdaysong/birthdaysong.ino
@@ -1,102 +1,62 @@
-//ONG LIT YIT 2013-07-20
-//This following code plays happy birthday melody on Arduino
-//Put Piezo Buzzer on GDN and 9 (Positive and negative are reversible)
-//this project requires a Piezo Buzzer and
-
-// an Arduino board and
-
-//jumper wires to connect Buzzer's (+) to ~9 and (-) to GND (any GND)
-
-//HAVE FUN
-
-//this project requires a Piezo Buzzer and
-
-// an Arduino board and
-
-//jumper wires to connect Buzzer's (+) to ~9 and (-) to GND (any GND)
-
-//HAVE FUN
-
-int speakerPin = 10;
-
-int length = 28; // the number of notes
-
-char notes[] = "GGAGcB GGAGdc GGxecBA yyecdc";
-
-int beats[] = { 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8,8, 16, 1, 2,2,8,8,8,8,16, 1,2,2,8,8,8,16 };
-
-int tempo = 150;
-
-void playTone(int tone, int duration) {
-
-for (long i = 0; i < duration * 1000L; i += tone * 2) {
-
-   digitalWrite(speakerPin, HIGH);
-
-   delayMicroseconds(tone);
-
-   digitalWrite(speakerPin, LOW);
-
-   delayMicroseconds(tone);
-
-}
-
-}
-
-void playNote(char note, int duration) {
-
-char names[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B',
-
-                 'c', 'd', 'e', 'f', 'g', 'a', 'b',
-
-                 'x', 'y' };
-
-int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014,
-
-                 956,  834,  765,  593,  468,  346,  224,
-
-                 655 , 715 };
-
-int SPEE = 5;
-
-// play the tone corresponding to the note name
-
-for (int i = 0; i < 17; i++) {
-
-   if (names[i] == note) {
-    int newduration = duration/SPEE;
-     playTone(tones[i], newduration);
-
-   }
-
-}
-
-}
-
-void setup() {
-
-pinMode(speakerPin, OUTPUT);
-
-}
-
-void loop() {
-
-for (int i = 0; i < length; i++) {
-
-   if (notes[i] == ' ') {
-
-     delay(beats[i] * tempo); // rest
-
-   } else {
-
-     playNote(notes[i], beats[i] * tempo);
-
-   }
-
-   // pause between notes
-
-   delay(tempo);
-
-}
-
+//ONG LIT YIT 2013-07-20
+//This following code plays happy birthday melody on Arduino
+//Put Piezo Buzzer on GDN and 13 (Positive and negative are reversible)
+//this project requires a Piezo Buzze an Arduino board and jumper wires to connect Buzzer's (+) to ~13 and (-) to GND (any GND)
+//HAVE FUN
+
+int speakerPin = 13;
+int length = 28; // the number of notes
+char notes[] = "GGAGcB GGAGdc GGxecBA yyecdc";
+int beats[] = { 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8,8, 16, 1, 2,2,8,8,8,8,16, 1,2,2,8,8,8,16 };
+int tempo = 150;
+
+void playTone(int tone, int duration) {
+
+for (long i = 0; i < duration * 1000L; i += tone * 2) {
+   digitalWrite(speakerPin, HIGH);
+   delayMicroseconds(tone);
+   digitalWrite(speakerPin, LOW);
+   delayMicroseconds(tone);
 }
+}
+
+void playNote(char note, int duration) {
+
+char names[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B',
+
+                 'c', 'd', 'e', 'f', 'g', 'a', 'b',
+
+                 'x', 'y' };
+
+int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014,
+
+                 956,  834,  765,  593,  468,  346,  224,
+
+                 655 , 715 };
+
+int SPEE = 5;
+// play the tone corresponding to the note name
+
+for (int i = 0; i < 17; i++) {
+   if (names[i] == note) {
+    int newduration = duration/SPEE;
+     playTone(tones[i], newduration);
+   }
+}
+}
+
+void setup() {
+pinMode(speakerPin, OUTPUT);
+}
+
+void loop() {
+for (int i = 0; i < length; i++) {
+   if (notes[i] == ' ') {
+     delay(beats[i] * tempo); // rest
+   } else {
+     playNote(notes[i], beats[i] * tempo);
+   }
+   // pause between notes
+   delay(tempo);
+}
+}


Enter shutdown process if mode button held down.

--- timer/timer.ino
+++ timer/timer.ino
@@ -28,9 +28,42 @@
   display.displayTime( time_remaining / 1000 );

   int button = buttons.get_button_press();
+
+  if ( button == BUTTON_MODE_HELD_DOWN ) {
+    enter_shutdown_state();
+    return;
+  }
+
   if ( button == BUTTON_RESTART ) {
     // reset the start time
     countdown_ends = millis() + countdown_duration + 500;
   }

 }
+
+void enter_shutdown_state () {
+
+  Serial.println("Starting shutdown...");
+  long off_at = millis() + 3999;
+
+  while ( buttons.get_button_press() == BUTTON_MODE_HELD_DOWN ) {
+    long remaining = off_at - millis();
+    if (remaining > 0) {
+      display.displayTime( remaining / 1000 );
+
+    } else {
+      // enter infinite loop displaying 'off'. Power down will be handled by
+      // external circuitry
+      shutdown();
+    }
+
+  }
+
+}
+
+void shutdown () {
+  Serial.println("OFF!");
+  while (true) {
+    delay(1000);
+  }
+}


Minor modifications.

Minor modifications.

--- cellar-climate-controller.ino
+++ cellar-climate-controller.ino
@@ -246,7 +246,7 @@
     pinMode(DHT_PIN_OUTSIDE_2, INPUT_PULLUP);
     pinMode(DHT_PIN_INSIDE, INPUT_PULLUP);
     pinMode(LED_PIN, OUTPUT);
-    ledOff();
+    ledOn();

     attachInterrupt(digitalPinToInterrupt(FAN_PIN_RPM), rpm, RISING);

@@ -261,7 +261,7 @@
     lcd.setCursor(0, 0);
     lcd.print("***FanControl***");
     lcd.setCursor(0, 1);
-    lcd.print("***   2.03   ***");
+    lcd.print("***   2.04   ***");
     time = millis() - time;
     Serial.print("Took "); Serial.print(time); Serial.println(" ms");
     lcd.setBacklight(WHITE);
@@ -633,7 +633,7 @@

 boolean isSensorFaulty(float humidity) {
     if (isnan(humidity)) {
-        return false; // do not consider missing sensor as faulty
+        return true;
     } else  if (humidity > 98.8 || humidity < 1.2) {
         return true;
     } else {


Actually use a 24-hour timeout in NTP messages, instead of ten seconds used for testing.

--- SetTime/SetTime.ino
+++ SetTime/SetTime.ino
@@ -222,7 +222,7 @@
 static const unsigned int timerPreload = 65536 - systemHz / prescaler / (1 / bitLength) + finetuning;

 static const double two_to_32 = 4294967296.0;
-static const uint32_t maxTimeAge = 10 /* 24ul * 3600ul */; // maximum number of seconds we maintain a time without hearing from network
+static const uint32_t maxTimeAge = 24ul * 3600ul; // maximum number of seconds we maintain a time without hearing from network

 uint32_t timeExpireSeconds = 0; // how long till we forget the time (as it has probably become stale)


Fixed random flickering bug when received data via UART

  Previously the LEDs would flash everytime a new frame
   was received due to insufficient processing time being
   available.
  I have increased the time between switching between each
   LED colour (effectively doubled) from a on time of ~ 0.5ms
   to 1ms. This reduces the amount of time spent in interrupt
   routines, and also sending data to the TLC5940 driver ICs

  Additionally I have increased the number of comments in
   the code, and credited solderlab.de for the orignal version

  There is also a different gamma correction curve available
   for each colour should we find the time to calibrate it.

--- driver_boards/firmware/DanceFloor.ino
+++ driver_boards/firmware/DanceFloor.ino
@@ -1,29 +1,57 @@
-
-//############################################################################################################################################################
-//Externe Bibliotheken einbinden                                                                                #
-//############################################################################################################################################################
-
+// AndyT's Dance Floor controller code.
+// Adapted from the original by solderlab.de
+
+// One AVR drives 3 TLC5940 constant current LED drivers, for a total of 48 LEDs.
+// LEDs are common cathode, with the TLC5940 connected to the cathode, and high side
+//  P-channel FETs providing the drive.
+// The FETs cycle RED/GREEN/BLUE along with changing TLC5940 data to give the illusion of
+//  constant RGB colour when in fact only one is on at any given time.
+
+// Data can be received from a PC through the serial port at 1000000 baud (1Mbps)
+
+// If no data is received in several seconds then the module starts to set the LEDs to random
+//  pure colours, changing 2 times a second
+
+// Include the pgmspace header for storing the gamma correction tables
 #include <avr/pgmspace.h>

-//############################################################################################################################################################
-//Programmspeicher beschreiben                                                                                #
-//############################################################################################################################################################
-
-//Exponentialfunktion für Gamma-Korrektur
-PROGMEM prog_uint16_t exp_table[] =
+// LEDs do not have a linear response curve, and particularly when they are driven by PWM.
+// Here we have three curves to adjust the brightness to match human vision.
+// (Currently these are all identical, and follow an exponential curve, and need to be tuned)
+PROGMEM prog_uint16_t exp_table_red[] =
 {
-0,15,15,16,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,25,26,27,27,28,28,29,30,30,31,32,32,33,34,35,35,36,37,38,39,39,40,41,42,43,44,45,46,
-47,48,49,50,51,53,54,55,56,57,59,60,61,63,64,65,67,68,70,72,73,75,76,78,80,82,83,85,87,89,91,93,95,97,99,102,104,106,109,111,114,116,119,121,124,127,130,132,
-135,138,141,145,148,151,154,158,161,165,169,172,176,180,184,188,192,197,201,206,210,215,220,225,230,235,240,245,251,256,262,268,274,280,286,292,299,305,312,319,
-326,334,341,349,356,364,372,381,389,398,407,416,425,434,444,454,464,474,485,496,507,518,529,541,553,566,578,591,604,618,631,645,660,674,689,705,720,736,753,770,
-787,804,822,840,859,878,898,918,938,959,980,1002,1024,1047,1070,1094,1119,1143,1169,1195,1221,1249,1276,1305,1334,1364,1394,1425,1457,1489,1522,1556,1591,1626,
-1662,1699,1737,1775,1815,1855,1897,1939,1982,2026,2071,2117,2164,2212,2262,2312,2363,2416,2470,2524,2581,2638,2697,2757,2818,2881,2945,3010,3077,3146,3216,3287,
-3360,3435,3511,3590,3669,3751,3834,3920,4007,4095
+  0,15,15,16,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,25,26,27,27,28,28,29,30,30,31,32,32,33,34,35,35,36,37,38,39,39,40,41,42,43,44,45,46,
+  47,48,49,50,51,53,54,55,56,57,59,60,61,63,64,65,67,68,70,72,73,75,76,78,80,82,83,85,87,89,91,93,95,97,99,102,104,106,109,111,114,116,119,121,124,127,130,132,
+  135,138,141,145,148,151,154,158,161,165,169,172,176,180,184,188,192,197,201,206,210,215,220,225,230,235,240,245,251,256,262,268,274,280,286,292,299,305,312,319,
+  326,334,341,349,356,364,372,381,389,398,407,416,425,434,444,454,464,474,485,496,507,518,529,541,553,566,578,591,604,618,631,645,660,674,689,705,720,736,753,770,
+  787,804,822,840,859,878,898,918,938,959,980,1002,1024,1047,1070,1094,1119,1143,1169,1195,1221,1249,1276,1305,1334,1364,1394,1425,1457,1489,1522,1556,1591,1626,
+  1662,1699,1737,1775,1815,1855,1897,1939,1982,2026,2071,2117,2164,2212,2262,2312,2363,2416,2470,2524,2581,2638,2697,2757,2818,2881,2945,3010,3077,3146,3216,3287,
+  3360,3435,3511,3590,3669,3751,3834,3920,4007,4095
 };

-//############################################################################################################################################################
-//Definitionen und Variablen                                                                                #
-//############################################################################################################################################################
+PROGMEM prog_uint16_t exp_table_green[] =
+{
+  0,15,15,16,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,25,26,27,27,28,28,29,30,30,31,32,32,33,34,35,35,36,37,38,39,39,40,41,42,43,44,45,46,
+  47,48,49,50,51,53,54,55,56,57,59,60,61,63,64,65,67,68,70,72,73,75,76,78,80,82,83,85,87,89,91,93,95,97,99,102,104,106,109,111,114,116,119,121,124,127,130,132,
+  135,138,141,145,148,151,154,158,161,165,169,172,176,180,184,188,192,197,201,206,210,215,220,225,230,235,240,245,251,256,262,268,274,280,286,292,299,305,312,319,
+  326,334,341,349,356,364,372,381,389,398,407,416,425,434,444,454,464,474,485,496,507,518,529,541,553,566,578,591,604,618,631,645,660,674,689,705,720,736,753,770,
+  787,804,822,840,859,878,898,918,938,959,980,1002,1024,1047,1070,1094,1119,1143,1169,1195,1221,1249,1276,1305,1334,1364,1394,1425,1457,1489,1522,1556,1591,1626,
+  1662,1699,1737,1775,1815,1855,1897,1939,1982,2026,2071,2117,2164,2212,2262,2312,2363,2416,2470,2524,2581,2638,2697,2757,2818,2881,2945,3010,3077,3146,3216,3287,
+  3360,3435,3511,3590,3669,3751,3834,3920,4007,4095
+};
+
+PROGMEM prog_uint16_t exp_table_blue[] =
+{
+  0,15,15,16,16,16,17,17,17,18,18,19,19,20,20,20,21,21,22,22,23,23,24,24,25,25,26,27,27,28,28,29,30,30,31,32,32,33,34,35,35,36,37,38,39,39,40,41,42,43,44,45,46,
+  47,48,49,50,51,53,54,55,56,57,59,60,61,63,64,65,67,68,70,72,73,75,76,78,80,82,83,85,87,89,91,93,95,97,99,102,104,106,109,111,114,116,119,121,124,127,130,132,
+  135,138,141,145,148,151,154,158,161,165,169,172,176,180,184,188,192,197,201,206,210,215,220,225,230,235,240,245,251,256,262,268,274,280,286,292,299,305,312,319,
+  326,334,341,349,356,364,372,381,389,398,407,416,425,434,444,454,464,474,485,496,507,518,529,541,553,566,578,591,604,618,631,645,660,674,689,705,720,736,753,770,
+  787,804,822,840,859,878,898,918,938,959,980,1002,1024,1047,1070,1094,1119,1143,1169,1195,1221,1249,1276,1305,1334,1364,1394,1425,1457,1489,1522,1556,1591,1626,
+  1662,1699,1737,1775,1815,1855,1897,1939,1982,2026,2071,2117,2164,2212,2262,2312,2363,2416,2470,2524,2581,2638,2697,2757,2818,2881,2945,3010,3077,3146,3216,3287,
+  3360,3435,3511,3590,3669,3751,3834,3920,4007,4095
+};
+
+// Port and constant definitions for driving the TLC5940 ICs

 //Gray Scale Depth for the PWM on TLC5940
 #define Gray_Scale_Depth 4095
@@ -60,31 +88,44 @@
 #define Debug_Low       PORTD &=  ~(1 << 7)
 #define Debug_High      PORTD |=   (1 << 7)

+// The character that indicates new data has been received.
+//  (This is effectively a 'sync' pulse)
 # define CMD_NEW_DATA 1
+
+// Module size constants

 #define MODULE_WIDTH 6
 #define MODULE_HEIGHT 8
 #define RGB_LEDS MODULE_HEIGHT * MODULE_WIDTH
 #define BUFFER_SIZE MODULE_WIDTH*MODULE_HEIGHT*3

+// temporary and live display buffers
 unsigned char display_buffer_1[BUFFER_SIZE];
 unsigned char display_buffer_2[BUFFER_SIZE];
-static unsigned char *display_buffer = display_buffer_1;
-
+
+static unsigned char *offscreen_display_buffer = display_buffer_1;
+static unsigned char *display_buffer = display_buffer_2;
+
+// Variables used in the UART ISR
+static unsigned char *ptr;
+static unsigned int pos = 0;
+
+// Temporary buffer to store the next set of random colours
+//  (These are calculated in advance over a period of cycles
+//   so that they do not take too much processing time)
 unsigned char random_colours_buffer[BUFFER_SIZE];
 unsigned int random_colours_buffer_pixel = 0;

 volatile byte display_buffer_live = 1;

+// Variables that keep track of state in the ISR and main loop
 volatile byte new_row = 0;
 volatile byte need_xlat = 0;
-
-static unsigned char *ptr;
-static unsigned int pos = 0;
-
 byte row = 0;

+// Variables used to decide when we should switch to the backup
+//  random pattern
 unsigned long tickcounter = 0;
 unsigned long lastdata_tickcounter = 0;
 // 40000 = 20 seconds
@@ -92,10 +133,12 @@

 volatile boolean cycling = false;
 // 1000 ~ 1/2 second
-unsigned long cycle_period = 1000;
+unsigned long cycle_period = 500;
 unsigned long cycle_tickcounter = 0;

-unsigned long colours[] = {0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0x00FFFF, 0xFF00FF, 0xFFFFFF};
+// The 'pure' colours that are used during random cycling
+unsigned long colours[] = {
+  0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0x00FFFF, 0xFF00FF, 0xFFFFFF};
 int colours_length = 7;

 void set_initial_pattern(void) {
@@ -103,117 +146,154 @@
 }

 void set_random_colours() {
-
+
   for (int pixel=0; pixel < RGB_LEDS; pixel++) {
     unsigned long colour = colours[random(colours_length)];
     display_buffer[pixel * 3 + 0] = colour & 0xFF;
     display_buffer[pixel * 3 + 1] = (colour >> 8 ) & 0xFF;
     display_buffer[pixel * 3 + 2] = (colour >> 16) & 0xFF;
   }
-
-}
-
-//############################################################################################################################################################
-//Setup - Prozedur                                                                                #
-//############################################################################################################################################################
-
+
+}
+
+// Configuration of the AVR registers for communication with external
+//  peripherals
 void setup()
 {
-  // Pins auf Ein- oder Ausgang stellen und einen Startwert zuweisen
+  // Set pins as inputs or outputs
+  // Setup the SPI connection pins and the TLC5940 BLANK signal on PORTB
   DDRB |= (1<<1)  | (1<<2)  | (1<<3) | (1<<5) ; // BLANK, SS, MOSI, SCLK as OUTPUTS
+  // Setup the remainder of the TLC5940 signal pins on PORTD
   DDRD |= (1<<3)  | (1<<4) |  (1<<6) | (1<<7) ; // VPRG, XLAT, GSCLK, Debug as OUTPUTS
+  // PORTC is used to cycle the row high-side MOSFETS, and although only
+  //  pins 0, 1 & 2 are used, set them all as outputs
   DDRC = 255;
-
+
+  // Configure the initial state of the TLC5940 control lines
   XLAT_Low;
   BLANK_High;
   VPRG_Low;
   Debug_Low;
-
+
+  // Set an initial random patter in the display buffer
   set_initial_pattern();
-
-  //Timer 1 (16bit)
+
+  // Set Timer 1 (16bit) in count (capture) mode to count the number of output pulses up to the
+  //  greyscale depth. This then triggers an ISR to say that this LED has completed it's
+  //  cycle and to move on to the next row
   TCCR1A  = (1<<WGM11) | (0<<WGM10);            // Fast PWM with ICR1 as top
   TCCR1B  = (1<<WGM13) | (1<<WGM12);            // Fast PWM with ICR1 as top
   TCCR1B |= (1<<CS12)  | (1<<CS11) | (1<<CS10); // external clock (T1) on rising egde
   TIMSK1 |= (1<<TOIE1);                         // enable overflow interupt
   ICR1    = Gray_Scale_Depth;                   // Grey scale depth for TLC-PW

-  //Timer 0 (8bit)
+  // Set Timer 0 (8bit) to output a PWM pulse (which is then externally routed into Timer 1),
+  //  which provides the clock source for the TLC5940 ICs.
+  // It is not set as fast as possible because that leaves too much processing for the AVR
+  //  to do, instead it is set a notch back (half speed)
   TCCR0A  = (1<<WGM01) | (0<<WGM00);            // CTC
   TCCR0A |= (0<<COM0A1) | (1<<COM0A0);          // Toggle on Compare Match
   TCCR0B  = (0<<CS02) | (0<<CS01) | (1<<CS00);  // No Prescaler
-  OCR0A   = 0;                                  // f(OCR) = F_CPU/2/Prescaler
-
-  //UART Initialisation
+  // 0x00 is a bit too quick if you want to do any other processing,
+  //  such as put in random pixels as well as receive data from the
+  //  serial port, so put it up to 0x01. This makes the on time of
+  //  each colour 1ms, so a complete cycle in 3ms, which is still
+  //  strobing all colours at > 300Hz, so lots of time to play with
+  OCR0A   = 0x01;                                  // f(OCR) = F_CPU/2/Prescaler
+
+  // Configure the UART to receive data at 1 Mb/s
   UCSR0A |= (1<<U2X0);                                 // Double up UART
   UCSR0B |= (1<<RXEN0)  | (1<<TXEN0) | (1<<RXCIE0);    // UART RX, TX und RX Interrupt enable
   UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00)             ;    // Asynchrous 8N1
   UBRR0H = 0;
   UBRR0L = 1; //Baud Rate 1 MBit   --> 0% Error at 16MHz :-)
-
-  //Enable global interrupts
+
+  // Enable global interrupts
   sei();
-
-  //Configure SPI
+
+  // Configure and enable SPI
   SPCR = (1<<SPE)|(1<<MSTR);
   SPSR = B00000000;
-
+
+  // Double buffering doesn't work yet
   /*ptr=display_buffer_2;
-  display_buffer = display_buffer_1;
-  display_buffer_live = 1;
-    */
+   display_buffer = display_buffer_1;
+   display_buffer_live = 1;
+   */
+  //  ptr = display_buffer;
+  // Set the incoming data pointer to the start of the main display buffer
   ptr = display_buffer;
-}
-
+
+  // Prepopulate the random colour buffer
+  if (random_colours_buffer_pixel < RGB_LEDS) {
+    unsigned long colour = colours[random(colours_length)];
+    random_colours_buffer[random_colours_buffer_pixel * 3 + 0] = colour & 0xFF;
+    random_colours_buffer[random_colours_buffer_pixel * 3 + 1] = (colour >> 8 ) & 0xFF;
+    random_colours_buffer[random_colours_buffer_pixel * 3 + 2] = (colour >> 16) & 0xFF;
+    random_colours_buffer_pixel++;
+  }
+
+}
+
+// If double buffering worked, we might use this, but it doesn't at the moment
 void flip_buffers() {
   if (display_buffer_live == 1) {
     display_buffer_live = 2;
     display_buffer = display_buffer_2;
     ptr = display_buffer_1;
-  } else {
+  }
+  else {
     display_buffer_live = 1;
     display_buffer = display_buffer_1;
     ptr = display_buffer_2;
   }
   lastdata_tickcounter = tickcounter;
   cycling = false;
-
-}
-
-//############################################################################################################################################################
-//Hauptprogramm                                                                                #
-//############################################################################################################################################################
-
+
+}
+
+// Main loop
 void loop()
 {
+  // The loop does nothing until a new set of data needs to be shifted out for the next LED.
+  // Everything else is handled by interrupts.
   if (new_row)
   {
     shift_out_data(row);
-
+
     need_xlat = 1;
-
+
     new_row = 0;
-    tickcounter++;
-
+
+    // Every time there is a new row we increment our tick counter, which is our way of keeping
+    //  track of time periods of the order of seconds, and we use this to cycle random colours
+    //  at 1-4Hz. 2Hz is a pleasing cycling pattern.
+        tickcounter++;
+
+    // When we are cycling it can take a while to call random(), so lets do this once per loop.
+    // If this is called many times in succession (e.g. 48), then you get a blip on the LED
+    //  where it presumably should be sending more data (e.g. the xlat thing), but it isn't, so
+    //  it does nothing, or something it shouldn't. either way, it's noticeable
+    if (random_colours_buffer_pixel < RGB_LEDS) {
+      unsigned long colour = colours[random(colours_length)];
+      random_colours_buffer[random_colours_buffer_pixel * 3 + 0] = colour & 0xFF;
+      random_colours_buffer[random_colours_buffer_pixel * 3 + 1] = (colour >> 8 ) & 0xFF;
+      random_colours_buffer[random_colours_buffer_pixel * 3 + 2] = (colour >> 16) & 0xFF;
+      random_colours_buffer_pixel++;
+    }
+
     // If we are cycling, then see if we need to cycle again
     if (cycling == true) {
-      if (random_colours_buffer_pixel < RGB_LEDS) {
-        unsigned long colour = colours[random(colours_length)];
-        //colour = colours[0];
-        random_colours_buffer[random_colours_buffer_pixel * 3 + 0] = colour & 0xFF;
-        random_colours_buffer[random_colours_buffer_pixel * 3 + 1] = (colour >> 8 ) & 0xFF;
-        random_colours_buffer[random_colours_buffer_pixel * 3 + 2] = (colour >> 16) & 0xFF;
-        random_colours_buffer_pixel++;
-      }
+
       if (tickcounter - cycle_tickcounter > cycle_period) {
-        //set_random_colours();
-        for (int i=0; i<BUFFER_SIZE;i++){
-           display_buffer[i] = random_colours_buffer[i];
-        }
+        // Copy the current random colour buffer into the live display buffer
+        // (TODO: If we had double buffering, we could just switch a pointer)
+        memcpy(display_buffer, random_colours_buffer, BUFFER_SIZE);
         random_colours_buffer_pixel = 0;
         cycle_tickcounter = tickcounter;
       }
-    } else {
+    }
+    else {
       // If we aren't cycling, then see if we need to start
       if (tickcounter - lastdata_tickcounter > timeout) {
         cycling = true;
@@ -223,149 +303,130 @@
   }
 }

-//############################################################################################################################################################
-// Timer-Interrupt-Prozedur                                                                                #
-//############################################################################################################################################################
-
+// Timer interupt for the TLC5940 clock input signal. Once this overflows we have
+//  completed the PWM cycle for the LEDs, and we should move onto the next row.
 ISR( TIMER1_OVF_vect )
 {
-
+
   if (need_xlat)
   {
     XLAT_High;
     XLAT_Low;
     need_xlat = 0;
   }
-
+
   PORTC = ~(1<<row);
-
+
   BLANK_High;
   BLANK_Low;
-
+
+  // Move through the rows
   row++;
-  if (row == 3) {row = 0;}
+  if (row == 3) {
+    row = 0;
+  }
   new_row = 1;
-
+
+  // Confirm we have handled the interrupt, clear the flag.
   TCNT1 = 0;
 }

-//############################################################################################################################################################
-// UART-Interrupt-Prozedur (called every time one byte is compeltely received)                                                                               #
-//############################################################################################################################################################
-
+// UART interrupt for receiving data from a controlling computer.
 ISR(USART_RX_vect)
 {
+  // Read the data out of the UART RX memory location
   unsigned char b;
-
   b=UDR0;
-
+
+  // If it is a frame sync pulse...
   if (b == CMD_NEW_DATA)  {
+    // ... retransmit the pulse to subsequent modules
     UDR0=b;
-    pos=0;
+    //pos=0;
+    // Reset our counter
+    pos=BUFFER_SIZE;
+
+    /*
+     if (offscreen_display_buffer == display_buffer_1) {
+     offscreen_display_buffer = display_buffer_2;
+     display_buffer = display_buffer_1;
+     } else {
+     offscreen_display_buffer = display_buffer_2;
+     display_buffer = display_buffer_1;
+     }
+
+     ptr=offscreen_display_buffer;
+     */
+    // And reset out buffer pointer location back to the start
     ptr=display_buffer;
     // Flip buffers to make the live one the one we have just populated,
     //  and the temporary one containing incoming data, the other one
     //flip_buffers();
+
+    // Make a note of when we last had a new frame - we use this to start
+    //  the counter going to see if we should switch to random cycling
     lastdata_tickcounter = tickcounter;
     cycling = false;
     return;
   }
-  if (pos == BUFFER_SIZE) {
+  //  if (pos == BUFFER_SIZE) {
+  // If we have received all the data we need (and have not yet received a new frame pulse),
+  //  then relay the data to the next module by re-transmitting it.
+  // This is a good way to keep signal integrity as each module is only receiving data from
+  //  the adjacent module in the chain, not from miles away where signal attenuation might be
+  //  a problem
+  if (pos == 0) {
     UDR0=b;
     return;
-  } else {
+  }
+  // If we are still filling up our buffer, then store the data and keep track of how many
+  //  piece of data we have had (so that we know when to stop)
+  else {
     *ptr=b;
     ptr++;
-    pos++;
+    pos--;
   }
 }

-//############################################################################################################################################################
-// Shift out Data                                                                                #
-//############################################################################################################################################################
-
+// Shift out data to the TLC5940 ICs via the most efficient way possible: high speed SPI
 void shift_out_data(byte row)
 {
+
+  // Get the appropriate gamma correction curve for this colour/row
+  prog_uint16_t * exp_table;
+  switch (row){
+  case 2:
+    exp_table = exp_table_blue;
+    break;
+  case 1:
+    exp_table = exp_table_green;
+    break;
+  case 0:
+  default:
+    exp_table = exp_table_red;
+    break;
+  }
+
+  //Shift Out Data
+  for(byte i = 0; i<24; i++)
+  {
+    unsigned int index = 6*(i) + row;
+    unsigned int t1 = pgm_read_word_near(exp_table + display_buffer[index + 3]);
+    unsigned int t2 = pgm_read_word_near(exp_table + display_buffer[index]);
+
+    byte d1 = (highByte(t2) << 4) | (lowByte(t2) >> 4);
+    spi_transfer(d1);
+
+    byte d2 = (lowByte(t2) << 4) | (highByte(t1));
+    spi_transfer(d2);
+
+    byte d3 = (lowByte(t1));
+    spi_transfer(d3);
+  }

-//    unsigned int index_offset = (row) * 48;
-
-    //Shift Out Data
-    for(byte i = 0; i<24; i++)
-    {
-      unsigned int index = 6*(i) + row;
-      unsigned int t1 = pgm_read_word_near(exp_table + display_buffer[index + 3]);
-      unsigned int t2 = pgm_read_word_near(exp_table + display_buffer[index]);
-
-      byte d1 = (highByte(t2) << 4) | (lowByte(t2) >> 4);
-      spi_transfer(d1);
-
-      byte d2 = (lowByte(t2) << 4) | (highByte(t1));
-      spi_transfer(d2);
-
-      byte d3 = (lowByte(t1));
-      spi_transfer(d3);
-    }
-
-/*
-    unsigned int index_offset = (row) * 48;
-
-    //Shift Out Blue Data
-    for(byte i = 0; i<8; i++)
-    {
-      unsigned int index = index_offset + 6*(i) + 2;
-      unsigned int t1 = pgm_read_word_near(exp_table + display_buffer[index + 3]);
-      unsigned int t2 = pgm_read_word_near(exp_table + display_buffer[index]);
-
-      byte d1 = (highByte(t2) << 4) | (lowByte(t2) >> 4);
-      spi_transfer(d1);
-
-      byte d2 = (lowByte(t2) << 4) | (highByte(t1));
-      spi_transfer(d2);
-
-      byte d3 = (lowByte(t1));
-      spi_transfer(d3);
-    }
-
-    //Shift Out Green Data
-    for(byte i = 0; i<8; i++)
-    {
-      unsigned int index = index_offset + 6*(i) + 1;
-      unsigned int t1 = pgm_read_word_near(exp_table + display_buffer[index + 3]);
-      unsigned int t2 = pgm_read_word_near(exp_table + display_buffer[index]);
-
-      byte d1 = (highByte(t2) << 4) | (lowByte(t2) >> 4);
-      spi_transfer(d1);
-
-      byte d2 = (lowByte(t2) << 4) | (highByte(t1));
-      spi_transfer(d2);
-
-      byte d3 = (lowByte(t1));
-      spi_transfer(d3);
-    }
-
-    //Shift Out Red Data
-    for(byte i = 0; i<8; i++)
-    {
-      unsigned int index = index_offset + 6*(i);
-      unsigned int t1 = pgm_read_word_near(exp_table + display_buffer[index + 3]);
-      unsigned int t2 = pgm_read_word_near(exp_table + display_buffer[index]);
-
-      byte d1 = (highByte(t2) << 4) | (lowByte(t2) >> 4);
-      spi_transfer(d1);
-
-      byte d2 = (lowByte(t2) << 4) | (highByte(t1));
-      spi_transfer(d2);
-
-      byte d3 = (lowByte(t1));
-      spi_transfer(d3);
-    }
-*/
-
-}
-//############################################################################################################################################################
-// SPI-Prozedur                                                                                #
-//############################################################################################################################################################
-
+}
+
+// SPI transmission function
 void spi_transfer(byte data)
 {
   SPDR = data;	  // Start the transmission
@@ -375,9 +436,3 @@
 }

-
-
-//############################################################################################################################################################
-//############################################################################################################################################################
-//############################################################################################################################################################
-


Delete TS_520_DG5_LCD_v2_0_1.ino.ino

Delete TS_520_DG5_LCD_v2_0_1.ino.ino

--- LCD/TS_520_DG5_LCD_v2_0_1.ino.ino
+++ LCD/TS_520_DG5_LCD_v2_0_1.ino.ino
@@ -1,380 +0,0 @@
- /*
-
-Kenwood DG5 digital display emulator, V2.0.0 - LCD version
-
-Updates made April 2017 by Stephen Leander, KV6O
-  - ported updated code back to LCD version from LED
-  - added correction factor (see variable "cf" in the "Frequency measurement variables" section
-  - added smoothing/averaging to reduce display jitter
-  - code cleaned up and better documented
-  - this version uses FreqCount library rather than timer code by Nick Gammon
-  - tested with latest Arduino IDE (1.8.2), you will need to get the FreqCount library under "Sketch/Include Library/Manage Libraries.."
-        Search on "FreqCount" and you should find Paul Stoffregen.  Install the latest version.
-
-Stephen Leander, KV6O, April 2, 2017
-
-4/4/17   - Version 2.0.1 - fixed averaging - display was using the raw "freq" var, not the avergaed one ("average")
-                         - moved display logic into a function to make maintaining code between versions (LCD,LED,NIXIE) easier
-
-
-Original release notes:
-********************************************************************************************************
-August 22, 2014
-
-Outputs Kenwood Commander commands on the Serial/USB port for a logging program (DXLab's Commander)
-No idea if it will work with other programs because I haven't tested anything else!
-
-Got the idea from Todd Harrison's website, Toddfun.com, where he outlined and built an Adrunio DG-5 emulator, with the plans of using this to display
-the frequency, just like the DG-5.
-
-http://www.toddfun.com/2013/02/07/arduino-frequency-display-for-kenwood-ts-520s-hf-ham-radio-part-1/
-
-
-Emulates a TS-790 for DX Commander, based on input from Dave, AA6YQ:
-
-        From Dave AA6YQ, DXLab's author:
-        From: dxlab@yahoogroups.com [mailto:dxlab@yahoogroups.com] Sent: Tuesday, August 05, 2014 10:42 PM To: dxlab@yahoogroups.com Subject: [dxlab] Kenwood
-
-          >>>If your emulator responds to the ID; command with
-
-        ID007;
-
-        >>>Commander will think its controlling a TS-790. The only other commands to which your emulator will then have to respond are IF; and FB;
-
-        >>>Note: Commander pays attention to the following bytes of the radio's response to an IF; command:
-
-        3-13: VFO A frequency
-        29: RX vs TX status
-        30: Mode
-        31: VFO selection
-        33: split status
-
-        >>>Operation won't be convenient unless your emulator can correctly report the radio's mode.
-
-
-See http://www.kenwood.com/i/products/info/amateur/ts_480/pdf/ts_480_pc.pdf for more on Kenwood command set.
-
-
-8/22/14 - Version 1.0  Prototyped the circuit using 3 TI PLL's (74HC4046A's), a 74HC93 counter for prescaling the HFO, and 74HC153 for selecting the
-signal (VFO, BFO, or HFO) to be counted by the Arduino on pin 5.
-
-8/29/14 Version 1.1 - Added LCD display using 4-bit parrallel display type, added "freq" to have single calculated frequency for serial port and LCD.
-
-9/9/14  Version 1.2 - Added DEBUG0;/DEBUG1; command line functionallity for turning on and off serial debugging
-
-10/11/14 - Version 1.4 (abandoned 1.3, was attempt to make gate time shorter) Added USB/LSB/CW logic using BFO (CAR) frequency.
-
-10/14/14 - Modifications to accomidate the V1.5 board.  Added SelectPinA/B for the new Arduino pins used for the select lines on the 153 (done to free up D2 and D3
-            for the later addition of an rotary encoder - these are external Inturrupt pins).  Also had to flip the VFO/HET logic selection, not sure why!
-
-10/17/14 - Change the counter gate time to 200ms (up from 100ms) due to the measured frequency being a little high (200-300 Hz) Not an issue on prototype,
-            need to troubleshoot.  Added "splash screen at startup" with adjustable call sign display during operation.
-
-***********************************************************************************************************
-
-1/17/16 - Version 1.6 - removed LCD code and added LED code.
-
-1/17/16 - Version 1.6.1 - Added correction factor option, USB/LSB/CW display on LED, counter gate time back to 100ms
-
-1/18/16 - Version 1.6.2 - added averaging routine to help with display jitter, cleaned up code, added commenting like a good person should.
-
-4/24/16 - Version 1.6.3 - corrected error in calculating correction factor (was being multiplied by 8 for HFO)
-
-4/25/16 - Version 1.6.4 - abandonded previous frequency counting method for the FreqCount library (https://github.com/PaulStoffregen/FreqCount)
-*/
-
-
-#include <LiquidCrystal.h>
-#include <FreqCount.h>
-
-boolean DEBUG = false;                                       // Debug switch
-
-LiquidCrystal lcd(12, 11, 10, 9, 8, 7);                      // Setup pins for LCD.  Do not use pin 5 - used for frequency counter.
-
-// Averaging variables for smoothing display jitter
-const int numReadings = 10;               // number of readings to average over
-unsigned long readings[numReadings];      // the readings from the frequency county
-int readIndex = 0;                        // the index of the current reading
-unsigned long total = 0;                  // the running total
-unsigned long average = 0;                // the average
-
-// timer varables
-volatile unsigned long timerCounts;
-volatile boolean counterReady;
-
-//the booleans are for tracking USB/LSB/CW.  Also tracked by the "mode" char, this is only used to track if the mode has changed at this point, could remove the boolean logic but I am lazy
-boolean USB = false;
-boolean LSB = false;
-boolean CW = false;
-char mode = 'U';        // current mode computed from the BFO frequency
-char OldMode = 'U';     // used in test to see if mode has changed
-
-// counting routine variables
-unsigned long overflowCount;
-unsigned int timerTicks;
-unsigned int timerPeriod;
-
-
-//Frequency measurement variables
-unsigned long frq = 0;        // From counter
-unsigned long vfo = 0;        // holds measured vfo frequency
-unsigned long bfo = 0;        // holds measured bfo frequency
-unsigned long hfo = 0;        // holds measured hfo frequency (which has been divided by 8 in hardware to get frequency into range that the Arduino can measure)
-unsigned long freq = 0;       // calculated frequency
-unsigned long FreqOld = 0;    // used in test to see if frequency has changed
-signed long cf = 0;           // correction factor in Hz - doesn't correct for ceramic oscillators, like on the UNO board - too drifty! If the display is low, use a negative number to move it up, such as "-100" to bump the display up 100Hz
-
-String inputString = "";         // a string to hold incoming command
-boolean stringComplete = false;  // whether the string is complete
-char buffer[9];                  // buffer used for spring function to assemble LCD display
-
-
-void setup ()
-  {
-    for (int thisReading = 0; thisReading < numReadings; thisReading++) {       //initilize averaging array
-    readings[thisReading] = 0;}
-
- //    FreqCount.begin(1000);
-
-  pinMode(4, OUTPUT);      //setup pins used to select vfo/bfo/hfo using 74LS153
-  pinMode(6, OUTPUT);
-
-
-lcd.begin(16, 2);                   // start LCD
-  lcd.print("KV6O DG5  V2.0.1");    // Display version on top line of LCD.  You can change this!
-  delay (1000);
-
-
- Serial.begin(9600);
-// reserve 15 bytes for input string for commands
-  inputString.reserve(15);
-
-
-   // end of setup
-}
-
-
-//Serial input function
-void serialEvent() {
-  while (Serial.available()) {
-    // get the new byte:
-    char inChar = (char)Serial.read();
-    // add it to the inputString:
-    inputString += inChar;
-    // if the incoming character is a newline, set a flag
-    // so the main loop can do something about it:
-    if (inChar == ';') {                // Look for ";" - this is the Kenwood command terminator.
-      stringComplete = true;
-    }
-  }
-}
-
-
-//LCD display function
-void DisplayFreq(long int Frequency) {
- int Freq;
-
-    unsigned int MHz = freq / 10000;                // seperate out the Mhz component
-    unsigned int kHz = (freq / 10) % 1000;          // do the same for the kHz
-    unsigned int Hz = freq % 10;                    // actually, 100s of Hz
-    sprintf(buffer, "%2u.%03u.%01u", MHz, kHz, Hz); // puts the output together
-
-      lcd.setCursor(0, 1);                            // position cursor for frequency update on LCD
-      lcd.print ("Freq:  ");
-      lcd.setCursor(6, 1);
-      lcd.print(buffer);                              // update display
-      lcd.setCursor(14,1);                            // set
-      lcd.print(" ");  // cleanup any over flow when switching bands
-
-}
-
-void loop ()
-  {
-
-  for (int x=0; x < 3; x++){                   // Loop thru the 3 signals to count the signals.
-         if (x==0) {                            //Select VFO
-             digitalWrite(4, LOW);
-             digitalWrite(6, LOW);
-         }
-          if (x==1) {                           //Select BFO
-             digitalWrite(4, HIGH);
-             digitalWrite(6, LOW);
-         }
-
-         if (x==2) {                            //Select HFO
-             digitalWrite(4, LOW);
-             digitalWrite(6, HIGH);
-         }
-
-delay (5);  //settle time
-
-// read the selected frequency using the FreCount library
-
-FreqCount.begin(100);
-
-while (FreqCount.available() == 0);
-     frq = (FreqCount.read())*10;
-//    Serial.println(frq);
-FreqCount.end();
-
-
-//Correction Factor, if needed.  This is added to each of the 3 frequencies read.
-
-          if (x==0)vfo=frq+cf;                  // load frequency's into vfo, bfo, and hfo.
-          if (x==1)bfo=frq+cf;
-          if (x==2)hfo=(frq*8)+cf;              //hfo multiplied by 8 to get actual frequency (hardware divided by 8 with 74LS93 to get frequency into readable range (Arduino can't count above 8Mhz)
-
-
-//Compute the actual dial frequency, round and drop least signifigant digits
-freq = ((((hfo-(bfo+vfo))/10)+5)/10);
-
-// use the BFO (CAR) frequency to determine USB/LSB/CW
-
-// In the TS-520S Service manual on pg. 6, it describes the frequencies used by the BFO for the different modes.
-// It states, “Frequencies are 3396.5 kHz for USB, 3393.5 kHz for LSB, and 3394.3 kHz (receive) and 3395.0 kHz (transmit) for CW.”
-// You might have to tweak these values for your BFO - this is a function that the origional DG5 didn't do.
-// If your Arduino's crystal is off, you might be able to fix both using the correction factor (cf) variable in the "Frequency measurement variables" section
-
-if (bfo > 3396000){
-  USB = true;
-  LSB = false;
-  CW = false;
-  mode = 'U';
-  }
-
-else if (bfo < 3393500){
-  USB = false;
-  LSB = true;
-  CW = false;
-  mode='L';
-  }
-
-  else{
-  USB = false;
-  LSB = false;
-  CW = true;
-  mode='C';
-  }
-
-// Debugging stuff.
-
-//#ifdef DEBUG                                  // for debugging and monitoring the results on the serial port
-if (DEBUG == true){                             // Type "DEBUG1;" (and enter) on the port to enable, "DEBUG0;" to turn off
-Serial.print("VFO: ");                          // prints measured VFO/BFO/HFO values, along with the calculated
-Serial.print (vfo);                             // frequency, and calculated USB/LSB/CW settings.
-Serial.print(" BFO: ");
-Serial.print (bfo);
-Serial.print(" HFO: ");
-Serial.print (hfo);
-Serial.print (" FREQ: ");
-Serial.print (freq);
-Serial.print (" USB: ");
-Serial.print (USB);
-Serial.print (" LSB: ");
-Serial.print (LSB);
-Serial.print (" CW: ");
-Serial.println (CW);
-}
-
-// write to LCD display
-// first, we add the new frequency into an array of 10 frequencies so we can average
-
-  total = total - readings[readIndex];            // subtract the last calculated freq
-  readings[readIndex] = freq;                     // load the new freq reading into the array
-  total = total + readings[readIndex];            // add the freq to the total
-  readIndex = readIndex + 1;                      // advance to the next position in the array
-    if (readIndex >= numReadings) {               // if we're at the end of the array...
-    readIndex = 0;                                // wrap around to the beginning
-  }
-  average = total / numReadings;                  // now, calculate the average:
-
- if (average != FreqOld) {{DisplayFreq(average);}     // has it changed since the last time we updated the display?  If so, update, if not, skip
-
- FreqOld = average;                               // copy new average to FreqOld so we can test if it's changed the next time we run thru the loop
-
-
-//  Display the mode on the last position of the LCD bottom row (far right)
-
-    lcd.setCursor(15,1);
-
-      if (USB == true){
-        lcd.print("U");
-      }
-      else if (LSB == true){
-        lcd.print("L");
-      }
-      else if (CW == true){
-        lcd.print("C");
-      }
-//#endif - end of frequency counting loop
-
-}
-
- //  Serial port handeling
- //  Check serial port to see if we have a command
-  if (stringComplete) {
-
-    if (inputString == "ID;") {            //ID the radio as a "ID007" - Kenwood TS790. There is no TS-520S. ;-)
-         Serial.print("ID007;");
-    }
-
-     else if (inputString =="DEBUG1;"){        // Turn on debugging when "DEBUG1;" is received.
-       DEBUG=true;
-     }
-
-     else if (inputString =="DEBUG0;"){        // Turn off debugging when "DEBUG0;" is received.
-       DEBUG=false;
-     }
-
-     else if (inputString == "IF;"){
-
-       // Output the frequency and mode in the Kenwood "IF;" return
-       // Reading strings from flash to save memory, could use a more elegant approach, but this works :-)
-
-
-       if (freq > 90000){  // if above 10Mhz set the padding correct for the IF; command
-
-       if (USB == true){
-       Serial.print (F("IF000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000020000000;"));  // The "2" is the mode,
-       }
-       else if (LSB == true){
-       Serial.print (F("IF000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000010000000;"));    // Mode set to 1 for "LSB".
-       }
-       else if (CW == true){
-       Serial.print (F("IF000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000030000000;"));  // The "3" is the mode, CW
-     }
-       }
-
-       else {             // if below 10Mhz set the padding correct for the IF; command
-       if (USB == true){
-       Serial.print (F("IF0000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000020000000;"));  // The "2" is the mode,
-       }
-       else if (LSB == true){
-       Serial.print (F("IF0000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000010000000;"));    // Mode set to 1 for "LSB".
-       }
-       else if (CW == true){
-       Serial.print (F("IF0000"));
-       Serial.print (freq);
-       Serial.print (F("00000000000000000030000000;"));  // The "3" is the mode, CW
-       }
-       }
-
-  }
-  }
-    // clear the string:
-    inputString = "";
-    stringComplete = false;
-
-    // end of loop
-  }
-  }


updated Fri 09/08/2017  8:06:44.73

updated Fri 09/08/2017  8:06:44.73

--- glowing-pumpkin-feather/glowing-pumpkin-feather.ino
+++ glowing-pumpkin-feather/glowing-pumpkin-feather.ino
@@ -2,7 +2,7 @@
    Glowing Pumpkin Project (Feather Version)

    By John M. Wargo
-   September 24, 2016
+   September, 2017
  **************************************************/

 //Adafruit Feather board


melhorado bloqueio e inter-travamento de alarmes

--- EMP-B-Due.ino
+++ EMP-B-Due.ino
@@ -112,7 +112,7 @@
 // MODOS DE TRABALHO

 void standBy(){
-  if (stand_by){
+  if (stand_by and !alarme_ativo){
     acionaGeral(); // Checa botão Geral
     acionaDosador(); // Checa botão Dosador
     acionaDatador(); // Checa botão Datador
@@ -121,7 +121,7 @@
     } else {
       reiniciaSaidas();
     }
-  } else {
+  } else if (!alarme_ativo) {
     delay(3000); // Espera 3 segundos após energização
     stand_by = VERDADEIRO; // Libera funcionamento
   }
@@ -177,6 +177,7 @@

 void bloqueioPorAlarme(String texto){
   alarme_ativo = VERDADEIRO;
+  stand_by = FALSO;
   escreveSerial("\n<< Alarme! >>\n");
   reiniciaSaidas();
   escreveSerial(texto + " detectou uma falha de segurança.");


fix code

fix code

--- little-switches/arduino/3_setup-rel/3_setup-rel.ino
+++ little-switches/arduino/3_setup-rel/3_setup-rel.ino
@@ -35,8 +35,16 @@
   pinMode(9,OUTPUT);
   pinMode(A0,OUTPUT);
   pinMode(A1,OUTPUT);
-  pinMode(A2,OUTPUT);
-  pinMode(A3,OUTPUT);
+
+  digitalWrite(2,LOW);
+  digitalWrite(4,LOW);
+  digitalWrite(5,LOW);
+  digitalWrite(6,LOW);
+  digitalWrite(7,LOW);
+  digitalWrite(8,LOW);
+  digitalWrite(9,LOW);
+  digitalWrite(A0,LOW);
+  digitalWrite(A1,LOW);

 }


Serial API - Settings modification and reset to defaults functionality was added.

--- DiveIno.ino
+++ DiveIno.ino
@@ -20,7 +20,7 @@
 #include "Logbook.h"
 #include "LastDive.h"

-const String VERSION_NUMBER = "1.2.3";
+const String VERSION_NUMBER = "1.2.4";

 SdFat SD;

@@ -326,7 +326,59 @@
 		Serial.println(responseMessage);
 	} else if (message.startsWith(F("SETTINGS")) || message.startsWith(F("settings"))) {
 		settings.printSettings();
-	}
+	} else if (message.startsWith(F("SOUND")) || message.startsWith(F("sound"))) {
+		String state = message.substring(5);
+		state.trim();
+		if (state.startsWith(F("ON")) || state.startsWith(F("on"))) {
+			soundSetting = true;
+			responseMessage += F("SOUND - ON");
+		} else {
+			soundSetting = false;
+			responseMessage += F("SOUND - OFF");
+		}
+		saveSettings();
+		Serial.println(responseMessage);
+	} else if (message.startsWith(F("METRIC")) || message.startsWith(F("metric"))) {
+		String state = message.substring(5);
+		state.trim();
+		if (state.startsWith(F("ON")) || state.startsWith(F("on"))) {
+			imperialUnitsSetting = false;
+			responseMessage += F("METRIC - ON");
+		} else {
+			imperialUnitsSetting = true;
+			responseMessage += F("METRIC - OFF");
+		}
+		saveSettings();
+		Serial.println(responseMessage);
+	} else if (message.startsWith(F("PRESSURE")) || message.startsWith(F("pressure"))) {
+		float seaLevelPressure = message.substring(8).toFloat();
+		if (seaLevelPressure > 900 && seaLevelPressure < 1200) {
+			seaLevelPressureSetting = seaLevelPressure;
+			responseMessage += F("PRESSURE - ");
+			responseMessage += seaLevelPressureSetting;
+			saveSettings();
+		} else {
+			responseMessage += F("ERROR: Invalid argument - Must be between 900 and 1200 millibar!");
+		}
+		Serial.println(responseMessage);
+	} else if (message.startsWith(F("OXYGEN")) || message.startsWith(F("oxygen"))) {
+		float oxygenRate = message.substring(6).toFloat();
+		if (oxygenRate >= 0.16 && oxygenRate <= 0.5) {
+			oxygenRateSetting = oxygenRate;
+			responseMessage += F("OXYGEN - ");
+			responseMessage += oxygenRateSetting;
+			saveSettings();
+		} else {
+			responseMessage += F("ERROR: Invalid argument - Must be between 0.16 and 0.50!");
+		}
+		Serial.println(responseMessage);
+	} else if (message.startsWith(F("DEFAULT")) || message.startsWith(F("default"))) {
+		setSettingsToDefault();
+		saveSettings();
+		responseMessage += F("DEFAULT settings were set.");
+		Serial.println(responseMessage);
+	}
+
 	Serial.flush();
 }


spped adjust

spped adjust

--- eMotion/flap/flap.ino
+++ eMotion/flap/flap.ino
@@ -99,7 +99,7 @@
         if(IR())
           delay(1000);
         else
-          delay(5000.0 / light() + rand() / RAND_MAX * 250);
+          delay(10000.0 / light() + rand() / RAND_MAX * 50);
     }

     for(int i = start; i < start+n_serial; ++i)
@@ -108,7 +108,7 @@
         if(IR())
           delay(1000);
         else
-          delay(5000.0 / light() + rand() / RAND_MAX * 250);
+          delay(10000.0 / light() + rand() / RAND_MAX * 50);
     }

 }


Tested and fixed bugs to enable blinkers

--- FH_Tbot.ino
+++ FH_Tbot.ino
@@ -9,10 +9,7 @@
 #include <Ticker.h>
 #include "MotorController.h"
 #include "US100Ping.h"
-#include <Adafruit_NeoPixel.h>
-#ifdef __AVR__
-  #include <avr/power.h>
-#endif
+#include <NeoPixelBus.h>

 // WebPage
 #include "WebPage.h"
@@ -32,11 +29,11 @@
 //   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
 //   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
 //   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
-#define PIN 3
+#define PIN D4
 #define NUMPIXELS      6
-Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
+NeoPixelBus<NeoGrbFeature, NeoEsp8266Uart800KbpsMethod> strip(6,D4);//6 [pixels on pin d4]
 int delayval = 500; // delay for half a second
-boolean useBlinkers = false;
+boolean useBlinkers = true;

@@ -57,8 +54,8 @@
 // stepper without PWM/speed input pins, don't use D0
 const int motorLeftA  = D5;
 const int motorLeftB  = D6;
-const int motorRightA = D2;
-const int motorRightB = D1;
+const int motorRightA = D3;
+const int motorRightB = D2;

 motorController motors(motorLeftA,motorLeftB,motorRightA,motorRightB);

@@ -120,45 +117,53 @@
  */
 void updateBlinkers(int indexOfX, int indexOfY){
   //Creates array for pixels
-  int px[NUMPIXELS];
+  RgbColor px[NUMPIXELS];
+  for(int i = 0; i < NUMPIXELS; i++){
+    px[i] = RgbColor(0,0,0);
+  }
   //Pick which variable is greater in magnitude.
     //If X>Y the result should be 0
     if((indexOfX % indexOfY) == 0){
       if(indexOfX < 0 ){
         //Update Left
-        px = {(NUMPIXELS/2 - 1),NUMPIXELS - 1};
+        //px[(NUMPIXELS/2 - 1)] = RgbColor(255,127,0);
+        //px[NUMPIXELS - 1] =  RgbColor(255,127,0);
+        px[2] = RgbColor(80,40,0);
+        px[5] =  RgbColor(80,40,0);
       }else if (indexOfX > 0){
         //update Right
-        px = {0,(NUMPIXELS/2)};
+        //px[0] =  RgbColor(255,127,0);
+        //px[(NUMPIXELS/2)] = RgbColor(255,127,0);
+        px[0] =  RgbColor(80,40,0);
+        px[3] = RgbColor(80,40,0);
       }else{
-        //Equals 0 no indication
-        for(int i=0;i<NUMPIXELS;i++){
-          px[i] = i;
-        }
+        //Equals 0 no indication
       }
     }else{
       if(indexOfY < 0 ){
-        for(int i=0;i<(NUMPIXELS/2);i++){
-          px[i] = i;
-        }
+        //px[(NUMPIXELS/2) - 2] = RgbColor(255,127,0);
+        //px[(NUMPIXELS/2) - 1] = RgbColor(255,127,0);
+        //px[(NUMPIXELS/2)] = RgbColor(255,127,0);
+        px[0] = RgbColor(80,40,0);
+        px[1] = RgbColor(80,40,0);
+        px[2] = RgbColor(80,40,0);
       }else if (indexOfY > 0){
-        for(int i=(NUMPIXELS/2);i<NUMPIXELS;i++){
-          px[i] = i;
-        }
+        //px[(NUMPIXELS) - 2] = RgbColor(255,127,0);
+        //px[(NUMPIXELS) - 1] = RgbColor(255,127,0);
+        //px[(NUMPIXELS)] = RgbColor(255,127,0);
+        px[3] = RgbColor(80,40,0);
+        px[4] = RgbColor(80,40,0);
+        px[5] = RgbColor(80,40,0);
       }else{
         //Equals 0 no indication
-        for(int i=0;i<NUMPIXELS;i++){
-          px[i] = i;
-        }
       }
     }
-    int i = 0;
-    while(px[i] != null){
+
+    for(int i = 0; i< NUMPIXELS; i++){
       // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
-      pixels.setPixelColor(px[i], pixels.Color(255,127,0)); // Orange colour.
-      pixels.show(); // This sends the updated pixel color to the hardware.
+      strip.SetPixelColor(i, px[i]); // Orange colour.
+      strip.Show(); // This sends the updated pixel color to the hardware.
       //delay(delayval); // Delay for a period of time (in milliseconds).
-      i ++;
     }
 }

@@ -174,19 +179,20 @@
   motors.setPWMFrequency(50);           // this setting is optional, depending on power supply and H-Bridge this option will alter motor noise and torque.
   //motors.setMinimumSpeed(0.25);         // this setting is optional, default is 0.1(10%) to prevent motor from stalling at low speed

-  pixels.begin();
-  pixels.show(); // Initialize all pixels to 'off'
+  strip.Begin();
+  strip.Show(); // Initialize all pixels to 'off'
      //////////////////////////
  for(int i=0;i<NUMPIXELS;i++){

-    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
-    pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.
-
-    pixels.show(); // This sends the updated pixel color to the hardware.
-
-    delay(delayval); // Delay for a period of time (in milliseconds).
-
-  }
+    // strip.Color takes RGB values, from 0,0,0 up to 255,255,255
+    strip.SetPixelColor(i, RgbColor(0,40,0)); // Moderately bright green color.
+
+  }
+  strip.Show(); // This sends the updated pixel color to the hardware.
+  //delay(delayval); // Delay for a period of time (in milliseconds).
+
+
+
   /////////////////////////////////////////////

   }
@@ -245,7 +251,7 @@
     //Blinker Addon
     //Only operates if enabled in RGB options above
     if(useBlinkers == true){
-      updateBlinkers(dx,dy);
+      updateBlinkers(dX,dY);
     }

   }else{


Update loopFunctions.ino

Update loopFunctions.ino

--- arduino/loopFunctions.ino
+++ arduino/loopFunctions.ino
@@ -1,6 +1,7 @@
 SENS readSensors() {
   SENS temp;

+  // These are temporary values, but needs to be changed to actual sensor readings
   temp.pressure = 3024;
   temp.temp = 18.3;
   temp.volt = 10.8;


TODO-632: WIP

TODO-632: WIP

--- test_SECFRAME/test_SECFRAME.ino
+++ test_SECFRAME/test_SECFRAME.ino
@@ -622,7 +622,7 @@
   AssertIsEqual(0, memcmp(input, inputDecoded, 32));
   }

-// Test encoding of entire secure frame for TX.
+// Test encoding/encryption then decoding/decryption of entire secure frame.
 static void testSecureSmallFrameEncoding()
   {
   Serial.println("SecureSmallFrameEncoding");
@@ -655,15 +655,17 @@
   const uint8_t id[] = { 0xaa, 0xaa, 0xaa, 0xaa };
   const uint8_t iv[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55, 0x00, 0x00, 0x2a, 0x00, 0x03, 0x19 };
   const uint8_t body[] = { 0x7f, 0x11, 0x7b, 0x22, 0x62, 0x22, 0x3a, 0x31 };
-  AssertIsEqual(63, OTRadioLink::encodeSecureSmallFrameRaw(buf, sizeof(buf),
+  const uint8_t encodedLength = OTRadioLink::encodeSecureSmallFrameRaw(buf, sizeof(buf),
                                     OTRadioLink::FTS_BasicSensorOrValve,
                                     0,
                                     id, 4,
                                     body, sizeof(body),
                                     iv,
                                     OTAESGCM::fixed32BTextSize12BNonce16BTagSimpleEnc_DEFAULT_STATELESS,
-                                    NULL, zeroKey));
-  //3f cf 04 aa aa aa aa 20 | ...
+                                    NULL, zeroKey);
+  AssertIsEqual(63, encodedLength);
+  AssertIsTrue(encodedLength <= sizeof(buf));
+  //3e cf 04 aa aa aa aa 20 | ...
   AssertIsEqual(0x3e, buf[0]);
   AssertIsEqual(0xcf, buf[1]);
   AssertIsEqual(0x04, buf[2]);
@@ -685,6 +687,9 @@
   AssertIsEqual(0x97, buf[46]); // 1st byte of tag.
   AssertIsEqual(0x8d, buf[61]); // 16th/last byte of tag.
   AssertIsEqual(0x80, buf[62]); // enc format.
+  // To decode, first unpick the header.
+  OTRadioLink::SecurableFrameHeader sfhRX;
+//  AssertIsTrue(0 != sfhRX.checkAndDecodeSmallFrameHeader(buf, encodedLength));
   }


Check unary encode/decode.

Check unary encode/decode.

--- test_SECFRAME/test_SECFRAME.ino
+++ test_SECFRAME/test_SECFRAME.ino
@@ -785,6 +785,21 @@
 //  Serial.println(after - before); // DHD20160207: 1442 for 8 rounds, or ~180ms per encryption.
   }

+// Test low-wear unary encoding.
+static void testUnaryEncoding()
+  {
+  Serial.println("UnaryEncoding");
+  // Check for conversion back and forth of all allowed represented values.
+  for(uint8_t i = 0; i <= 8; ++i) { AssertIsEqual(i, OTV0P2BASE::eeprom_unary_1byte_decode(OTV0P2BASE::eeprom_unary_1byte_encode(i))); }
+  for(uint8_t i = 0; i <= 16; ++i) { AssertIsEqual(i, OTV0P2BASE::eeprom_unary_2byte_decode(OTV0P2BASE::eeprom_unary_2byte_encode(i))); }
+  // Ensure that all-1s (erased) EEPROM values equate to 0.
+  AssertIsEqual(0, OTV0P2BASE::eeprom_unary_1byte_decode(0xff));
+  AssertIsEqual(0, OTV0P2BASE::eeprom_unary_1byte_decode(0xffffU));
+  // Check rejection of at least one bad value.
+  AssertIsEqual(-1, OTV0P2BASE::eeprom_unary_1byte_decode(0xef));
+  AssertIsEqual(-1, OTV0P2BASE::eeprom_unary_2byte_decode(0xcccc));
+  }
+
 // Test some basic parameters of node associations.
 // Does not wear non-volatile memory (eg EEPROM).
 static void testNodeAssoc()
@@ -977,6 +992,7 @@
   testLibVersion();
   testLibVersions();

+  testUnaryEncoding();
   testFrameQIC();
   testFrameHeaderEncoding();
   testFrameHeaderDecoding();


comments

comments

--- angu/angu.ino
+++ angu/angu.ino
@@ -1,7 +1,8 @@
 #include <CurieBLE.h>

 const int ledPin = 13; // set ledPin to on-board LED
-
+//                                                        V
+//ID IS A TEST. IT WAS 19B10010-E8F2-537E-4F6C-D104768A1214<<<<<
 BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1215"); // create service


updated opencm firmware

updated opencm firmware

--- ThingThree/Code/OpenCM/OpenCM.ino
+++ ThingThree/Code/OpenCM/OpenCM.ino
@@ -1,8 +1,38 @@
+#define START_1 512
+#define START_2 800
+#define START_3 950
+#define GRIPPER_OPEN 800
+#define GRIPPER_CLOSED 450
+
 Dynamixel Dxl(1);
+
+void gripper(boolean open) {
+	if (open) {
+		Dxl.goalPosition(4,GRIPPER_OPEN);
+		Dxl.goalPosition(5,1024-GRIPPER_OPEN);
+	} else {
+		Dxl.goalPosition(4,GRIPPER_CLOSED);
+		Dxl.goalPosition(5,1024-GRIPPER_CLOSED);
+	}
+}

 void setup() {
 	Serial2.begin(57600);
 	Dxl.begin(3);
+
+	for (int id=1; id<6; id++) {
+		Dxl.jointMode(id);
+		Dxl.ledOn(id);
+	}
+
+	Dxl.goalPosition(1, START_1);
+	Dxl.goalPosition(2, START_2);
+	Dxl.goalPosition(3, START_3);
+
+	for (int i=0; i<5; i++) {
+		gripper(i%2);
+		delay(500);
+	}
 }

 byte blockingRead() {
@@ -23,30 +53,25 @@
 }

 void processWrite(byte cmd, byte id) {
-	switch (cmd) {
-		case 'i': { // initialize
-			Dxl.jointMode(id);
-			break;
-		} case 'n': { // set new id
-			int newID;
-			if (!readInt(&newID)) break;
-			Dxl.setID(id, newID);
-			Dxl.jointMode(newID);
-			break;
-		} case 's': { // set speed
-			int add, val;
-			if (!(readInt(&add) && readInt(&val))) break;
-			//Dxl.writeWord(id, add, val);
+	int val;
+	readInt(&val);
+
+  	switch (cmd) {
+		case 's': { // set speed
 			Dxl.goalSpeed(id, val);
 			break;
 		} case 'p': { // move to position
-			int pos, vel;
-			if (!(readInt(&pos) && readInt(&vel))) break;
-			Dxl.setPosition(id, pos, vel);
+			Dxl.goalPosition(id, val);
 			break;
+		} case 'o': {
+			gripper(true);
+			break;
+		} case 'c': {
+			gripper(false);
+			break;
 		} case 'g': { // general write command
-			int add, val;
-			if (!(readInt(&add) && readInt(&val))) break;
+			int add;
+			if (!readInt(&add)) break;
 			Dxl.writeWord(id, add, val);
 			break;

@@ -85,8 +110,10 @@
 		byte cmd = blockingRead();
 		byte id = blockingRead();

-		(inByte == 'W') ? processWrite(cmd, id) : processRead(cmd, id);
-	}
+		if (inByte == 'W') processWrite(cmd, id);
+		else if (inByte == 'R') processRead(cmd, id);
+		else Serial2.println("wut");
+	}
 }