revert to 2 spaces for a tab

revert to 2 spaces for a tab

--- src/Light/Light.ino
+++ src/Light/Light.ino
@@ -40,370 +40,370 @@
 extern ConcurrentAnimator animator;

 void setup() {
-    Serial.begin(115200);
-
-    delay(500);
-
-    Serial << F("Light startup.") << endl;
-
-    Serial1.begin(115200);
-    //start the library, pass in the data details and the name of the serial port.
-    // Can be Serial, Serial1, Serial2, etc.
-    ET.begin(details(inst), &Serial1);
-
-    Serial << F("Total strip memory usage: ") << TOTAL_LED_MEM << F(" bytes.") << endl;
-    Serial << F("Free RAM: ") << freeRam() << endl;
-
-    // random seed from analog noise.
-    randomSeed(analogRead(0));
-
-    pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW);
-
-    Serial << F("RimJob: ") << RIM_N << F(" pixels in 4 segments of length ") << RIM_SEG_LENGTH << endl;
-    Serial << F("RimJob: YEL starts at: ") << YEL_SEG_START << endl;
-    Serial << F("RimJob: BLU starts at: ") << BLU_SEG_START << endl;
-    Serial << F("RimJob: RED starts at: ") << RED_SEG_START << endl;
-    Serial << F("RimJob: GRN starts at: ") << GRN_SEG_START << endl;
-
-    configureAnimations();
-
-    Serial << F("Free RAM: ") << freeRam() << endl;
-    Serial << F("Light: startup complete.") << endl;
+  Serial.begin(115200);
+
+  delay(500);
+
+  Serial << F("Light startup.") << endl;
+
+  Serial1.begin(115200);
+  //start the library, pass in the data details and the name of the serial port.
+  // Can be Serial, Serial1, Serial2, etc.
+  ET.begin(details(inst), &Serial1);
+
+  Serial << F("Total strip memory usage: ") << TOTAL_LED_MEM << F(" bytes.") << endl;
+  Serial << F("Free RAM: ") << freeRam() << endl;
+
+  // random seed from analog noise.
+  randomSeed(analogRead(0));
+
+  pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, LOW);
+
+  Serial << F("RimJob: ") << RIM_N << F(" pixels in 4 segments of length ") << RIM_SEG_LENGTH << endl;
+  Serial << F("RimJob: YEL starts at: ") << YEL_SEG_START << endl;
+  Serial << F("RimJob: BLU starts at: ") << BLU_SEG_START << endl;
+  Serial << F("RimJob: RED starts at: ") << RED_SEG_START << endl;
+  Serial << F("RimJob: GRN starts at: ") << GRN_SEG_START << endl;
+
+  configureAnimations();
+
+  Serial << F("Free RAM: ") << freeRam() << endl;
+  Serial << F("Light: startup complete.") << endl;
 }

 void setupStrip(Adafruit_NeoPixel &strip, const uint32_t color) {
-    Serial << F("Initializing strip with pixel count: ") << strip.numPixels() << endl;
-
-    strip.begin();
-
-    for ( uint16_t i = 0; i < strip.numPixels(); i++ ) {
-        strip.setPixelColor(i, color);
-    }
-
-    strip.show();
+  Serial << F("Initializing strip with pixel count: ") << strip.numPixels() << endl;
+
+  strip.begin();
+
+  for ( uint16_t i = 0; i < strip.numPixels(); i++ ) {
+    strip.setPixelColor(i, color);
+  }
+
+  strip.show();
 }
 int gameplayCounter = 0;
 const int maxGameplayCounter = 100;

 void loop() {
-    if (fasterStripUpdateInterval.check()) {
-        // animation instructions
-        mapToAnimation(animator, inst);
-
-        fasterStripUpdateInterval.reset();
-    }
-
-    static Metro quietUpdateInterval(10UL *1000UL); // after 10 second of not instructions, we should do something.
-
-    //check and see if a data packet has come in.
-    if (ET.receiveData()) {
-
-        Serial << F("I");
-
-        //    for( byte i=0; i<N_COLORS; i++ ) {
-        //      Serial << F(" Color ") << i << F("; R:") << inst.light[i].red << F(" G:") << inst.light[i].green << F(" B:") << inst.light[i].blue << endl;
-        //    }
-
-        // dispatch the requests
-        setStripColor(redL, inst.light[I_RED]);
-        setStripColor(grnL, inst.light[I_GRN]);
-        setStripColor(bluL, inst.light[I_BLU]);
-        setStripColor(yelL, inst.light[I_YEL]);
-        // toggle LED to ACK new button press
-        static boolean ledStatus=false;
-        ledStatus = !ledStatus;
-        digitalWrite(LED_PIN, ledStatus);
-
-        quietUpdateInterval.reset();
-    }
-
-    // when it's quiet, we need to do something with the LEDs
-    if( quietUpdateInterval.check() ) {
-        Serial << F("Quiet interval elapsed.") << endl;
-        Serial << F("Free RAM=") << freeRam() << endl;
-    }
-
-    /*
+  if (fasterStripUpdateInterval.check()) {
+    // animation instructions
+    mapToAnimation(animator, inst);
+
+    fasterStripUpdateInterval.reset();
+  }
+
+  static Metro quietUpdateInterval(10UL *1000UL); // after 10 second of not instructions, we should do something.
+
+  //check and see if a data packet has come in.
+  if (ET.receiveData()) {
+
+    Serial << F("I");
+
+    //    for( byte i=0; i<N_COLORS; i++ ) {
+    //      Serial << F(" Color ") << i << F("; R:") << inst.light[i].red << F(" G:") << inst.light[i].green << F(" B:") << inst.light[i].blue << endl;
+    //    }
+
+    // dispatch the requests
+    setStripColor(redL, inst.light[I_RED]);
+    setStripColor(grnL, inst.light[I_GRN]);
+    setStripColor(bluL, inst.light[I_BLU]);
+    setStripColor(yelL, inst.light[I_YEL]);
+    // toggle LED to ACK new button press
+    static boolean ledStatus=false;
+    ledStatus = !ledStatus;
+    digitalWrite(LED_PIN, ledStatus);
+
+    quietUpdateInterval.reset();
+  }
+
+  // when it's quiet, we need to do something with the LEDs
+  if( quietUpdateInterval.check() ) {
+    Serial << F("Quiet interval elapsed.") << endl;
+    Serial << F("Free RAM=") << freeRam() << endl;
+  }
+
+  /*
 TODO: fix this and put it in a metro loop
-    // compute the next step and flag for show.
-    updateRule90(rimJob, PIXEL_TTL); rimUpdated = true;
-
-    // if we wanted the buttons to animate differently than the rim, this would be the place to do it.
-    updateRule90(redL, PIXEL_TTL); redUpdated = true;
-    updateRule90(grnL, PIXEL_TTL); grnUpdated = true;
-    updateRule90(bluL, PIXEL_TTL); bluUpdated = true;
-    updateRule90(yelL, PIXEL_TTL); yelUpdated = true;
-
-    // if we wanted the middle chotsky to animate differently than the rim, this would be the place to do it.
-    updateRule90(midL, PIXEL_TTL); midUpdated = true;
-    */
+  // compute the next step and flag for show.
+  updateRule90(rimJob, PIXEL_TTL); rimUpdated = true;
+
+  // if we wanted the buttons to animate differently than the rim, this would be the place to do it.
+  updateRule90(redL, PIXEL_TTL); redUpdated = true;
+  updateRule90(grnL, PIXEL_TTL); grnUpdated = true;
+  updateRule90(bluL, PIXEL_TTL); bluUpdated = true;
+  updateRule90(yelL, PIXEL_TTL); yelUpdated = true;
+
+  // if we wanted the middle chotsky to animate differently than the rim, this would be the place to do it.
+  updateRule90(midL, PIXEL_TTL); midUpdated = true;
+  */

 }

 int freeRam () {
-    extern int __heap_start, *__brkval;
-    int v;
-    return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
+  extern int __heap_start, *__brkval;
+  int v;
+  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
 }

 // unpack and pack functions
 void extractColor(uint32_t c, uint8_t * cv) {
-    cv[0] = (c << 8 ) >> 24;
-    cv[1] = (c << 16) >> 24;
-    cv[2] = (c << 24) >> 24;
+  cv[0] = (c << 8 ) >> 24;
+  cv[1] = (c << 16) >> 24;
+  cv[2] = (c << 24) >> 24;
 }
 // apprently, the color handling is slightly different btw matrix and strip?
 uint32_t packColor(Adafruit_NeoPixel &strip, uint8_t * cv) {
-    return ( strip.Color(cv[0], cv[1], cv[2]) );
+  return ( strip.Color(cv[0], cv[1], cv[2]) );
 }
 uint32_t packColor(Adafruit_NeoMatrix &matrix, uint8_t * cv) {
-    return ( matrix.Color(cv[0], cv[1], cv[2]) );
+  return ( matrix.Color(cv[0], cv[1], cv[2]) );
 }
 void printColor(uint32_t c) {
-    // pull out RGB elements
-    uint8_t cv[3];
-    extractColor(c, cv);
-    Serial << F(" R: ") << cv[0] << F(" G: ") << cv[1] << F(" B: ") << cv[2] << endl;
+  // pull out RGB elements
+  uint8_t cv[3];
+  extractColor(c, cv);
+  Serial << F(" R: ") << cv[0] << F(" G: ") << cv[1] << F(" B: ") << cv[2] << endl;
 }

 // adjust color with a decrement
 uint32_t adjustColor(uint32_t c, unsigned long ttl) {
-    // pull out RGB elements
-    uint8_t cv[3];
-    signed int cvl[3];
-    extractColor(c, cv);
-    int adj;
-
-    // for each color
-    for ( uint8_t i = 0; i < 3; i++ ) {
-
-        // try to smoothly drop the colors
-        if ( i == 0 ) adj = RED_MAX / (PIXEL_TTL / STRIP_UPDATE);
-        else if ( i == 1 ) adj = GRN_MAX / (PIXEL_TTL / STRIP_UPDATE);
-        else adj = BLU_MAX / (PIXEL_TTL / STRIP_UPDATE);
-
-        if ( cv[i] >= adj + LED_OFF ) { // unsiged stuff.  take care.
-            cv[i] = cv[i] - adj;
-        } else {
-            cv[i] = LED_OFF;
-        }
-        //    Serial << cv[i] << endl;
-    }
-
-    //  while(1);
-    // repack and return
-    return ( packColor(redL, cv) );
+  // pull out RGB elements
+  uint8_t cv[3];
+  signed int cvl[3];
+  extractColor(c, cv);
+  int adj;
+
+  // for each color
+  for ( uint8_t i = 0; i < 3; i++ ) {
+
+    // try to smoothly drop the colors
+    if ( i == 0 ) adj = RED_MAX / (PIXEL_TTL / STRIP_UPDATE);
+    else if ( i == 1 ) adj = GRN_MAX / (PIXEL_TTL / STRIP_UPDATE);
+    else adj = BLU_MAX / (PIXEL_TTL / STRIP_UPDATE);
+
+    if ( cv[i] >= adj + LED_OFF ) { // unsiged stuff.  take care.
+      cv[i] = cv[i] - adj;
+    } else {
+      cv[i] = LED_OFF;
+    }
+    //    Serial << cv[i] << endl;
+  }
+
+  //  while(1);
+  // repack and return
+  return ( packColor(redL, cv) );
 }

 // merge colors with some kind of XOR
 uint32_t mergeColor(uint32_t c1, uint32_t c2) {
-    // use bitwise operations to get at packed color vector contents
-    const uint8_t bitIndex[3] = {8, 16, 24};
-    // store the color vector result
-    uint8_t c1v[3], c2v[3], cv[3];
-
-    // get the RGB components.
-    extractColor(c1, c1v);
-    extractColor(c2, c2v);
-
-    // for each color
-    for ( uint8_t i = 0; i < 3; i++ ) {
-        // xor by color channel
-        if ( c1v[i] > 0 && c2v[i] > 0 ) {
-            // alive in both cells, so drop this channel.
-            cv[i] = LED_OFF;
-        } else {
-            // dead in one, so sum them.  unsigned type is doing some funky stuff when >255.
-            cv[i] = max(c1v[i], c2v[i]);
-        }
-    }
-    return ( packColor(redL, cv) );
+  // use bitwise operations to get at packed color vector contents
+  const uint8_t bitIndex[3] = {8, 16, 24};
+  // store the color vector result
+  uint8_t c1v[3], c2v[3], cv[3];
+
+  // get the RGB components.
+  extractColor(c1, c1v);
+  extractColor(c2, c2v);
+
+  // for each color
+  for ( uint8_t i = 0; i < 3; i++ ) {
+    // xor by color channel
+    if ( c1v[i] > 0 && c2v[i] > 0 ) {
+      // alive in both cells, so drop this channel.
+      cv[i] = LED_OFF;
+    } else {
+      // dead in one, so sum them.  unsigned type is doing some funky stuff when >255.
+      cv[i] = max(c1v[i], c2v[i]);
+    }
+  }
+  return ( packColor(redL, cv) );
 }

 // updates the automata using a modified Rule 90
 void updateRule90(Adafruit_NeoPixel &strip, unsigned long ttl) {
-    // intialize first cell
-    uint32_t cs = strip.getPixelColor(0);
-    uint32_t ps = strip.getPixelColor(strip.numPixels() - 1);
-    uint32_t ns, color;
-    // store the color vector result
-    uint8_t cv[3];
-
-    // loop to update
-    for (uint16_t i = 0; i < strip.numPixels(); i++) {
-        // get next state
-        if (i < strip.numPixels() - 1) {
-            ns = strip.getPixelColor(i + 1);
-        }
-        else { // wrapping back around
-            ns = strip.getPixelColor(0);
-        }
-
-        // apply Rule 90
-        if ( ps == 0 ) {
-            color = adjustColor(ns, ttl);
-        } else if ( ns == 0 ) {
-            color = adjustColor(ps, ttl);
-        } else {
-            color = mergeColor(adjustColor(ps, ttl), adjustColor(ns, ttl));
-        }
-
-        // set the pixel
-        strip.setPixelColor(i, color);
-
-        // next iteration setting
-        ps = cs;
-        cs = ns;
-    }
+  // intialize first cell
+  uint32_t cs = strip.getPixelColor(0);
+  uint32_t ps = strip.getPixelColor(strip.numPixels() - 1);
+  uint32_t ns, color;
+  // store the color vector result
+  uint8_t cv[3];
+
+  // loop to update
+  for (uint16_t i = 0; i < strip.numPixels(); i++) {
+    // get next state
+    if (i < strip.numPixels() - 1) {
+      ns = strip.getPixelColor(i + 1);
+    }
+    else { // wrapping back around
+      ns = strip.getPixelColor(0);
+    }
+
+    // apply Rule 90
+    if ( ps == 0 ) {
+      color = adjustColor(ns, ttl);
+    } else if ( ns == 0 ) {
+      color = adjustColor(ps, ttl);
+    } else {
+      color = mergeColor(adjustColor(ps, ttl), adjustColor(ns, ttl));
+    }
+
+    // set the pixel
+    strip.setPixelColor(i, color);
+
+    // next iteration setting
+    ps = cs;
+    cs = ns;
+  }
 }

 void test(Adafruit_NeoPixel &strip) {
-    // Some example procedures showing how to display to the pixels:
-    colorWipe(strip, strip.Color(255, 0, 0), 50); // Red
-    colorWipe(strip, strip.Color(0, 255, 0), 50); // Green
-    colorWipe(strip, strip.Color(0, 0, 255), 50); // Blue
-
-    // Send a theater pixel chase in...
-    theaterChase(strip, strip.Color(127, 127, 127), 50); // White
-    theaterChase(strip, strip.Color(127,   0,   0), 50); // Red
-    theaterChase(strip, strip.Color(  0,   0, 127), 50); // Blue
-
-    rainbow(strip, 20);
-    rainbowCycle(strip, 20);
-    theaterChaseRainbow(strip, 50);
+  // Some example procedures showing how to display to the pixels:
+  colorWipe(strip, strip.Color(255, 0, 0), 50); // Red
+  colorWipe(strip, strip.Color(0, 255, 0), 50); // Green
+  colorWipe(strip, strip.Color(0, 0, 255), 50); // Blue
+
+  // Send a theater pixel chase in...
+  theaterChase(strip, strip.Color(127, 127, 127), 50); // White
+  theaterChase(strip, strip.Color(127,   0,   0), 50); // Red
+  theaterChase(strip, strip.Color(  0,   0, 127), 50); // Blue
+
+  rainbow(strip, 20);
+  rainbowCycle(strip, 20);
+  theaterChaseRainbow(strip, 50);
 }

 // Fill the dots one after the other with a color
 void colorWipe(Adafruit_NeoPixel &strip, uint32_t c, uint8_t wait) {
-    for (uint16_t i = 0; i < strip.numPixels(); i++) {
-        strip.setPixelColor(i, c);
-        strip.show();
-        delay(wait);
-    }
+  for (uint16_t i = 0; i < strip.numPixels(); i++) {
+    strip.setPixelColor(i, c);
+    strip.show();
+    delay(wait);
+  }
 }

 void rainbow(Adafruit_NeoPixel &strip, uint8_t wait) {
-    uint16_t i, j;
-
-    for (j = 0; j < 256; j++) {
-        for (i = 0; i < strip.numPixels(); i++) {
-            strip.setPixelColor(i, Wheel(strip, (i + j) & 255));
-        }
-        strip.show();
-        delay(wait);
-    }
+  uint16_t i, j;
+
+  for (j = 0; j < 256; j++) {
+    for (i = 0; i < strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel(strip, (i + j) & 255));
+    }
+    strip.show();
+    delay(wait);
+  }
 }

 // Slightly different, this makes the rainbow equally distributed throughout
 void rainbowCycle(Adafruit_NeoPixel &strip, uint8_t wait) {
-    uint16_t i, j;
-
-    for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
-        for (i = 0; i < strip.numPixels(); i++) {
-            strip.setPixelColor(i, Wheel(strip, ((i * 256 / strip.numPixels()) + j) & 255));
-        }
-        strip.show();
-        delay(wait);
-    }
+  uint16_t i, j;
+
+  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
+    for (i = 0; i < strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel(strip, ((i * 256 / strip.numPixels()) + j) & 255));
+    }
+    strip.show();
+    delay(wait);
+  }
 }

 //Theatre-style crawling lights.
 void theaterChase(Adafruit_NeoPixel &strip, uint32_t c, uint8_t wait) {
-    for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
-        for (int q = 0; q < 3; q++) {
-            for (int i = 0; i < strip.numPixels(); i = i + 3) {
-                strip.setPixelColor(i + q, c);  //turn every third pixel on
-            }
-            strip.show();
-
-            delay(wait);
-
-            for (int i = 0; i < strip.numPixels(); i = i + 3) {
-                strip.setPixelColor(i + q, 0);      //turn every third pixel off
-            }
-        }
-    }
+  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
+    for (int q = 0; q < 3; q++) {
+      for (int i = 0; i < strip.numPixels(); i = i + 3) {
+        strip.setPixelColor(i + q, c);  //turn every third pixel on
+      }
+      strip.show();
+
+      delay(wait);
+
+      for (int i = 0; i < strip.numPixels(); i = i + 3) {
+        strip.setPixelColor(i + q, 0);      //turn every third pixel off
+      }
+    }
+  }
 }

 //Theatre-style crawling lights with rainbow effect
 void theaterChaseRainbow(Adafruit_NeoPixel &strip, uint8_t wait) {
-    for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
-        for (int q = 0; q < 3; q++) {
-            for (int i = 0; i < strip.numPixels(); i = i + 3) {
-                strip.setPixelColor(i + q, Wheel(strip, (i + j) % 255)); //turn every third pixel on
-            }
-            strip.show();
-
-            delay(wait);
-
-            for (int i = 0; i < strip.numPixels(); i = i + 3) {
-                strip.setPixelColor(i + q, 0);      //turn every third pixel off
-            }
-        }
-    }
+  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
+    for (int q = 0; q < 3; q++) {
+      for (int i = 0; i < strip.numPixels(); i = i + 3) {
+        strip.setPixelColor(i + q, Wheel(strip, (i + j) % 255)); //turn every third pixel on
+      }
+      strip.show();
+
+      delay(wait);
+
+      for (int i = 0; i < strip.numPixels(); i = i + 3) {
+        strip.setPixelColor(i + q, 0);      //turn every third pixel off
+      }
+    }
+  }
 }

 // Input a value 0 to 255 to get a color value.
 // The colours are a transition r - g - b - back to r.
 uint32_t Wheel(Adafruit_NeoPixel &strip, byte WheelPos) {
-    WheelPos = 255 - WheelPos;
-    if (WheelPos < 85) {
-        return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
-    } else if (WheelPos < 170) {
-        WheelPos -= 85;
-        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
-    } else {
-        WheelPos -= 170;
-        return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
-    }
+  WheelPos = 255 - WheelPos;
+  if (WheelPos < 85) {
+    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
+  } else if (WheelPos < 170) {
+    WheelPos -= 85;
+    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
+  } else {
+    WheelPos -= 170;
+    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+  }
 }

 void HSVtoRGB(int hue, int sat, int val, int *colors) {
-    int r, g, b, base;
-
-    // hue: 0-359, sat: 0-255, val (lightness): 0-255
-
-    if (sat == 0) { // Achromatic color (gray).
+  int r, g, b, base;
+
+  // hue: 0-359, sat: 0-255, val (lightness): 0-255
+
+  if (sat == 0) { // Achromatic color (gray).
+    colors[0] = val;
+    colors[1] = val;
+    colors[2] = val;
+  } else  {
+    base = ((255 - sat) * val) >> 8;
+    switch (hue / 60) {
+      case 0:
         colors[0] = val;
+        colors[1] = (((val - base) * hue) / 60) + base;
+        colors[2] = base;
+        break;
+      case 1:
+        colors[0] = (((val - base) * (60 - (hue % 60))) / 60) + base;
         colors[1] = val;
+        colors[2] = base;
+        break;
+      case 2:
+        colors[0] = base;
+        colors[1] = val;
+        colors[2] = (((val - base) * (hue % 60)) / 60) + base;
+        break;
+      case 3:
+        colors[0] = base;
+        colors[1] = (((val - base) * (60 - (hue % 60))) / 60) + base;
         colors[2] = val;
-    } else  {
-        base = ((255 - sat) * val) >> 8;
-        switch (hue / 60) {
-            case 0:
-                colors[0] = val;
-                colors[1] = (((val - base) * hue) / 60) + base;
-                colors[2] = base;
-                break;
-            case 1:
-                colors[0] = (((val - base) * (60 - (hue % 60))) / 60) + base;
-                colors[1] = val;
-                colors[2] = base;
-                break;
-            case 2:
-                colors[0] = base;
-                colors[1] = val;
-                colors[2] = (((val - base) * (hue % 60)) / 60) + base;
-                break;
-            case 3:
-                colors[0] = base;
-                colors[1] = (((val - base) * (60 - (hue % 60))) / 60) + base;
-                colors[2] = val;
-                break;
-            case 4:
-                colors[0] = (((val - base) * (hue % 60)) / 60) + base;
-                colors[1] = base;
-                colors[2] = val;
-                break;
-            case 5:
-                colors[0] = val;
-                colors[1] = base;
-                colors[2] = (((val - base) * (60 - (hue % 60))) / 60) + base;
-                break;
-        }
-
-    }
+        break;
+      case 4:
+        colors[0] = (((val - base) * (hue % 60)) / 60) + base;
+        colors[1] = base;
+        colors[2] = val;
+        break;
+      case 5:
+        colors[0] = val;
+        colors[1] = base;
+        colors[2] = (((val - base) * (60 - (hue % 60))) / 60) + base;
+        break;
+    }
+
+  }
 }

