TODO-970: moving remaining unit tests to lib

--- test/test.ino
+++ test/test.ino
@@ -514,115 +514,6 @@
   }

-// OTRadValve
-
-// Test calibration calculations in CurrentSenseValveMotorDirect.
-// Also check some of the use of those calculations.
-static void testCSVMDC()
-  {
-  Serial.println("CSVMDC");
-  OTRadValve::CurrentSenseValveMotorDirect::CalibrationParameters cp;
-  volatile uint16_t ticksFromOpen, ticksReverse;
-  // Test the calculations with one plausible calibration data set.
-  AssertIsTrue(cp.updateAndCompute(1601U, 1105U)); // Must not fail...
-  AssertIsEqual(4, cp.getApproxPrecisionPC());
-  AssertIsEqual(25, cp.getTfotcSmall());
-  AssertIsEqual(17, cp.getTfctoSmall());
-  // Check that a calibration instance can be reused correctly.
-  const uint16_t tfo2 = 1803U;
-  const uint16_t tfc2 = 1373U;
-  AssertIsTrue(cp.updateAndCompute(tfo2, tfc2)); // Must not fail...
-  AssertIsEqual(3, cp.getApproxPrecisionPC());
-  AssertIsEqual(28, cp.getTfotcSmall());
-  AssertIsEqual(21, cp.getTfctoSmall());
-  // Check that computing position works...
-  // Simple case: fully closed, no accumulated reverse ticks.
-  ticksFromOpen = tfo2;
-  ticksReverse = 0;
-  AssertIsEqual(0, cp.computePosition(ticksFromOpen, ticksReverse));
-  AssertIsEqual(tfo2, ticksFromOpen);
-  AssertIsEqual(0, ticksReverse);
-  // Simple case: fully open, no accumulated reverse ticks.
-  ticksFromOpen = 0;
-  ticksReverse = 0;
-  AssertIsEqual(100, cp.computePosition(ticksFromOpen, ticksReverse));
-  AssertIsEqual(0, ticksFromOpen);
-  AssertIsEqual(0, ticksReverse);
-  // Try at half-way mark, no reverse ticks.
-  ticksFromOpen = tfo2 / 2;
-  ticksReverse = 0;
-  AssertIsEqual(50, cp.computePosition(ticksFromOpen, ticksReverse));
-  AssertIsEqual(tfo2/2, ticksFromOpen);
-  AssertIsEqual(0, ticksReverse);
-  // Try at half-way mark with just one reverse tick (nothing should change).
-  ticksFromOpen = tfo2 / 2;
-  ticksReverse = 1;
-  AssertIsEqual(50, cp.computePosition(ticksFromOpen, ticksReverse));
-  AssertIsEqual(tfo2/2, ticksFromOpen);
-  AssertIsEqual(1, ticksReverse);
-  // Try at half-way mark with a big-enough block of reverse ticks to be significant.
-  ticksFromOpen = tfo2 / 2;
-  ticksReverse = cp.getTfctoSmall();
-  AssertIsEqual(51, cp.computePosition(ticksFromOpen, ticksReverse));
-  AssertIsEqual(tfo2/2 - cp.getTfotcSmall(), ticksFromOpen);
-  AssertIsEqual(0, ticksReverse);
-// DHD20151025: one set of actual measurements during calibration.
-//    ticksFromOpenToClosed: 1529
-//    ticksFromClosedToOpen: 1295
-  }
-
-
-class DummyHardwareDriver : public OTRadValve::HardwareMotorDriverInterface
-  {
-  public:
-    // Detect if end-stop is reached or motor current otherwise very high.
-    virtual bool isCurrentHigh(OTRadValve::HardwareMotorDriverInterface::motor_drive mdir = motorDriveOpening) const { return(currentHigh); }
-  public:
-    DummyHardwareDriver() : currentHigh(false) { }
-    virtual void motorRun(uint8_t maxRunTicks, motor_drive dir, OTRadValve::HardwareMotorDriverInterfaceCallbackHandler &callback)
-      { }
-    // isCurrentHigh() returns this value.
-    bool currentHigh;
-  };
-
-// Test that direct abstract motor drive logic is sane.
-// DHD20160206: possibly causing a crash periodically when run on an UNO.
-static void testCurrentSenseValveMotorDirect()
-  {
-  Serial.println("CurrentSenseValveMotorDirect");
-  DummyHardwareDriver dhw;
-  OTRadValve::CurrentSenseValveMotorDirect csvmd1(&dhw);
-  // POWER UP
-  // Whitebox test of internal state: should be init.
-  AssertIsEqual(OTRadValve::CurrentSenseValveMotorDirect::init, csvmd1.getState());
-  // Verify NOT marked as in normal run state immediately upon initialisation.
-  AssertIsTrue(!csvmd1.isInNormalRunState());
-  // Verify NOT marked as in error state immediately upon initialisation.
-  AssertIsTrue(!csvmd1.isInErrorState());
-  // Target % open must start off in a sensible state; fully-closed is good.
-  AssertIsEqual(0, csvmd1.getTargetPC());
-
-  // FIRST POLL(S) AFTER POWER_UP; RETRACTING THE PIN.
-  csvmd1.poll();
-//  // Whitebox test of internal state: should be valvePinWithdrawing.
-//  AssertIsEqual(OTRadValve::CurrentSenseValveMotorDirect::valvePinWithdrawing, csvmd1.getState());
-//  // More polls shouldn't make any difference initially.
-//  csvmd1.poll();
-//  // Whitebox test of internal state: should be valvePinWithdrawing.
-//  AssertIsEqual(OTRadValve::CurrentSenseValveMotorDirect::valvePinWithdrawing, csvmd1.getState());
-//  csvmd1.poll();
-//  // Whitebox test of internal state: should be valvePinWithdrawing.
-//  AssertIsEqual(OTRadValve::CurrentSenseValveMotorDirect::valvePinWithdrawing, csvmd1.getState());
-//  // Simulate hitting end-stop (high current).
-//  dhw.currentHigh = true;
-//  AssertIsTrue(dhw.isCurrentHigh());
-//  csvmd1.poll();
-//  // Whitebox test of internal state: should be valvePinWithdrawn.
-//  AssertIsEqual(CurrentSenseValveMotorDirect::valvePinWithdrawn, csvmd1.getState());
-//  dhw.currentHigh = false;
-  // TODO
-  }
-

 // BASE

@@ -823,34 +714,252 @@
     }
   }

+
+// Test elements of encoding and decoding FullStatsMessageCore_t.
+// These are the routines primarily under test:
+//     uint8_t *encodeFullStatsMessageCore(uint8_t *buf, uint8_t buflen, stats_TX_level secLevel, bool secureChannel, const FullStatsMessageCore_t *content)
+//     const uint8_t *decodeFullStatsMessageCore(const uint8_t *buf, uint8_t buflen, stats_TX_level secLevel, bool secureChannel, FullStatsMessageCore_t *content)
+static void testFullStatsMessageCoreEncDec()
+  {
+  Serial.println("FullStatsMessageCoreEncDec");
+
+  // Ensure that with null buffer/content encode and decode fail regardless of other arguments.
+  uint8_t buf[OTV0P2BASE::FullStatsMessageCore_MAX_BYTES_ON_WIRE + 1];
+  OTV0P2BASE::FullStatsMessageCore_t content;
+  AssertIsTrue(NULL == OTV0P2BASE::encodeFullStatsMessageCore(NULL, OTV0P2BASE::randRNG8(), OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), NULL));
+  AssertIsTrue(NULL == OTV0P2BASE::decodeFullStatsMessageCore(NULL, OTV0P2BASE::randRNG8(), OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), NULL));
+  AssertIsTrue(NULL == OTV0P2BASE::encodeFullStatsMessageCore(NULL, OTV0P2BASE::FullStatsMessageCore_MAX_BYTES_ON_WIRE+1, OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), &content));
+  AssertIsTrue(NULL == OTV0P2BASE::encodeFullStatsMessageCore(buf, OTV0P2BASE::FullStatsMessageCore_MAX_BYTES_ON_WIRE+1, OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), NULL));
+  AssertIsTrue(NULL == OTV0P2BASE::decodeFullStatsMessageCore(NULL, OTV0P2BASE::FullStatsMessageCore_MIN_BYTES_ON_WIRE+1, OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), &content));
+  AssertIsTrue(NULL == OTV0P2BASE::decodeFullStatsMessageCore(buf, OTV0P2BASE::FullStatsMessageCore_MIN_BYTES_ON_WIRE+1, OTV0P2BASE::stTXalwaysAll, OTV0P2BASE::randRNG8NextBoolean(), NULL));
+
+  // Prepare a minimal (empty) non-secure message.
+  memset(buf, 0, sizeof(buf));
+  clearFullStatsMessageCore(&content);
+  const uint8_t *emptyMsg = OTV0P2BASE::encodeFullStatsMessageCore(buf, sizeof(buf), OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != emptyMsg); // Must succeed.
+  AssertIsTrueWithErr(emptyMsg - buf == OTV0P2BASE::FullStatsMessageCore_MIN_BYTES_ON_WIRE, emptyMsg - buf); // Must correspond to minimum size.
+  AssertIsTrueWithErr(OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_MSBS == buf[0], buf[0]); // Header byte.
+  AssertIsTrueWithErr(0x60 /*OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_FLAGS_HEADER_MSBS*/ == buf[1], buf[1]); // Flags header byte.
+  AssertIsTrueWithErr(0x65 == buf[2], buf[2]); // CRC.
+  AssertIsTrue(((uint8_t)0xff) == *emptyMsg); // Must be correctly terminated.
+  // Decode the message just generated into a freshly-scrubbed content structure.
+  clearFullStatsMessageCore(&content);
+  const uint8_t *emptyMsgDE = OTV0P2BASE::decodeFullStatsMessageCore(buf, emptyMsg-buf, OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != emptyMsgDE); // Must succeed.
+  AssertIsTrue(emptyMsg == emptyMsgDE); // Must return correct end of message.
+  // Verify that there is no content.
+  AssertIsTrue(!content.containsID);
+  AssertIsTrue(!content.containsTempAndPower);
+  AssertIsTrue(!content.containsAmbL);
+
+  // Prepare a non-secure message with ID.
+  memset(buf, 0, sizeof(buf));
+  clearFullStatsMessageCore(&content);
+  content.id0 = 0x80;
+  content.id1 = 0x00;
+  content.containsID = true;
+  AssertIsTrue(NULL == OTV0P2BASE::encodeFullStatsMessageCore(buf, sizeof(buf), OTV0P2BASE::stTXalwaysAll, false, &content)); // Should reject ID bytes with differring msbits.
+  content.id1 = 0x81;
+  const uint8_t *onlyIDMsg = OTV0P2BASE::encodeFullStatsMessageCore(buf, sizeof(buf), OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != onlyIDMsg); // Must succeed.
+  AssertIsTrueWithErr(onlyIDMsg - buf == OTV0P2BASE::FullStatsMessageCore_MIN_BYTES_ON_WIRE + 2, onlyIDMsg - buf); // Must correspond to minimum size + 2 ID bytes.
+  AssertIsTrueWithErr((OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_MSBS | OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_BITS_ID_PRESENT | OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_BITS_ID_HIGH) == buf[0], buf[0]); // Header byte.
+  AssertIsTrueWithErr(0x00 == buf[1], buf[1]); // ID0 without msbit.
+  AssertIsTrueWithErr(0x01 == buf[2], buf[2]); // ID1 without msbit.
+  AssertIsTrueWithErr(0x60 /* V0P2_MESSAGING_LEADING_FULL_STATS_FLAGS_HEADER_MSBS */ == buf[3], buf[3]); // Flags header byte.
+  AssertIsTrueWithErr(0x01 == buf[4], buf[4]); // CRC.
+  AssertIsTrue(((uint8_t)0xff) == *onlyIDMsg); // Must be correctly terminated.
+  // Decode the message just generated into a freshly-scrubbed content structure.
+  clearFullStatsMessageCore(&content);
+  const uint8_t *onlyIDMsgDE = OTV0P2BASE::decodeFullStatsMessageCore(buf, onlyIDMsg-buf, OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != onlyIDMsgDE); // Must succeed.
+  AssertIsTrue(onlyIDMsg == onlyIDMsgDE); // Must return correct end of message.
+  // Verify that there is only ID.
+  AssertIsTrue(content.containsID);
+  AssertIsTrueWithErr(content.id0 == (uint8_t)0x80, content.id0);
+  AssertIsTrueWithErr(content.id1 == (uint8_t)0x81, content.id1);
+  AssertIsTrue(!content.containsTempAndPower);
+  AssertIsTrue(!content.containsAmbL);
+
+  // Prepare a non-secure message with ID, temp/power, ambient light level and occupancy.
+  memset(buf, 0, sizeof(buf));
+  clearFullStatsMessageCore(&content);
+  content.id0 = 0x83;
+  content.id1 = 0x98;
+  content.containsID = true;
+  content.tempAndPower.tempC16 = (19 << 4) + 1; // (19 + 1/16)C.
+  content.tempAndPower.powerLow = false; // Normal power.
+  content.containsTempAndPower = true;
+  content.ambL = 42; // Allowed value in range [1,254].
+  content.containsAmbL = true;
+  content.occ = 3; // Not occupied recently.
+  const uint8_t *msg1 = OTV0P2BASE::encodeFullStatsMessageCore(buf, sizeof(buf), OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != msg1); // Must succeed.
+  AssertIsTrueWithErr(msg1 - buf == OTV0P2BASE::FullStatsMessageCore_MAX_BYTES_ON_WIRE, msg1 - buf); // Must correspond to minimum size + 2 ID bytes.
+  AssertIsTrueWithErr((OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_MSBS | OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_BITS_ID_PRESENT | OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_HEADER_BITS_ID_HIGH) == buf[0], buf[0]); // Header byte.
+  AssertIsTrueWithErr(0x03 == buf[1], buf[1]); // ID0 without msbit.
+  AssertIsTrueWithErr(0x18 == buf[2], buf[2]); // ID1 without msbit.
+  AssertIsTrueWithErr(0x60 /* (MESSAGING_TRAILING_MINIMAL_STATS_HEADER_MSBS + 1) */ == buf[3], buf[3]); // Temp/power first byte.
+  AssertIsTrueWithErr((19 + 20) == buf[4], buf[4]); // Temp second byte.
+  AssertIsTrueWithErr((0x60 /* OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_FLAGS_HEADER_MSBS */ | 8 /* OTRadioLink::V0P2_MESSAGING_LEADING_FULL_STATS_FLAGS_HEADER_AMBL */ | 3) == buf[5], buf[5]); // Flags header (no extension byte follows).
+  AssertIsTrueWithErr(42 == buf[6], buf[6]); // Ambient light.
+  AssertIsTrueWithErr(0x44 == buf[7], buf[7]); // CRC.
+  AssertIsTrue(((uint8_t)0xff) == *msg1); // Must be correctly terminated.
+  // Decode the message just generated into a freshly-scrubbed content structure.
+  clearFullStatsMessageCore(&content);
+  const uint8_t *msg1DE = OTV0P2BASE::decodeFullStatsMessageCore(buf, msg1-buf, OTV0P2BASE::stTXalwaysAll, false, &content);
+  AssertIsTrue(NULL != msg1DE); // Must succeed.
+  AssertIsTrue(msg1 == msg1DE); // Must return correct end of message.
+  AssertIsTrue(content.containsID);
+  AssertIsTrueWithErr(content.id0 == (uint8_t)0x83, content.id0);
+  AssertIsTrueWithErr(content.id1 == (uint8_t)0x98, content.id1);
+  AssertIsTrue(content.containsTempAndPower);
+  AssertIsTrue(!content.tempAndPower.powerLow);
+  AssertIsTrue((19 << 4) + 1 == content.tempAndPower.tempC16);
+  AssertIsTrue(content.containsAmbL);
+  AssertIsTrue(42 == content.ambL);
+  }
+
+
+
+// Test sleepUntilSubCycleTime() routine.
+void testSleepUntilSubCycleTime()
+  {
+#ifdef ENABLE_WAKEUP_32768HZ_XTAL
+  DEBUG_SERIAL_PRINTLN_FLASHSTRING("SleepUntilSubCycleTime");
+
+  const uint8_t start = OTV0P2BASE::getSubCycleTime();
+
+  // Check that this correctly notices/vetoes attempt to sleep until time already past.
+  if(start > 0) { AssertIsTrue(!sleepUntilSubCycleTime(start-1)); }
+
+  // Don't attempt rest of test if near the end of the current minor cycle...
+  if(start > (OTV0P2BASE::GSCT_MAX/2)) { return; }
+
+  // Set a random target significantly before the end of the current minor cycle.
+//#if 0x3f > GSCT_MAX/4
+//#error
+//#endif
+  AssertIsTrue(0x3f <= OTV0P2BASE::GSCT_MAX/4);
+  const uint8_t sleepTicks = 2 + (OTV0P2BASE::randRNG8() & 0x3f);
+  const uint8_t target = start + sleepTicks;
+  AssertIsTrue(target > start);
+  AssertIsTrue(target < OTV0P2BASE::GSCT_MAX);
+
+  // Call should succeed.
+  AssertIsTrue(sleepUntilSubCycleTime(target));
+
+  // Call should return with some of specified target tick still to run...
+  const uint8_t end = OTV0P2BASE::getSubCycleTime();
+  AssertIsTrueWithErr(target == end, end); // FIXME: DHD2014020: getting occasional failures.
+
+#if 0
+  DEBUG_SERIAL_PRINT_FLASHSTRING("Sleep ticks: ");
+  DEBUG_SERIAL_PRINT(sleepTicks);
+  DEBUG_SERIAL_PRINTLN();
+#endif
+#endif
+  }
+
+
+// Test some of the mask/port calculations.
+static void testFastDigitalIOCalcs()
+  {
+  Serial.println("FastDigitalIOCalcs");
+  AssertIsEqual(digitalPinToBitMask(0), fastDigitalMask(0));
+  AssertIsEqual(digitalPinToBitMask(2), fastDigitalMask(2));
+  AssertIsEqual(digitalPinToBitMask(13), fastDigitalMask(13));
+  AssertIsEqual(digitalPinToBitMask(19), fastDigitalMask(19));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(0)), (intptr_t)fastDigitalInputRegister(0));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(2)), (intptr_t)fastDigitalInputRegister(2));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(7)), (intptr_t)fastDigitalInputRegister(7));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(8)), (intptr_t)fastDigitalInputRegister(8));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(14)), (intptr_t)fastDigitalInputRegister(14));
+  AssertIsEqual((intptr_t)portInputRegister(digitalPinToPort(19)), (intptr_t)fastDigitalInputRegister(19));
+  }
+
+
+
+//#if !defined(DISABLE_SENSOR_UNIT_TESTS)
+//// Test temperature sensor returns value in reasonable bounds for a test environment.
+//// Attempts to test that the sensor is actually present.
+//static void testTempSensor()
+//  {
+//  Serial.println("TempSensor");
+//  const int temp = TemperatureC16.read();
+//#if 0
+//  OTV0P2BASE::serialPrintAndFlush("  temp: ");
+//  OTV0P2BASE::serialPrintAndFlush(temp >> 4, DEC);
+//  OTV0P2BASE::serialPrintAndFlush('C');
+//  OTV0P2BASE::serialPrintAndFlush(temp & 0xf, HEX);
+//  OTV0P2BASE::serialPrintlnAndFlush();
+//#endif
+//  // During testing temp should be above 0C (0C might indicate a missing/broken sensor) and below 50C.
+//  AssertIsTrueWithErr((temp > 0) && (temp < (50 << 4)), temp);
+//  }
+//#endif
+
 #if !defined(DISABLE_SENSOR_UNIT_TESTS)