@@ -412,33 +412,33 @@

 // twinkle random number of pixels
 void twinkleRand(Adafruit_NeoPixel &strip, int num, uint32_t c, uint32_t bg) {
-    // set background
-    //	 stripSet(bg,0);
-    for (uint16_t i = 0; i < strip.numPixels(); i++) {
-        strip.setPixelColor(i, bg);
-    }
-    // for each num
-    for (int i = 0; i < num; i++) {
-        strip.setPixelColor(random(strip.numPixels()), c);
-    }
+  // set background
+  //	 stripSet(bg,0);
+  for (uint16_t i = 0; i < strip.numPixels(); i++) {
+    strip.setPixelColor(i, bg);
+  }
+  // for each num
+  for (int i = 0; i < num; i++) {
+    strip.setPixelColor(random(strip.numPixels()), c);
+  }
 }

 // other options for effects at: http://funkboxing.com/wordpress/wp-content/_postfiles/sk_qLEDFX_POST.ino

 void setStripColor(Adafruit_NeoPixel &strip, uint32_t c) {
-    for (int i = 0; i < strip.numPixels(); i++) {
-        strip.setPixelColor(i, c);
-    }
-    strip.show();
+  for (int i = 0; i < strip.numPixels(); i++) {
+    strip.setPixelColor(i, c);
+  }
+  strip.show();
 }
 void setStripColor(Adafruit_NeoPixel &strip, colorInstruction &inst) {
-    setStripColor(strip, strip.Color(inst.red, inst.green, inst.blue) );
+  setStripColor(strip, strip.Color(inst.red, inst.green, inst.blue) );
 }

 void setStripColor(Adafruit_NeoMatrix &matrix, uint32_t c) {
-    for (int i = 0; i < matrix.numPixels(); i++) {
-        matrix.setPixelColor(i, c);
-    }
-    matrix.show();
-}
-
+  for (int i = 0; i < matrix.numPixels(); i++) {
+    matrix.setPixelColor(i, c);
+  }
+  matrix.show();
+}
+


add tcp server

add tcp server

--- devices/cc3200_launchpad/example_energia/example_energia.ino
+++ devices/cc3200_launchpad/example_energia/example_energia.ino
@@ -3,36 +3,24 @@
 In order to test the COSSB system, we will support temporary open & public hardware platforms like TI Launchpad, Odroid, Raspberry Pi...
 If you have any questions for this sample code, please contact us(bhhwang@nsynapse.com).
 */