-static OTV0P2BASE::SupplyVoltageCentiVolts Supply_cV;
+// Test that on-chip temperature sensor returns value in half-reasonable bounds for a test environment.
+// Internal sensor may be +/- 10C out.
+static void testInternalTempSensor()
+  {
+  Serial.println("InternalTempSensor");
+  const int temp = OTV0P2BASE::readInternalTemperatureC16();
+#if 0
+  OTV0P2BASE::serialPrintAndFlush("  int temp: ");
+  OTV0P2BASE::serialPrintAndFlush(temp >> 4, DEC);
+  OTV0P2BASE::serialPrintAndFlush('C');
+  OTV0P2BASE::serialPrintAndFlush(temp & 0xf, HEX);
+  OTV0P2BASE::serialPrintlnAndFlush();
+#endif
+  // During testing temp should be above 0C (0C might indicate a missing/broken sensor) and below 50C.
+  // Internal sensor may be +/- 10C out.
+  // DHD20141223: Just has a reading of ~17C from an otherwise-OK AVR with room temp ~20C.
+  AssertIsTrueWithErr((temp > (-20 << 4)) && (temp < (60 << 4)), temp);
+  }
+#endif
+
+#if !defined(DISABLE_SENSOR_UNIT_TESTS)
 static void testSupplyVoltageMonitor()
   {
-//  Serial.println("SupplyVoltageMonitor");
-//  const bool neededPowerUp = OTV0P2BASE::powerUpADCIfDisabled();
-//  const uint8_t cV = Supply_cV.read();
-//  const uint8_t ri = Supply_cV.getRawInv();
-//#if 1
-//  OTV0P2BASE::serialPrintAndFlush("  Battery cV: ");
-//  OTV0P2BASE::serialPrintAndFlush(cV);
-//  OTV0P2BASE::serialPrintlnAndFlush();
-//  OTV0P2BASE::serialPrintAndFlush("  Raw inverse: ");
-//  OTV0P2BASE::serialPrintAndFlush(ri);
+  Serial.println("SupplyVoltageMonitor");
+
+  //  const int mv = Supply_mV.read();
+//#if 0
+//  OTV0P2BASE::serialPrintAndFlush("  Battery mv: ");
+//  OTV0P2BASE::serialPrintAndFlush(mv, DEC);
 //  OTV0P2BASE::serialPrintlnAndFlush();
 //#endif
 //  // During testing power supply voltage should be above ~1.7V BOD limit,
 //  // and no higher than 3.6V for V0p2 boards which is RFM22 Vss limit.
 //  // Note that REV9 first boards are running at 3.6V nominal!
-//  // Also, this test may get run on UNO/5V hardware.
-//  AssertIsTrueWithErr((cV >= 170) && (cV < 510), cV);
-//  // Would expect raw inverse to be <= 1023 for Vcc >= 1.1V.
-//  // Should be ~512 at 2.2V, ~310 at 3.3V.
-//  AssertIsTrueWithErr((ri >= 200) && (ri < 1023), ri);
-//  if(neededPowerUp) { OTV0P2BASE::powerDownADC(); }
-  }
-#endif
-
+//  AssertIsTrueWithErr((mv >= 1700) && (mv < 3700), mv);
+
+  const bool neededPowerUp = OTV0P2BASE::powerUpADCIfDisabled();
+  OTV0P2BASE::SupplyVoltageCentiVolts Supply_cV;
+  const uint8_t cV = Supply_cV.read();
+  const uint16_t ri = Supply_cV.getRawInv();
+#if 1
+  OTV0P2BASE::serialPrintAndFlush("  Battery cV: ");
+  OTV0P2BASE::serialPrintAndFlush(cV);
+  OTV0P2BASE::serialPrintlnAndFlush();
+  OTV0P2BASE::serialPrintAndFlush("  Raw inverse: ");
+  OTV0P2BASE::serialPrintAndFlush(ri);
+  OTV0P2BASE::serialPrintlnAndFlush();
+#endif
+  // During testing power supply voltage should be above ~1.7V BOD limit,
+  // and no higher than 3.6V for V0p2 boards which is RFM22 Vss limit.
+  // Note that REV9 first boards are running at 3.6V nominal!
+  // Also, this test may get run on UNO/5V hardware.
+  AssertIsTrueWithErr((cV >= 170) && (cV < 510), cV);
+  // Would expect raw inverse to be <= 1023 for Vcc >= 1.1V.
+  // Should be ~512 at 2.2V, ~310 at 3.3V.
+  AssertIsTrueWithErr((ri >= 200) && (ri < 1023), ri);
+  if(neededPowerUp) { OTV0P2BASE::powerDownADC(); }
+  }
+#endif

 // Tests generally flag an error and stop the test cycle with a call to panic() or error().
@@ -887,8 +996,8 @@
 #endif

   // OTRadValve
-  testCSVMDC();
-  testCurrentSenseValveMotorDirect();
+//  testCSVMDC();
+//  testCurrentSenseValveMotorDirect();

   // OTV0p2Base
   testParseHexVal();


more arduino code

more arduino code

--- ArduinoController/ArduinoController.ino
+++ ArduinoController/ArduinoController.ino
@@ -26,7 +26,9 @@
 #include <RBL_nRF8001.h>

 const int BTN_PIN = 4;
-const int LED_PIN = 2;
+const int LED_PIN = 3;
+const int SERVO_PIN = 6;
+const int POT_PIN = A0;

 void setup()
 {
@@ -40,13 +42,14 @@

   pinMode(BTN_PIN,INPUT);
-
   pinMode(LED_PIN,OUTPUT);
+  pinMode(SERVO_PIN, OUTPUT);
+  pinMode(POT_PIN, INPUT);
   digitalWrite( LED_PIN, LOW );

   // Init. and start BLE library.
   ble_begin();
-
+
   // Enable serial debug
   Serial.begin(57600);
 }
@@ -55,6 +58,7 @@
 unsigned char len = 0;
 String command;
 int buttonState = 0;
+int potVal = 0;

 void loop()
 {
@@ -73,6 +77,10 @@
     }
     else if ( command.substring(0,10) == "Light OFF;" ) {
       digitalWrite( LED_PIN, LOW );
+    }
+    else if ( command.substring(0,5) == "Servo" ) {
+        String servoSpeed = command.substring(6,command.indexOf(';'));
+        analogWrite(SERVO_PIN, servoSpeed.toInt());
     }

@@ -100,6 +108,19 @@
     }
   }

+  //read from pot
+  int newPotVal = analogRead(POT_PIN);
+  if( newPotVal != potVal ) {
+
+    potVal = newPotVal;
+    int newBrightness = potVal/4;
+    analogWrite(LED_PIN, newBrightness);
+    String sendCommand = "POT " + String(potVal);
+    for( int i = 0; i < sendCommand.length(); i++ ) {
+      ble_write( sendCommand[i] );
+    }
+  }
+
   delay(10);


send alive headers filled with radioUtils

--- src/wsn/Alive.ino
+++ src/wsn/Alive.ino
@@ -4,6 +4,8 @@

 int counter = 0; //
 int msgCounter = 0;
+
+radioUtils ru = radioUtils();

 void setup () {
   Serial.begin(57600);
@@ -24,6 +26,8 @@
       //propagate to parent
       byte header = B00000000;
       //fill header using radioUtils
+      ru.resetAck(&header);
+      ru.setID(&header, PARENTID);
       rf12_sendNow(header, (const void*)rf12_data, rf12_len);
     }
   }
@@ -35,8 +39,9 @@
     msgCounter++;
     //send still alive msg
     byte header;
-    //fill header using radioUtils
-    //void* data;
+    //fill header using radioUtils
+    ru.resetAck(&header);
+    ru.setID(&header, PARENTID);
     rf12_sendNow(header, (const void*) &msgCounter, sizeof(counter));
     counter = 0;
   }


Keyboard example: Include Keyboard.h.

Keyboard example: Include Keyboard.h.

This is needed because of the new Pluggable USB library system that
was added in Arduino 1.6.6.

--- examples/Keyboard/Keyboard.ino
+++ examples/Keyboard/Keyboard.ino
@@ -24,6 +24,7 @@
 other electronics connected, make sure they do not use those
 pins in a conflicting way. */

+#include <Keyboard.h>
 #include <AStar32U4.h>

 // These objects provide access to the A-Star's on-board


Modify pwm write Method

Modify pwm write Method

--- Software/OpenCM9.04/RovMain/RovMain.ino
+++ Software/OpenCM9.04/RovMain/RovMain.ino
@@ -11,11 +11,12 @@
 //
 //    파일명       : RovMain.ino
 //----------------------------------------------------------------------------
+#include <Servo.h>
 #include "RSP.h"