+
 #include <WiFi.h>
 #include <WiFiUdp.h>
 #include <WiFiServer.h>
 #include <WiFiClient.h>

-
-
-char ssid[] = "nsynapseap";
+char ssid[] = "hellfire";
 char password[] = "elec6887";
 WiFiClient client = 0;
+WiFiServer server(8000);

-void printWifiStatus() {
-  Serial.print("Network Name: ");
-  Serial.println(WiFi.SSID());
-
-  IPAddress ip = WiFi.localIP();
-  Serial.print("IP Address: ");
-  Serial.println(ip);
-
-  long rssi = WiFi.RSSI();
-  Serial.print("signal strength (RSSI):");
-  Serial.print(rssi);
-  Serial.println(" dBm");
-}
+boolean bConnected = false;

 void setup()
 {
   Serial.begin(115200);
-  WiFi.init();
   WiFi.begin(ssid, password);
+
   while(WiFi.status()!=WL_CONNECTED) {
     Serial.print(".");
     delay(300);
@@ -45,31 +33,48 @@
     delay(300);
   }

-  Serial.print("Network Name: ");
+  printWifiStatus();
+  server.begin();
+}
+
+
+void loop()
+{
+  WiFiClient client = server.available();
+
+  if(client) {
+    if(!bConnected) {
+      bConnected = true;
+      client.flush();
+      client.println("hello, client!!");
+      Serial.println("client connected");
+    }
+
+    if(client.available() > 0) {
+      char recv = client.read();
+      server.write(recv);
+      Serial.write(recv);
+    }
+  }
+}
+
+
+void printWifiStatus() {
+
+  // print the SSID of the network you're attached to:
+  Serial.print("SSID: ");
   Serial.println(WiFi.SSID());

+  // print your WiFi shield's IP address:
   IPAddress ip = WiFi.localIP();
   Serial.print("IP Address: ");
   Serial.println(ip);

+  // print the received signal strength:
   long rssi = WiFi.RSSI();
   Serial.print("signal strength (RSSI):");
   Serial.print(rssi);
   Serial.println(" dBm");
-
+
 }

-void loop()
-{
-  mdnsAdvertiser(1, "CC3000", 6);
-
-  /*client = server.available();
-  int ret = 0;
-  ret = mdnsAdvertise(1."cc3200", 6);
-  Serial.println("MDNS Advertising returning");
-  Serial.println(ret);*/
-  delay(5000);
-
-}
-
-


Thruster sketch data updates instead of sending test 0's.

--- riptide_serial/firmware/thruster_control_sketch/thruster_control_sketch.ino
+++ riptide_serial/firmware/thruster_control_sketch/thruster_control_sketch.ino
@@ -11,7 +11,7 @@

 void callback(const std_msgs::Int8 &cmd)
 {
-  state.data = 0;
+  state.data = cmd.data;
   state_pub.publish(&state);

   Wire.beginTransmission(3);
@@ -48,7 +48,7 @@

   nh.initNode();
   nh.advertise(state_pub);
-
+  nh.subscribe(cmd_sub);
 }

 void loop()


Turtlebot 3 setup motors - Maybe a little more robust

Try to make the code a little more robust to handle when the servos are somewhat setup.

So in different places the code knows which servo id it is looking for and if found it tries to use that one.  Where before if you had servo ID #1 and #2 and was trying to setup left, it would grab the last servo found #2 and then set it's id to #1...

Also used ping to know if the specific servo was found that is expected for the test servo cases and only does this at baud of 1000000 as that is what turtle expects

--- arduino/opencr_arduino/opencr/libraries/turtlebot3/examples/turtlebot3_setup/turtlebot3_setup_motor/turtlebot3_setup_motor.ino
+++ arduino/opencr_arduino/opencr/libraries/turtlebot3/examples/turtlebot3_setup/turtlebot3_setup_motor/turtlebot3_setup_motor.ino
@@ -1,17 +1,17 @@
 /*******************************************************************************
-* Copyright 2016 ROBOTIS CO., LTD.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
+  Copyright 2016 ROBOTIS CO., LTD.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
 *******************************************************************************/

 /* Authors: Yoonseok Pyo, Leon Jung, Darby Lim, HanCheol Cho */
@@ -24,7 +24,7 @@

 // Default setting
 #define DEVICENAME                      "/dev/OpenCR"       // Check which port is being used on your controller
-                                                            // ex) Windows: "COM1"   Linux: "/dev/ttyUSB0"
+// ex) Windows: "COM1"   Linux: "/dev/ttyUSB0"
 #define CMD_SERIAL                      Serial              // USB Serial

@@ -43,8 +43,8 @@
 char *dev_name = (char*)DEVICENAME;

 // Initialize Packethandler2 instance
- dynamixel::PacketHandler *packetHandler2;
- dynamixel::PortHandler   *portHandler;
+dynamixel::PacketHandler *packetHandler2;
+dynamixel::PortHandler   *portHandler;

 int tb3_id = -1;
@@ -52,7 +52,7 @@

 bool requestConfirm(void);
-bool findMotor(void);
+bool findMotor(int id);
 bool setupMotorLeft(void);
 bool setupMotorRight(void);
 void testMotor(uint8_t id);