-#include <Servo.h>
-
-
-#define USE_RC_SETUP  0
+
+RSP     RovSerial;
+
+#define USB_TEST_AVAILABLE 1  // control Motor & LED by using USB serial

 #define RC_MOTOR_L    0
 #define RC_MOTOR_C    1
@@ -24,20 +25,20 @@
 #define RC_MOTOR_PIN_L  2
 #define RC_MOTOR_PIN_C  3
 #define RC_MOTOR_PIN_R  5
+
 #define LED_PIN_L  8
 #define LED_PIN_R  9

-RSP     RovSerial;
-Servo   RovServo[3];
-
 bool IsConnected;

+void rc_usb_test();
 void led_setup();
-void rc_setup( void );
 void process_recv_cmd( void );

 void send_cmd_info( void );
 void recv_cmd_control( RSP_CMD_OBJ *pCmd );
+
+Servo   RovServo[3];

 void setup()
 {
@@ -48,9 +49,9 @@
   RovServo[RC_MOTOR_C].attach(RC_MOTOR_PIN_C, 1000, 2000, 0, 255 );
   RovServo[RC_MOTOR_R].attach(RC_MOTOR_PIN_R, 1000, 2000, 0, 255 );

-  RovServo[RC_MOTOR_L].write(0);
-  RovServo[RC_MOTOR_C].write(0);
-  RovServo[RC_MOTOR_R].write(0);
+  RovServo[RC_MOTOR_L].writeMicroseconds(0);
+  RovServo[RC_MOTOR_C].writeMicroseconds(0);
+  RovServo[RC_MOTOR_R].writeMicroseconds(0);

   pinMode(LED_PIN_L, PWM);
   pinMode(LED_PIN_R, PWM);
@@ -70,10 +71,8 @@
   //
   process_recv_cmd();

-  #if USE_RC_SETUP ==  1
-  rc_setup();
-  #endif
-
+  if(USB_TEST_AVAILABLE)
+  rc_usb_test();

   //-- 100ms마다 ROV정보 전달
   //
@@ -91,130 +90,17 @@

   //-- 연결이 끊어진 상태
   //
+/*
   if( IsConnected == false )
   {
     RovServo[RC_MOTOR_L].write(0);
     RovServo[RC_MOTOR_C].write(0);
     RovServo[RC_MOTOR_R].write(0);
   }
+  */
 }

-void rc_setup( void )
-{
-  volatile char ch;
-  volatile static int  rc_pwm_L = 0, rc_pwm_R = 0, rc_pwm_C = 0, led_L = 0, led_R = 0;
-
-  if( Serial.available() )
-  {
-    ch = Serial.read();
-    //시동
-    if( ch == 'o' )
-    {
-      rc_pwm_L = 0, rc_pwm_R = 0, rc_pwm_C = 0;
-      RovServo[0].write(rc_pwm_L);
-      RovServo[1].write(rc_pwm_C);
-      RovServo[2].write(rc_pwm_R);
-      Serial.println("Start");
-    }
-    //정지 (시동끄기)
-    if( ch == 'p' )
-    {
-      rc_pwm_L = 0, rc_pwm_R = 0, rc_pwm_C = 0;
-      RovServo[0].write(rc_pwm_L);
-      RovServo[1].write(rc_pwm_C);
-      RovServo[2].write(rc_pwm_R);
-      Serial.println("Stop");
-    }
-    //전진 모터 가속
-    if( ch == 'w' )
-    {
-      rc_pwm_L = constrain(rc_pwm_L++, 0, 1000);
-      rc_pwm_R = constrain(rc_pwm_R++, 0, 1000);
-      RovServo[0].write(rc_pwm_L);
-      RovServo[2].write(rc_pwm_R);
-      Serial.print("Left=");
-      Serial.print(rc_pwm_L);
-      Serial.print("  Right=");
-      Serial.println(rc_pwm_R);
-    }
-    //전진 모터 감속
-    if( ch == 's' )
-    {
-      rc_pwm_L = constrain(rc_pwm_L--, 0, 1000);
-      rc_pwm_R = constrain(rc_pwm_R--, 0, 1000);
-      RovServo[0].write(rc_pwm_L);
-      RovServo[2].write(rc_pwm_R);
-      Serial.print("Left=");
-      Serial.print(rc_pwm_L);
-      Serial.print("  Right=");
-      Serial.println(rc_pwm_R);
-    }
-    //좌회전
-    if( ch == 'a' )
-    {
-      rc_pwm_L = constrain(rc_pwm_L--, 0, 1000);
-      rc_pwm_R = constrain(rc_pwm_R++, 0, 1000);
-      RovServo[0].write(rc_pwm_L);    //좌측모터 출력 감소
-      RovServo[2].write(rc_pwm_R);    //우측모터 출력 증가
-      Serial.print("Left=");
-      Serial.print(rc_pwm_L);
-      Serial.print("  Right=");
-      Serial.println(rc_pwm_R);
-    }
-    //우회전
-    if( ch == 'd' )
-    {
-      rc_pwm_L = constrain(rc_pwm_L++, 0, 1000);
-      rc_pwm_R = constrain(rc_pwm_R--, 0, 1000);
-      RovServo[0].write(rc_pwm_L);   // 좌측모터 출력 증가
-      RovServo[2].write(rc_pwm_R);    //우측모터 출력 감소
-      Serial.print("Left=");
-      Serial.print(rc_pwm_L);
-      Serial.print("  Right=");
-      Serial.println(rc_pwm_R);
-    }
-    //상단모터 가속
-    if( ch == 'q' )
-    {
-      rc_pwm_C = constrain(rc_pwm_C++, 0, 1000);
-      RovServo[1].write(rc_pwm_C);
-      Serial.print("Center=");
-      Serial.println(rc_pwm_C);
-    }
-    //상단모터 감속
-    if( ch == 'e' )
-    {
-      rc_pwm_C = constrain(rc_pwm_C--, 0, 1000);
-      RovServo[1].write(rc_pwm_C);
-      Serial.print("Center=");
-      Serial.println(rc_pwm_C);
-    }
-    if(ch == 'b')
-    {
-      led_L = constrain(led_L+=255, 0, 65535);
-      led_R = constrain(led_R+=255, 0, 65535);
-      analogWrite(LED_PIN_L, led_L);
-      analogWrite(LED_PIN_R, led_R);
-      Serial.print("brighteness++");
-      Serial.print(led_L);
-      Serial.print("+++");
-      Serial.println(led_R);
-    }
-    if(ch == 'v')
-    {
-      led_L = constrain(led_L-=255, 0, 65535);
-      led_R = constrain(led_R-=255, 0, 65535);
-      analogWrite(LED_PIN_L, led_L);
-      analogWrite(LED_PIN_R, led_R);
-      Serial.println("brighteness--");
-      Serial.print(led_L);
-      Serial.print("+++");
-      Serial.println(led_R);
-    }
-  }
-}
-
 void process_recv_cmd( void )
 {
   bool Ret;
@@ -254,14 +140,14 @@
         break;
     }
   }
-  else
+  /*else
   {
     if( (tTime-millis()) >= 1000 )
     {
       IsConnected = false;
     }
     tTime = millis();
-  }
+  }*/
 }

 void send_cmd_info( void )
@@ -286,7 +172,7 @@
     Pwm[0] = (pCmd->Data[8]<<8) | (pCmd->Data[7]);
     Serial.print("Moter_L : ");
     Serial.println(Pwm[0]);
-    RovServo[RC_MOTOR_L].write(Pwm[0]);
+    RovServo[RC_MOTOR_L].writeMicroseconds(Pwm[0]);
   }
   //Moter_Center
   if(pCmd->Data[9] == 1)
@@ -294,7 +180,7 @@
     Pwm[1] = (pCmd->Data[11]<<8) | (pCmd->Data[10]);
     Serial.print("Moter_C : ");
     Serial.println(Pwm[1]);
-    RovServo[RC_MOTOR_C].write(Pwm[1]);
+    RovServo[RC_MOTOR_C].writeMicroseconds(Pwm[1]);
   }
   //Moter_Right
   if(pCmd->Data[12] == 1)
@@ -302,7 +188,7 @@
     Pwm[2] = (pCmd->Data[14]<<8) | (pCmd->Data[13]);
     Serial.print("Moter_R : ");
     Serial.println(Pwm[2]);
-    RovServo[RC_MOTOR_R].write(Pwm[2]);
+    RovServo[RC_MOTOR_R].writeMicroseconds(Pwm[2]);
   }

@@ -324,3 +210,38 @@
     analogWrite(LED_PIN_R, Led[1]);
   }
 }
+
+
+//---------RCtest(control Motor & LED by using USB serial)---------
+
+void rc_usb_test()
+{
+  char ch;
+  static uint16_t  rc_pwm = 1000;
+
+  if( Serial.available() )
+  {
+    ch = Serial.read();
+
+    if( ch == 'p' )
+    {
+      rc_pwm = 1000;
+      RovServo[RC_MOTOR_C].writeMicroseconds(rc_pwm);
+      Serial.println("Pwm = 0");
+    }
+
+    if( ch == 'w' )
+    {
+      rc_pwm = constrain(rc_pwm++, 1000, 2000);
+      RovServo[RC_MOTOR_C].writeMicroseconds(rc_pwm);
+      Serial.println(rc_pwm);
+    }
+
+    if( ch == 's' )
+    {
+      rc_pwm = constrain(rc_pwm--, 1000, 2000);
+      RovServo[RC_MOTOR_C].writeMicroseconds(rc_pwm);
+      Serial.println(rc_pwm);
+    }
+  }
+}


Changed BLE device name to 🍣

Changed BLE device name to 🍣

--- CurieIMU/CurieIMU.ino
+++ CurieIMU/CurieIMU.ino
@@ -18,7 +18,7 @@
   CurieIMU.setAccelerometerRange(2);

   // Setting for BLE device
-  blePeripheral.setLocalName("IMUTestSketch");
+  blePeripheral.setLocalName("🍣");
   blePeripheral.setAdvertisedServiceUuid(IMUService.uuid());
   blePeripheral.addAttribute(IMUService);
   blePeripheral.addAttribute(IMUAXChar);


Update

Update

Signed-off-by: Abraham Arce <1dfe57b55ce8f50c56dfae5c09e251b17f16c0ac@gmail.com>

--- Kanki/device/main.ino
+++ Kanki/device/main.ino
@@ -0,0 +1,89 @@
+/*
+  This a simple example of the aREST Library for the ESP8266 WiFi chip.
+  See the README file for more details.
+
+  Written in 2015 by Marco Schwartz under a GPL license.
+*/
+
+// Import required libraries
+#include <ESP8266WiFi.h>
+#include <aREST.h>
+
+// Create aREST instance
+aREST rest = aREST();
+
+// WiFi parameters
+const char* ssid = "";
+const char* password = "";
+
+// The port to listen for incoming TCP connections
+#define LISTEN_PORT           80
+
+// Create an instance of the server
+WiFiServer server(LISTEN_PORT);
+
+// Variables to be exposed to the API
+int temperature;
+int humidity;
+
+// Declare functions to be exposed to the API
+int ledControl(String command);
+
+void setup(void)
+{
+  // Start Serial
+  Serial.begin(115200);
+
+  // Init variables and expose them to REST API
+  temperature = 24;
+  humidity = 40;
+  rest.variable("temperature",&temperature);
+  rest.variable("humidity",&humidity);
+
+  // Function to be exposed
+  rest.function("led",ledControl);
+
+  // Give name & ID to the device (ID should be 6 characters long)
+  rest.set_id("1");
+  rest.set_name("esp8266");
+
+  // Connect to WiFi
+  WiFi.begin(ssid, password);
+  while (WiFi.status() != WL_CONNECTED) {
+    delay(500);
+    Serial.print(".");
+  }
+  Serial.println("");
+  Serial.println("WiFi connected");
+
+  // Start the server
+  server.begin();
+  Serial.println("Server started");
+
+  // Print the IP address
+  Serial.println(WiFi.localIP());
+}
+
+void loop() {
+
+  // Handle REST calls
+  WiFiClient client = server.available();
+  if (!client) {
+    return;
+  }
+  while(!client.available()){
+    delay(1);
+  }
+  rest.handle(client);
+
+}
+
+// Custom function accessible by the API
+int ledControl(String command) {
+
+  // Get state from command
+  int state = command.toInt();
+
+  digitalWrite(13,HIGH);
+  return 1;
+}


add test code

add test code

--- arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/dynamixel/dynamixel.ino
+++ arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/dynamixel/dynamixel.ino
@@ -0,0 +1,83 @@
+#include <OMDynamixel.h>
+#include <vector>
+
+#define DXL_SIZE 3
+#define BAUD_RATE 57600
+
+#define DEG2RAD (M_PI / 180.0)
+#define RAD2DEG (180.0 / M_PI)
+
+std::vector<float> goal_position;
+std::vector<float> present_position;
+
+OMDynamixel dxl(BAUD_RATE);
+
+void setup()
+{
+  Serial.begin(57600);
+  while(!Serial);
+
+  dxl.init();
+  dxl.setMaxPositionLimit(1, 180*DEG2RAD);
+  dxl.setMinPositionLimit(1, -180*DEG2RAD);
+
+  dxl.enableAllDynamixel();
+
+  goal_position.reserve(DXL_SIZE);
+  goal_position.push_back(90.0f * DEG2RAD);
+  goal_position.push_back(90.0f * DEG2RAD);
+  goal_position.push_back(90.0f * DEG2RAD);
+
+  present_position.reserve(DXL_SIZE);
+}
+
+void loop()
+{
+  dxl.setAngle(goal_position);
+
+  do
+  {
+    present_position = dxl.getAngle();
+
+    log();
+  }while(abs(dxl.convertRadian2Value(1, goal_position.at(0)) - dxl.convertRadian2Value(1, present_position.at(0))) > 5);
+
+  swap();
+}
+
+void log()
+{
+  Serial.print("[");
+  for (int8_t index = 0; index < DXL_SIZE; index++)
+  {
+    Serial.print("ID : ");
+    Serial.print(dxl.getDynamixelIDs().at(index));
+    Serial.print(" GoalPos: ");
+    Serial.print(dxl.convertRadian2Value(1, goal_position.at(index)));
+    Serial.print(" PresPos: ");
+    Serial.print(dxl.convertRadian2Value(1, present_position.at(index)));
+    Serial.print(" | ");
+  }
+  Serial.println("]");
+}
+
+void swap()
+{
+  static bool flag = true;
+  goal_position.clear();
+
+  if (flag == true)
+  {
+    goal_position.push_back(-90.0f * DEG2RAD);
+    goal_position.push_back(-90.0f * DEG2RAD);
+    goal_position.push_back(-90.0f * DEG2RAD);
+  }
+  else
+  {
+    goal_position.push_back(90.0f * DEG2RAD);
+    goal_position.push_back(90.0f * DEG2RAD);
+    goal_position.push_back(90.0f * DEG2RAD);
+  }
+
+  flag = !flag;
+}


-Removed Serial.

-Removed Serial.

--- aquacontrol32.ino
+++ aquacontrol32.ino
@@ -284,7 +284,7 @@

   btStop();

-  Serial.begin( 115200 );
+  //Serial.begin( 115200 );
   ESP_LOGI( TAG, "aquacontrol32 %s", SKETCH_VERSION );
   ESP_LOGI( TAG, "ESP32 SDK: %s", ESP.getSdkVersion() );


-Added link to stickbreakers OneWire library.

--- aquacontrol32.ino
+++ aquacontrol32.ino
@@ -4,6 +4,7 @@
 #include <Preferences.h>           /* should be installed together with ESP32 Arduino install */
 #include "Adafruit_ILI9341.h"      /* Install via 'Manage Libraries' in Arduino IDE */
 #include "OneWire.h"               /* Install via 'Manage Libraries' in Arduino IDE */
+/* or use stickbreakers library:      https://github.com/stickbreaker/OneWire */
 #include "SSD1306.h"               /* https://github.com/squix78/esp8266-oled-ssd1306 */
 #include <AsyncTCP.h>              /* https://github.com/me-no-dev/ESPAsyncTCP */
 #include <ESPAsyncWebServer.h>     /* https://github.com/me-no-dev/ESPAsyncWebServer */


Forgot to sync beforehand haha

Forgot to sync beforehand haha

A few of my changes ended up being redundant haha… Fixed the code
attribution because your name was erased w/ the last commit

--- FlightCode/FlightCode.ino
+++ FlightCode/FlightCode.ino
@@ -1,43 +1,7 @@
 /*
-<<<<<<< Updated upstream
- * Notre Dame Rocket Team Roll Control Payload Master Code V. 0.91
- * Aidan McDonald, 2/1/17
- * Kyle Miller, 2/2/17
- *
- * Most recent changes:
- * Moved the GPS enable code again, to <600 ft post-apogee
- * Incorporated receiving data from the ground station
-    * Added two master flags to control sensor enabling and fin control disabling
- * Revised the data transmission section to send altitude data when gps/gyro data isn't being sent
- * Changed Pin Variables to match what the inputs to the servo will be
- *
- * To-dones:
-  * Basic switch-case structure
-  * Incorporation of Adafruit sensor code
-  * Added GPS functionality
-  * Integration of radio-transmission/reception code
-  * Datalogging capacity (untested)
-  * Running-average calcs for critical sensor values and Simpson's Rule integration of gyro data
-  * Multi-sensor verification of flight progress switch-case transitions (untested)
-  * Github Sync system working
-  * Packet transmission/reception over radio (ADD THIS TO GROUND STATION CODE TOO!!)
- *
- * To-dos:
-  * Reconfigure the servo control for the new control scheme!!!!!!!
-  * Revise and enhance the staging/thresholds, particularly burnout/apogee accel values
-  * Reconfigure the SD datalogging section to allow for easy spreadsheet conversion
-  * TEST EVERYTHING
-  * NO REALLY, EVERYTHING
-   *  Ada Sensors
-   *  SD Saving
-   *  Servo Control
-   *  Flight Staging
-   *  Etc., etc.
- *
- */
-=======
    Notre Dame Rocket Team Roll Control Payload Master Code V. 1.0.0
    Aidan McDonald, 2/4/17
+   Kyle Miller, 2/2/17

    Most recent changes:
    Reconfigured the roll control subroutine for the new, increment-based servo mode
@@ -70,7 +34,6 @@
       Etc., etc.

 */
->>>>>>> Stashed changes

 #include <Wire.h>
 #include <SPI.h>
@@ -130,12 +93,6 @@
 long flightTime = 0;

 //Constants for servo pin output
-<<<<<<< Updated upstream
-const int controlPin = 0; //"control" is the master switch- must be 1 to enable servo, pulse this pin to trigger a move
-const int inputA = 1; //The inputA and inputB pins control which way the fins will increment when the move is triggered
-const int inputB = 2; //inputA = 0, inputB = 0 is +4 Degrees, inputA = 1, inputB = 0 is -4 Degrees, inputA = 0, inputB = 1 is +8 Degrees,
-					  // inputA = 1, inputB = 1 is -8 Degrees
-=======
 const int controlPin = 0; //"control" is the pin which is pulsed to trigger the servo to move
 const int statePinA = 1; //The state of pins A and B determines which of four motions the servo takes when the control pin is pulsed.
 const int statePinB = 2; // If B is low, move 1 position, if B is high, move two positions. High A is negative (counterclockwise?), low A is positive (clockwise?)
@@ -143,7 +100,6 @@
 const int CENTER = 1;
 const int RIGHT = 2;
 int finPosition = CENTER; //Since the servo moves based on increments and not absolute positions, these constants and variable are needed to track the fins' position.
->>>>>>> Stashed changes

 //Constants for flight staging
 const int waiting = 0;
@@ -183,29 +139,16 @@
   digitalWrite(RFM95_RST, HIGH);

   pinMode(controlPin, OUTPUT);
-<<<<<<< Updated upstream
-  pinMode(inputA, OUTPUT);
-  pinMode(inputB, OUTPUT);
-=======
   pinMode(statePinA, OUTPUT);
   pinMode(statePinB, OUTPUT);
->>>>>>> Stashed changes

   accel.begin();
   bmp.begin();
   gyro.enableAutoRange(true);
   gyro.begin();
   SD.begin(cardSelectPin);//Initialize the sensors and SD card
-<<<<<<< Updated upstream
-
-  digitalWrite(controlPin, HIGH); //Enable servo
-  servoOnFlag = true;
-  digitalWrite(inputA, HIGH); //Set servo to "home" position
-  servoHomeFlag = true;
-=======

   digitalWrite(controlPin, LOW); //Set the servo control pin to low to make sure it doesn't pulse accidentally
->>>>>>> Stashed changes

   //Manual radio reset
   digitalWrite(RFM95_RST, LOW);