@@ -66,7 +66,7 @@
 void setup()
 {
   CMD_SERIAL.begin(57600);
-  while(!CMD_SERIAL);
+  while (!CMD_SERIAL);

   packetHandler2 = dynamixel::PacketHandler::getPacketHandler(PROTOCOL_VERSION2);
@@ -84,7 +84,7 @@
   {
     CMD_SERIAL.printf("Failed to open the port! [%s]\n", dev_name);
     CMD_SERIAL.printf("Press any key to terminate...\n");
-    while(1);
+    while (1);
   }

@@ -107,7 +107,7 @@
       {
         CMD_SERIAL.println("setup.... left");

-        if (findMotor() == true)
+        if (findMotor(1) == true)
         {
           setupMotorLeft();
         }
@@ -120,7 +120,7 @@
       {
         CMD_SERIAL.println("setup.... right");

-        if (findMotor() == true)
+        if (findMotor(2) == true)
         {
           setupMotorRight();
         }
@@ -162,7 +162,7 @@

   CMD_SERIAL.print("Do you really want to setup ? y/n : ");

-  while(1)
+  while (1)
   {
     if (CMD_SERIAL.available())
     {
@@ -187,16 +187,17 @@
 {
   uint8_t ch;

-  while(CMD_SERIAL.available())
+  while (CMD_SERIAL.available())
   {
     ch = CMD_SERIAL.read();
   }
 }

-bool findMotor(void)
+bool findMotor(int id)
 {
   uint32_t baud_tbl[2] = { 57600, 1000000 };
+#define COUNT_BAUD (sizeof(baud_tbl)/sizeof(baud_tbl[0]))
   uint32_t index;
   uint32_t baud_pre;

@@ -209,13 +210,44 @@

   CMD_SERIAL.println("Find Motor...");

-  for (index=0; index<2; index++)
+  // First try to find the specific servo ID wanted
+  for (index = 0; index < COUNT_BAUD; index++)
+  {
+    portHandler->setBaudRate(baud_tbl[index]);
+    uint16_t model_number;
+    int dxl_comm_result = packetHandler2->ping(portHandler, id, &model_number);
+    if (dxl_comm_result == COMM_SUCCESS)
+    {
+      if (tb3_id == -1)
+      {
+        tb3_id = id;
+        tb3_baud =  baud_tbl[index];
+      }
+      else
+      {
+        CMD_SERIAL.printf("Warning Servo %d found at two baud rates %d and %d using %d\n",
+                          id, tb3_baud, baud_tbl[index], baud_tbl[index]);
+        tb3_baud =  baud_tbl[index];
+      }
+    }
+  }
+
+  if (tb3_id != -1)
+  {
+    CMD_SERIAL.println("    ... SUCCESS");
+    CMD_SERIAL.printf("    [ID: %d found at baud: %d]\n", id, tb3_baud );
+    return true;
+  }
+
+  // Did not find the actual ID we were looking for so see if we find any servos?
+  for (index = 0; index < COUNT_BAUD; index++)
   {
     CMD_SERIAL.printf("    setbaud : %d\r\n", baud_tbl[index]);

     portHandler->setBaudRate(baud_tbl[index]);
     tb3_baud =  baud_tbl[index];

+    // Lets see if we find the actual one we want to update?
     int dxl_comm_result = packetHandler2->broadcastPing(portHandler, vec);
     if (dxl_comm_result != COMM_SUCCESS)
     {
@@ -233,6 +265,15 @@
     if (vec.size() > 0)
     {
       CMD_SERIAL.println("    found motor");
+      if (vec.size() > 1)
+      {
+        CMD_SERIAL.printf("    WARNING: multiple servos found, using id: %d\n", tb3_id);
+        if (!requestConfirm())
+        {
+          tb3_id = -1;  // setup to abort...
+        }
+      }
+
       break;
     }
     else
@@ -259,11 +300,11 @@

   if (tb3_id < 0)
   {
-       CMD_SERIAL.println("    no dxl motors");
-  }
-  else
-  {
-    write(portHandler, packetHandler2, tb3_id,64, 1, 0);
+    CMD_SERIAL.println("    no dxl motors");
+  }
+  else
+  {
+    write(portHandler, packetHandler2, tb3_id, 64, 1, 0);
     write(portHandler, packetHandler2, tb3_id, 7, 1, 1);
     tb3_id = 1;
     write(portHandler, packetHandler2, tb3_id, 8, 1, 3);
@@ -281,11 +322,11 @@

   if (tb3_id < 0)
   {
-       CMD_SERIAL.println("    no dxl motors");
-  }
-  else
-  {
-    write(portHandler, packetHandler2, tb3_id,64, 1, 0);
+    CMD_SERIAL.println("    no dxl motors");
+  }
+  else
+  {
+    write(portHandler, packetHandler2, tb3_id, 64, 1, 0);
     write(portHandler, packetHandler2, tb3_id, 7, 1, 2);
     tb3_id = 2;
     write(portHandler, packetHandler2, tb3_id, 8, 1, 3);
@@ -301,21 +342,28 @@
   uint32_t pre_time;
   uint8_t  toggle = 0;

-  CMD_SERIAL.println("Test Motor Left...");
-
-
-  if (tb3_id < 0)
-  {
-       CMD_SERIAL.println("    no dxl motors");
-  }
-  else
-  {
+  if (id == 1)
+  {
+    CMD_SERIAL.printf("Test Motor Left...");
+  }
+  else
+  {
+    CMD_SERIAL.printf("Test Motor Right...");
+  }
+  // We run at 1000000
+  portHandler->setBaudRate(1000000);
+
+  uint16_t model_number;
+  int dxl_comm_result = packetHandler2->ping(portHandler, id, &model_number);
+  if (dxl_comm_result == COMM_SUCCESS)
+  {
+    CMD_SERIAL.printf(" found type: %d\n", model_number);
     write(portHandler, packetHandler2, id, 64, 1, 1);

     toggle = 0;
     pre_time = millis();
     write(portHandler, packetHandler2, id, 104, 4, 100);
-    while(1)
+    while (1)
     {
       if (CMD_SERIAL.available())
       {
@@ -323,7 +371,7 @@
         break;
       }

-      if (millis()-pre_time > 1000)
+      if (millis() - pre_time > 1000)
       {
         pre_time = millis();

@@ -341,6 +389,10 @@
     }
     write(portHandler, packetHandler2, id, 104, 4, 0);
   }
+  else
+  {
+    CMD_SERIAL.printf("    dxl motor ID:%d not found\n", id);
+  }
 }

 void write(dynamixel::PortHandler *portHandler, dynamixel::PacketHandler *packetHandler, uint8_t id, uint16_t addr, uint16_t length, uint32_t value)
@@ -420,4 +472,4 @@
   }

   return ret;
-}
+}


--- AOA_TONE_EFIS_SERIAL/AOA_TONE_EFIS_SERIAL.ino
+++ AOA_TONE_EFIS_SERIAL/AOA_TONE_EFIS_SERIAL.ino
@@ -2,7 +2,7 @@
 ////////////////////////////////////////////////////
 // AOA EFIS Serial to audio tone
 // Supports: Dynon EFIS data using a Arduino Due board
-// Ver 1.5
+// Ver 1.5.1
 // Christopher Jones 6/10/2016
 //
 // - Read data in from Serial3 on DUE board. (Dynon is at 115200 baud)
@@ -11,6 +11,7 @@
 // - If no serial data is detected audio tone turns off and LED1 is off
 // - MUTE_AUDIO_UNDER_IAS define is used to only activate audio tones if above a given airspeed
 //
+// 7/9/2018 - fix for tone PPS between solid tones.  was not calucating the right ratio for the PPS changes.

 #include <DueTimer.h>         // timer lib functions for using DUE timers and callbacks.
 #include <stdint.h>
@@ -255,7 +256,7 @@
     OldValue = AOA-(HIGH_TONE_AOA_START-1);
     toneMode = PULSE_TONE;
     // scale number using this. http://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
-    OldRange = 20 - 1;  //(OldMax - OldMin)
+    OldRange = HIGH_TONE_AOA_STALL - HIGH_TONE_AOA_START; //20 - 1;  //(OldMax - OldMin)
     NewRange = HIGH_TONE_PPS_MAX - HIGH_TONE_PPS_MIN; // (NewMax - NewMin)
     NewValue = (((OldValue - 1) * NewRange) / OldRange) + HIGH_TONE_PPS_MIN; //(((OldValue - OldMin) * NewRange) / OldRange) + NewMin
     setPPSTone(NewValue);
@@ -269,7 +270,7 @@
     // play LOW tone at Pulse Rate 1.5 PPS to 8.2 PPS (depending on AOA value)
     // scale number using this. http://stackoverflow.com/questions/929103/convert-a-number-range-to-another-range-maintaining-ratio
     OldValue = AOA-LOW_TONE_AOA_START;
-    OldRange = 40 - 1;  //(OldMax - OldMin)
+    OldRange = LOW_TONE_AOA_SOLID - LOW_TONE_AOA_START; //40 - 1;  //(OldMax - OldMin)
     NewRange = LOW_TONE_PPS_MAX - LOW_TONE_PPS_MIN; // (NewMax - NewMin)
     NewValue = (((OldValue - 1) * NewRange) / OldRange) + LOW_TONE_PPS_MAX; //(((OldValue - OldMin) * NewRange) / OldRange) + NewMin
     setPPSTone(NewValue);


Update E02_KY-040_RotaryEncoder.ino

Update E02_KY-040_RotaryEncoder.ino

--- RotaryEncoder/examples/E02_KY-040_RotaryEncoder/E02_KY-040_RotaryEncoder.ino
+++ RotaryEncoder/examples/E02_KY-040_RotaryEncoder/E02_KY-040_RotaryEncoder.ino
@@ -47,9 +47,9 @@

 #if ARDUINO >= 100
 #include "Arduino.h"
-#else
+#else  /* !ARDUINO */
 #include "WProgram.h"
-#endif
+#endif /* end !ARDUINO */

 #include <RotaryEncoder.h>
 #include <Time.h>


Temporarily remove setFirmware, register and subscribe

--- src/homie-sonoff-touch.ino
+++ src/homie-sonoff-touch.ino
@@ -71,7 +71,6 @@
     if ( function == 1 ) {
       Serial.println("SINGLE click");
       // FIXME Homie.setNodeProperty(buttonNode, "event", "SINGLE", 0);
-
     }

     if ( function == 2 ) {
@@ -135,14 +134,14 @@
   button1.multiclickTime = 250;  // Time limit for multi clicks
   button1.longClickTime  = 1000; // time until "held-down clicks" register

-  Homie.setFirmware(FW_NAME, FW_VERSION);
+  // FIXME Homie.setFirmware(FW_NAME, FW_VERSION);
   Homie.setLedPin(PIN_LED, HIGH); // Status LED
   // This is a full reset, and will wipe the config
   Homie.setResetTrigger(PIN_BUTTON, LOW, 30000);
   Homie.setLoopFunction(loopHandler);
-  relayNode.subscribe("relayState", RelayHandler);
-  Homie.registerNode(relayNode);
-  Homie.registerNode(buttonNode);
+  // FIXME relayNode.subscribe("relayState", RelayHandler);
+  // FIXME Homie.registerNode(relayNode);
+  // FIXME Homie.registerNode(buttonNode);
   Homie.setup();
 }


Fixed a bug that cause RAM to run out: when every time loop function is called, it doesn't free the memory given to gpstime. Solution: Added "free(gpstime);" at the end of loop function.

--- Drones/Drones.ino
+++ Drones/Drones.ino
@@ -146,5 +146,6 @@
   array_length = 1;

   free(gpsbuffer);//Free memory that given to temp containter
+  free(gpstime);
   delay(1000);//Waiting for bytes to fill IO buffer
 }


make basic FA/response parsing work

make basic FA/response parsing work

--- src/sketch.ino
+++ src/sketch.ino
@@ -4,34 +4,50 @@
 #define LED_PIN 13
 #define BLINK_DELAY 75

-serLCD lcd(LCD_PIN);
+/*serLCD lcd(LCD_PIN);*/

 void setup() {
-  delay(500);
+  delay(2000);

-  Serial.begin(19200);
-  lcd.clear();
-  lcd.print("  MediBot 5000");
+  Serial.begin(9600);
+  Serial.println("hello world");

   for (int i = 0; i < 4; i++) {
     blink();
   }

-  lcd.setCursor(2,1);
+  delay(1000);
+
 }

-String vfo = "";
+String str = "";
 char character;

 void loop() {
+  ledOn();
+
+  delay(1000);
   Serial.print("fa;");
-  delay(250);

+  // wait for FA00000000000;
   while (Serial.available() > 0) {
     character = Serial.read();
-    lcd.listen();
-    lcd.print(character);
-    lcd.print(':');
+
+    if (character != ';') {
+      str += character;
+    } else {
+      ledOff();
+
+      Serial.println();
+      Serial.println("------------");
+      Serial.println(str);
+      Serial.println("------------");
+
+      str = "";
+
+      delay(1000);
+      break;
+    }
   }

 }


-Increase wifiTask stack size.

-Increase wifiTask stack size.

--- wifitask.ino
+++ wifitask.ino
@@ -83,7 +83,7 @@
   xTaskCreatePinnedToCore(
     webServerTask,                  /* Function to implement the task */
     "webServerTask",                /* Name of the task */
-    1000,                           /* Stack size in words */
+    2000,                           /* Stack size in words */
     NULL,                           /* Task input parameter */
     webserverTaskPriority,          /* Priority of the task */
     NULL,                           /* Task handle. */


Fixed bug in Arduino

Fixed bug in Arduino

The Raspberry cannot obtain negative values.

--- Testing_Arduino101_2/Testing_Arduino101_2.ino
+++ Testing_Arduino101_2/Testing_Arduino101_2.ino
@@ -347,9 +347,9 @@
   encoder_B.zero();
 }
 void encoder_report(){
-  Serial.print(round(encoder_A.getPosition()));
+  Serial.print(abs(round(encoder_A.getPosition())));
   Serial.print('-');
-  Serial.print(round(encoder_B.getPosition()));
+  Serial.print(abs(round(encoder_B.getPosition())));
   Serial.print('&');
 }


Fixed Alexa functionality

Fixed Alexa functionality

--- ASC_Alexa_Sprinkler_Controller/ASC_Alexa_Sprinkler_Controller.ino
+++ ASC_Alexa_Sprinkler_Controller/ASC_Alexa_Sprinkler_Controller.ino
@@ -46,15 +46,24 @@
 #define SERIAL_BAUDRATE 115200  //Set USB serial baud rate

 // LIBRARY INITIALIZATION
+SSD1306  display(0x3c, I2C_SDA, I2C_SCL); // SSD1306 Pin Assignments
 fauxmoESP fauxmo;                         // Initialize fauxmo
 TMP102 sensor0(0x48);                     // Initialize sensor at I2C address 0x48
 Adafruit_MCP23017 mcp;                    // Adafruit-MCP23017-Arduino-Library
-SSD1306  display(0x3c, I2C_SDA, I2C_SCL); // SSD1306 Pin Assignments
+

 //------------------------------------------------------------------------------------------------
 //SETUP
 //------------------------------------------------------------------------------------------------
 void setup() {
+
+  //START I2C COMMUNICATION
+  display.init();   // SSD12306 - OLED screen start I2C comms
+  mcp.begin();      // MCP23017 - I/O Expander start I2C comms
+  sensor0.begin();  // TMP102 - Temp Sensor start I2C comms
+
+  //Flip Screen orientation in software, (pins on top)
+  display.flipScreenVertically(); //SSD12306

   //CONFIGURE PIN USAGE
   pinMode(alertPin,INPUT);  // Declare alertPin as an input TMP102
@@ -68,8 +77,10 @@
   mcp.pinMode(relayPin_K7, OUTPUT);
   mcp.pinMode(relayPin_K8, OUTPUT);

-  //FAUXMO DEVICES
-  //(each of these devices will appear in Alexa App
+  // FAUXMO DEVICES
+  // Each of these devices will appear in Alexa App.
+  // Create a group from these devices "Front Yeard Sprinklers"
+  // Each controller will have its own letter "A" followed by a zone "1"
   fauxmo.addDevice("Zone A1");
   fauxmo.addDevice("Zone A2");
   fauxmo.addDevice("Zone A3");
@@ -80,13 +91,7 @@
   fauxmo.addDevice("Zone A8");
   fauxmo.onMessage(callback); //function call?

-  //START I2C COMMUNICATION
-  mcp.begin();      // MCP23017 - I/O Expander start I2C comms
-  sensor0.begin();  // TMP102 - Temp Sensor start I2C comms
-  display.init();   // SSD12306 - OLED screen start I2C comms
-  //Flip Screen orientation in software, (pins on top)
-  display.flipScreenVertically(); //SSD12306
-
+
 //------------TMP102 Setup----------------------------------------------------------
   // Initialize sensor0 settings
   // These settings are saved in the sensor, even if it loses power
@@ -126,6 +131,7 @@
   Serial.println("ALEXA Sprinkler Controller V1.0"); //vanity title for serial window
 //----------------------------------------------------------------------------------

+ wifiSetup();
 }

 //------------------------------------------------------------------------------------------------


Save ADC mode in EEPROM so it can be remembered over reset.

--- tiny_scope.ino
+++ tiny_scope.ino
@@ -14,6 +14,7 @@
 #include <Adafruit_GFX.h>
 #endif
 #include <Arduino.h>
+#include <EEPROM.h>
 #include "adc.h"
 #include "scope.h"
 #include "capture.h"
@@ -32,11 +33,6 @@
 // Change this if AREF is connected to a different voltage reference
 #define AREF_MV ADC_AREF_MV

-// ADC mode (0-5, 0 = default, 5 = fastest less accurate)
-// This is NOT the prescaler value, just an index in a table in adc.cpp
-// On a 16MHz UNO R3, the grid is 2ms apart while on 5 it goes down to 0.1ms
-#define ADC_MODE 0
-
 // Address of I2C OLED display. If screen looks scaled edit Adafruit_SSD1306.h
 // and pick SSD1306_128_64 or SSD1306_128_32 that matches display type.
 #define DISPLAY_I2C_ADDRESS 0x3C
@@ -48,6 +44,8 @@
  * End Configurable parameters
  ****************************************************************************/

+// Address to start last ADC mode used in EEPROM.
+#define ADC_MODE_ADDR 0

 extern Display display;
 static Capture capture;
@@ -74,7 +72,7 @@

 void setup(){
     int success = capture.init(ADCInput(), SCREEN_WIDTH, AREF_MV);
-    capture.adc.init(ADC_PIN, ADC_MODE);
+    capture.adc.init(ADC_PIN, EEPROM.read(ADC_MODE_ADDR));
     delay(100);  // give time for display to init; if display blank increase delay
     display.begin(SSD1306_SWITCHCAPVCC, DISPLAY_I2C_ADDRESS);
     display.setRotation(2);
@@ -117,14 +115,15 @@
         BUTTON_ON,
         BUTTON_OFF
     };
-    static int modeButtonState = BUTTON_OFF;
-    static int adcMode = ADC_MODE;
-
-    if (!digitalRead(MODE_BUTTON_PIN)){
+    static uint8_t modeButtonState = BUTTON_OFF;
+    int adcMode = EEPROM.read(ADC_MODE_ADDR);
+
+    if (digitalRead(MODE_BUTTON_PIN) == LOW){
         if (modeButtonState == BUTTON_OFF){
             modeButtonState = BUTTON_ON;
             adcMode = (adcMode+1) % capture.adc.getModeCount();
             capture.adc.setMode(adcMode);
+            EEPROM.write(ADC_MODE_ADDR, byte(adcMode));
         }
     } else {
         modeButtonState = BUTTON_OFF;


reorganizado o código

reorganizado o código

--- EMP-B-Due.ino
+++ EMP-B-Due.ino
@@ -27,8 +27,9 @@

 // Variáveis
   // Configurações
-    #define ModoBotoes INPUT_PULLUP // INPUT ou INPUT_PULLUP
-    #define ModoLeds OUTPUT
+    #define BOTAO INPUT_PULLUP // INPUT ou INPUT_PULLUP
+    #define SENSOR INPUT // INPUT ou INPUT_PULLUP
+    #define SAIDA OUTPUT
     #define ALTO LOW // Deve ser invertido para INPUT_PULLUP
     #define BAIXO HIGH // Deve ser invertido para INPUT_PULLUP
     #define LIGA HIGH
@@ -69,35 +70,29 @@
 void setup() {
   Serial.begin(9600);
   // Botões
-  pinMode(bt_geral, ModoBotoes);
-  pinMode(bt_dosador, ModoBotoes);
-  pinMode(bt_datador, ModoBotoes);
-  // Potenciômetros
-  pinMode(pot_solda_vertical, INPUT);
-  pinMode(pot_solda_horizontal, INPUT);
-  pinMode(pot_solda_horizontal, INPUT);
-  // PWM
-  pinMode(solda_vertical, OUTPUT);
-  pinMode(solda_horizontal, OUTPUT);
-  pinMode(solda_datador, OUTPUT);
+  pinMode(bt_geral, BOTAO);
+  pinMode(bt_dosador, BOTAO);
+  pinMode(bt_datador, BOTAO);
+  // Potenciômetros das Soldas
+  pinMode(pot_solda_vertical, SENSOR);
+  pinMode(pot_solda_horizontal, SENSOR);
+  pinMode(pot_solda_horizontal, SENSOR);
+  // Saídas PWM das Soldas
+  pinMode(solda_vertical, SAIDA);
+  pinMode(solda_horizontal, SAIDA);
+  pinMode(solda_datador, SAIDA);
   // Sensores
-  pinMode(sensor_porta, ModoBotoes);
-  pinMode(sensor_painel, ModoBotoes);
-  pinMode(sensor_maquina, ModoBotoes);
-
-
-  pinMode(geral, ModoLeds);
-  pinMode(dosador, ModoLeds);
-  pinMode(datador, ModoLeds);
+  pinMode(sensor_porta, BOTAO);
+  pinMode(sensor_painel, BOTAO);
+  pinMode(sensor_maquina, BOTAO);
+
+
+  pinMode(geral, SAIDA);
+  pinMode(dosador, SAIDA);
+  pinMode(datador, SAIDA);

   // Define estado inicial das saídas
-  digitalWrite(geral, DESLIGA);
-  digitalWrite(dosador, DESLIGA);
-  digitalWrite(datador, DESLIGA);
-  digitalWrite(solda_vertical, DESLIGA);
-  digitalWrite(solda_horizontal, DESLIGA);
-  digitalWrite(solda_datador, DESLIGA);
-  digitalWrite(53, DESLIGA); // Temporário, ver e apagar
+  resetCompleto();
 }

@@ -111,6 +106,56 @@
   if (!alarme_ativo){
     standBy();
     modoTeste();
+  }
+}
+
+// MODOS DE TRABALHO
+
+void standBy(){
+  if (stand_by){
+    acionaGeral(); // Checa botão Geral
+    acionaDosador(); // Checa botão Dosador
+    acionaDatador(); // Checa botão Datador
+    if (maquina_ligada){
+      iniciaTrabalho();
+    } else {
+      reiniciaSaidas();
+    }
+  } else {
+    delay(3000); // Espera 3 segundos após energização
+    stand_by = VERDADEIRO; // Libera funcionamento
+  }
+}
+
+void iniciaTrabalho(){
+
+}
+
+void modoAlarme(){
+  if (!alarme_ativo){
+    if (ativo(sensor_porta)){
+      bloqueioPorAlarme("Sensor da Porta");
+    } else if (ativo(sensor_painel)){
+      bloqueioPorAlarme("Sensor do Painel");
+    } else if (ativo(sensor_maquina)){
+      bloqueioPorAlarme("Sensor da Máquina");
+    }
+  }
+}
+
+// FUNÇÕES ADICIONAIS
+
+void acionaGeral(){
+  btUmClique(bt_geral, &estbt_geral, &estbta_geral, &atr_geral, &maquina_ligada);
+}
+
+void acionaDosador(){
+  btUmClique(bt_dosador, &estbt_dosador, &estbta_dosador, &atr_dosador, &dosador_ligado);
+}
+
+void acionaDatador(){
+  if (maquina_ligada and !alarme_ativo){
+    btUmClique(bt_datador, &estbt_datador, &estbta_datador, &atr_datador, &datador_ligado);
   }
 }

@@ -130,52 +175,6 @@
   }
 }

-void acionaGeral(){
-  btUmClique(bt_geral, &estbt_geral, &estbta_geral, &atr_geral, &maquina_ligada);
-}
-
-void acionaDosador(){
-  btUmClique(bt_dosador, &estbt_dosador, &estbta_dosador, &atr_dosador, &dosador_ligado);
-}
-
-void acionaDatador(){
-  if (maquina_ligada){
-    btUmClique(bt_datador, &estbt_datador, &estbta_datador, &atr_datador, &datador_ligado);
-  }
-}
-
-void standBy(){
-  if (stand_by){
-    acionaGeral(); // Checa botão Geral
-    acionaDosador(); // Checa botão Dosador
-    acionaDatador(); // Checa botão Datador
-    if (maquina_ligada){
-      iniciaTrabalho();
-    } else {
-      reiniciaSaidas();
-    }
-  } else {
-    delay(3000); // Espera 3 segundos após energização
-    stand_by = VERDADEIRO; // Libera funcionamento
-  }
-}
-
-void iniciaTrabalho(){
-
-}
-
-void modoAlarme(){
-  if (!alarme_ativo){
-    if (ativo(sensor_porta)){
-      bloqueioPorAlarme("Sensor da Porta");
-    } else if (ativo(sensor_painel)){
-      bloqueioPorAlarme("Sensor do Painel");
-    } else if (ativo(sensor_maquina)){
-      bloqueioPorAlarme("Sensor da Máquina");
-    }
-  }
-}
-
 void bloqueioPorAlarme(String texto){
   alarme_ativo = VERDADEIRO;
   escreveSerial("\n<< Alarme! >>\n");
@@ -200,6 +199,8 @@
   *est_ant = leitura;
 }

+// FERRAMENTAS AUXILIARES
+
 byte leEntrada(byte pino){
   return digitalRead(pino);
 }
@@ -265,6 +266,16 @@
   desliga(datador, NomeDatador);
 }

+void resetCompleto(){
+  digitalWrite(geral, DESLIGA);
+  digitalWrite(dosador, DESLIGA);
+  digitalWrite(datador, DESLIGA);
+
+  digitalWrite(solda_vertical, DESLIGA);
+  digitalWrite(solda_horizontal, DESLIGA);
+  digitalWrite(solda_datador, DESLIGA);
+}
+

 void modoTeste(){
   if (maquina_ligada){


shorter sync time

shorter sync time

--- ISKOClean.ino
+++ ISKOClean.ino
@@ -42,7 +42,7 @@
   USE_SERIAL.println("Index v Libusi: ");
   USE_SERIAL.println(ISKOClient.getIndex());
   indexShow(ISKOClient.getIndex());
-  delay(900000);
+  delay(120000);

 }


spped adjust

spped adjust


criado variáveis de ciclo médio para cada função

--- EMP-B-Due.ino
+++ EMP-B-Due.ino
@@ -27,10 +27,12 @@
 const byte refrigeracao = 44;
 const byte datador = 46;
 const byte soldas = 48;
-
+// SAÍDAS PWM
 const byte solda_vertical_PWM = 33;        // Saída da Solda Vertical
 const byte solda_horizontal_PWM = 35;      // Saída da Solda Horizontal
 const byte solda_datador_PWM = 37;         // Saída da Solda do Datador
+
+
 // REMOVER
 const byte saida_teste = 2;
 const byte entrada_teste = 4;
@@ -104,28 +106,42 @@
 unsigned long ultimo_ciclo = ciclo_padrao;

 // MANDÍBULA
-unsigned long inicio_mandibula = 550;
-unsigned long fim_mandibula = 1500;
-
+const unsigned int inicio_mandibula = 550;
+const unsigned int fim_mandibula = 1500;
 // FOTOCÉLULA
-unsigned long inicio_fotocelula = 1250;
-unsigned long fim_fotocelula = 1400;
-
+const unsigned int inicio_fotocelula = 1250;
+const unsigned int fim_fotocelula = 1400;
 // FACA
-unsigned long inicio_faca = 600;
-unsigned long fim_faca = 800;
-
+const unsigned int inicio_faca = 600;
+const unsigned int fim_faca = 800;
 // REFRIGERAÇÃO
-unsigned long inicio_refrigeracao = 800;
-unsigned long fim_refrigeracao = 1450;
-
+const unsigned int inicio_refrigeracao = 800;
+const unsigned long fim_refrigeracao = 1450;
 // DATADOR
-unsigned long inicio_datador = 5;
-unsigned long fim_datador = 400;
-
+const unsigned int inicio_datador = 5;
+const unsigned int fim_datador = 400;
 // SOLDAS VERTICAL E HORIZONTAL
-unsigned long inicio_soldas = 5;
-unsigned long fim_soldas = 400;
+const unsigned int inicio_soldas = 5;
+const unsigned int fim_soldas = 400;
+// TEMPOS MÉDIOS
+// MANDÍBULA
+unsigned long ti_mandibula = (unsigned long)inicio_mandibula; // NÃO ALTERE
+unsigned long tf_mandibula = (unsigned long)fim_mandibula; // NÃO ALTERE
+// FOTOCÉLULA
+unsigned long ti_fotocelula = (unsigned long)inicio_fotocelula; // NÃO ALTERE
+unsigned long tf_fotocelula = (unsigned long)fim_fotocelula; // NÃO ALTERE
+// FACA
+unsigned long ti_faca = (unsigned long)inicio_faca; // NÃO ALTERE
+unsigned long tf_faca = (unsigned long)fim_faca; // NÃO ALTERE
+// REFRIGERAÇÃO
+unsigned long ti_refrigeracao = (unsigned long)inicio_refrigeracao; // NÃO ALTERE
+unsigned long tf_refrigeracao = (unsigned long)fim_refrigeracao; // NÃO ALTERE
+// DATADOR
+unsigned long ti_datador = (unsigned long)inicio_datador; // NÃO ALTERE
+unsigned long tf_datador = (unsigned long)fim_datador; // NÃO ALTERE
+// SOLDAS VERTICAL E HORIZONTAL
+unsigned long ti_soldas = (unsigned long)inicio_soldas; // NÃO ALTERE
+unsigned long tf_soldas = (unsigned long)fim_soldas; // NÃO ALTERE

 void setup() {
   Serial.begin(9600);


Nothing.

Nothing.

--- monitor_client/monitor_client.ino
+++ monitor_client/monitor_client.ino
@@ -4,17 +4,13 @@
 #include "Suli.h"
 #include "DHT11.h"
 #define DHT11PIN 2
-const int pin_tx = 7;
-const int pin_rx = 8;
-SoftwareSerial gprs(pin_tx,pin_rx);//TX,RX
+dht11 DHT11;
+GPRS gprs(PIN_TX, PIN_RX, BAUDRATE,"cmnet");
+char buffer[128];

-//char http_cmd[162];
-dht11 DHT11;
 void setup(){
+
   Serial.begin(9600);
-  sim900_init(&gprs, -1, 9600);
-  int a = DHT11.read(DHT11PIN);
-
   Serial.print("Temperature (oC): ");
   Serial.println((float)DHT11.temperature, 2);
   Serial.print("Humidity (%): ");
@@ -22,11 +18,45 @@
   //snprintf(http_cmd,sizeof(http_cmd),"GET monitor.ourjnu.com/submit.php?device_index=13726247339&longitude=113.540718&latitude=22.256467&temperature=%03d&humidity=%03d&particulate_matter=25 HTTP/1.0\r\n\r\n",DHT11.temperature,DHT11.humidity);
   //sprintf(http_cmd,"GET /submit.php?device_index=13726247339&longitude=113.540718&latitude=22.256467&temperature=%03d&humidity=%03d&particulate_matter=25 HTTP/1.0\r\n\r\n",DHT11.temperature,DHT11.humidity);
   //Serial.println(http_cmd);
-  while(!gprs.available()) {
-      sim900_send_cmd("AT+CGATT?");
+  //Use rewrited url to prevent memory overflow
+  snprintf(target_url, sizeof(target_url), "GET /13726247339-113.540718-22.256467-%03d-%03d-25 HTTP/1.0\r\n\r\n",DHT11.temperature,DHT11.humidity);
+  Serial.println(target_url);
+
+
+ gprs.init();
+  // attempt DHCP
+  while(false == gprs.join()) {
+      Serial.println("gprs join network error");
       delay(2000);
   }
-  Serial.println(gprs.read());
+
+  // successful DHCP
+  Serial.print("IP Address is ");
+  Serial.println(gprs.getIPAddress());
+
+  if(false == gprs.connect(TCP,"monitor.ourjnu.com", 80)) {
+      Serial.println("connect error");
+  }else{
+      Serial.println("connect mbed.org success");
+  }
+
+  Serial.println("waiting to fetch...");
+  gprs.send(target_url, sizeof(target_url)-1);
+  while (true) {
+      int ret = gprs.recv(buffer, sizeof(buffer)-1);
+      if (ret <= 0){
+          Serial.println("fetch over...");
+          break;
+      }
+      buffer[ret] = '\0';
+      Serial.print("Recv: ");
+      Serial.print(ret);
+      Serial.print(" bytes: ");
+      Serial.println(buffer);
+  }
+  gprs.close();
+  gprs.disconnect();
+
 }

 void loop(){


Add files via upload

Add files via upload

Fixed minor timestamp formatting bug (seconds leading zero came before colon)

--- src/piggy_back_loggers/SD_prototype_Firmware/Firmware/Firmware.ino
+++ src/piggy_back_loggers/SD_prototype_Firmware/Firmware/Firmware.ino
@@ -1,364 +1,364 @@
-// Firmware for the CIWS Residential Datalogger
-// Arduino IDE ver. 1.8.7
-// Utah Water Research Lab
-// Updated: 3/20/2019
-// Daniel Henshaw and Josh Tracy
-// Note: F("String") keeps string literals in program memory and out of RAM. Saves RAM space. Very good. Don't remove the F. I know it looks funny. But don't do it. Really. The program might crash if you do. And then you'll have dishonor on yourself, dishonor on your cow...
-
-/*******************************************************************************************\
-* Hardware Description
-*                     ___________________                             ___
-*                    |                   |<------------------------->[___] RTC
-*  ________          |                   |                            _______
-* |        |         |                   |<------------------------->|       | SD
-* |        |<------->|                   |<-----[] Activate Serial   |______/
-* |________|         |___________________|<-----[] Sensor
-*  Serial             Controller
-*
-* Serial:          Serial interface for user interaction with the logger
-* Controller:      Arduino Pro/Pro Mini (used for SD library and lower power options)
-* SD:              External SD Card storage for the logger.
-* Activate Serial: Button to wake up the controller and activate the Serial interface
-* Sensor:          Hall Effect Sensor for logging pulses from water meters.
-* RTC:             Real Time Clock to track time and wake up controller every four seconds.
-\*******************************************************************************************/
-
-/*********************************************************\
-* Software Description
-* Overview:
-*   User inputs:
-*     Serial input.
-*   Device outputs:
-*     Serial output
-*     Datalog file
-*
-* Structure:
-*   1. Setup
-*   2. Handle Serial (for start-up configuration)
-*   3. Loop
-*        If serial is enabled
-*          Handle serial input
-*        If four seconds are up
-*          Update the time
-*          Construct a timestamp
-*          Power-on the SD card
-*          Write data
-*          Power-off the SD card
-*        If sleep is enabled (disabled when serial is enabled)
-*          Enter Sleep (low-power mode)
-*          < Will wake up on Interrupt and continue: >
-*      Repeat Loop
-*
-* Interrupts:
-*   1. INT0_ISR()
-*
-*   2. INT1_ISR()
-*
-\*********************************************************/
-
-#include <SPI.h>
-#include <SD.h>
-#include "handleSerial.h"
-#include "powerSleep.h"
-#include "state.h"
-#include "RTC_PCF8523.h"
-#include "storeNewRecord.h"
-
-// These six macros below are the ten's place mask for the various real time clock registers
-#define SECONDS_REG_MASK 0x7                            // keep lower 3 bits
-#define MINUTES_REG_MASK 0x7
-#define HOURS_REG_MASK   0x3                            // keep lower 2 bits
-#define DAYS_REG_MASK    0x3
-#define MONTHS_REG_MASK  0x1                            // keep lower 1 bit
-#define YEARS_REG_MASK   0xF                            // keep all four bits
-
-
-/*********************************************************************************\
- * Setup:
- *    System State structure      Complete
- *    Setup Digital I/O pins
- *      Pin 2 (INT0)
- *      Pin 3 (INT1)
- *      Pin 4 (SD power on/off)
- *      Pin 5 (Serial Activate Button)
- *    Setup interrupts
-\*********************************************************************************/
-
-volatile State_t State;           // System State structure
-Date_t Date;                      // System Time and Date structure
-File dataFile;                    // File pointer for SD Card operations
-
-void setup()
-{
-  resetState(&State);             // Setup the System State structure
-
-  pinMode(2, INPUT);              // Setup the Digital Pins
-  pinMode(3, INPUT_PULLUP);
-  pinMode(4, OUTPUT);
-  digitalWrite(4, HIGH);
-  pinMode(5, INPUT);
-
-  rtcTransfer(reg_Tmr_CLKOUT_ctrl, WRITE, 0x3A);                  // Setup RTC Timer
-  rtcTransfer(reg_Tmr_A_freq_ctrl, WRITE, 0x02);
-  rtcTransfer(reg_Tmr_A_reg, WRITE, 0x04);
-  rtcTransfer(reg_Control_2, WRITE, 0x02);
-  rtcTransfer(reg_Control_3, WRITE, 0x80);
-
-  attachInterrupt(digitalPinToInterrupt(2), INT0_ISR, FALLING);   // Setup Interrupts
-  attachInterrupt(digitalPinToInterrupt(3), INT1_ISR, FALLING);
-  EIMSK &= ~(1 << INT0);        // Disable Hall Effect Sensor interrupt
-  EIMSK |= (1 << INT1);         // Enable 4-Second RTC interrupt.
-
-  loadDateTime(&Date);            // Load Date_t with Date/Time info
-
-  disableUnneededPeripherals();   // Disable unneeded peripherals
-}
-
-void loop()
-{
-  // JOSH
-  /*****************************************\
-  * ButtonCheck: Is the button pressed?
-  * If button is pressed (active-low):
-  *   Set serialOn flag.
-  *   call serialPowerUp()
-  \*****************************************/
-  if((digitalRead(5) == 0) && !State.serialOn)
-  {
-    State.serialOn = true;
-    serialPowerUp();
-  }
-
-  // JOSH
-  /*****************************************\
-  * Serial: User I/O over serial
-  * serialOn flag is set:
-  *   call function handleSerial();
-  \*****************************************/
-  if(State.serialOn)
-    handleSerial(&State, &Date);
-
-  // DANIEL
-  /*****************************************\
-  * 4-second update: Update at 4 seconds
-  * If 4-second flag is set:
-  *   Store a new record
-  \*****************************************/
-  if(State.flag4)
-  {
-    State.flag4 = 0;                                    //     Reset flag4 to zero
-    rtcTransfer(reg_Control_2, WRITE, 0x02);            //     Reset real time clock interrupt flag
-    loadDateTime(&Date);
-    if(State.logging)
-      storeNewRecord();
-  }
-  // JOSH
-  /*****************************************\
-  * Sleep: put processor to sleep
-  *        to be woken by interrupts
-  * If serialOn is not set:
-  *   call function Sleep();
-  \*****************************************/
-  if(!State.serialOn)
-    enterSleep();
-}
-
-// DANIEL
-/* Function Title: INT0_ISR()
- *
- * Friendly Name:  Sensor Interrupt Service Routine (ISR)
- *
- * Description: increments the value of the pulse count variable by one, each time this
- *              function is called by hardware.
- */
-void INT0_ISR()
-{
-  State.pulseCount += 1;  // increment pulseCount variable by one
-}
-
-// DANIEL
-/* Function Title: INT1_ISR()
- *
- * Friendly Name:  Real Time Clock OUT Interrupt Service Routine (ISR)
- *
- * Description: sets the 4-second flag to true each time this function
- *              is called by hardware. The Real Time Clock generates
- *              the signal that calls this ISR once every four seconds.
- */
-void INT1_ISR()
-{
-  State.flag4 = true;     // sets the "four second flag" to true
-}
-
-/* Function: storeNewRecord
- *
- * Author: Daniel Henshaw
- * Date: 11/10/18
- *
- * Description: This function gets the current time from the Real Time Clock, and then
- *              carries out the communication to write a new record to the SD card and
- *              then turns off the I2C and SD card.
- *
- * Pseudocode:
- *
- * Begin
- *   Reset flag4 to zero
- *   Reset real time clock interrupt flag
- *   Declare variables
- *   Store pulse count to a variable named final count
- *   Set pulseCount to zero
- *   Read current time from the Real Time Clock and update the Date struct with the current time
- *     turn on the I2C interface (function rtcTransfer does this for us)
- *       read the year and store into temp variable
- *       convert from binary-coded decimal into binary, and store into years field of Date struct
- *       read the month and store into temp variable
- *       convert from binary-coded decimal into binary, and store into months field of Date struct
- *       read the day and store into temp variable
- *       convert from binary-coded decimal into binary, and store into days field of Date struct
- *       read the hour and store into temp variable
- *       convert from binary-coded decimal into binary, and store into hours field of Date struct
- *       read the minutes and store into temp variable
- *       convert from binary-coded decimal into binary, and store into minutes field of Date struct
- *       read the seconds and store into temp variable
- *       convert from binary-coded decimal into binary, and store into seconds field of Date struct
- *     turn off the I2C interface (function rtcTransfer does this for us)
- *   Write the new record to the SD card
- *     power on SD card
- *       write new record to SD card
- *         open the date-time string by writing a double quotation mark
- *           write year, month, day, hours,
- *           if minutes is less than ten
- *           then
- *             write a leading zero (the minutes value will be appended to it by the next statement)
- *           endIf
- *           write the minutes
- *           if seconds is less than ten
- *           then
- *             write a leading zero (the seconds value will be appended to it by the next statement)
- *           endIf
- *           write the seconds
- *         close the date-time string by writing a double quotation mark
- *         write a comma to begin a new field (CSV file format)
- *         write the record number
- *         write a comma to begin a new field (CSV file format)
- *         write the number of pulses counted when function was called (finalCount)
- *       end of writing the record to SD card
- *     power down SD card
- * End of function storeNewRecord()
- */
-
-
-
-void storeNewRecord()
-{                                                       // Begin
-    //State.flag4 = 0;                                    //     Reset flag4 to zero
-    //rtcTransfer(reg_Control_2, WRITE, 0x02);            //     Reset real time clock interrupt flag
-    byte finalCount;                                    //     Declare variables
-    byte temp;
-    finalCount = State.pulseCount;                      //     Store pulse count to a variable named final count
-    State.pulseCount = 0;                               //     Set pulseCount to zero
-                                                        //     Read current time from the Real Time Clock and update the Date struct with the current time
-      temp         = rtcTransfer(reg_Years,  READ, 0);  //         read the Years and store into temp variable
-      Date.years   = bcdtobin(temp, YEARS_REG_MASK);    //         convert from binary-coded decimal into binary, and store into years field of Date struct
-      temp         = rtcTransfer(reg_Months, READ, 0);  //         read the Months and store into temp variable
-      Date.months  = bcdtobin(temp, MONTHS_REG_MASK);   //         convert from binary-coded decimal into binary, and store into months field of Date struct
-      temp         = rtcTransfer(reg_Days,   READ, 0);  //         read the Days and store into temp variable
-      Date.days    = bcdtobin(temp, DAYS_REG_MASK);     //         convert from binary-coded decimal into binary, and store into days field of Date struct
-      temp         = rtcTransfer(reg_Hours,  READ, 0);  //         read the Hours and store into temp variable
-      Date.hours   = bcdtobin(temp, HOURS_REG_MASK);    //         convert from binary-coded decimal into binary, and store into hours field of Date struct
-      temp         = rtcTransfer(reg_Minutes,READ, 0);  //         read the Minutes and store into temp variable
-      Date.minutes = bcdtobin(temp, MINUTES_REG_MASK);  //         convert from binary-coded decimal into binary, and store into minutes field of Date struct
-      temp         = rtcTransfer(reg_Seconds,READ, 0);  //         read the Seconds and store into temp variable
-      Date.seconds = bcdtobin(temp, SECONDS_REG_MASK);  //         convert from binary-coded decimal into binary, and store into seconds field of Date struct
-                                                        //     Write the new record to the SD card
-      //SDPowerUp();                                      //         power on SD card
-      //SD.begin();
-        //Serial.println(F("SD Powerd up."));
-        dataFile = SD.open(F("datalog.csv"), FILE_WRITE);     //         Write new record to SD card
-        dataFile.print('\"');                          //           open the date-time string by writing a double quotation mark
-        dataFile.print(Date.years);                     //             write year, month, day, hours
-        dataFile.print('-');
-        dataFile.print(Date.months);
-        dataFile.print('-');
-        dataFile.print(Date.days);
-        dataFile.print(' ');
-        dataFile.print(Date.hours);
-        dataFile.print(':');
-        if(Date.minutes < 10)                           //             if minutes is less than ten
-        {                                               //             then
-          dataFile.print('0');                         //               write a leading zero (the minutes value will be appended to it by the next statement)
-        }                                               //             endIf
-        dataFile.print(Date.minutes);                   //             write the minutes
-        if(Date.seconds < 10)                           //             if seconds is less than ten
-        {                                               //             then
-          dataFile.print('0');                         //               write a leading zero (the seconds value will be appended to it by the next statement)
-        }                                               //             endIf
-        dataFile.print(':');                            //             write a colon to separate minutes from seconds
-        dataFile.print(Date.seconds);                   //             write the seconds
-        dataFile.print('\"');                           //           close date-time string by writing a double quotation mark
-        dataFile.print(',');                            //           write a comma to begin a new field (CSV file format)
-        dataFile.print(State.recordNum);                //           write the record number
-        dataFile.print(',');                            //           write a comma to begin a new field (CSV file format)
-        dataFile.println(finalCount);                   //           write the number of pulses counted when function was called (finalCount) and then print a new line
-
-        dataFile.close();                               //         end of writing the record to SD card
-        State.recordNum += 1;
-      //SDPowerDown();                                    //       power down SD card
-}                                                       // End of function storeNewRecord()
-
-
-
-
-
-
-/* Function: bcdtobin
- *
- * Author: Daniel Henshaw
- * Date: 11/17/18
- *
- * Description: This function converts Binary Coded Decimal (BCD) numbers to
- *              standard binary format. This is particularly useful when working
- *              with the real time clock, which stores time data in BCD format
- *              in its registers. The function takes in the value to convert, and
- *              the source register the value is coming from. The source register
- *              is required so that the conversion will be compatible with the
- *              number of bits into which the BCD value is stored into the RTC's
- *              registers.
- *
- * Optional dependencies: set of macro definitions, included below, improve
- *              this function's usability or user friendliness. These make it
- *              straightforward for the user to specify from which register
- *              the data is coming from. These also do double duty as masks for the
- *              value, as not all 8 bits in the register are for the BCD value; some
- *              of the upper bits serve other purposes or are "unused"
- *              (see datasheet for PCF8523 by NXP).
- *
- *              #define SECONDS_REG_MASK 0x7
- *              #define MINUTES_REG_MASK 0x7
- *              #define HOURS_REG_MASK   0x3
- *              #define DAYS_REG_MASK    0x3
- *              #define MONTHS_REG_MASK  0x1
- *              #define YEARS_REG_MASK   0xF
- *
- * Pseudocode:
- *
- * Begin
- *   Declare variable
- *   shift right by four the bcdValue (Puts upper 4 bits at the bottom)
- *   tensPlace is tensPlace ANDed with the provided bit mask a.k.a. conversion constant (hexadecimal value)
- *   Return the binary value result (the unit's place plus tensPlace times ten)
- * End
- */
-
-byte bcdtobin(byte bcdValue, byte sourceReg)
-{
-  byte tensPlace;
-
-  tensPlace  = bcdValue >> 4;
-  tensPlace &= sourceReg;         /* NOTE: sourceReg is actually a bit mask */
-
-  return (bcdValue & 0x0F) + (tensPlace * 10); // return the binary value result:
-                                               //   step 1) First parenthesis: bcdValue ANDed with mask 0xF gives us the one's place,
-                                               //   step 2) Second parenthesis: move the ten's place value over by multiplying by ten
-                                               //   step 3) Add the first parenthesis group to the second parenthesis group
-}
+// Firmware for the CIWS Residential Datalogger
+// Arduino IDE ver. 1.8.7
+// Utah Water Research Lab
+// Updated: 3/20/2019
+// Daniel Henshaw and Josh Tracy
+// Note: F("String") keeps string literals in program memory and out of RAM. Saves RAM space. Very good. Don't remove the F. I know it looks funny. But don't do it. Really. The program might crash if you do. And then you'll have dishonor on yourself, dishonor on your cow...
+
+/*******************************************************************************************\
+* Hardware Description
+*                     ___________________                             ___
+*                    |                   |<------------------------->[___] RTC
+*  ________          |                   |                            _______
+* |        |         |                   |<------------------------->|       | SD
+* |        |<------->|                   |<-----[] Activate Serial   |______/
+* |________|         |___________________|<-----[] Sensor
+*  Serial             Controller
+*
+* Serial:          Serial interface for user interaction with the logger
+* Controller:      Arduino Pro/Pro Mini (used for SD library and lower power options)
+* SD:              External SD Card storage for the logger.
+* Activate Serial: Button to wake up the controller and activate the Serial interface
+* Sensor:          Hall Effect Sensor for logging pulses from water meters.
+* RTC:             Real Time Clock to track time and wake up controller every four seconds.
+\*******************************************************************************************/
+
+/*********************************************************\
+* Software Description
+* Overview:
+*   User inputs:
+*     Serial input.
+*   Device outputs:
+*     Serial output
+*     Datalog file
+*
+* Structure:
+*   1. Setup
+*   2. Handle Serial (for start-up configuration)
+*   3. Loop
+*        If serial is enabled
+*          Handle serial input
+*        If four seconds are up
+*          Update the time
+*          Construct a timestamp
+*          Power-on the SD card
+*          Write data
+*          Power-off the SD card
+*        If sleep is enabled (disabled when serial is enabled)
+*          Enter Sleep (low-power mode)
+*          < Will wake up on Interrupt and continue: >
+*      Repeat Loop
+*
+* Interrupts:
+*   1. INT0_ISR()
+*
+*   2. INT1_ISR()
+*
+\*********************************************************/
+
+#include <SPI.h>
+#include <SD.h>
+#include "handleSerial.h"
+#include "powerSleep.h"
+#include "state.h"
+#include "RTC_PCF8523.h"
+#include "storeNewRecord.h"
+
+// These six macros below are the ten's place mask for the various real time clock registers
+#define SECONDS_REG_MASK 0x7                            // keep lower 3 bits
+#define MINUTES_REG_MASK 0x7
+#define HOURS_REG_MASK   0x3                            // keep lower 2 bits
+#define DAYS_REG_MASK    0x3
+#define MONTHS_REG_MASK  0x1                            // keep lower 1 bit
+#define YEARS_REG_MASK   0xF                            // keep all four bits
+
+
+/*********************************************************************************\
+ * Setup:
+ *    System State structure      Complete
+ *    Setup Digital I/O pins
+ *      Pin 2 (INT0)
+ *      Pin 3 (INT1)
+ *      Pin 4 (SD power on/off)
+ *      Pin 5 (Serial Activate Button)
+ *    Setup interrupts
+\*********************************************************************************/
+
+volatile State_t State;           // System State structure
+Date_t Date;                      // System Time and Date structure
+File dataFile;                    // File pointer for SD Card operations
+
+void setup()
+{
+  resetState(&State);             // Setup the System State structure
+
+  pinMode(2, INPUT);              // Setup the Digital Pins
+  pinMode(3, INPUT_PULLUP);
+  pinMode(4, OUTPUT);
+  digitalWrite(4, HIGH);
+  pinMode(5, INPUT);
+
+  rtcTransfer(reg_Tmr_CLKOUT_ctrl, WRITE, 0x3A);                  // Setup RTC Timer
+  rtcTransfer(reg_Tmr_A_freq_ctrl, WRITE, 0x02);
+  rtcTransfer(reg_Tmr_A_reg, WRITE, 0x04);
+  rtcTransfer(reg_Control_2, WRITE, 0x02);
+  rtcTransfer(reg_Control_3, WRITE, 0x80);
+
+  attachInterrupt(digitalPinToInterrupt(2), INT0_ISR, FALLING);   // Setup Interrupts
+  attachInterrupt(digitalPinToInterrupt(3), INT1_ISR, FALLING);
+  EIMSK &= ~(1 << INT0);        // Disable Hall Effect Sensor interrupt
+  EIMSK |= (1 << INT1);         // Enable 4-Second RTC interrupt.
+
+  loadDateTime(&Date);            // Load Date_t with Date/Time info
+
+  disableUnneededPeripherals();   // Disable unneeded peripherals
+}
+
+void loop()
+{
+  // JOSH
+  /*****************************************\
+  * ButtonCheck: Is the button pressed?
+  * If button is pressed (active-low):
+  *   Set serialOn flag.
+  *   call serialPowerUp()
+  \*****************************************/
+  if((digitalRead(5) == 0) && !State.serialOn)
+  {
+    State.serialOn = true;
+    serialPowerUp();
+  }
+
+  // JOSH
+  /*****************************************\
+  * Serial: User I/O over serial
+  * serialOn flag is set:
+  *   call function handleSerial();
+  \*****************************************/
+  if(State.serialOn)
+    handleSerial(&State, &Date);
+
+  // DANIEL
+  /*****************************************\
+  * 4-second update: Update at 4 seconds
+  * If 4-second flag is set:
+  *   Store a new record
+  \*****************************************/
+  if(State.flag4)
+  {
+    State.flag4 = 0;                                    //     Reset flag4 to zero
+    rtcTransfer(reg_Control_2, WRITE, 0x02);            //     Reset real time clock interrupt flag
+    loadDateTime(&Date);
+    if(State.logging)
+      storeNewRecord();
+  }
+  // JOSH
+  /*****************************************\
+  * Sleep: put processor to sleep
+  *        to be woken by interrupts
+  * If serialOn is not set:
+  *   call function Sleep();
+  \*****************************************/
+  if(!State.serialOn)
+    enterSleep();
+}
+
+// DANIEL
+/* Function Title: INT0_ISR()
+ *
+ * Friendly Name:  Sensor Interrupt Service Routine (ISR)
+ *
+ * Description: increments the value of the pulse count variable by one, each time this
+ *              function is called by hardware.
+ */
+void INT0_ISR()
+{
+  State.pulseCount += 1;  // increment pulseCount variable by one
+}
+
+// DANIEL
+/* Function Title: INT1_ISR()
+ *
+ * Friendly Name:  Real Time Clock OUT Interrupt Service Routine (ISR)
+ *
+ * Description: sets the 4-second flag to true each time this function
+ *              is called by hardware. The Real Time Clock generates
+ *              the signal that calls this ISR once every four seconds.
+ */
+void INT1_ISR()
+{
+  State.flag4 = true;     // sets the "four second flag" to true
+}
+
+/* Function: storeNewRecord
+ *
+ * Author: Daniel Henshaw
+ * Date: 11/10/18
+ *
+ * Description: This function gets the current time from the Real Time Clock, and then
+ *              carries out the communication to write a new record to the SD card and
+ *              then turns off the I2C and SD card.
+ *
+ * Pseudocode:
+ *
+ * Begin
+ *   Reset flag4 to zero
+ *   Reset real time clock interrupt flag
+ *   Declare variables
+ *   Store pulse count to a variable named final count
+ *   Set pulseCount to zero
+ *   Read current time from the Real Time Clock and update the Date struct with the current time
+ *     turn on the I2C interface (function rtcTransfer does this for us)
+ *       read the year and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into years field of Date struct
+ *       read the month and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into months field of Date struct
+ *       read the day and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into days field of Date struct
+ *       read the hour and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into hours field of Date struct
+ *       read the minutes and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into minutes field of Date struct
+ *       read the seconds and store into temp variable
+ *       convert from binary-coded decimal into binary, and store into seconds field of Date struct
+ *     turn off the I2C interface (function rtcTransfer does this for us)
+ *   Write the new record to the SD card
+ *     power on SD card
+ *       write new record to SD card
+ *         open the date-time string by writing a double quotation mark
+ *           write year, month, day, hours,
+ *           if minutes is less than ten
+ *           then
+ *             write a leading zero (the minutes value will be appended to it by the next statement)
+ *           endIf
+ *           write the minutes
+ *           if seconds is less than ten
+ *           then
+ *             write a leading zero (the seconds value will be appended to it by the next statement)
+ *           endIf
+ *           write the seconds
+ *         close the date-time string by writing a double quotation mark
+ *         write a comma to begin a new field (CSV file format)
+ *         write the record number
+ *         write a comma to begin a new field (CSV file format)
+ *         write the number of pulses counted when function was called (finalCount)
+ *       end of writing the record to SD card
+ *     power down SD card
+ * End of function storeNewRecord()
+ */
+
+
+
+void storeNewRecord()
+{                                                       // Begin
+    //State.flag4 = 0;                                    //     Reset flag4 to zero
+    //rtcTransfer(reg_Control_2, WRITE, 0x02);            //     Reset real time clock interrupt flag
+    byte finalCount;                                    //     Declare variables
+    byte temp;
+    finalCount = State.pulseCount;                      //     Store pulse count to a variable named final count
+    State.pulseCount = 0;                               //     Set pulseCount to zero
+                                                        //     Read current time from the Real Time Clock and update the Date struct with the current time
+      temp         = rtcTransfer(reg_Years,  READ, 0);  //         read the Years and store into temp variable
+      Date.years   = bcdtobin(temp, YEARS_REG_MASK);    //         convert from binary-coded decimal into binary, and store into years field of Date struct
+      temp         = rtcTransfer(reg_Months, READ, 0);  //         read the Months and store into temp variable
+      Date.months  = bcdtobin(temp, MONTHS_REG_MASK);   //         convert from binary-coded decimal into binary, and store into months field of Date struct
+      temp         = rtcTransfer(reg_Days,   READ, 0);  //         read the Days and store into temp variable
+      Date.days    = bcdtobin(temp, DAYS_REG_MASK);     //         convert from binary-coded decimal into binary, and store into days field of Date struct
+      temp         = rtcTransfer(reg_Hours,  READ, 0);  //         read the Hours and store into temp variable
+      Date.hours   = bcdtobin(temp, HOURS_REG_MASK);    //         convert from binary-coded decimal into binary, and store into hours field of Date struct
+      temp         = rtcTransfer(reg_Minutes,READ, 0);  //         read the Minutes and store into temp variable
+      Date.minutes = bcdtobin(temp, MINUTES_REG_MASK);  //         convert from binary-coded decimal into binary, and store into minutes field of Date struct
+      temp         = rtcTransfer(reg_Seconds,READ, 0);  //         read the Seconds and store into temp variable
+      Date.seconds = bcdtobin(temp, SECONDS_REG_MASK);  //         convert from binary-coded decimal into binary, and store into seconds field of Date struct
+                                                        //     Write the new record to the SD card
+      //SDPowerUp();                                      //         power on SD card
+      //SD.begin();
+        //Serial.println(F("SD Powerd up."));
+        dataFile = SD.open(F("datalog.csv"), FILE_WRITE);     //         Write new record to SD card
+        dataFile.print('\"');                          //           open the date-time string by writing a double quotation mark
+        dataFile.print(Date.years);                     //             write year, month, day, hours
+        dataFile.print('-');
+        dataFile.print(Date.months);
+        dataFile.print('-');
+        dataFile.print(Date.days);
+        dataFile.print(' ');
+        dataFile.print(Date.hours);
+        dataFile.print(':');
+        if(Date.minutes < 10)                           //             if minutes is less than ten
+        {                                               //             then
+          dataFile.print('0');                         //               write a leading zero (the minutes value will be appended to it by the next statement)
+        }                                               //             endIf
+        dataFile.print(Date.minutes);                   //             write the minutes
+        dataFile.print(':');                            //             write a colon to separate minutes from seconds
+        if(Date.seconds < 10)                           //             if seconds is less than ten
+        {                                               //             then
+          dataFile.print('0');                         //               write a leading zero (the seconds value will be appended to it by the next statement)
+        }                                               //             endIf
+        dataFile.print(Date.seconds);                   //             write the seconds
+        dataFile.print('\"');                           //           close date-time string by writing a double quotation mark
+        dataFile.print(',');                            //           write a comma to begin a new field (CSV file format)
+        dataFile.print(State.recordNum);                //           write the record number
+        dataFile.print(',');                            //           write a comma to begin a new field (CSV file format)
+        dataFile.println(finalCount);                   //           write the number of pulses counted when function was called (finalCount) and then print a new line
+
+        dataFile.close();                               //         end of writing the record to SD card
+        State.recordNum += 1;
+      //SDPowerDown();                                    //       power down SD card
+}                                                       // End of function storeNewRecord()
+
+
+
+
+
+
+/* Function: bcdtobin
+ *
+ * Author: Daniel Henshaw
+ * Date: 11/17/18
+ *
+ * Description: This function converts Binary Coded Decimal (BCD) numbers to
+ *              standard binary format. This is particularly useful when working
+ *              with the real time clock, which stores time data in BCD format
+ *              in its registers. The function takes in the value to convert, and
+ *              the source register the value is coming from. The source register
+ *              is required so that the conversion will be compatible with the
+ *              number of bits into which the BCD value is stored into the RTC's
+ *              registers.
+ *
+ * Optional dependencies: set of macro definitions, included below, improve
+ *              this function's usability or user friendliness. These make it
+ *              straightforward for the user to specify from which register
+ *              the data is coming from. These also do double duty as masks for the
+ *              value, as not all 8 bits in the register are for the BCD value; some
+ *              of the upper bits serve other purposes or are "unused"
+ *              (see datasheet for PCF8523 by NXP).
+ *
+ *              #define SECONDS_REG_MASK 0x7
+ *              #define MINUTES_REG_MASK 0x7
+ *              #define HOURS_REG_MASK   0x3
+ *              #define DAYS_REG_MASK    0x3
+ *              #define MONTHS_REG_MASK  0x1
+ *              #define YEARS_REG_MASK   0xF
+ *
+ * Pseudocode:
+ *
+ * Begin
+ *   Declare variable
+ *   shift right by four the bcdValue (Puts upper 4 bits at the bottom)
+ *   tensPlace is tensPlace ANDed with the provided bit mask a.k.a. conversion constant (hexadecimal value)
+ *   Return the binary value result (the unit's place plus tensPlace times ten)
+ * End
+ */
+
+byte bcdtobin(byte bcdValue, byte sourceReg)
+{
+  byte tensPlace;
+
+  tensPlace  = bcdValue >> 4;
+  tensPlace &= sourceReg;         /* NOTE: sourceReg is actually a bit mask */
+
+  return (bcdValue & 0x0F) + (tensPlace * 10); // return the binary value result:
+                                               //   step 1) First parenthesis: bcdValue ANDed with mask 0xF gives us the one's place,
+                                               //   step 2) Second parenthesis: move the ten's place value over by multiplying by ten
+                                               //   step 3) Add the first parenthesis group to the second parenthesis group
+}


explain serial port in comments

explain serial port in comments

--- OpenStage.ino
+++ OpenStage.ino
@@ -168,7 +168,7 @@

 // numAxes
-const byte numAxes=3; //The number of motorised axes
+const byte numAxes=3; //The number of motorised axes

 // axisPresent
 // Allows particular axes to be skipped. Useful for testing. 1 means present. 0 means absent.
@@ -397,7 +397,8 @@

 //------------------------------------------------------------------------------------------------
 // * Serial communiciation via serial shifter (Sparkfun) to allow the PC to interface with the
-// the stage
+// the stage. We use the serial shifter rather than the virtual serial port because this makes
+// debugging easier.
 int doSerialInterface=1;
 long values[numAxes]; // array holding values for all the received fields from the seria1 port
                      // see serialMove(). For some reason this must be a global.


Keep accessories on (e.g. radio) when starting

--- PushStart.ino
+++ PushStart.ino
@@ -97,7 +97,7 @@

 void ST() {
   mode = 3;
-  digitalWrite(pinACC, HIGH); // 2-3
+  digitalWrite(pinACC, LOW); // 2-3
   digitalWrite(pinIG1, LOW);  // 2-4
   digitalWrite(pinIG2, LOW);  // 7-6
   digitalWrite(pinST2, LOW);  // 7-8


replace mySerial.print() calls with macro, to make other schemes easier to implement

--- SAMD_pins.ino
+++ SAMD_pins.ino
@@ -1,15 +1,25 @@
 #include <Wire.h>
 #include <SPI.h>

+/*
+ * Adjust these as necessary
+ */
+
+/*
+ * For Sparkfun SAMD21 boards, use SerialUSB device
+ */
 #define mySerial SerialUSB
-#define ARRAYSIZE(a) (sizeof a/sizeof a[0])
+#define PRINT(...) mySerial.print(__VA_ARGS__)
+#define PRINTLN(...) mySerial.println(__VA_ARGS__)
+
+

 void setup() {
   mySerial.begin(9600);
   while (!mySerial)
     ;
-  mySerial.println("SAMD Pin State Report");
-  mySerial.println();
+  PRINTLN("SAMD Pin State Report");
+  PRINTLN();

   // Set some pins up doing something different, so that the display will be
   //   more ... interesting.
@@ -45,20 +55,20 @@
 	print_pinmux(pin, pmuxval);
       } else {
         // Pinmux not enabled - port is GPIO
-        mySerial.print("GPIO ");
+        PRINT("GPIO ");
         if (port->DIR.reg & (1 << bitno)) { // Decode pinmode (direction.)
-          mySerial.print("O");
+          PRINT("O");
         } else {
-          mySerial.print("I");
+          PRINT("I");
         }
       } // Pinmux or GPIO
     } // Pin existance
-    mySerial.println();
+    PRINTLN();
   } // "pin" for loop

   while (mySerial.read() < 0)
     ;  // wait for character to run again.
-  mySerial.println("\nRunning again!\n");
+  PRINTLN("\nRunning again!\n");
 }

@@ -68,18 +78,21 @@
   if (pintype == PIO_NOT_A_PIN) {
     return false;
   }
-  mySerial.print(i);
+  PRINT(i);
   if (i < 10)
-    mySerial.print(" ");
+    PRINT(" ");
   if (pintype == PIO_ANALOG) {  // try to detect and renumber Analog pins.
-    mySerial.print(" (A");
-    mySerial.print(i - PIN_A0);
-    mySerial.print(") ");
+    PRINT(" (A");
+    PRINT(i - PIN_A0);
+    PRINT(") ");
   } else {
-    mySerial.print("      ");
+    PRINT("      ");
   }
   return true;
 }
+
+
+#define ARRAYSIZE(a) (sizeof a/sizeof a[0])

 void (*PMUX_decode_func[8])(int, int) = {
   decode_EIC,
@@ -94,10 +107,10 @@

 void print_pinmux(int pin, int pmuxval)
 {
-  mySerial.print("PMUX");
-  mySerial.print("(");
-  mySerial.print(pmuxval);
-  mySerial.print(") ");
+  PRINT("PMUX");
+  PRINT("(");
+  PRINT(pmuxval);
+  PRINT(") ");
   if (pmuxval < (sizeof PMUX_decode_func/sizeof PMUX_decode_func[0])) {
     PMUX_decode_func[pmuxval](pin, pmuxval);
   }
@@ -123,11 +136,11 @@

 void decode_EIC(int pin, int pmux)
 {
-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
 }
 void decode_ADC(int pin, int pmux)
 {
-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
 }
 const char *pin_to_SERCOMA_info[] = {
   /* PA00 */ nullstr,
@@ -197,10 +210,10 @@
   int sercomno, sercomtype;
   Sercom *s;

-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
   if (port == &PORT->Group[0]) {
     if (bitno < (sizeof pin_to_SERCOMA_info/sizeof pin_to_SERCOMA_info[0])) {
-      mySerial.print(pin_to_SERCOMA_info[bitno]);
+      PRINT(pin_to_SERCOMA_info[bitno]);
       /*
        * Get sercom number from the string.  (Ugly, but saves space.)
        */
@@ -209,7 +222,7 @@
   }
   if (port == &PORT->Group[1]) {
     if (bitno < (sizeof pin_to_SERCOMB_info/sizeof pin_to_SERCOMB_info[0])) {
-      mySerial.print(pin_to_SERCOMB_info[bitno]);
+      PRINT(pin_to_SERCOMB_info[bitno]);
       /*
        * Get sercom number from the string.  (Ugly, but saves space.)
        */
@@ -220,7 +233,7 @@
     s = sercomports[sercomno];
     sercomtype = s->USART.CTRLA.bit.MODE;
     if (sercomtype < ARRAYSIZE(sercomtype_names)) {
-      mySerial.print(sercomtype_names[sercomtype]);
+      PRINT(sercomtype_names[sercomtype]);
     }
   }
 }
@@ -302,10 +315,10 @@
   int sercomno, sercomtype;
   Sercom *s;

-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
   if (port == &PORT->Group[0]) {
     if (bitno < ARRAYSIZE(pin_to_SERCOMALTA_info)) {
-      mySerial.print(pin_to_SERCOMALTA_info[bitno]);
+      PRINT(pin_to_SERCOMALTA_info[bitno]);
       /*
        * Get sercom number from the string.  (Ugly, but saves space.)
        */
@@ -314,7 +327,7 @@
   }
   if (port == &PORT->Group[1]) {
     if (bitno < ARRAYSIZE(pin_to_SERCOMALTB_info)) {
-      mySerial.print(pin_to_SERCOMALTB_info[bitno]);
+      PRINT(pin_to_SERCOMALTB_info[bitno]);
       /*
        * Get sercom number from the string.  (Ugly, but saves space.)
        */
@@ -325,7 +338,7 @@
     s = sercomports[sercomno];
     sercomtype = s->USART.CTRLA.bit.MODE;
     if (sercomtype < ARRAYSIZE(sercomtype_names)) {
-      mySerial.print(sercomtype_names[sercomtype]);
+      PRINT(sercomtype_names[sercomtype]);
     }
   }
 }
@@ -399,12 +412,12 @@

   if (port == &PORT->Group[0]) {
     if (bitno < ARRAYSIZE(pin_to_tc_info_a)) {
-      mySerial.print(pin_to_tc_info_a[bitno]);
+      PRINT(pin_to_tc_info_a[bitno]);
     }
   }
   if (port == &PORT->Group[1]) {
     if (bitno < ARRAYSIZE(pin_to_tc_info_a)) {
-      mySerial.print(pin_to_tc_info_b[bitno]);
+      PRINT(pin_to_tc_info_b[bitno]);
     }
   }
 }
@@ -470,12 +483,12 @@

   if (port == &PORT->Group[0]) {
     if (bitno < ARRAYSIZE(pin_to_tc_info_a)) {
-      mySerial.print(pin_to_tcc_info_a[bitno]);
+      PRINT(pin_to_tcc_info_a[bitno]);
     }
   }
   if (port == &PORT->Group[1]) {
     if (bitno < ARRAYSIZE(pin_to_tc_info_a)) {
-      mySerial.print(pin_to_tcc_info_b[bitno]);
+      PRINT(pin_to_tcc_info_b[bitno]);
     }
   }
 }
@@ -484,19 +497,19 @@
   PortGroup *port = digitalPinToPort(pin);
   int bitno = g_APinDescription[pin].ulPin;

-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
   // PA23..PA25 are for USB
   if (port == &PORT->Group[0] && (bitno >= 23 && bitno <= 25)) {
-    mySerial.print("(USB)");
+    PRINT("(USB)");
   }
   // PA30..PA31 are for SWD (Serial JTAG debug)
   if (port == &PORT->Group[0] && (bitno >= 30 && bitno <= 31)) {
-    mySerial.print("(SWD)");
+    PRINT("(SWD)");
   }
 }
 void decode_CLK(int pin, int pmux)
 {
-  mySerial.print(pinmux_names[pmux]);
+  PRINT(pinmux_names[pmux]);
 }

 void print_portname(int pin)
@@ -505,14 +518,14 @@
   int bitno = g_APinDescription[pin].ulPin;

   if (port == &PORT->Group[0]) {
-    mySerial.print("PA");
+    PRINT("PA");
   }
   if (port == &PORT->Group[1]) {
-    mySerial.print("PB");
+    PRINT("PB");
   }
   if (bitno < 10) {
-    mySerial.print("0");
-  }
-  mySerial.print(bitno);
-  mySerial.print("  ");
-}
+    PRINT("0");
+  }
+  PRINT(bitno);
+  PRINT("  ");
+}