@@ -315,26 +258,6 @@

 void Roll_Control(sensors_event_t event) {

-<<<<<<< Updated upstream
-  if(!startRollFlag) { //For roll initialization, cant fins in the direction of current roll
-    digitalWrite(inputA, LOW);
-    servoHomeFlag = false;
-    startRollFlag = true;
-    if(event.gyro.z > 0) {
-      digitalWrite(inputB, HIGH);
-      finState = true;
-    }
-    else {
-      digitalWrite(inputB, LOW);
-      finState = false;
-    }
-  }
-  else if(!endRollFlag) { //Wait until two revolutions have been completed to begin counter-roll
-
-    if(rotationCounter > 2) {
-      finState = !finState;
-      digitalWrite(inputB, finState);
-=======
   if (!startRollFlag) { //For roll initialization, cant fins in the direction of current roll
     startRollFlag = true;
     if (event.gyro.z > 0) {
@@ -348,32 +271,12 @@

     if (rotationCounter > 2) {
       Set_Servo(finPosition, abs(finPosition - 2)); //This will output LEFT if finPosition = RIGHT, and vice-versa
->>>>>>> Stashed changes
       endRollFlag = true;
     }
   }
   else { //At this point, continue to make adjustments to prevent roll
     if (abs(event.gyro.z) < MIN_ROLL_THRESHOLD)
     {
-<<<<<<< Updated upstream
-      digitalWrite(inputA, HIGH);
-      servoHomeFlag = true;
-    }
-    else if(event.gyro.z > 0)
-      {
-      digitalWrite(inputA, LOW);
-      servoHomeFlag = false;
-      digitalWrite(inputB, LOW);
-      finState = false;
-      }
-    else if(event.gyro.z < 0)
-      {
-      digitalWrite(inputA, LOW);
-      servoHomeFlag = false;
-      digitalWrite(inputB, HIGH);
-      finState = true;
-      }
-=======
       Set_Servo(finPosition, CENTER);
     }
     else if (event.gyro.z > 0) //Again, this assumes positive gyro values are clockwise.
@@ -384,7 +287,6 @@
     {
       Set_Servo(finPosition, LEFT);
     }
->>>>>>> Stashed changes
   }

 }


full information about 595 shift register

--- ksp-gegi-mini/ksp-gegi-mini.ino
+++ ksp-gegi-mini/ksp-gegi-mini.ino
@@ -11,7 +11,9 @@
 // 17=A3 RCK(12)   // latch
 // /SRCLR(8) -> +5V
 // /G (9) -> GND
-// /DRAINx = GND od LEDa (LED niebieskie, bez rezystora, krótka nożka do drain; białe, z rezystorem, długa nóżka do +5V)
+// VCC (2) -> +5V
+// GND (19,10,11) -> GND
+// /DRAINx (4,5,6,7;14,15,16,17) = GND od LEDa (LED niebieskie, bez rezystora, krótka nożka do drain; białe, z rezystorem, długa nóżka do +5V)

 // UART:
 // receive commands like: ^L{GR}{id}={val}$


Repair Arduino compilation.

Repair Arduino compilation.

--- mech/mech.ino
+++ mech/mech.ino
@@ -5,7 +5,7 @@
 // Measured 2964 steps 360 degrees revolution.

 #include "proto/device_id.h"  // communication protocol device ID
-#include <AccelStepper.h>     / Accel Stepper library
+#include <AccelStepper.h>     // Accel Stepper library

 #define PJON_ID ID_MECH       // PJON definition (communication protocol)
 #include "proto/common.h"     // communication protocol library
@@ -22,6 +22,33 @@
 const byte optInpinL = A1;  // Signal pin Optical Interruptor Motor 1
 const byte optInpinC1 = A2;  // Signal pin Optical Interruptor Motor 2
 const byte optInpinC2 = A3;  // Signal pin Optical Interruptor Motor 3 C2
+
+
+void calibrate(AccelStepper *chanel, uint8_t sensorPin, boolean run) {
+  long oldPosition = chanel->currentPosition();
+  chanel->setSpeed(-2000);
+  while (digitalRead(sensorPin) == LOW) {
+    chanel->runSpeed();
+    busLoop();
+  }
+  chanel->stop();
+  chanel->setCurrentPosition(0);
+  if (run) {
+    chanel->moveTo(oldPosition);
+  }
+}
+
+void inline calibrateL(boolean run) {
+  calibrate(&stepperL, optInpinL, run);
+}
+
+void inline calibrateC1(boolean run) {
+  calibrate(&stepperC1, optInpinC1, run);
+}
+
+void inline calibrateC2(boolean run) {
+  calibrate(&stepperC2, optInpinC2, run);
+}

 void busReceiver(const TCommand *payload, const PJON_Packet_Info &packet_info) {
 	switch (payload->id) {
@@ -103,18 +130,23 @@
 }

 void optimize(AccelStepper *chanel, int16_t step, int16_t hysteresis) {
+  boolean isFirstStep = true;
   yeld();
   uint16_t prevSetepPwr = rflPwrVal;
   while (step != 0) {
     chanel->move(step);
     yeld();
     if (prevSetepPwr < (rflPwrVal + hysteresis)) {
-      step = -(step >> 1);
+      step = -step;
+      if (!isFirstStep) {
+        step = step >> 1;
+      }
     }
     prevSetepPwr = rflPwrVal;
     if ((fwdPwrVal == 0) || (rflPwrVal == 0)) {
       break;
     }
+    isFirstStep = false;
   }
 }

@@ -141,32 +173,6 @@
   optimize(&stepperC2, 10, 0);
   optimize(&stepperC1, 10, 0);
   isAutoTune = 0;
-}
-
-void calibrate(AccelStepper *chanel, uint8_t sensorPin, boolean run) {
-  long oldPosition = chanel->currentPosition();
-  chanel->setSpeed(-2000);
-  while (digitalRead(sensorPin) == LOW) {
-    chanel->runSpeed();
-    busLoop();
-  }
-  chanel->stop();
-  chanel->setCurrentPosition(0);
-  if (run) {
-    chanel->moveTo(oldPosition);
-  }
-}
-
-void inline calibrateL(boolean run) {
-  calibrate(&stepperL, optInpinL, run);
-}
-
-void inline calibrateC1(boolean run) {
-  calibrate(&stepperC1, optInpinC1, run);
-}
-
-void inline calibrateC2(boolean run) {
-  calibrate(&stepperC2, optInpinC2, run);
 }

 void updateStatus() {


tx: only send BusVolt/Current

tx: only send BusVolt/Current

Signed-off-by: Robert Nelson <d6c41255011d14bfa93d8562b946ca186cfa0c7b@gmail.com>

--- ws_bm_rtc.ino
+++ ws_bm_rtc.ino
@@ -81,60 +81,75 @@
 	shuntvoltage_A = ina219_A.getShuntVoltage_mV();
 	busvoltage_A = ina219_A.getBusVoltage_V();
 	current_mA_A = ina219_A.getCurrent_mA();
-	loadvoltage_A = busvoltage_A + (shuntvoltage_A / 1000);
+//	loadvoltage_A = busvoltage_A + (shuntvoltage_A / 1000);

 	shuntvoltage_B = ina219_B.getShuntVoltage_mV();
 	busvoltage_B = ina219_B.getBusVoltage_V();
 	current_mA_B = ina219_B.getCurrent_mA();
-	loadvoltage_B = busvoltage_B + (shuntvoltage_B / 1000);
+//	loadvoltage_B = busvoltage_B + (shuntvoltage_B / 1000);

 	Serial1.print("$LOAD:");
 	Serial1.print(now.unixtime());
-	Serial1.print(":BusVolt:"); Serial1.print(busvoltage_A); Serial1.println("V*");
+	Serial1.print(":BusVolt:");
+	Serial1.print(busvoltage_A);
+	Serial1.println("V*");
 	delay(ws_short_delay);
+
+//	Serial1.print("$LOAD:");
+//	Serial1.print(now.unixtime());
+//	Serial1.print(":ShuntVolt:");
+//	Serial1.print(shuntvoltage_A);
+//	Serial1.println("mV*");
+//	delay(ws_short_delay);
+
+//	Serial1.print("$LOAD:");
+//	Serial1.print(now.unixtime());
+//	Serial1.print(":LoadVolt:");
+//	Serial1.print(loadvoltage_A);
+//	Serial1.println("V*");
+//	delay(ws_short_delay);

 	Serial1.print("$LOAD:");
 	Serial1.print(now.unixtime());
-	Serial1.print(":ShuntVolt:"); Serial1.print(shuntvoltage_A); Serial1.println("mV*");
-	delay(ws_short_delay);
-
-	Serial1.print("$LOAD:");
-	Serial1.print(now.unixtime());
-	Serial1.print(":LoadVolt:"); Serial1.print(loadvoltage_A); Serial1.println("V*");
-	delay(ws_short_delay);
-
-	Serial1.print("$LOAD:");
-	Serial1.print(now.unixtime());
-	Serial1.print(":Current:"); Serial1.print(current_mA_A); Serial1.println("mA*");
+	Serial1.print(":Current:");
+	Serial1.print(current_mA_A);
+	Serial1.println("mA*");
 	delay(ws_short_delay);

 	delay(ws_short_delay);

 	Serial1.print("$CHARGER:");
 	Serial1.print(now.unixtime());
-	Serial1.print(":BusVolt:"); Serial1.print(busvoltage_B); Serial1.println("V*");
+	Serial1.print(":BusVolt:");
+	Serial1.print(busvoltage_B);
+	Serial1.println("V*");
 	delay(ws_short_delay);
+
+//	Serial1.print("$CHARGER:");
+//	Serial1.print(now.unixtime());
+//	Serial1.print(":ShuntVolt:");
+//	Serial1.print(shuntvoltage_B);
+//	Serial1.println("mV*");
+//	delay(ws_short_delay);
+
+//	Serial1.print("$CHARGER:");
+//	Serial1.print(now.unixtime());
+//	Serial1.print(":LoadVolt:");
+//	Serial1.print(loadvoltage_B);
+//	Serial1.println("V*");
+//	delay(ws_short_delay);

 	Serial1.print("$CHARGER:");
 	Serial1.print(now.unixtime());
-	Serial1.print(":ShuntVolt:"); Serial1.print(shuntvoltage_B); Serial1.println("mV*");
-	delay(ws_short_delay);
+	Serial1.print(":Current:");
+	Serial1.print(current_mA_B);
+	Serial1.println("mA*");

-	Serial1.print("$CHARGER:");
-	Serial1.print(now.unixtime());
-	Serial1.print(":LoadVolt:"); Serial1.print(loadvoltage_B); Serial1.println("V*");
-	delay(ws_short_delay);
-
-	Serial1.print("$CHARGER:");
-	Serial1.print(now.unixtime());
-	Serial1.print(":Current:"); Serial1.print(current_mA_B); Serial1.println("mA*");
 	Serial1.println("");
-	delay(ws_short_delay);
 	delay(ws_short_delay);

 	delay(ws_one_second);
 	delay(ws_one_second);
 	delay(ws_one_second);
+	delay(ws_one_second);
 }
-
-


Added user input

Added user input

--- src/src.ino
+++ src/src.ino
@@ -29,7 +29,8 @@
   pinMode (BUTTON_PIN, INPUT);
   pinMode(LED_PIN, OUTPUT);
   randomSeed(analogRead(0));
-  //timer.every(30, ButtonPressScan);
+  running = false
+  timer.every(30, ButtonPressScan);
   GameStart(true);
 }

@@ -37,7 +38,7 @@
 {
   if (ask)
   {
-    //running = !running;
+    running = true;
     game.pipe1.Xcrd = 7;
     game.pipe1.parts = PipeGen();
     game.pipe2.Xcrd = 7;
@@ -47,7 +48,7 @@
   }
   else
   {
-    running = !running;
+    running = false;
     timer.stop(Update);
     timer.stop(Pipe1MoveTimer);
     timer.stop(Pipe2MoveTimer);
@@ -120,6 +121,31 @@
   byte holeBits = (1 << hole) - 1;
   byte offset = random(1, 8 - hole);
   return 0xff & ~(holeBits << offset);
+}
+
+void ButtonPressScan()
+{
+  static boolean init = false;
+  boolean ButtonPress = digitalRead(BUTTON_PIN);
+
+  if (ButtonPress)
+  {
+    if (running = true)
+    {
+
+      if (!init)
+      {
+     	//change bird pos
+      }
+    }
+    else
+    {
+      transition();
+      startGame(true);
+    }
+  }
+  init = ButtonPress;
+  digitalWrite(LED_PIN, ButtonPress);
 }


Refactoring for clarity and DRYness.

Refactoring for clarity and DRYness.

--- teensy-stim/teensy-stim.ino
+++ teensy-stim/teensy-stim.ino
@@ -4,11 +4,6 @@

 #include <EEPROM.h>
 #include <math.h>
-
-int eepsigN = 8;
-int idN = 12;
-int eN = eepsigN + idN;
-byte* eepsig = (byte*)"stim1.0 ";

 int lo = LOW;
 int hi = HIGH;
@@ -23,10 +18,6 @@
 int digi[DIG];

 int16_t wave[256];
-
-#define CLIP(i, lo, hi) ((i < lo) ? lo : ((i > hi) ? hi : i))
-#define HEXTRI(i) (i + ((i < 10) ? '0' : '7'))
-#define DEHEXT(i) (i - ((i > '9') ? '7' : '0'))

 struct Dura {
   int s;
@@ -41,9 +32,9 @@
   Dura p;    // Pulse time
   Dura q;    // Pulse off time
   byte i;    // Invert? 0 = no
-  byte s;    // What is this for?
+  byte s;    // Shape: 0 = digital, 1 = sinusoidal, 2 = triangular
   byte next; // Number of next protocol, 255 = none
-  byte unused0;
+  byte used; // 0 = unused, otherwise (channel # + 1)
 };

 struct Channel {
@@ -60,20 +51,32 @@
   byte unused1;
 };

-int protoi = 0;
-Protocol protocols[PROT];
+int protoi = 0;            // Index of next empty protocol slot
+int proton = 0;            // Total number of protocols
+Protocol protocols[PROT];  // Slots for protocols (not necessarily contiguous)

 Channel channels[CHAN];

 int errormsgN = 12;
 byte errormsg[12];

-int whoamiN = 0;
-byte whoami[24];
-
-int bufi;
-int bufN = 63;
-byte buf[63];
+int eepsigN = 8;                    // Stimulator signature size
+byte* eepsig = (byte*)"stim1.0 ";   // Expected string
+int idN = 12;                       // Size of identifying string that follows
+int eN = eepsigN + idN;             // Whole identifier (stim + name)
+int whoamiN = 0;                    // Size of string returned to client
+byte whoami[24];                    // ~ + eepsig + id + $ + zero terminator
+
+int bufi = 0;    // Input buffer index
+int bufN = 63;   // Input buffer size
+byte buf[63];    // Input buffer
+void shiftbuf(int n) {
+  if (n > 0) {
+    for (int i = n, j = 0; i < bufi; i++, j++) buf[j] = buf[i];
+    bufi = (n >= bufi) ? 0 : bufi - n;
+  }
+}
+

 int tick;               // Last clock tick (microseconds), used to update time
 Dura global_clock;      // Counts up from the start of protocols
@@ -85,8 +88,13 @@
   sei();
 }

-Dura blinking;
-volatile bool blink_is_on;
+Dura blinking;              // Countdown timer for blinking
+volatile bool blink_is_on;  // State reflecting whether blink is on or off
+
+
+/***************************************************
+** Initialization code -- run once only at start! **
+***************************************************/

 void read_my_eeprom() {
   // Make sure the EEPROM corresponds to the expected device
@@ -151,28 +159,6 @@
   for (int i = 0; i < digiN; i++) pinMode(digi[i], OUTPUT);
 }

-void advance(Dura *x, int us) {
-  x->u += us;
-  while (x->u >= 1000000) { x->u -= 1000000; x->s += 1; }
-}
-
-void advance_from(Dura *x, Dura v) {
-  x->u += v.u;
-  x->s += v.s;
-  while (x->u >= 1000000) { x->u -= 1000000; x->s += 1; }
-}
-
-void diminish(Dura *x, int us) {
-  x->u -= us;
-  while (x->u < 0) { x->u += 1000000; x->s -= 1; }
-}
-
-void diminish_by(Dura *x, Dura v) {
-  x->u -= v.u;
-  x->s -= v.s;
-  while (x->u < 0) { x->u += 1000000; x->s -= 1; }
-}
-
 // Setup runs once at reset / power on
 void setup() {
   running = 0;
@@ -196,6 +182,92 @@
   bufi = 0;
 }

+
+/********************************
+** Number manipulation and I/O **
+*********************************/
+
+#define CLIP(i, lo, hi) ((i < lo) ? lo : ((i > hi) ? hi : i))
+
+#define HEXTRI(i) (i + ((i < 10) ? '0' : '7'))
+
+#define DEHEXT(i) (i - ((i > '9') ? '7' : '0'))
+
+void six_write(int value, byte *target) {
+  for (int i = 5; i >= 0; i--, value /= 10) target[i] = '0'+(value%10);
+}
+
+int six_read(byte *target) {
+  int s = 0;
+  for (int i = 0; i < 6; i++) {
+    byte c = target[i];
+    if (c < '0' || c > '9') return -1;
+    s = 10*s + (c-'0');
+  }
+  return s;
+}
+
+
+/************************************
+** Manipulation and I/O of timings **
+************************************/
+
+void advance(Dura *x, int us) {
+  x->u += us;
+  while (x->u >= 1000000) { x->u -= 1000000; x->s += 1; }
+}
+
+void advance_from(Dura *x, Dura v) {
+  x->u += v.u;
+  x->s += v.s;
+  while (x->u >= 1000000) { x->u -= 1000000; x->s += 1; }
+}
+
+void diminish(Dura *x, int us) {
+  x->u -= us;
+  while (x->u < 0) { x->u += 1000000; x->s -= 1; }
+}
+
+void diminish_by(Dura *x, Dura v) {
+  x->u -= v.u;
+  x->s -= v.s;
+  while (x->u < 0) { x->u += 1000000; x->s -= 1; }
+}
+
+void seven_write(Dura t, byte *target) {
+  if (t.s >= 1000) {
+    six_write(t.s, target);
+    target[6] = 's';
+  }
+  else if (t.s >= 1) {
+    six_write(t.s*1000 + t.u/1000, target);
+    target[6] = 'm';
+  }
+  else {
+    if (t.s < 0 || t.u < 0) six_write(0, target);
+    else six_write(t.u, target);
+    target[6] = 'u';
+  }
+}
+
+Dura seven_read(byte *target) {
+  Dura dura;
+  int i = six_read(target);
+  if (i < 0) { dura.s = dura.u = -1; }
+  else {
+    if      (target[6] == 's') { dura.s = i; dura.u = 0; }
+    else if (target[6] == 'u') { dura.s = 0; dura.u = i; }
+    else if (target[6] == 'm') { dura.s = i/1000; dura.u = 1000*(i%1000); }
+    else                       { dura.s = -1; dura.u = -1; }
+  }
+  return dura;
+}
+
+
+/*************************************
+** Control of channel state machine **
+*************************************/
+
 void turn_off(Channel *ci) {
   Protocol *p = (protocols + ci->protocol);
   if (p->i == 0) digitalWrite(ci->pin, LOW);
@@ -224,38 +296,16 @@
   if (running > 0) running = 0;
 }

+
+/******************************
+** Generic parsing utilities **
+******************************/
+
 void die_with_message(const char *msg) {
-  // TODO--actually set state etc.
-}
-
-void six_in(int value, byte *target) {
-  for (int i = 5; i >= 0; i--, value /= 10) target[i] = '0'+(value%10);
-}
-
-int six_out(byte *target) {
-  int s = 0;
-  for (int i = 0; i < 6; i++) {
-    byte c = target[i];
-    if (c < '0' || c > '9') return -1;
-    s = 10*s + (c-'0');
-  }
-  return s;
-}
-
-void seven_in(Dura t, byte *target) {
-  if (t.s >= 1000) {
-    six_in(t.s, target);
-    target[6] = 's';
-  }
-  else if (t.s >= 1) {
-    six_in(t.s*1000 + t.u/1000, target);
-    target[6] = 'm';
-  }
-  else {
-    if (t.s < 0 || t.u < 0) six_in(0, target);
-    else six_in(t.u, target);
-    target[6] = 'u';
-  }
+  int n = strnlen(msg, 63);
+  halt_channels();
+  Serial.write(msg, n);
+  Serial.send_now();
 }

 void parse_time_error() {
@@ -265,29 +315,57 @@
 }

 Dura parse_time(byte *target) {
-  Dura result;
-  result.s = 0;
-  result.u = 0;
-  int s = six_out(target);
-  if (s < 0) parse_time_error();
-  else {
-    byte c = target[6];
-    if (c == 's') result.s = s;
-    else if (c == 'u') result.u = s;
-    else if (c == 'm') { result.s = s/1000; result.u = s%1000; }
-    else parse_time_error();
-  }
+  Dura result = seven_read(target);
+  if (result.s < 0) parse_time_error();
   return result;
 }

-volatile int count_me;
-
-void shiftbuf(int n) {
-  if (n > 0) {
-    for (int i = n, j = 0; i < bufi; i++, j++) buf[j] = buf[i];
-    bufi = (n >= bufi) ? 0 : bufi - n;
-  }
-}
+void write_now(byte *msg, int n) {
+  Serial.write(msg, n);
+  Serial.send_now();
+}
+
+void raise_unknown_command_error(byte cmd, byte chan) {
+  shiftbuf(2);
+  halt_channels();
+  running = -1;
+  memcpy(errormsg, "unknown", 7);
+  memset(errormsg + 7, ' ', errormsgN - 7);
+  errormsg[8] = cmd;
+  errormsg[10] = chan;
+}
+
+Protocol not_a_protocol;
+
+Protocol* ensure_protocol(Channel *ch) {
+  // TODO--make something that works
+  return &not_a_protocol;
+}
+
+bool assert_not_running(Channel *ch) {
+  // TODO--make this check something
+  return false;
+}
+
+bool assert_is_wave(Channel *ch) {
+  // TODO--make this check something
+  return false;
+}
+
+bool assert_is_digital(Channel *ch) {
+  // TODO--make this check something
+  return false;
+}
+
+void set_channel_shape(Channel *ch, byte shape) {
+  Protocol *p = ensure_protocol(ch);
+  if ((shape == 0 || assert_is_wave(ch)) && assert_not_running(ch)) p->s = shape;
+}
+
+
+/********************************************************
+** Interpretation of global commands with no arguments **
+********************************************************/

 void start_running() {
   shiftbuf(2);  // TODO--actually do something
@@ -299,8 +377,7 @@
   two[0] = '~';
   int r = running;
   two[1] = (r < 0) ? '$' : HEXTRI(r);
-  Serial.write(two, 2);
-  Serial.send_now();
+  write_now(two, 2);
 }

 void report_timing() {
@@ -318,35 +395,65 @@
     i += 14;
   }
   else {
-    six_in(global_clock.s, msg + i);
+    six_write(global_clock.s, msg + i);
     i += 6;
     msg[i++] = 's';
-    six_in(global_clock.u, msg + i);
+    six_write(global_clock.u, msg + i);
     i += 6;
     msg[i++] = 'u';
   }
-  Serial.write(msg, i);
+  write_now(msg, i);
+}
+
+void abort_and_reset() {
+  shiftbuf(2);
+  if (running > 0) halt_channels();
+  running = 0;
+}
+
+void reset_parameters() {
+  shiftbuf(2);  // TODO--actually do something
+}
+
+void report_identity() {
+  shiftbuf(2);
+  Serial.println(whoamiN, DEC);
+  Serial.write(whoami, whoamiN);
   Serial.send_now();
 }
+
+void report_pins() {
+  shiftbuf(2);
+  byte pinout[27];
+  int i = 0;
+  pinout[i++] = '~';
+  for (; i <= digiN; i++) pinout[i] = HEXTRI(digi[i-1]);
+  if (waveN > 0) pinout[i++] = '@';
+  pinout[i++] = '$';
+  Serial.write(pinout, i);
+  Serial.send_now();
+}
+
+
+/*****************************************************
+** Interpretation of global commands with arguments **
+*****************************************************/

 void shift_timing(int direction) {
   if (bufi >= 9) {
     Dura my_shift = parse_time(buf + 2);
     shiftbuf(9);
-    if (direction < 0) diminish_by(&pending_shift, my_shift);
-    else advance_from(&pending_shift, my_shift);
-  }
-}
-
-void raise_unknown_command_error(byte cmd, byte chan) {
-  shiftbuf(2);
-  halt_channels();
-  running = -1;
-  memcpy(errormsg, "unknown", 7);
-  memset(errormsg + 7, ' ', errormsgN - 7);
-  errormsg[8] = cmd;
-  errormsg[10] = chan;
-}
+    if (my_shift.s >= 0) {
+      if (direction < 0) diminish_by(&pending_shift, my_shift);
+      else advance_from(&pending_shift, my_shift);
+    }
+  }
+}
+
+
+/******************************************************************
+** Interpretation of channel-specific commands with no arguments **
+******************************************************************/

 void abort_channel(Channel *ch) {
   shiftbuf(3);
@@ -369,44 +476,18 @@
   // TODO--actually run the channel
 }

-void set_and_run_only_channel(Channel *ch) {
-  // TODO--actually do this
-}
-
-Protocol not_a_protocol;
-
-Protocol* ensure_protocol(Channel *ch) {
-  // TODO--make something that works
-  return &not_a_protocol;
-}
-
-bool assert_not_running(Channel *ch) {
-  // TODO--make this check something
-  return false;
-}
-
-bool assert_is_wave(Channel *ch) {
-  // TODO--make this check something
-  return false;
-}
-
-bool assert_is_digital(Channel *ch) {
-  // TODO--make this check something
-  return false;
-}
-
 void report_channel_protocol(Channel *ch) {
   shiftbuf(3);
   byte msg[45];
   int i = 0;
   msg[i++] = '~';
   Protocol *p = ensure_protocol(ch);
-  seven_in(p->t, msg+i); i += 7;
-  seven_in(p->d, msg+i); i += 7;
-  seven_in(p->y, msg+i); i += 7;
-  seven_in(p->n, msg+i); i += 7;
-  seven_in(p->p, msg+i); i += 7;
-  seven_in(p->q, msg+i); i += 7;
+  seven_write(p->t, msg+i); i += 7;
+  seven_write(p->d, msg+i); i += 7;
+  seven_write(p->y, msg+i); i += 7;
+  seven_write(p->n, msg+i); i += 7;
+  seven_write(p->p, msg+i); i += 7;
+  seven_write(p->q, msg+i); i += 7;
   msg[i++] = (p->i == 0) ? ';' : 'i';
   msg[i++] = (p->s == 0) ? ';' : ((p->s == 1) ? 's' : 'r');
   Serial.write(msg, i);
@@ -424,11 +505,6 @@
   if (assert_not_running(ch)) p->i = (p->i == 0) ? 255 : 0;
 }

-void set_channel_shape(Channel *ch, byte shape) {
-  Protocol *p = ensure_protocol(ch);
-  if ((shape == 0 || assert_is_wave(ch)) && assert_not_running(ch)) p->s = shape;
-}
-
 void make_sinusoidal(Channel *ch) {
   shiftbuf(3);
   set_channel_shape(ch, 1);
@@ -439,68 +515,39 @@
   set_channel_shape(ch, 2);
 }

-void set_channel_time(Channel *ch) {
+/******************************************************************
+** Interpretation of channel-specific commands with no arguments **
+******************************************************************/
+
+void set_a_duration(Channel *ch, size_t offset, bool isdig, bool iswave) {
   if (bufi >= 10) {
     Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch)) p->t = parse_time(buf + 3);
+    Dura *d = (Dura*)((size_t)(p) + offset);
+    if (assert_not_running(ch) && (!isdig || assert_is_digital(ch)) && (!iswave || assert_is_wave(ch))) *d = parse_time(buf+3);
     shiftbuf(10);
   }
 }

-void set_channel_delay(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch)) p->d = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
-
-void set_channel_stim_on(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch)) p->y = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
-
-void set_channel_stim_off(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch)) p->n = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
-
-void set_channel_pulse_on(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch) && assert_is_digital(ch)) p->p = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
-
-void set_channel_pulse_off(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch) && assert_is_digital(ch)) p->q = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
-
-void set_channel_wave_period(Channel *ch) {
-  if (bufi >= 10) {
-    Protocol *p = ensure_protocol(ch);
-    if (assert_not_running(ch) && assert_is_wave(ch)) p->p = parse_time(buf + 3);
-    shiftbuf(10);
-  }
-}
+void set_channel_time(Channel *ch)        { set_a_duration(ch, offsetof(Protocol,t), false, false); }
+
+void set_channel_delay(Channel *ch)       { set_a_duration(ch, offsetof(Protocol,d), false, false); }
+
+void set_channel_stim_on(Channel *ch)     { set_a_duration(ch, offsetof(Protocol,y), false, false); }
+
+void set_channel_stim_off(Channel *ch)    { set_a_duration(ch, offsetof(Protocol,n), false, false); }
+
+void set_channel_pulse_on(Channel *ch)    { set_a_duration(ch, offsetof(Protocol,p), true, false); }
+
+void set_channel_pulse_off(Channel *ch)   { set_a_duration(ch, offsetof(Protocol,q), true, false); }
+
+void set_channel_wave_period(Channel *ch) { set_a_duration(ch, offsetof(Protocol,p), false, true); }

 void set_channel_wave_amplitude(Channel *ch) {
   if (bufi >= 10) {
     Protocol *p = ensure_protocol(ch);
     if (assert_not_running(ch) && assert_is_wave(ch)) {
       p->q.s = 0;
-      p->q.u = six_out(buf + 3);
+      p->q.u = six_read(buf + 3);
     }
     // TODO -- error message if u > 2047.
     shiftbuf(10);
@@ -517,7 +564,7 @@
     p->n = parse_time(buf + i); i += 7;
     p->p = parse_time(buf + i); i += 7;
     if (ch->pin != 255) p->q = parse_time(buf + i);
-    else { p->q.u = six_out(buf + i); p->q.s = 0; }
+    else { p->q.u = six_read(buf + i); p->q.s = 0; }
     i += 7;
     byte c = buf[i++];
     if (c == ';') p->i = 0; else if (c == 'i') p->i = 255; else die_with_message("bad invert");
@@ -532,9 +579,18 @@
   }
 }

+void set_and_run_only_channel(Channel *ch) {
+  // TODO--actually do this
+}
+
 void append_protocol(Channel *ch) {
   // TODO--actually do it
 }
+
+
+/**************************************
+** Select which command to interpret **
+**************************************/

 void parse_command_on(Channel *ch, char who) {
   if (ch->disabled) {
@@ -568,34 +624,28 @@
   }
 }

-void abort_and_reset() {
-  shiftbuf(2);
-  if (running > 0) halt_channels();
-  running = 0;
-}
-
-void reset_parameters() {
-  shiftbuf(2);  // TODO--actually do something
-}
-
-void report_identity() {
-  shiftbuf(2);
-  Serial.println(whoamiN, DEC);
-  Serial.write(whoami, whoamiN);
-  Serial.send_now();
-}
-
-void report_pins() {
-  shiftbuf(2);
-  byte pinout[27];
-  int i = 0;
-  pinout[i++] = '~';
-  for (; i <= digiN; i++) pinout[i] = HEXTRI(digi[i-1]);
-  if (waveN > 0) pinout[i++] = '@';
-  pinout[i++] = '$';
-  Serial.write(pinout, i);
-  Serial.send_now();
-}
+void interpret(char cmd) {
+  if      (cmd == '!') start_running();
+  else if (cmd == '$') report_errors();
+  else if (cmd == '?') report_timing();
+  else if (cmd == '>') shift_timing(1);
+  else if (cmd == '<') shift_timing(-1);
+  else if ((cmd >= '0' && cmd <= '9') || (cmd >= 'A' && cmd <= 'N'))
+                       parse_command_on(channels + DEHEXT(cmd), cmd);
+  else if (cmd == '@') parse_command_on(channels + DIG, '@');
+  else if (cmd == '.') abort_and_reset();
+  else if (cmd == '"') reset_parameters();
+  else if (cmd == ':') report_identity();
+  else if (cmd == '*') report_pins();
+  else                 raise_unknown_command_error(cmd, ' ');
+}
+
+
+/*****************************************
+** State machine for stimuli and/or I/O **
+*****************************************/
+
+int count_me = 0;

 // Loop runs forever (after setup)
 void loop() {
@@ -726,22 +776,9 @@
   // Interpret any fully buffered commands
   if (bufi > 1) {
     // NOTE--subcommands are responsible for checking for completeness and consuming input if it is complete!
-    char cmd = buf[1];
-    Serial.println(cmd,DEC);
+    Serial.println(buf[1],DEC);
     Serial.send_now();
-    if      (cmd == '!') start_running();
-    else if (cmd == '$') report_errors();
-    else if (cmd == '?') report_timing();
-    else if (cmd == '>') shift_timing(1);
-    else if (cmd == '<') shift_timing(-1);
-    else if ((cmd >= '0' && cmd <= '9') || (cmd >= 'A' && cmd <= 'N'))
-                         parse_command_on(channels + DEHEXT(cmd), cmd);
-    else if (cmd == '@') parse_command_on(channels + DIG, '@');
-    else if (cmd == '.') abort_and_reset();
-    else if (cmd == '"') reset_parameters();
-    else if (cmd == ':') report_identity();
-    else if (cmd == '*') report_pins();
-    else                 raise_unknown_command_error(cmd, ' ');
+    interpret(buf[1]);
   }

   // int r = ARM_DWT_CYCCNT;   // Read cycle count (effectively a 72 MHz clock)


Fix for Arduino compilation

Fix for Arduino compilation

--- examples/ArtnetNeopixel/ArtnetNeopixel.ino
+++ examples/ArtnetNeopixel/ArtnetNeopixel.ino
@@ -16,7 +16,7 @@
 byte channelBuffer[numberOfChannels]; // Combined universes into a single array

 // Check if we got all universes
-const int maxUniverses = ceil(numberOfChannels / 512.);
+const int maxUniverses = numberOfChannels / 512 + ((numberOfChannels % 512) ? 1 : 0);
 bool universesReceived[maxUniverses];
 bool sendFrame = 1;


Do not use mavlink anymore (the parse function was slowing down everything for unknown reason. Just forward "raw" data from analog sensor and encoder at 20Hz. Works very well so far!


Cleaning code

Cleaning code


added IR remote

added IR remote


Accelerometer shouldn't be calibrated this way

--- src/main/main.ino
+++ src/main/main.ino
@@ -14,54 +14,13 @@
 const float gScale = 0x7FFF / (float)8;
 const float dpsScale = 0x7FFF / (float)1000;

-void setup()
-{
-	Serial.begin(115200);
-
-	Wire.begin();
-	Wire.setClock(400000);
-
-	if(!imu.init())
-	{
-		Serial.println("Failed to detect and initialize IMU!");
-
-		delay(500);
-		void (*f)() = nullptr;
-		f();
-		while(1);
-	}
-
-	imu.enableDefault();
-
-	imu.writeReg(LSM6::CTRL1_XL, // Accelerometer
-		0x8 << 4 | // 1.66 kHz sample frequency
-		0x3 << 2 | // 8g
-		0x1);      // Anti-aliasing: 200 Hz
-	imu.writeReg(LSM6::CTRL2_G, // Gyroscope
-		0x8 << 4 | // 1.66 kHz sample frequency
-		0x2 << 2 | // 1000 degrees per second
-		0x0);
-
-	calibrate_sensors();
-
-	ahrs.begin((float) SAMPLE_FREQUENCY);
-}
-
-int acc_x_offset;
-int acc_y_offset;
-int acc_z_offset;
-
 int gyro_x_offset;
 int gyro_y_offset;
 int gyro_z_offset;

-void calibrate_sensors()
+void calibrate_gyroscope()
 {
 	int samples_count = 0;
-
-	int64_t acc_x_sum = 0;
-	int64_t acc_y_sum = 0;
-	int64_t acc_z_sum = 0;

 	int64_t gyro_x_sum = 0;
 	int64_t gyro_y_sum = 0;
@@ -72,21 +31,12 @@
 	{
 		imu.read();

-		acc_x_sum += imu.a.x;
-		acc_y_sum += imu.a.y;
-		acc_z_sum += imu.a.z;
-
 		gyro_x_sum += imu.g.x;
 		gyro_y_sum += imu.g.y;
 		gyro_z_sum += imu.g.z;

 		++samples_count;
 	}
-
-	// Should I use floats here?
-	acc_x_offset = acc_x_sum / samples_count;
-	acc_y_offset = acc_y_sum / samples_count;
-	acc_z_offset = acc_z_sum / samples_count - gScale;

 	gyro_x_offset = gyro_x_sum / samples_count;
 	gyro_y_offset = gyro_y_sum / samples_count;
@@ -97,10 +47,7 @@
 {
 	imu.read();

-	imu.a.x -= acc_x_offset;
-	imu.a.y -= acc_y_offset;
-	imu.a.z -= acc_z_offset;
-
+	// Apply gyroscope offsets
 	imu.g.x -= gyro_x_offset;
 	imu.g.y -= gyro_y_offset;
 	imu.g.z -= gyro_z_offset;
@@ -164,6 +111,39 @@
 	Serial.println("");
 }

+void setup()
+{
+	Serial.begin(115200);
+
+	Wire.begin();
+	Wire.setClock(400000);
+
+	if(!imu.init())
+	{
+		Serial.println("Failed to detect and initialize IMU!");
+
+		delay(500);
+		void (*f)() = nullptr;
+		f();
+		while(1);
+	}
+
+	imu.enableDefault();
+
+	imu.writeReg(LSM6::CTRL1_XL, // Accelerometer
+		0x8 << 4 | // 1.66 kHz sample frequency
+		0x3 << 2 | // 8g
+		0x1);      // Anti-aliasing: 200 Hz
+	imu.writeReg(LSM6::CTRL2_G, // Gyroscope
+		0x8 << 4 | // 1.66 kHz sample frequency
+		0x2 << 2 | // 1000 degrees per second
+		0x0);
+
+	calibrate_gyroscope();
+
+	ahrs.begin((float) SAMPLE_FREQUENCY);
+}
+
 uint32_t lastSampleMicros = 0;
 uint32_t lastPrintMicros = 0;


Set BC127 to use BLE mode for android devices.

--- examples/02-Utility/EchoBLE/EchoBLE.ino
+++ examples/02-Utility/EchoBLE/EchoBLE.ino
@@ -94,6 +94,11 @@
   BT_Serial->print("ADVERTISING ON\r"); delay(500); echoIncomingBTSerial();
   USB_Serial->println("*** Advertising on.");

+  // use BLE on android
+  USB_Serial->println("*** Setting to BLE mode for Android...");
+  BT_Serial->print("SET ENABLE_ANDROID_BLE=ON\r"); delay(500); echoIncomingBTSerial();
+  USB_Serial->println("*** BLE Android mode on.");
+
   while(1) {
     if(BT_Serial->available()) {
       readBTResponse();


Enable sensor

Enable sensor

--- dayrider/dayrider.ino
+++ dayrider/dayrider.ino
@@ -41,6 +41,7 @@
   movement.begin();
   pixel.begin();
   pixel.reset();
+  s1.begin();
   digitalWrite(13, HIGH); // ready to go
 }


Add first cut of volume normalization

Add first cut of volume normalization

--- Arduino/spectrum_i2c/spectrum_i2c.ino
+++ Arduino/spectrum_i2c/spectrum_i2c.ino
@@ -18,8 +18,17 @@
 float bpm = 120;
 boolean offBeat = true;
 boolean sentBeat = false;
+long MAX_VOLUME = (255 << 2);
+long MIN_VOLUME = (180 << 2);
+double MAX_MODIFIER = 10.0;
+double MIN_MODIFIER = 0.5;
+double modifier = 1.0;
+
+
+long running_volume = 200;

 void setup() {
+  //Serial.begin(9600);
   start = t = millis();
   Wire.begin(0x29);
   Wire.onRequest(sendSpectrum);
@@ -51,6 +60,7 @@
 {
   // Band 0 = Lowest Frequencies.
   byte i;
+  long volume = 0;
   for(i=0;i <7; i++)
   {
     //Read twice and take the average by dividing by 2
@@ -59,12 +69,26 @@
     value -= 80;
     if (value < 0)
       value=0;
+    value *= modifier;
+    volume = value > volume?value:volume;
     //value is 10 bit, we need 8 bit, so divide by 4
     value >>= 2;
-    spectrum[i] = (byte)((float)spectrum[i] * 0.7 + (float)value * 0.3);
+    spectrum[i] = (byte)((float)spectrum[i] * 0.9 + (float)value * 0.1);
     //request the next value
     digitalWrite(spectrumStrobe,HIGH);
     digitalWrite(spectrumStrobe,LOW);
+  }
+  running_volume = running_volume * .95 + volume * .05;
+  if (running_volume < MIN_VOLUME) {
+    modifier += .001;
+  } else if (running_volume > MAX_VOLUME) {
+    modifier -= .02;
+  }
+  if (modifier > MAX_MODIFIER){
+    modifier = MAX_MODIFIER;
+  }
+  if (modifier < MIN_MODIFIER){
+  modifier = MIN_MODIFIER;
   }
   captureBeat(spectrum[0]);
 }
@@ -79,6 +103,7 @@
     sentBeat = false;
   }
   Wire.write(spectrum, 9);
+  //Serial.println(modifier);
 }


Add comments and change minimal time as a global parameter

--- HBridgePWM/HBridgePWM.ino
+++ HBridgePWM/HBridgePWM.ino
@@ -1,30 +1,47 @@
-// constants won't change. Used here to
-// set pin numbers:
+/*
+Author: Baptiste LABAT (Nautilabs)
+Project: robokite
+Date : March 2013
+This file ensures the control of a continuous current motor and gearbox through an H-bridge.
+A Pulse Width Modulation is used. The algorithm uses varying cycle frequency to allow control at low rotation speed.
+Due to minimum quantity of energy to make the motor turn, the motor will not turn smoothly at low speed.
+There is now feedback nor stall control on speed, so the output rotation speed may depend on load torque.
+The motor is controlled through a parameter alpha which is signed and vary from -1 to -1.
+This parameter can be set thanks to a an analog voltage (set through a potentiometer for example) or sent over serial connection
+There is not guarantee that there is a linear relationship between alpha and the rotation speed
+*/
+// \todo this code needs refactorization
+
+// Minimal time to have motor starting at maximum voltage. This will depend on the motor used
+// Try to reduce to get a smooth motion
+double minTime_ms = 30;
+
+// These constants will not change. Used here to
+// give names to set pin numbers:
 const int HbridgeEnablePin =  13;
 const int HbridgeLogicPin1 = 4;
 const int HbridgeLogicPin2 = 5;
-int sensorValue = 0;        // value read from the potentiometer
-// These constants won't change.  They're used to give names
-// to the pins used:
 const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

+int sensorValue = 0;        // Value read from the potentiometer
+
 double alphaSigned = 0;
-String inputString = "";         // a string to hold incoming data
-boolean stringComplete = false;  // whether the string is complete
+String inputString = "";         // A string to hold incoming data
+boolean stringComplete = false;  // Whether the string is complete

 void setup()
 {
-  // set the digital pin as output:
+  // Set the digital pin as output:
   pinMode(HbridgeEnablePin, OUTPUT);
   pinMode(HbridgeLogicPin1, OUTPUT);
   pinMode(HbridgeLogicPin2, OUTPUT);
-  // initialize serial communications at 9600 bps:
+  // Initialize serial communications at 9600 bps:
   Serial.begin(9600);

 }
 float StrToFloat(String str){
-  char carray[str.length() + 1]; //determine size of the array
-  str.toCharArray(carray, sizeof(carray)); //put str into an array
+  char carray[str.length() + 1]; // Determine the size of the array
+  str.toCharArray(carray, sizeof(carray)); // Put str into an array
   return atof(carray);
 }

@@ -36,11 +53,11 @@
  */
 void serialEvent() {
   while (Serial.available()) {
-    // get the new byte:
+    // Get the new byte:
     char inChar = (char)Serial.read();
-    // add it to the inputString:
+    // Add it to the inputString:
     inputString += inChar;
-    // if the incoming character is a newline, set a flag
+    // If the incoming character is a newline, set a flag
     // so the main loop can do something about it:
     if (inChar == '\n') {
       stringComplete = true;
@@ -55,17 +72,19 @@
 void loop()
 {
   digitalWrite(HbridgeEnablePin, HIGH);
-  double minTime_ms = 30;//Minimal time to have motor starting at maximum voltage
-  // read the analog in value:
+  // Read the analog in value
+  // The range was reduced
   double sensorValueMin = 255;//0
   double sensorValueMax = 767;//1023
-  double deadBand = 0.05; // Should not be zero
+  double deadBand = 0.05; // Use to ensure zero speed. Should not be zero
   sensorValue = analogRead(analogInPin);
-  //alphaSigned = 2*((sensorValue-sensorValueMin)/(sensorValueMax - sensorValueMin)-0.5);
+  // \todo: add a selection of voltage or serial input
+  // alphaSigned = 2*((sensorValue-sensorValueMin)/(sensorValueMax - sensorValueMin)-0.5);
   double alpha = max(fabs(alphaSigned), deadBand);
   alpha = min(alpha, 1);
   if (alphaSigned>fabs(deadBand))
   {
+    // Forward rotation
     digitalWrite(HbridgeLogicPin1, HIGH);
     digitalWrite(HbridgeLogicPin2, LOW);
   }
@@ -73,14 +92,17 @@
   {
     if (alphaSigned<-fabs(deadBand))
     {
+	  // Backward rotation
       digitalWrite(HbridgeLogicPin1, LOW);
       digitalWrite(HbridgeLogicPin2, HIGH);
     }
     else
     {
+	  // Brake
       digitalWrite(HbridgeLogicPin1, LOW);
       digitalWrite(HbridgeLogicPin2, LOW);
     }
+	// \todo: add an input to enable manual rotation of the motor
   }
   delay(minTime_ms);

@@ -120,24 +142,24 @@
 //    Serial.println(alphaSigned);
     alpha = max(fabs(alphaSigned), deadBand);
     alpha = min(alpha, 1);
-      if (alphaSigned>fabs(deadBand))
-  {
-    digitalWrite(HbridgeLogicPin1, HIGH);
-    digitalWrite(HbridgeLogicPin2, LOW);
-  }
-  else
-  {
-    if (alphaSigned<-fabs(deadBand))
+    if (alphaSigned>fabs(deadBand))
     {
-      digitalWrite(HbridgeLogicPin1, LOW);
-      digitalWrite(HbridgeLogicPin2, HIGH);
-    }
-    else
-    {
-      digitalWrite(HbridgeLogicPin1, LOW);
+      digitalWrite(HbridgeLogicPin1, HIGH);
       digitalWrite(HbridgeLogicPin2, LOW);
     }
-  }
+    else
+    {
+      if (alphaSigned<-fabs(deadBand))
+      {
+        digitalWrite(HbridgeLogicPin1, LOW);
+        digitalWrite(HbridgeLogicPin2, HIGH);
+      }
+      else
+      {
+        digitalWrite(HbridgeLogicPin1, LOW);
+        digitalWrite(HbridgeLogicPin2, LOW);
+      }
+    }
 //    Serial.print("alpha = " );
 //    Serial.println(alpha);
     elapsedTime_ms = millis() - initialTime;


cleanup

cleanup

--- source/TempSensor/TempSensor.ino
+++ source/TempSensor/TempSensor.ino
@@ -1,3 +1,6 @@
+#include <OneWire.h>
+#include <DallasTemperature.h>
+
 #include <LiquidCrystal.h>

 LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
@@ -84,4 +87,4 @@
 	celsius = celsius / 8;

 	return celsius;
-}+}


Small fix

Small fix

--- sw/basestation/menu.ino
+++ sw/basestation/menu.ino
@@ -150,6 +150,8 @@
     selected_receiver.active = s;

     state.menu_active = false;
+
+    write_tx_fifo();
 }
 void force_recv_on()  { force_recv(true);  }
 void force_recv_off() { force_recv(false); }


v8.2 Add day of week

v8.2 Add day of week

--- WeatherDisplay.ino
+++ WeatherDisplay.ino
@@ -277,7 +277,13 @@
                   temperature,
                   timeS,
                   idString.toInt(),
+#ifdef DISPLAYDATE // Display the date
                   dateS,
+#else              // Display the day of week
+                  dayI,
+                  monthI,
+                  yearI,
+#endif
                   description);
   }
 } // void getWeatherData()
@@ -400,6 +406,7 @@
 }

 // Displays the main weather
+#ifdef DISPLAYDATE // Dislpays the date
 void printMainData(String humidityString,
                    String temperature,
                    String time,
@@ -407,6 +414,17 @@
                    String dateS,
                    String description)
 {
+#else // Dislpays the day of week
+void printMainData(String humidityString,
+                   String temperature,
+                   String time,
+                   int weatherID,
+                   int dayI,
+                   int monthI,
+                   int yearI,
+                   String description)
+{
+#endif
   byte maxLeghtOfParam;

   tft.setTextColor(YELLOW);
@@ -437,9 +455,16 @@
   tft.print("% RH");
   tft.setTextColor(YELLOW);
   tft.setTextSize(1);
+#ifdef DISPLAYDATE // Dislpays the date
   maxLeghtOfParam = std::min((int)dateS.length(), 22); // Limit characters
   tft.setCursor((11 - (maxLeghtOfParam / 2)) * 4, 150); // Center text
   tft.print(dateS);
+#else // Dislpays the day of week
+  String theDayOfWeek = getDayOfWeek(dayOfWeek(yearI, monthI, dayI));
+  maxLeghtOfParam = std::min((int)theDayOfWeek.length(), 22); // Limit characters
+  tft.setCursor((11 - (maxLeghtOfParam / 2)) * 4, 150); // Center text
+  tft.print(theDayOfWeek);
+#endif
 }

 void printWeatherIcon(int id)


Add required conditionals around RGBW/RGBWW lines so that we dont break RGB devices

--- Arilux_AL-LC0X.ino
+++ Arilux_AL-LC0X.ino
@@ -135,12 +135,15 @@
     } else if (payload.equals(String(MQTT_STATE_OFF_PAYLOAD))) {
       if (arilux.turnOff())
         cmd = ARILUX_CMD_STATE_CHANGED;
-    } else if (payload.equals(String(MQTT_STATE_ON_WHITE_PAYLOAD))) {
-      if (arilux.turnOn())
-        cmd = ARILUX_CMD_STATE_CHANGED;
-      arilux.setWhite(255, 255);
-      arilux.setBrightness(255);
     }
+    #if defined(RGBW) || defined (RGBWW)
+      if (payload.equals(String(MQTT_STATE_ON_WHITE_PAYLOAD))) {
+        if (arilux.turnOn())
+          cmd = ARILUX_CMD_STATE_CHANGED;
+        arilux.setWhite(255, 255);
+        arilux.setBrightness(255);
+      }
+    #endif
   } else if (String(ARILUX_MQTT_BRIGHTNESS_COMMAND_TOPIC).equals(p_topic)) {
     if (arilux.setBrightness(payload.toInt()))
       cmd = ARILUX_CMD_BRIGHTNESS_CHANGED;
@@ -158,11 +161,14 @@

     if (arilux.setColor(r, g, b))
       cmd = ARILUX_CMD_COLOR_CHANGED;
-  } else if (String(ARILUX_MQTT_WHITE_COMMAND_TOPIC).equals(p_topic)) {
-    uint8_t firstIndex = payload.indexOf(',');
-    if (arilux.setWhite(payload.substring(0, firstIndex).toInt(), payload.substring(firstIndex + 1).toInt()))
-      cmd = ARILUX_CMD_WHITE_CHANGED;
-  }
+  }
+  #if defined(RGBW) || defined (RGBWW)
+    if (String(ARILUX_MQTT_WHITE_COMMAND_TOPIC).equals(p_topic)) {
+      uint8_t firstIndex = payload.indexOf(',');
+      if (arilux.setWhite(payload.substring(0, firstIndex).toInt(), payload.substring(firstIndex + 1).toInt()))
+        cmd = ARILUX_CMD_WHITE_CHANGED;
+    }
+  #endif
 }

 /*
@@ -517,11 +523,13 @@
       publishToMQTT(ARILUX_MQTT_COLOR_STATE_TOPIC, msgBuffer);
       cmd = ARILUX_CMD_NOT_DEFINED;
       break;
-    case ARILUX_CMD_WHITE_CHANGED:
-      snprintf(msgBuffer, sizeof(msgBuffer), "%d,%d", arilux.getWhite1Value(), arilux.getWhite2Value());
-      publishToMQTT(ARILUX_MQTT_WHITE_STATE_TOPIC, msgBuffer);
-      cmd = ARILUX_CMD_NOT_DEFINED;
-      break;
+    #if defined(RGBW) || defined (RGBWW)
+      case ARILUX_CMD_WHITE_CHANGED:
+        snprintf(msgBuffer, sizeof(msgBuffer), "%d,%d", arilux.getWhite1Value(), arilux.getWhite2Value());
+        publishToMQTT(ARILUX_MQTT_WHITE_STATE_TOPIC, msgBuffer);
+        cmd = ARILUX_CMD_NOT_DEFINED;
+        break;
+    #endif
     default:
       break;
   }


PWM is 0..1023

PWM is 0..1023

--- WifiWeatherGuy.ino
+++ WifiWeatherGuy.ino
@@ -38,7 +38,8 @@
   bool metric;
   uint32_t conditions_interval, forecasts_interval;
   uint32_t on_time, retry_interval;
-  uint8_t bright, dim, rotate;
+  uint16_t bright, dim;
+  uint8_t rotate;

   void configure(JsonObject &o);
 } cfg;


clear screen on start

clear screen on start

--- WifiWeatherGuy.ino
+++ WifiWeatherGuy.ino
@@ -85,6 +85,7 @@
 	fade = cfg.bright;
 	analogWrite(TFT_LED, fade);

+	tft.fillScreen(TFT_BLACK);
 	tft.setRotation(cfg.rotate);
 	tft.println(F("Weather Guy (c)2018"));
 	tft.print(F("ssid: "));


typo fixed

typo fixed

--- ESP8266-code/HackspacePIREnv.ino
+++ ESP8266-code/HackspacePIREnv.ino
@@ -80,7 +80,7 @@
    float humidity =htu.readHumidity();

 // log the data
-   String data =String("occupied=") + pir_active+"&rssi="+rssi+"&temperatureC"+temp +"&humidity" + humidity;
+   String data =String("occupied=") + pir_active+"&rssi="+rssi+"&temperatureC="+temp +"&humidity=" + humidity;
    Serial.println(data);
    log_data(data);
    if (pir_active = 1)


Turned off Low Pass Filter

Turned off Low Pass Filter

--- scr_arduino/scr_arduino.ino
+++ scr_arduino/scr_arduino.ino
@@ -76,7 +76,7 @@
 long R_LastEncoderValue = 0;
 double R_EncoderDelta = 0;
 double R_LastEncoderDelta = 0;
-double beta = .95;  // Low Pass Parameter for encoder velocity
+double beta = 0.0;  // Low Pass Parameter for encoder velocity

 // Speed Controller Initialization
 double L_PIDout = 0;


Update RTC test cases; additional measurement of baseline.

--- examples/Benchmarks/CosaRTCBenchmark/CosaRTCBenchmark.ino
+++ examples/Benchmarks/CosaRTCBenchmark/CosaRTCBenchmark.ino
@@ -43,12 +43,18 @@

   // Start the timers
   Watchdog::begin();
+  Watchdog::delay(1);
   RTC::begin();

   // Measure baseline
   start = RTC::micros();
   stop = RTC::micros();
   INFO("RTC::micros(): %ul", stop - start);
+
+  start = RTC::micros();
+  uint32_t ms = RTC::millis();
+  stop = RTC::micros();
+  INFO("RTC::millis(): %ul", stop - start);

   start = RTC::micros();
   DELAY(1);


more ui stuff

more ui stuff

--- master/master.ino
+++ master/master.ino
@@ -1272,16 +1272,27 @@

 		ledBlink();
 		/* debugging */
-
+		Serial.println(playMode);
 		//serialDebug();
 		if (loopCount % 30 == 0){
 			if (tftEnabled){
 				debugTFT();
+				if (playMode == OFFENSE){
+					tftEnableBtn.setColour(ILI9341_RED);
+				}
+				else if (playMode == DEFENSE){
+					tftEnableBtn.setColour(ILI9341_BLUE);
+				}
+				else{
+					tftEnableBtn.setColour(ILI9341_WHITE);
+				}
+				tftEnableBtn.draw(false);
 			}
 		}

 		/* end debugging */

 		loopCount++;  // update loop count
+		linelocation_prev = linelocation;
 	}
 }


Improved code.

Improved code.

--- aquacontrol2.ino
+++ aquacontrol2.ino
@@ -115,8 +115,8 @@
   WiFi.mode( WIFI_STA );

   WiFi.begin( myWIFIssid.c_str(), myWIFIpassword.c_str() );
-  myWIFItimeout = now() + 30;
-  while ( now() < myWIFItimeout && WiFi.status() != WL_CONNECTED ) {
+  time_t timeout = now() + myWIFItimeout;
+  while ( now() < timeout && WiFi.status() != WL_CONNECTED ) {
     delay ( 500 );
     Serial.print ( F( "." ) );
   }


time authentication successfully tested

time authentication successfully tested

--- module/module.ino
+++ module/module.ino
@@ -53,14 +53,18 @@
 	responseFlag = getResponse(readData);
 	// Analyze response packet and data
 	if(responseFlag == false)
-		Serial.println("Read unsuccesful, please try again");
+		Serial.println("Read unsuccessful, please try again.");
 	else {
-		existingTime = getTime(readData);
+		//existingTime = getTime(readData);
+		existingTime = 3600;
 		if(readData[8] != 0xDD)
 			Serial.println("Invalid card");
 		else if(existingTime >= quota)
-			Serial.println("You have reached your quota for this month");
+			Serial.println("You have reached your quota for this month.");
 		else {
+			Serial.print("Time used this month: ");
+			Serial.println(existingTime);
+			Serial.println("User authenticated. Machine is ready to fire");
 			elapsedTime = accumulator();
 			Serial.print("Total time used: ");
 			Serial.println(elapsedTime + existingTime);


encoder reading done

encoder reading done

encoder information is read from buf[4] and buf[5] and converted to
decimal

--- send/send.ino
+++ send/send.ino
@@ -16,53 +16,58 @@

 void setup()
 {
-    Serial.begin(115200);
+  Serial.begin(115200);

-    while (CAN_OK != CAN.begin(CAN_1000KBPS))              // init can bus : baudrate = 500k
-    {
-        Serial.println("CAN BUS Shield init fail");
-        Serial.println(" Init CAN BUS Shield again");
-        delay(100);
-    }
-    Serial.println("CAN BUS Shield init ok!");
+  while (CAN_OK != CAN.begin(CAN_1000KBPS))              // init can bus : baudrate = 500k
+  {
+    Serial.println("CAN BUS Shield init fail");
+    Serial.println(" Init CAN BUS Shield again");
+    delay(100);
+  }
+  Serial.println("CAN BUS Shield init ok!");
 }

 void loop()
 {
-    unsigned char len = 0;
-    unsigned char buf[8];
+  unsigned char len = 0;
+  unsigned char buf[8];

-    if(CAN_MSGAVAIL == CAN.checkReceive())            // check if data coming
+  if (CAN_MSGAVAIL == CAN.checkReceive())           // check if data coming
+  {
+    CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
+
+    unsigned int canId = CAN.getCanId();
+
+    Serial.println("-----------------------------");
+    Serial.print("Get data from ID: ");
+    Serial.println(canId, HEX);
+
+    for (int i = 0; i < len; i++) // print the data
     {
-        CAN.readMsgBuf(&len, buf);    // read data,  len: data length, buf: data buf
+      Serial.print(buf[i], HEX);
+      Serial.print("\t");
+    }
+    Serial.println();

-        unsigned int canId = CAN.getCanId();
-
-        Serial.println("-----------------------------");
-        Serial.print("Get data from ID: ");
-        Serial.println(canId, HEX);
-
-        for(int i = 0; i<len; i++)    // print the data
-        {
-            Serial.print(buf[i], HEX);
-            Serial.print("\t");
-        }
-        Serial.println();
-    }
-
-        // data = buf[1]*256*256 + buf[2]*256 + buf[3];
-    data = (buf[5]*256 + buf[6])*(360/4096);
-
+    // encoder information is read from buf[4] and buf[5] and converted to decimal
+        data = buf[4];
+        data <<= 8;
+        data = data | buf[5];

     // if (buf[1] >= 128) {
-        data = data - 16777216;
+    //        data = data - 16777216;
     // }

     Serial.print("Data: ");
-    Serial.println(data);
+    Serial.println(data, DEC);
+
+    delay(400);
+  }
+
 }
+

 /*********************************************************************************************************
   END FILE
-*********************************************************************************************************/+*********************************************************************************************************/


Make debug output conditional on a DEBUG macro

--- Arduino/LightPlayer/LightPlayer.ino
+++ Arduino/LightPlayer/LightPlayer.ino
@@ -1,6 +1,8 @@
 #include <SPI.h>
 #include <SdFat.h>
 #include <FAB_LED.h>
+
+#define DEBUG 1

 apa106<D, 6>   LEDstrip;
 rgb frame[200];
@@ -73,9 +75,11 @@
     infile.openNext(sd.vwd());
     if (infile.isOpen()) {
       if (!infile.isHidden() && !infile.isSystem()) {
+#ifdef DEBUG
         char buf[13];
         infile.getName(buf, sizeof(buf));
         cout << F("\nOpened file: ") << buf;
+#endif
         return;
       }
       infile.close();


Improve click on attack & release

Improve click on attack & release

--- roto2.ino
+++ roto2.ino
@@ -136,9 +136,9 @@
 }

 void initEnvelope(AudioEffectEnvelope *env) {
-  env->attack(0.5);
+  env->attack(2.0);
   env->sustain(1.0);
-  env->release(0.75);
+  env->release(2.0);
 }

 void initMixer(AudioMixer4 *mix) {


Improve MCP23008 example sketch; add measurements.

--- libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
+++ libraries/MCP23008/examples/CosaMCP23008/CosaMCP23008.ino
@@ -18,10 +18,11 @@
  * @section Description
  * Cosa MCP23008 Remote 8-bit I/O expander driver example. Includes
  * benchmarking of read/write of port and pins;
- *  1. write pin, 340 us
- *  2. write sequence, 113 us per byte
- *  3. read without cached address, 472 us
- *  4. read with cached address, 236 us
+ *  1. read pin, 472 us
+ *  2. read pin (cached address), 236 us
+ *  3. write pin, 340 us
+ *  4. pulse pin, 676 us
+ *  5. pulse pin (sequence), 226 us
  *
  * @section Circuit
  * @code
@@ -98,7 +99,19 @@
   start = RTC::micros();
   port.write(buf, sizeof(buf));
   stop = RTC::micros();
-  trace << (stop - start) / sizeof(buf)	<< PSTR(": write(buf)") << endl;
+  trace << (stop - start) / sizeof(buf)
+	<< PSTR(": write(buf[") << sizeof(buf) << PSTR("])")
+	<< endl;
+
+  // Toggle pin(0)
+  start = RTC::micros();
+  for (uint8_t i = 0; i < sizeof(buf); i++) {
+    port.write(p, i & 1);
+  }
+  stop = RTC::micros();
+  trace << (stop - start) / sizeof(buf)
+	<< PSTR(": write():") << sizeof(buf) << PSTR("X")
+	<< endl;

   // Read input pins
   start = RTC::micros();