minor changes

minor changes

--- slave3/slave3.ino
+++ slave3/slave3.ino
@@ -191,7 +191,6 @@

 extern "C" int main(void){
 	CORE_PIN33_CONFIG = 0;  // completely disables the pin
-	noInterrupts();
 	Serial.begin(115200);

 	pinMode(LED, OUTPUT);
@@ -240,12 +239,20 @@
 	analogWriteFrequency(MT_C_PWM, PWM_FREQ);
 	analogWriteFrequency(MT_D_PWM, PWM_FREQ);
 	analogWriteFrequency(MT_E_PWM, PWM_FREQ);
+
+	// MOVEMOTOR(0, MT_A_DIR, MT_A_BRK, MT_A_PWM);
+	// MOVEMOTOR(0, MT_B_DIR, MT_B_BRK, MT_B_PWM);
+	// MOVEMOTOR(0, MT_C_DIR, MT_C_BRK, MT_C_PWM);
+	// MOVEMOTOR(0, MT_D_DIR, MT_D_BRK, MT_D_PWM);
+	// MOVEMOTOR(0, MT_E_DIR, MT_E_BRK, MT_E_PWM);

 	// for fastest speeds configure 8 bit analog reads and no averaging
 	analogReadResolution(8);
 	analogReadAveraging(32);

 	ledBlinkTime = 0;
+
+	noInterrupts();

 	SPI.begin_SLAVE(ALT_SCK, MOSI, MISO, ALT_CS0);
   	SPI.setCTAR_SLAVE(8, SPI_MODE0);
@@ -348,6 +355,7 @@
 	noInterrupts();
 	if (dataExpected == 0){
 		command = SPI0_POPR;
+		Serial.println(command);
 		CLEARARRAY(spiBuff);

 		switch(command){


scanner_stepper.ino: Reduces amount printed in output.

--- scanner_stepper/scanner_stepper.ino
+++ scanner_stepper/scanner_stepper.ino
@@ -29,14 +29,14 @@
   float revolutionsPerMinute = frequency * 60.0 / stepsPerRevolution;
   float steps = 1.0 * frequency * duration / 1000.0;

-  Serial.print("Freq: ");
+  Serial.print("F: ");
   Serial.println(frequency);
-  Serial.print("Dur: ");
+  Serial.print("T: ");
   Serial.println(duration);
   Serial.print("RPM: ");
-  Serial.println(revolutionsPerMinute);
-  Serial.print("Steps: ");
-  Serial.println(steps);
+  Serial.println((int) revolutionsPerMinute);
+  Serial.print("s: ");
+  Serial.println((int) steps);

   if (revolutionsPerMinute > maxRpm) {
     Serial.println("Max RPM exceeded.");


Improved commenting and diagnostic info

Improved commenting and diagnostic info

--- ComposterSketch/ComposterSketch.ino
+++ ComposterSketch/ComposterSketch.ino
@@ -1,7 +1,7 @@

 /******************************************************************************************************************
- * ComposterSketch Arduino sketch, the main program, for the Composter Controller
+ * ComposterSketch, an Arduino sketch, the main program, for the Composter Controller
  *
  * Control Panel Functionality
  *  Button1 press:    Rotate drum clockwise (CW) until released
@@ -81,16 +81,21 @@
 static long  totalLoopTime;                          //milliseconds in loop()
 static long  nTimesLoopInvoked;                      //Counts invocations of loop()

-//Initialize the composter system
+//------------------------------------------------------------------------------------------------------
+//  The arduino kernel invokes setup() to initialize the composter controller
+//------------------------------------------------------------------------------------------------------
 void setup() {

-  //Reset the loop timing data
+  //Initialize some variables that are used during development to determine the average time spent
+  //in each pass through the controller's loop() code
   totalLoopTime=0L;
   nTimesLoopInvoked=0L;
-
+
+  //Initial machine state following arduino reset
   state=IDL;                              //Initial state is IDL

-  //Try to setup 32U4 USB communication with host computer if present, blinking 3X or until USB is ready
+  //Try upto 3 times to detect a USB-connected host to our arduino 32U4 CPU.  After
+  //each failing attempt to detect SerialUSB ready, we beep and blink all the LEDs
   Serial.begin(57600);
   for(int i=1;(i<=3)&&(!SerialUSB);i++) {
     audio.doBeep(FREQG);
@@ -109,16 +114,18 @@
   attachInterrupt(digitalPinToInterrupt(pinB2),intHan,CHANGE);
   attachInterrupt(digitalPinToInterrupt(pinB3),intHan,CHANGE);

-  //Startup the remainder
-  sked.start();                                     //Scheduler
+  //Startup the composter's autorun scheduler
+  sked.start();

 }

-//Composter's activity loop executed forever
+//------------------------------------------------------------------------------------------------------------
+//  The arduino kernel repeatedly invokes loop() which drives the composter's state machine
+//------------------------------------------------------------------------------------------------------------
 void loop() {

   //The loop-timing feature is for software developers, not the end-user of the composter
-  long t0 = millis();                             //Time at start of loop()
+  long t0 = millis();                             //Time at start of a pass through loop()

   //Poll and Update the status of objects that won't get updated otherwise
   b3t.update();
@@ -132,9 +139,10 @@
   scheduled.set(sked.enabled());                    //Autorun scheduler enabled?
   delay(5L);                                        //Ensure the LEDs flash for a few ms

-  //Press *both* b1 and b2 for diagnostic information
+  //Press *both* buttons b1 and b2 for diagnostic information
   if (b1.isPressed()&&b2.isPressed()) {
     if (nTimesLoopInvoked>0) {DPRINT(String("Avg loop time = "+String(totalLoopTime/nTimesLoopInvoked)+" ms"));}
+    DPRINT(String("State="+state));
   }

   //Composter state determines what to do with incoming events


Adjust probe pins.

Adjust probe pins.

--- examples/Tools/CosaClockCalibration/CosaClockCalibration.ino
+++ examples/Tools/CosaClockCalibration/CosaClockCalibration.ino
@@ -159,9 +159,9 @@
 };

 // Pulse generators from the different clocks (logic analyzer channel colors)
-Pulse black(&clock, 1, Board::D7);
-Pulse brown(&wall, 1, Board::D8);
-Pulse red(&bark, 1, Board::D9);
+Pulse black(&clock, 1, Board::LED);
+Pulse brown(&wall, 1, Board::D12);
+Pulse red(&bark, 1, Board::D11);

 void setup()
 {


First management of the received OLEDData objects via serial port

--- HIDVolumeKnobV2/HIDVolumeKnobV2.ino
+++ HIDVolumeKnobV2/HIDVolumeKnobV2.ino
@@ -1,9 +1,9 @@
-#include "HID-Project.h"
-
+#include <HID-Project.h>
 #include <SPI.h>
 #include <Wire.h>
 #include <Adafruit_GFX.h>
 #include <Adafruit_SSD1306.h>
+#include "oleddata.h"

 #define OLED_RESET 4
 Adafruit_SSD1306 display(OLED_RESET);
@@ -36,7 +36,14 @@
 #error("Height incorrect, please fix Adafruit_SSD1306.h!");
 #endif

-void setup() {
+// Meta data
+/**
+ * @brief olds the meta datas
+ */
+char* metaDatas[4] = { NULL, NULL, NULL, NULL };
+
+void setup()
+{
     Consumer.begin();

     // Encoder configuration
@@ -74,7 +81,12 @@
     display.display();
 }

-void showToastInfo(const char* string) {
+/**
+ * @brief Displays the given string as a 'toast'
+ * @param string string to be displayed
+ */
+void showToastInfo(const char* string)
+{
     display.clearDisplay();
     display.setCursor(30, 15);
     display.println(string);
@@ -82,7 +94,36 @@
     clearAndUpdate = false;
 }

-void loop() {
+/**
+ * @brief Show the meta datas
+ */
+void showMetaData()
+{
+    display.clearDisplay();
+    for (int i = 0; i < 4; i++) {
+        char* data = metaDatas[i];
+        int cursorPosition = 8 * i;
+        display.setCursor(0, cursorPosition);
+        display.println(data);
+    }
+    display.display();
+}
+
+/**
+ * @brief Sets the meta data for the given index
+ * @param index
+ * @param data
+ */
+void setMetaData(int index, const char *data)
+{
+    if (metaDatas[index])
+        free(metaDatas[index]);
+    metaDatas[index] = (char*)malloc(strlen(data) * sizeof(char));
+    strcpy(metaDatas[index], data);
+}
+
+void loop()
+{
     // Toast time elapsed
     unsigned long currentTime = millis();
     if ((currentTime - lastToastTime) > toastDuration) {
@@ -90,12 +131,30 @@
         clearAndUpdate = true;
     }

-    if (!isMediaPlayerDetected && clearAndUpdate) {
-        display.clearDisplay();
-        display.setCursor(0, 0);
-        display.println("No media player");
-        display.println("detected");
-        display.display();
+    int availableBytes = Serial.available();
+    if (availableBytes && clearAndUpdate) {
+        isMediaPlayerDetected = true;
+        char *data = (char *)malloc(availableBytes * sizeof(char));
+        Serial.readBytes(data, availableBytes);
+        OLEDData oledData;
+        if (OLEDData::decode(data, availableBytes, &oledData)) {
+            //display.clearDisplay();
+            switch (oledData.type()) {
+            case OLEDData::Artist:
+                setMetaData(0, oledData.data());
+                break;
+            case OLEDData::Album:
+                setMetaData(1, oledData.data());
+                break;
+            case OLEDData::Track:
+                setMetaData(2, oledData.data());
+                break;
+            default:
+                break;
+            }
+        }
+        free(data);
+        showMetaData();
     }

     if (!keySent) {


predict next packet times

predict next packet times

--- examples/RF12/syncRecv/syncRecv.ino
+++ examples/RF12/syncRecv/syncRecv.ino
@@ -4,68 +4,112 @@
 // 2012-10-30 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php

 #include <JeeLib.h>
+#include <avr/eeprom.h>

-#define SEND_ID 9       // wait for packets from node 9
+#define SEND_FREQ   RF12_868MHZ   // listening frequency
+#define SEND_GROUP  5             // listening net group
+#define SEND_ID     9             // listen for this node ID

-word estimate = 3000;   // packet expected every 3s
-word window = 512;      // start with +/- 17 % window, power of 2
-byte missed;            // count how often in a row receive failed
+#define CYCLE_TIME  3000          // expected cycle, milliseconds
+
+#define EEADDR ((word*) 0)        // save estimate at this EEPROM address
+
+word estimate;      // packet expected every 3s
+word window;        // start with +/- 17 % window, power of 2
+byte missed;        // count how often in a row receive failed
+uint32_t lastRecv;  // time of last reception

 ISR(WDT_vect) { Sleepy::watchdogEvent(); }
+
+static void radioSleep (word ms) {
+  rf12_sleep(RF12_SLEEP);
+  Sleepy::loseSomeTime(ms);
+  rf12_sleep(RF12_WAKEUP);
+}

 static bool isDesiredPacket () {
   return rf12_recvDone() && rf12_crc == 0 && rf12_hdr == SEND_ID;
 }

-// since the watchdog timer is inaccurate, we must estimate
 static bool estimateWithWatchdog () {
   // first wait indefinitely for a packet to come in
   while (!isDesiredPacket())
     ;
-  Serial.print("R");
-  delayMicroseconds(250);

   // sleep until estimate - window
   word lowEstimate = estimate - window;
   uint32_t start = millis();
-  rf12_sleep(RF12_SLEEP);
-  Sleepy::loseSomeTime(lowEstimate);
-  rf12_sleep(RF12_WAKEUP);
+  radioSleep(lowEstimate);

   // using the millis() timer, measure when the next packet comes
-  word diff;
   do {
-    diff = millis() - start;
-    if (diff > estimate + window)
+    lastRecv = millis();
+    if (lastRecv - start > estimate + window)
       return false;
   } while (!isDesiredPacket());

-  int offset = window - (diff - lowEstimate);
-  // the new estimate shouldn't be too close to the exact time
-  estimate = (diff + 2) & ~0x0F; // truncate down to 16 ms multiple
+  estimate = lastRecv - start;
+  int offset = (estimate - lowEstimate) - window;

-  Serial.print(" ok at "); Serial.print(diff);
+  Serial.print(" got "); Serial.print(estimate);
   Serial.print(", window = "); Serial.print(window);
-  Serial.print(", offset = "); Serial.print(offset);
-  Serial.print(", new estimate = "); Serial.println(estimate);
+  Serial.print(", offset = "); Serial.println(offset);
   return true;
+}
+
+static void chooseEstimate () {
+  // use estimate in EEPROM, if it's sensible
+  estimate = eeprom_read_word(EEADDR);
+  if (estimate < CYCLE_TIME - CYCLE_TIME/5 ||
+      estimate > CYCLE_TIME + CYCLE_TIME/5)
+    estimate = CYCLE_TIME;
+  Serial.print("start estimate = "); Serial.println(estimate);
+  // narrow down estimate from 20 % -> 2 %
+  window = estimate / 5;
+  while (window >= 16)
+    if (estimateWithWatchdog())
+      window /= 2;
+  // save best estimaet so far
+  eeprom_write_word(EEADDR, estimate);
+  Serial.print("save estimate "); Serial.println(estimate);
 }

 void setup () {
   Serial.begin(57600);
   Serial.println("\n[syncRecv]");
-  rf12_initialize(1, RF12_868MHZ, 5); // never sends anything
+  rf12_initialize(1, SEND_FREQ, SEND_GROUP); // we never send
+  chooseEstimate();
 }

 void loop () {
-  if (estimateWithWatchdog()) {
-    // gradually narrow down the window whenever reception succeeds
-    if (window >= 32)
-      window /= 2;
-    missed = 0;
-  } else {
-    // but widen the window again if reception fails for too long
-    if (window <= 512 && ++missed % 10 == 0)
-      window *= 4; // increase window x4 at every 10 packets missed
+  uint32_t now = millis();
+  byte lost = (now - lastRecv + estimate/2) / estimate;
+  Serial.print(" #"); Serial.print(lost);
+  if (lost > 20)
+    chooseEstimate();
+  else {
+    uint32_t predict = lastRecv + (lost + 1) * estimate;
+    word sleep = predict - now - window;
+
+    Serial.print(" s "); Serial.print(sleep);
+    Serial.flush(); delayMicroseconds(250);
+
+    radioSleep(sleep);
+
+    uint32_t recvTime;
+    do {
+      recvTime = millis();
+      if (recvTime > predict + window)
+        return;
+    } while (!isDesiredPacket());
+
+    estimate = (recvTime - lastRecv) / (lost + 1);
+    int offset = (estimate - sleep) - window;
+    lastRecv = recvTime;
+
+    Serial.print(" e "); Serial.print(estimate);
+    Serial.print(" w "); Serial.print(window);
+    Serial.print(" o "); Serial.print(offset);
+    Serial.print(" rf "); Serial.println(offset + window);
   }
 }


Update charlieplexing_low_power_flasher.ino

--- examples/charlieplexing_low_power_flasher.ino
+++ examples/charlieplexing_low_power_flasher.ino
@@ -4,13 +4,14 @@
   Purpose: Burning Man 2017 Flasher Gift Project

   @author Mike Tarrant
-  @version  1.1   Add comments and some code cleanup
+  @version  1.1   Add LDR code, comments, and code cleanup
             1.0   Initial release

 */

-#include "LowPower.h"   // RocketScream library so so we can use low-power sleep for timing delays
-#include "charlieplexing.h"  //Charlieplexing library for a six LED display
+//#include "LowPower.h"   // RocketScream library so so we can use low-power sleep for timing delays
+#include "charlieplexing.h"  // Charlieplexing library for a six LED display
+#inclued "lowPowerSleeps.h"  // Specify low-power sleep values using the RocketScream library

 const int lightThreshold = 200;  // LDR values > 200 indicate it's not dark out anymore
 const int analogPinLDR = 0;  // make this a constant, so if we have to change it later, it'll be easy


Update PlayIMF.ino

Update PlayIMF.ino

--- examples/PlayIMF/PlayIMF.ino
+++ examples/PlayIMF/PlayIMF.ino
@@ -50,7 +50,7 @@
     wait -= (millis() - time);      // Take into account time that was spent on IO.

     if (wait > 0) {
-      delay(wait );
+      delay(wait);
       time = millis();
     }


Update PlayIMF.ino

Update PlayIMF.ino

--- examples/PlayIMF/PlayIMF.ino
+++ examples/PlayIMF/PlayIMF.ino
@@ -84,4 +84,4 @@
   songLength -= 3;

   return round(wait * (1000 / imfSpeed));
-}+}


colocando para enviar e vi que ele faz piscar os dois leds o de status e o IR(no caso testei com um led normal). nao sei ainda se funciona se for um led IR(teria q ter um para saber

--- codigo.ino
+++ codigo.ino
@@ -230,7 +230,7 @@
     {
         Serial.println("Pressed, sending");
         digitalWrite(STATUS_PIN, HIGH);
-        // sendCode(lastButtonState == firstButtonState);
+        sendCode(lastButtonState == firstButtonState);
         digitalWrite(STATUS_PIN, LOW);
         delay(50); // Wait a bit between retransmissions
     }


updated example code for iBeacon to include nRF52

--- examples/iBeacon/iBeacon.ino
+++ examples/iBeacon/iBeacon.ino
@@ -1,7 +1,7 @@
 #include <BLEPeripheral.h>
 #include <iBeacon.h>

-#if !defined(NRF51) && !defined(__RFduino__)
+#if !defined(NRF51) && !defined(NRF52) && !defined(__RFduino__)
 #error "This example only works with nRF51 boards"
 #endif


Fix grammar in serial printouts

Fix grammar in serial printouts

--- examples/Basics/Speaker/Speaker.ino
+++ examples/Basics/Speaker/Speaker.ino
@@ -35,13 +35,13 @@

 void loop() {
   if(M5.BtnA.wasPressed()) {
-    M5.Lcd.printf("wasPressed A \r\n");
+    M5.Lcd.printf("A wasPressed \r\n");
     M5.Speaker.beep(); //beep
   }

   if(M5.BtnB.wasPressed())
   {
-    M5.Lcd.printf("wasPressed B \r\n");
+    M5.Lcd.printf("B wasPressed \r\n");
     M5.Speaker.tone(NOTE_DH2, 200); //frequency 3000, with a duration of 200ms
   }


started rewriting firmware

started rewriting firmware

--- discont/Motor_Shield/MotorShield/MotorShield.ino
+++ discont/Motor_Shield/MotorShield/MotorShield.ino
@@ -2,11 +2,11 @@
 const int encoderRightData2 = 5;
 const int encoderLeftData1 = 2;
 const int encoderLeftData2 = 4;
-const int rightDir = 7;
-const int rightSpeed = 6;
+const int rightForwardSpeed = 7; //BLi
+const int rightBackwardSpeed = 6; //HLi
 const int rightDisable = 8;
-const int leftDir = 10;
-const int leftSpeed = 9;
+const int leftForwardSpeed = 10;
+const int leftBackwardSpeed = 9;
 const int leftDisable = 11;

 volatile int tickDataRight = 0;
@@ -74,11 +74,11 @@
   digitalWrite(encoderLeftData1,  HIGH);
   digitalWrite(encoderLeftData2,  HIGH);

-  pinMode(rightDir, OUTPUT);
-  pinMode(rightSpeed, OUTPUT);
+  pinMode(rightForwardSpeed, OUTPUT);
+  pinMode(rightBackwardSpeed, OUTPUT);
   pinMode(rightDisable, OUTPUT);
-  pinMode(leftDir, OUTPUT);
-  pinMode(leftSpeed, OUTPUT);
+  pinMode(leftForwardSpeed, OUTPUT);
+  pinMode(leftBackwardSpeed, OUTPUT);
   pinMode(leftDisable, OUTPUT);
   attachInterrupt(1, tickRight, CHANGE);
   attachInterrupt(0, tickLeft, CHANGE);
@@ -104,37 +104,39 @@

 void loop()
 {
-  gotCommand = false;
+  /*gotCommand = false;
   while(Serial.available())
   {
-    if(Serial.read() == '$')
-    {
-      desiredSpeedL = -1*Serial.parseFloat();
-      desiredSpeedR = -1*Serial.parseFloat();
-      lastCmdTime = millis();
-      gotCommand = true;
-    }
+	if(Serial.read() == '$')
+	{
+	  desiredSpeedL = Serial.parseFloat();
+	  desiredSpeedR = Serial.parseFloat();
+	  lastCmdTime = millis();
+	  gotCommand = true;
+	}
   }
   if(gotCommand)
   {
-    Serial.print('$');
-    Serial.print(actualSpeedL);
-    Serial.print(',');
-    Serial.print(actualSpeedR);
-    Serial.print(',');
-    Serial.print(dT_sec);
-    Serial.print('\n');
-  }
-
+	Serial.print('$');
+	Serial.print(actualSpeedL);
+	Serial.print(',');
+	Serial.print(actualSpeedR);
+	Serial.print(',');
+	Serial.print(dT_sec);
+	Serial.print('\n');
+  }
+
   if( millis() - lastCmdTime > 500)
   {
-    Serial.println("TIMEOUT");
-    desiredSpeedL = 0;
-    desiredSpeedR = 0;
-    PWM_L = 0;
-    PWM_R = 0;
-  }
-  `*/
+	Serial.println("TIMEOUT");
+	desiredSpeedL = 0;
+	desiredSpeedR = 0;
+	PWM_L = 0;
+	PWM_R = 0;
+  }*/
+  desiredSpeedL = 1.0;
+  desiredSpeedR = 1.0;
+
   dT_sec = (float)( millis() - lastLoopTime ) / 1000.0;
   lastLoopTime = millis();
   actualSpeedL = ( metersPerTick * tickDataLeft ) / dT_sec;
@@ -155,33 +157,35 @@
   int dPWM_R = (int)( P_r * ErrorR + D_r * dErrorR );

   PWM_L += dPWM_L;
-  PWM_R -= dPWM_R;
+  PWM_R += dPWM_R;

   PWM_L = min(255, max(-255, PWM_L) );
   PWM_R = min(255, max(-255, PWM_R) );
-
+
   // Deadband
-  if( abs(PWM_L) < DEADBAND )
-    PWM_L = 0;
-  if( abs(PWM_R) < DEADBAND )
-    PWM_R = 0;
-
-  int dirL = PWM_L < 0;
-  int dirR = PWM_R > 0;
-
-  int powerL = dirL ? 255 + PWM_L : PWM_L;
-  int powerR = dirR ? 255 - PWM_R : -PWM_R;
-
-  if(desiredSpeedL == 0)
-    PWM_L = 0;
-  if(desiredSpeedR == 0)
-    PWM_R = 0;
-
-  digitalWrite(rightDir, dirR);
-  digitalWrite(leftDir, dirL);
-  analogWrite(rightSpeed, powerR);
-  analogWrite(leftSpeed, powerL);
-
+  if( abs(PWM_L) < 0 )
+	PWM_L = 0;
+  if( abs(PWM_R) < 0 )
+	PWM_R = 0;
+
+  if(PWM_L < 0) {
+	analogWrite(leftForwardSpeed, 0);
+	analogWrite(leftBackwardSpeed, -PWM_L);
+  } else {
+	analogWrite(leftForwardSpeed, PWM_L);
+	analogWrite(leftBackwardSpeed, 0);
+  }
+
+  /*if(PWM_R < 0) {
+	analogWrite(rightForwardSpeed, 0);
+	analogWrite(rightBackwardSpeed, 255);
+  } else {
+	analogWrite(rightForwardSpeed, 255);
+	analogWrite(rightBackwardSpeed, 0);
+  }*/
+  analogWrite(rightForwardSpeed, 100);
+  analogWrite(rightBackwardSpeed, 0);
+
   lastErrorL = ErrorL;
   lastErrorR = ErrorR;
 }
@@ -190,11 +194,11 @@
 {
   if (digitalRead(encoderRightData1) == digitalRead(encoderRightData2))
   {
-    tickDataRight++;
+	tickDataRight++;
   }
   else
   {
-    tickDataRight--;
+	tickDataRight--;
   }
 }

@@ -202,17 +206,17 @@
 {
   if (digitalRead(encoderLeftData1) == digitalRead(encoderLeftData2))
   {
-    tickDataLeft++;
+	tickDataLeft++;
   }
   else
   {
-    tickDataLeft--;
+	tickDataLeft--;
   }
 }

 /**
  * Divides a given PWM pin frequency by a divisor.
- *
+ *
  * The resulting frequency is equal to the base frequency divided by
  * the given divisor:
  *   - Base frequencies:
@@ -223,13 +227,13 @@
  *        256, and 1024.
  *      o The divisors available on pins 3 and 11 are: 1, 8, 32, 64,
  *        128, 256, and 1024.
- *
+ *
  * PWM frequencies are tied together in pairs of pins. If one in a
  * pair is changed, the other is also changed to match:
  *   - Pins 5 and 6 are paired on timer0
  *   - Pins 9 and 10 are paired on timer1
  *   - Pins 3 and 11 are paired on timer2
- *
+ *
  * Note that this function will have side effects on anything else
  * that uses timers:
  *   - Changes on pins 3, 5, 6, or 11 may cause the delay() and
@@ -237,7 +241,7 @@
  *     functions may also be affected.
  *   - Changes on pins 9 or 10 will cause the Servo library to function
  *     incorrectly.
- *
+ *
  * Thanks to macegr of the Arduino forums for his documentation of the
  * PWM frequency divisors. His post can be viewed at:
  *   http://forum.arduino.cc/index.php?topic=16612#msg121031
@@ -245,30 +249,30 @@
 void setPwmFrequency(int pin, int divisor) {
   byte mode;
   if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
-    switch(divisor) {
-      case 1: mode = 0x01; break;
-      case 8: mode = 0x02; break;
-      case 64: mode = 0x03; break;
-      case 256: mode = 0x04; break;
-      case 1024: mode = 0x05; break;
-      default: return;
-    }
-    if(pin == 5 || pin == 6) {
-      TCCR0B = TCCR0B & 0b11111000 | mode;
-    } else {
-      TCCR1B = TCCR1B & 0b11111000 | mode;
-    }
+	switch(divisor) {
+	  case 1: mode = 0x01; break;
+	  case 8: mode = 0x02; break;
+	  case 64: mode = 0x03; break;
+	  case 256: mode = 0x04; break;
+	  case 1024: mode = 0x05; break;
+	  default: return;
+	}
+	if(pin == 5 || pin == 6) {
+	  TCCR0B = TCCR0B & 0b11111000 | mode;
+	} else {
+	  TCCR1B = TCCR1B & 0b11111000 | mode;
+	}
   } else if(pin == 3 || pin == 11) {
-    switch(divisor) {
-      case 1: mode = 0x01; break;
-      case 8: mode = 0x02; break;
-      case 32: mode = 0x03; break;
-      case 64: mode = 0x04; break;
-      case 128: mode = 0x05; break;
-      case 256: mode = 0x06; break;
-      case 1024: mode = 0x07; break;
-      default: return;
-    }
-    TCCR2B = TCCR2B & 0b11111000 | mode;
-  }
-}
+	switch(divisor) {
+	  case 1: mode = 0x01; break;
+	  case 8: mode = 0x02; break;
+	  case 32: mode = 0x03; break;
+	  case 64: mode = 0x04; break;
+	  case 128: mode = 0x05; break;
+	  case 256: mode = 0x06; break;
+	  case 1024: mode = 0x07; break;
+	  default: return;
+	}
+	TCCR2B = TCCR2B & 0b11111000 | mode;
+  }
+}


update motion

update motion

--- eMotion/flap/flap.ino
+++ eMotion/flap/flap.ino
@@ -93,7 +93,7 @@
         if(IR())
           delay(1000);
         else
-          delay((light() * rand()) % 2000);
+          delay((rand() / RAND_MAX) * light());
     }

     for(int i = start; i < start+n_serial; ++i)
@@ -102,7 +102,7 @@
         if(IR())
           delay(1000);
         else
-          delay((light() * rand()) % 2000);
+          delay((rand() / RAND_MAX) * light());
     }

 }


Update RGBSerielArd.ino

Update RGBSerielArd.ino

--- home/Markus/RGBSerielArd.ino
+++ home/Markus/RGBSerielArd.ino
@@ -56,14 +56,14 @@
       analogWrite(redPin, red);
       analogWrite(greenPin, green);
       analogWrite(bluePin, blue);
+    }

-      // print the three numbers in one string as hexadecimal:
-      Serial.print(red);
-      Serial.print(',');
-      Serial.print(green);
-      Serial.print(',');
-      Serial.println(blue);
-    }
+    Serial.print(red);
+    Serial.print(',');
+    Serial.print(green);
+    Serial.print(',');
+    Serial.println(blue);
+
     Serial.println("Data received");
   }
 }


Disabled flash CS

Disabled flash CS


[YunSerialTerminal example]: corrected the CRC in the Bridge shutdown command

--- libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino
+++ libraries/Bridge/examples/YunSerialTerminal/YunSerialTerminal.ino
@@ -66,7 +66,7 @@
         Serial1.begin(500000);        //        set speed to 500000
         Serial.println("Speed set to 500000");
       } else if (c == '~') {
-        Serial1.write((uint8_t *)"\xff\0\0\x05XXXXX\x0d\xaf", 11);
+        Serial1.write((uint8_t *)"\xff\0\0\x05XXXXX\x7f\xf9", 11);
         Serial.println("Sending bridge's shutdown command");
       } else {                        //     any other key pressed?
         Serial1.write('~');           //        write '~' to Linino


modulo funcionando

modulo funcionando

--- arduino/test_post_gps/test_post_gps.ino
+++ arduino/test_post_gps/test_post_gps.ino
@@ -28,12 +28,10 @@

 void setup()
 {
-
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  uart_gps.begin(9600);
  sim800.begin(4800);
-
  Serial.println("esperando a que cargue");
  delay(2000);
  imei();
@@ -77,12 +75,9 @@
 void loop() // run over and over

 {
-
    f_SendPost();
-
    getgps(gps);         // then grab the data.
    smartdelay(1000);
-
 }

 void getgps(TinyGPS &gps)
@@ -134,12 +129,10 @@
           Serial.write(sim800.read());
     }
 }
-
 //FUNCION para ver en consola lo que se envia y recibe
 void respuesta(){
  while (sim800.available())
     Serial.write(sim800.read());
-
 }
 //****************************************************

@@ -149,14 +142,12 @@
   delay(300);
   while (sim800.available())
  {
-
       if(c=='\n')
         temp++;
       if( temp==1)
         recepcion+=c;
       c=sim800.read();
       Serial.print(c);
-
  }
   temp=0;
   recepcion.replace("\n","");
@@ -216,7 +207,7 @@
   delay(20);
   Serial.println(_Data);
   sim800.println("aT+HTTPDATA=100,10000");
-  Stop(3000);
+  Stop(3500);

   sim800.println(_Data);
   Stop(10000);
@@ -225,7 +216,7 @@
   Stop(5000);

   sim800.println("AT+HTTPREAD");
-  Stop(1000);
+  Stop(2000);

 }
 //void AT_ok(String a)


BUGFIX: color_palette copy lookup was wrong

--- super_freq/super_freq.ino
+++ super_freq/super_freq.ino
@@ -227,7 +227,7 @@
 };

 Color color_palette[24];
-byte palette_choice = 0;  // there's 2 palettes: choose 0 or 1
+byte palette_choice = 5;  // there's 2 palettes: choose 0 or 1

 void setup() {
     if (DEBUG) {
@@ -251,9 +251,9 @@

     // initial color palette
     for (int i = 0; i < 24; i++) {
-        color_palette[i].red = pgm_read_byte(&(palettes[i + ((palette_color_count - 1) * palette_choice)].red));
-        color_palette[i].green = pgm_read_byte(&(palettes[i + ((palette_color_count - 1) * palette_choice)].green));
-        color_palette[i].blue = pgm_read_byte(&(palettes[i + ((palette_color_count - 1) * palette_choice)].blue));
+        color_palette[i].red = pgm_read_byte(&(palettes[i + (palette_color_count * palette_choice)].red));
+        color_palette[i].green = pgm_read_byte(&(palettes[i + (palette_color_count * palette_choice)].green));
+        color_palette[i].blue = pgm_read_byte(&(palettes[i + (palette_color_count * palette_choice)].blue));
     }

     // Start up the LED strip


Immediately return after mode change

Immediately return after mode change

--- ableton-midi-foot-controller.ino
+++ ableton-midi-foot-controller.ino
@@ -189,6 +189,7 @@
   if (modeChange) {
     Serial.println(modeNames[mode]);
     resetLeds();
+    return;
   }

   switch (mode) {


define and fix bug

define and fix bug

--- scripts-arduino/bp_led_lp.ino
+++ scripts-arduino/bp_led_lp.ino
@@ -6,7 +6,8 @@

 // ######## DEF ########
 #define LONGPRESS_LEN    25         // Min nr of loops for a long press
-#define DELAY            20         // Delay per loop in ms
+#define DELAY            20        // Delay per loop in ms
+

 // ######## VAR ########
 int buttonState = 0;                // variable for reading the pushbutton status
@@ -15,11 +16,13 @@
 int button_pressed_counter;         // press running duration
 boolean button_was_pressed;         // previous state

+
+
 // ######## ENUM ########
 enum {
     EV_NONE=0,
-    EV_SHORTPRESS=1,
-    EV_LONGPRESS=2
+    EV_SHORTPRESS,
+    EV_LONGPRESS
 };

 // ######## SETUP ########
@@ -38,18 +41,15 @@
     switch(eventResult){
         case EV_NONE:               // if nothing append
             //TODO : Ne rien faire de particulier, ou attendre la fin d'une synchronisation
+
             break;
         case EV_SHORTPRESS:         // if short press
             //TODO : Allumer ou éteindre la LED (a check)
-            if(ledState == HIGH){
-                if (buttonState == LOW) {
+            if(digitalRead(LED_PIN) == HIGH){
                     turnOff();
-                }
             }
             else{
-                if (buttonState == LOW) {
                     turnOn();
-                }
             }
             break;
         case EV_LONGPRESS:          // if long press
@@ -71,6 +71,8 @@
         }
         else{
             event = EV_LONGPRESS;
+
+            Serial.println(CONST_ID+":"+CONST_TYPE+":4");
         }
     }
     else{
@@ -79,8 +81,10 @@

     if (button_now_pressed)
         ++button_pressed_counter;
-    else
-        button_pressed_counter = 0;
+    else{
+        button_pressed_counter = 0;
+    }
+

     button_was_pressed = button_now_pressed;
     return event;


Update firmware version to 1.0.0 in preparation for release

--- firmware/removinator/removinator.ino
+++ firmware/removinator/removinator.ino
@@ -566,7 +566,7 @@
 //
 void usage()
 {
-    Serial.println("--- Smart Card Removinator (v0.1) ---");
+    Serial.println("--- Smart Card Removinator (v1.0.0) ---");
     Serial.println("Command Format:");
     Serial.print("\t");
     Serial.print("Prefix:");


restart/retry game

restart/retry game

used functions and not using setup(), everything is in loop() and has
it's own function

--- game_one/game_one.ino
+++ game_one/game_one.ino
@@ -1,6 +1,7 @@
 #include <Wire.h>
 #include "/hackTX14/rgb_lcd.h"
 #include "/hackTX14/rgb_lcd.cpp"
+#include <stdio.h>

 rgb_lcd lcd;

@@ -14,32 +15,31 @@
 const int buzz_pin = 8;
 const char blank_writer[17] = "                ";
 int level = 0;
-int max_level = 5;
+int max_level = 1; //index count
 const int rxn_time[6] = {30, 29, 27, 24, 19, 13};//time to react, decreases as levels go up
+

 int button_state = 0;
 int touch_state = 0;
+/*
 boolean toggle = false;
 int button_count = 0;
 int hold_time = 0;
+*/

 const unsigned int map_0[] = {0,0,1,0,0,1,0,1,1,1,0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 const unsigned int map_1[] = {1,0,0,1,1,0,1,1,1,0,1,1,0,1,0,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-unsigned int ptr0 = 0;
-unsigned int ptr1 = 0;
+unsigned int ptr0, ptr1;
 unsigned int ptr_max = 21; //when pointer gets to index 15 we know that is the last part of map

-int val0 = 0;
-int val1 = 0;
-int user0 = 0;
-int user1 = 0;
-boolean good = false;
-int loop_count = 0;
-boolean start_delay = true;
+int val0, val1, user0, user1, loop_count;
+boolean good, start_delay;
+boolean need_setup = true;

 boolean correct_press();//checks to see if the user pressed the correct buttons
 void map_display();//const unsigned int& map0, const unsigned int& map1, unsigned int& p0, unsigned int& p1);
 void clear_screen();
+void our_setup();

 void clear_screen()
 {
@@ -67,12 +67,29 @@

 void setup()
 {
+}
+
+//our_setup
+void our_setup()
+{
     pinMode(button_pin, INPUT);
     pinMode(touch_pin, INPUT);
     pinMode(buzz_pin, OUTPUT);
     pinMode(led_pin, OUTPUT);
     lcd.begin(16,2);
     lcd.setRGB(100,100,100);
+
+    val0 = 0;
+    val1 = 0;
+    user0 = 0;
+    user1 = 0;
+    good = false;
+    loop_count = 0;
+    start_delay = true;
+    ptr0 = 0;
+    ptr1 = 0;
+    level = 0;
+
     //print_intro();
     lcd.setCursor(0,0);
     lcd.print("BEGIN GAME 0");
@@ -85,7 +102,7 @@
     clear_screen();
     delay(200);
     map_display();
-    delay(30);
+    delay(30);
 }

 //map display function
@@ -133,7 +150,7 @@
     }
 }

-void loop()
+void our_loop()
 {
   start_delay_beep(400);
   ++loop_count;
@@ -187,11 +204,40 @@
     ptr1 = 0;
     if(level > max_level)//you beat the game
     {
-       clear_screen();
-       lcd.setCursor(0,0);
-       lcd.print("GAME CHAMP!");
        while(true)
        {
+         clear_screen();
+         lcd.setRGB(0,255,0);
+         lcd.setCursor(0,0);
+         lcd.print("GAME CHAMP!");
+         if(digitalRead(button_pin) || digitalRead(touch_pin))
+         {
+           need_setup = true;
+           break;
+         }
+         delay(1000);
+         clear_screen();
+         lcd.setCursor(0,0);
+         lcd.print("press button");
+         lcd.setCursor(0,1);
+         lcd.print("to play again");
+         if(digitalRead(button_pin) || digitalRead(touch_pin))
+         {
+           need_setup = true;
+           break;
+         }
+         delay(500);
+         if(digitalRead(button_pin) || digitalRead(touch_pin))
+         {
+           need_setup = true;
+           break;
+         }
+         delay(500);
+         if(digitalRead(button_pin) || digitalRead(touch_pin))
+         {
+           need_setup = true;
+           break;
+         }
          /*
          champion of game tune
          */
@@ -205,21 +251,39 @@
     delay(500);
     start_delay = true;
   }
-  if(loop_count>=rxn_time[level] && !good)//lost
-  {
-    clear_screen();
-    lcd.setCursor(0,0);
-    lcd.print("GAME OVER");
+  else if(loop_count>=rxn_time[level] && !good)//lost
+  {
+    lcd.setRGB(200,0,0);//red bg
+    while(true)
+    {
+      clear_screen();
+      lcd.setCursor(0,0);
+      lcd.print("GAME OVER");
+      delay(1000);
+      //::game over tune::
+      clear_screen();
+      lcd.setCursor(0,0);
+      lcd.print("press button");
+      lcd.setCursor(0,1);
+      lcd.print("to play again");
+      if(digitalRead(button_pin) || digitalRead(touch_pin))
+      {
+        need_setup = true;
+        break;
+      }
+      delay(500);
+      if(digitalRead(button_pin) || digitalRead(touch_pin))
+      {
+        need_setup = true;
+        break;
+      }
+      delay(500);
+    }
+
     /*
     :: insert game over tune::
     */
     //lcd.print(ptr0); //used to figure out which index it failed at
-    lcd.setCursor(0,1);
-    lcd.print("TRY AGAIN");
-    level = 0;
-    while(true){
-      lcd.setRGB(200,0,0);
-    }
   }
   else if(loop_count>=rxn_time[level] && good)//continue
   {
@@ -228,7 +292,17 @@
     loop_count = 0;
     good = false;
   }
-  delay(10);
+  delay(10);
+}
+
+void loop()
+{
+  if(need_setup)
+  {
+    our_setup();
+    need_setup = false;
+  }
+  our_loop();
 }

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


Actually fix last example

Actually fix last example

--- examples/LightOnOff/LightOnOff.ino
+++ examples/LightOnOff/LightOnOff.ino
@@ -9,7 +9,7 @@

   bool on = (value == "true");
   digitalWrite(PIN_RELAY, on ? HIGH : LOW);
-  Homie.setNodeProperty(lighthNode, "on").send(value);
+  Homie.setNodeProperty(lightNode, "on").send(value);
   Serial << "Light is " << (on ? "on" : "off") << endl;

   return true;


Simplified quadcopter state machine

Simplified quadcopter state machine

--- examples/quadcopter/quadcopter.ino
+++ examples/quadcopter/quadcopter.ino
@@ -12,15 +12,15 @@
 const uint8_t CHANNEL_MIN = 32;
 const uint8_t CHANNEL_MAX = 148;
 float yawTarget = 0.0;
-enum {
+enum State {
     DISARMED,
-    ARM,
-    CALIBRATE_MOTORS,
-    OFF,
-    ENABLE,
     CALIBRATE,
     FLYING
-} state = OFF;
+};
+const char* stateString[] = {
+    [DISARMED] = "DISARMED", [CALIBRATE] = "CALIBRATE", [FLYING] = "FLYING" };
+State state;
+
 enum RadioChannel{
     RADIO_PITCH    = 0,
     RADIO_ROLL     = 1,
@@ -33,6 +33,12 @@
 void setup() {
     setupQuad();
     horizon.standby();
+    setState(DISARMED);
+}
+
+void setState(State s){
+    state = s;
+    comms.sendString(stateString[s]);
 }

 void loop() {
@@ -42,44 +48,36 @@

     //flight mode state machine
     switch(state){
+        /*#DISARMED Quadcopter is in a safe state. hold Down and to the right on
+         * the Throttle stick for two seconds to begin the arming process
+        **/
         case DISARMED:
-            if(timeState<&radio_downRight>() > 5000) state = ARM;
-            if(timeState<&radio_downLeftUpRight>() > 5000) state = CALIBRATE_MOTORS;
+            if(timeState<&radio_downRight>() > 2000) {
+                calStartTime = millis();
+                setState(CALIBRATE);
+            }
             break;
-        case ARM:
-            arm();
-            state = FLYING;
-            break;
-        case CALIBRATE_MOTORS:
-            calibrateESCs();
-            state = FLYING;
-            break;
-        case OFF:
-            output.disable();
-            if(timeState<&radio_downRight>() > 5000) state = ENABLE;
-            break;
-        case ENABLE:
-            if(calibrated) {
-                output.enable();
-                state = FLYING;
-            } else {
-                calStartTime = millis();
-                state = CALIBRATE;
-            }
-            yawTarget = orientation.getYaw();
-            break;
+        /*#CALIBRATE Calibrating the gyroscope
+         * This lasts for two seconds. Keep the quadcopter as still as possible.
+        **/
         case CALIBRATE:
             orientation.calibrate(true);
             if(calStartTime + 2000 < millis()) {
+                orientation.calibrate(false);
+                yawTarget = orientation.getYaw();
                 output.enable();
-                state = FLYING;
-                orientation.calibrate(false);
-                calibrated = true;
+                setState(FLYING);
             }
             break;
+        /*#FLYING Quadcopter is like
+         * Hold down and to the left on the throttle stick to disarm
+        **/
         case FLYING:
             fly();
-            if(timeState<&radio_downLeft>() > 750) state = OFF;
+            if(timeState<&radio_downLeft>() > 750) {
+                output.disable();
+                setState(DISARMED);
+            }
             break;
     }


-More calls inlined.

-More calls inlined.

--- webservertask.ino
+++ webservertask.ino
@@ -724,7 +724,7 @@
   vTaskDelete( NULL );
 }

-int8_t checkChannelNumber( const AsyncWebServerRequest *request )
+static inline __attribute__((always_inline)) int8_t checkChannelNumber( const AsyncWebServerRequest *request )
 {
   if ( !request->hasArg( "channel" ) )
   {
@@ -771,33 +771,7 @@
   Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling)
 */

-String getContentType( const String& path )
-{
-  if (path.endsWith(".html")) return "text/html";
-  else if (path.endsWith(".htm")) return "text/html";
-  else if (path.endsWith(".css")) return "text/css";
-  else if (path.endsWith(".txt")) return "text/plain";
-  else if (path.endsWith(".js")) return "application/javascript";
-  else if (path.endsWith(".png")) return "image/png";
-  else if (path.endsWith(".gif")) return "image/gif";
-  else if (path.endsWith(".jpg")) return "image/jpeg";
-  else if (path.endsWith(".ico")) return "image/x-icon";
-  else if (path.endsWith(".svg")) return "image/svg+xml";
-  else if (path.endsWith(".ttf")) return "application/x-font-ttf";
-  else if (path.endsWith(".otf")) return "application/x-font-opentype";
-  else if (path.endsWith(".woff")) return "application/font-woff";
-  else if (path.endsWith(".woff2")) return "application/font-woff2";
-  else if (path.endsWith(".eot")) return "application/vnd.ms-fontobject";
-  else if (path.endsWith(".sfnt")) return "application/font-sfnt";
-  else if (path.endsWith(".xml")) return "text/xml";
-  else if (path.endsWith(".pdf")) return "application/pdf";
-  else if (path.endsWith(".zip")) return "application/zip";
-  else if (path.endsWith(".gz")) return "application/x-gzip";
-  else if (path.endsWith(".appcache")) return "text/cache-manifest";
-  return "application/octet-stream";
-}
-
-String urlDecode( const String& text )
+static inline __attribute__((always_inline)) String urlDecode( const String& text )
 {
   String decoded = "";
   char temp[] = "0x00";
@@ -829,7 +803,7 @@
 }

 /* format bytes as KB, MB or GB string */
-String humanReadableSize( size_t bytes )
+static inline __attribute__((always_inline)) String humanReadableSize( const size_t bytes )
 {
   if ( bytes < 1024)
   {


factorize send / receive byte

factorize send / receive byte

--- dummycomm.ino
+++ dummycomm.ino
@@ -111,29 +111,38 @@
 	delay(sleepms);
 }

+void sendByte(byte value) {
+	bytebitsSet(value);
+	sendBytebits();
+}
+
+byte getByte() {
+	int frame,i;
+	i=8;
+	while (i) {
+		while((frame = getFrame(BRX)) >= CARRIER) {
+			i=8;
+		}
+		bytebits[--i] = frame;
+	}
+	return bytebitsGet();
+}
+
 void loop() {
 	unsigned int angle;
-	int frame,i;
+	int i;
 	digitalWrite(LED, LOW);
 	digitalWrite(BTX, LOW);
 	for(i=0; i<16; i++) {
 		sendCarrier(BTX, sleepms);
 	}
-	bytebitsSet(iobyte);
-	sendBytebits();
+	sendByte(iobyte);
 	sendCarrier(BTX, sleepms);
 	sendCarrier(BTX, sleepms);
 	Serial.print("byte sent: ");
 	Serial.println(iobyte);
-	i=8;
-	while (i) {
-		while((frame = getFrame(BRX)) == CARRIER) {
-			i=8;
-		}
-		bytebits[--i] = frame;
-	}
+	iobyte=getByte();
 	digitalWrite(LED, HIGH);
-	iobyte=bytebitsGet();
 	Serial.print("byte read: ");
 	Serial.println(iobyte);
 	angle=((unsigned int)iobyte)*180/255;


Delay time between logs added.

Delay time between logs added.

--- scadacar_sketch/scadacar_sketch.ino
+++ scadacar_sketch/scadacar_sketch.ino
@@ -18,6 +18,9 @@
 static const uint32_t GPSBaud = 9600;
 TinyGPSPlus gps; // The TinyGPS++ object
 SoftwareSerial ss(RXPin, TXPin);
+
+int readCount = 0;
+int delayTime = 10; // delay time (in seconds) between messages.

 void setup()
 {
@@ -89,5 +92,9 @@
   }

   //Serial.println();
-  sendMessage(strValue);
+  // This will execute the sending message function when we want suposing that
+  // each second it reads the TinyGPS
+  if(readCount++ % delayTime == 0) {
+    sendMessage(strValue);
+  }
 }


Correct RX signal detect

Correct RX signal detect

Correct RX signal detection, NoRX switch processing, comments

--- KillSwitchduino/KillSwitchduino.ino
+++ KillSwitchduino/KillSwitchduino.ino
@@ -91,7 +91,7 @@
 #define SYSTEM_MENU_34_EN_CURRENT_RENDER 34               //Enable/Disable CurrentSensor info render to Serial Port  (for Feature ver 2.2)
 #define SYSTEM_MENU_40_DEFAULTS 50                        //Reset Config to Default
 #define SYSTEM_CALIBRATING 100                            //RX inpout Calibrating mode
-
+

 //Menus
 #define MENU_INITIAL_PERIOD 5000                          //Time period from end SYSTEM_FIRST_START procedure for enter in Menu Mode (3 times switch press)
@@ -137,7 +137,7 @@
 bool SystemServiceMode = false;                           //Enable embedded servotester for PPM generating(SYSTEM_SERVICE_PIN must be HIGH)

 //System state vars
-bool SwitchPOS = false;                                   //Switch position. TRUE if down, FALSE if UP
+bool SwitchPOS = true;                                    //Switch position. TRUE if down, FALSE if UP
 bool SwitchPOS_fromUp = false;                            //from upper position flag
 bool EngineSTOP = false;                                  //Switch for cut-off engine ignition
 bool EngineSTOP_flag = false;                             //Stopflag for prevent fast double switching
@@ -248,15 +248,12 @@
 // ================================================================

 void MainSWHandler(){
-//reset packets counter
-  if (MainSWPacketsCounter >= 50) { MainSWPacketsCounter=0;}
-
 //reading PPM signal from channel
-     if (digitalRead(MAINSWITCH_IN_PIN) == HIGH)
+     if (digitalRead(MAINSWITCH_IN_PIN) == HIGH) //if LOW->HIGH front detected, save it!
         {MainSWTime1 = micros(); }
-     else {MainSWTime2 = micros();
+     else {MainSWTime2 = micros();//if HIGH->LOW front detected, save it too!
            //counter overflow correction (~70min)
-           if (MainSWTime2<MainSWTime1) {MainSWTime2=MainSWTime1+100;}
+           if (MainSWTime2<MainSWTime1) {MainSWTime2=MainSWTime1+2000;}
            //calc PPM signal length and packets count
            MainSWTime = MainSWTime2 - MainSWTime1;
            MainSWPacketsCounter++;
@@ -265,9 +262,12 @@

 //switch handling
  if (MainSWTime >= PPMSwitchLevel)
-    {//Switch in Upper position
-     SwitchPOS=true;
-     SwitchPOS_fromUp=true;}
+    {//Switch in Upper position! proccessing for only one time change
+     if (!SwitchPOS_fromUp){
+     SwitchPOS=true;
+     SwitchPOS_fromUp=true;
+     }
+     }
  else
    {
      //Switch in Lower position and if last position is Upper then proccessing for only one time change
@@ -279,9 +279,9 @@
       MainSWPressCounterChange=true;
       //reset position change flag
       SwitchPOS_fromUp=false;
-      }
    }
-
+  }
+  if (MainSWPacketsCounter >= 50) { MainSWPacketsCounter=1;}
 }

 //-----------------------------------------------------------------
@@ -293,7 +293,7 @@
 int value =0;
 float vout=0;
   value = analogRead(MAIN_VOLTAGE_BATT_PIN);
-  vout = (value * V_REF) / 1024.0;
+  vout = (value * V_REF) / 1024.0;
   MainBattVoltage = (vout / (MainBattR2/(MainBattR1+MainBattR2))) + MAIN_BATT_VADD;
 }

@@ -1101,31 +1101,35 @@

 //Engine STOP handling
 //in Normal operating mode Engine stop signal equal Switch position: lower pos = OFF, upper pos = ON
- if (SystemMode==SYSTEM_NORMAL){EngineSTOP=!SwitchPOS;} //Set EngineSTOP with Switch position Up=FALSE, Down=TRUE
-
+ if (SystemMode==SYSTEM_NORMAL){
+  LastEngineSTOP=EngineSTOP;
+  EngineSTOP=!SwitchPOS;} //Set EngineSTOP with Switch position Up=FALSE, Down=TRUE
+
+if (!SystemStatusNoRX) {
  if (!EngineSTOP) { //if SwitchPOS in Upper position(ignition is ON) then setup output pin to HIGH one time!
   //prevent high speed duplicate switching with potential glitches with flags
   if (!EngineSTOP_flag) {
      digitalWrite(KILLSWITCH_OUT_PIN, HIGH);
      tone(BUZZER_PIN,2300,30);
-     LastEngineSTOP=EngineSTOP;
      EngineSTOP_flag=true;
   }
  }
  else
  { //if SwitchPOS in Lower position(ignition is OFF) then setup output pin to LOW one time!
    //prevent high speed duplicate switching with potential glitches.
-  if (EngineSTOP!=LastEngineSTOP) //if EngineSTOP real change his state then setup output pin and play sound
+  if (EngineSTOP_flag)
       {digitalWrite(KILLSWITCH_OUT_PIN, LOW);
        tone(BUZZER_PIN,200,30);
-       LastEngineSTOP=EngineSTOP;
        EngineSTOP_flag=false;}
  }
+} else {EngineSTOP=LastEngineSTOP;};
+

  //NoRX handling
   if (MaxMainSWPacketsCounter<=1) {
       SystemStatusNoRX=true;
      } else {SystemStatusNoRX=false;}
+

  //if Switch pressed(from Up to Down) then handling options
    if (millis()-MainSWPressLaststime<=BUZZER_SEARCHER_PERIOD && MainSWPressCounter>=1)
@@ -1288,40 +1292,42 @@
    Serial.begin(38400);
    Wire.begin();

-  //Pin setup
-  pinMode(MAINSWITCH_IN_PIN, INPUT);
-  pinMode(SYSTEM_SERVICE_PIN, INPUT);
-  pinMode(SERVO_TESTER_OUT_PIN, OUTPUT);
-  pinMode(KILLSWITCH_OUT_PIN, OUTPUT);
-  digitalWrite(KILLSWITCH_OUT_PIN, LOW);
-  pinMode(BUZZER_PIN, OUTPUT);
-  digitalWrite(BUZZER_PIN, LOW);
-
- //Setup the LED pin as an output:
+//Setup the LED pin as an output:
   pinMode(LED_PIN, OUTPUT);
   pinMode(MAIN_LED_R, OUTPUT);
   pinMode(MAIN_LED_G, OUTPUT);
   pinMode(MAIN_LED_B, OUTPUT);

- //Setup hardware interrupt point
+//Setup PPM and Servo pins
+  pinMode(MAINSWITCH_IN_PIN, INPUT);
   digitalWrite(MAINSWITCH_IN_PIN, HIGH);
+  pinMode(KILLSWITCH_OUT_PIN, OUTPUT);
+//attach hardware interrupt with ANY CHANGE option
   attachInterrupt(0,MainSWHandler,CHANGE);

-  SystemServiceMode=false;
-
-  SearchBuzzerOn_flag=false;
-
- //Setup software timer interrupt
+//Setup Buzzer Pin
+  pinMode(BUZZER_PIN, OUTPUT);
+//  digitalWrite(BUZZER_PIN, LOW);
+
+//Setup Service Mode pin
+ pinMode(SYSTEM_SERVICE_PIN, INPUT);
+ if (digitalRead(SYSTEM_SERVICE_PIN)==HIGH) {
+ pinMode(SERVO_TESTER_OUT_PIN, OUTPUT);
+ SystemServiceMode=true;
+  myservo.attach(SERVO_TESTER_OUT_PIN);}
+ else {SystemServiceMode=false;}
+
+ //Setup software timer interrupt. 250ms cycle
   int tickEvent = m_timer.every(250, MainTimerHandler);

  //Setup system mode to first start for normal use interrupts
   SystemMode = SYSTEM_FIRST_START;
-
 }

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

 void FirstTimeRunInit(){
+
  if (ReadEEPROMConfig()) {
         Serial.println("EEPROM Config clean. Use DEFAULTS!");
         WriteEEPROMConfig();
@@ -1329,19 +1335,38 @@
         else
         {Serial.println("Use EEPROM Config. Set parameters");}

- if (digitalRead(SYSTEM_SERVICE_PIN)==HIGH) {
-  SystemServiceMode=true;
-  myservo.attach(SERVO_TESTER_OUT_PIN);}
-  RenderCurrentConfig();
-  PlayMenuSound(SOUND_KSW_INTRO);
-
+//Setup voltages
+   readMainBattVoltage();
+   MainBattVoltageAverage=MainBattVoltage;
+
    //reset counters
+   MainSWPacketsCounter=0;
    MainSWPressCounter=0;
-   readMainBattVoltage();
    MainBattVoltageCount=0;
    MainBattVoltageSum=0.0;
    MainBattVoltageAverage_time=7;
-   MainBattVoltageAverage=MainBattVoltage;
+
+//Setup flags
+   EngineSTOP_flag=false;
+   SearchBuzzerOn_flag=false;
+
+
+//First MainSwitch reading
+   if (MainSWTime >= PPMSwitchLevel)
+    {
+     //Switch in Upper position
+     SwitchPOS=true;
+     SwitchPOS_fromUp=true;} else
+     {
+     //Switch in Lower position
+     SwitchPOS=false;
+     SwitchPOS_fromUp=false;}
+
+
+  PlayMenuSound(SOUND_KSW_INTRO);
+
+
+  RenderCurrentConfig();

   //initial menu time readings
    MainSWPressLaststime=millis();


Update FunkyFellow1_1.ino

Update FunkyFellow1_1.ino

Add description of usage

--- FunkyFellow1_1.ino
+++ FunkyFellow1_1.ino
@@ -1,449 +1,451 @@
-/*
-FunkyFellow1_1.ino
-Filter effect using state variable filters.
-Thanks to Paul Stoffregen, www.PJRC.com, that made the great audio library fro Teensy! Plus all the other great stuff!
-This code can be loaded into a Teensy3.1/3.2 with a Audio sheild. Use a I2C 64x128 OLED screen to show the graphics.
-All in all use the OpenEffectsBox from OnkartGromt.
- */
-#include <EEPROM.h>
-#include <Bounce.h>
-#include <Audio.h>
-#include <Wire.h>
-#include <SPI.h>
-#include <SD.h>
-#include <SerialFlash.h>
-#include <Adafruit_GFX.h>
-#include <Adafruit_SSD1306.h>
-
-#define OLED_RESET 4
-Adafruit_SSD1306 display(OLED_RESET);
-
-// GUItool: begin automatically generated code
-AudioSynthWaveform       waveform1;      //xy=106,573
-AudioSynthWaveformDc     dc1;            //xy=109,473
-AudioInputI2S            i2s1;           //xy=140,314
-AudioSynthWaveformDc     dc2;            //xy=140.88888549804688,358.8888854980469
-AudioEffectMultiply      multiply2;      //xy=248,532
-AudioAnalyzePeak         peak3;          //xy=254,573
-AudioEffectMultiply      multiply3;      //xy=298.8888854980469,313.8888854980469
-AudioMixer4              mixer3;         //xy=393,492
-AudioFilterStateVariable filter1;        //xy=456,147
-AudioEffectMultiply      multiply1;      //xy=495,420
-AudioAnalyzePeak         peak1;          //xy=673,420
-AudioFilterStateVariable filter2;        //xy=759,151
-AudioFilterStateVariable filter3;        //xy=759,204
-AudioFilterStateVariable filter4;        //xy=759,257
-AudioMixer4              mixer2;         //xy=911,78
-AudioMixer4              mixer1;         //xy=911,216
-AudioMixer4              mixer4;         //xy=1187,295
-AudioAnalyzeFFT1024      fft1024_1;      //xy=1385,389
-AudioAnalyzePeak         peak2;          //xy=1394,297
-AudioOutputI2S           i2s2;           //xy=1394,342
-AudioConnection          patchCord1(waveform1, 0, multiply2, 1);
-AudioConnection          patchCord2(waveform1, peak3);
-AudioConnection          patchCord3(dc1, 0, multiply2, 0);
-AudioConnection          patchCord4(dc1, 0, mixer3, 0);
-AudioConnection          patchCord5(i2s1, 0, multiply3, 0);
-AudioConnection          patchCord6(dc2, 0, multiply3, 1);
-AudioConnection          patchCord7(multiply2, 0, mixer3, 1);
-AudioConnection          patchCord8(multiply3, 0, multiply1, 0);
-AudioConnection          patchCord9(multiply3, 0, filter1, 0);
-AudioConnection          patchCord10(multiply3, fft1024_1);
-AudioConnection          patchCord11(multiply3, 0, mixer4, 3);
-AudioConnection          patchCord12(mixer3, 0, multiply1, 1);
-AudioConnection          patchCord13(filter1, 0, filter2, 0);
-AudioConnection          patchCord14(filter1, 0, mixer2, 0);
-AudioConnection          patchCord15(filter1, 1, filter3, 0);
-AudioConnection          patchCord16(filter1, 1, mixer2, 1);
-AudioConnection          patchCord17(filter1, 2, filter4, 0);
-AudioConnection          patchCord18(filter1, 2, mixer2, 2);
-AudioConnection          patchCord19(multiply1, peak1);
-AudioConnection          patchCord20(multiply1, 0, filter1, 1);
-AudioConnection          patchCord21(multiply1, 0, filter2, 1);
-AudioConnection          patchCord22(multiply1, 0, filter3, 1);
-AudioConnection          patchCord23(multiply1, 0, filter4, 1);
-AudioConnection          patchCord24(filter2, 0, mixer1, 0);
-AudioConnection          patchCord25(filter3, 1, mixer1, 1);
-AudioConnection          patchCord26(filter4, 2, mixer1, 2);
-AudioConnection          patchCord27(mixer2, 0, mixer4, 0);
-AudioConnection          patchCord28(mixer1, 0, mixer4, 1);
-AudioConnection          patchCord29(mixer4, peak2);
-AudioConnection          patchCord30(mixer4, 0, i2s2, 0);
-AudioConnection          patchCord31(mixer4, 0, i2s2, 1);
-AudioControlSGTL5000     sgtl5000_1;     //xy=662.0000305175781,536.0000305175781
-// GUItool: end automatically generated code
-
-//Pinout board rev1
-int Pot1 = A6;    // select the input pin for the potentiometer
-int Pot2 = A3;    // select the input pin for the potentiometer
-int Pot3 = A2;    // select the input pin for the potentiometer
-int Pot4 = A1;    // select the input pin for the potentiometer
-int CV1 = A10;
-int CV2 = A11;
-
-int Tap1 = 0;
-int Tap2 = 1;
-
-int SW1 = A12;
-int SW2 = A13;
-
-int ledPin1 = 3;      // select the pin for the LEDonoff
-int ledPin2 = 4;      // select the pin for the LEDyellow
-int ledPin3 = 5;      // select the pin for the LEDmode/tap
-
-//Variables for values
-boolean Tap1Value = 0;
-boolean Tap2Value = 0;
-float Pot1Value = 0;
-float Pot2Value = 0;
-float Pot3Value = 0;
-float Pot4Value = 0;
-int SW1Value = 0;
-int SW2Value = 0;
-float CV1Value = 0;
-float CV2Value = 0;
-float Pot1ValueOld = 0;  // variable to store the previous value
-float Pot2ValueOld = 0;
-float Pot3ValueOld = 0;
-float Pot4ValueOld = 0;
-int SW1ValueOld = 0;
-int SW2ValueOld = 0;
-int Tap1ValueOld = 1;
-int Tap2ValueOld = 1;
-int CV1ValueOld = 0;
-int Tap1Timer = 0;
-int Tap2Timer = 0;
-float margin  = 0.1;
-int modulationMode = 0;
-boolean Tap2Pressed = 0;
-int filterOrder = 24;
-int GraphFreq = 0;
-float ffund = 0;
-
-// Variables
-int ledStateONOFF = LOW;         // the current state of the output pin
-int buttonState0;             // the current reading from the input pin
-int lastButtonState0 = LOW;   // the previous reading from the input pin
-int ledStateBOOST = LOW;         // the current state of the output pin
-int buttonState1;             // the current reading from the input pin
-int lastButtonState1 = LOW;   // the previous reading from the input pin
-
-unsigned long lastDebounceTime0 = 0;  // the last time the output pin was toggled
-unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
-unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
-
-float peak = 0.0;
-float peak_2 = 0.0;
-float peak_3 =0.0;
-int spanfreq = 500;
-int offsetfreq = 201;
-int movingfreq = 500;
-int octave = 7;
-float level = 0.85;
-float modFreq = 3;
-float modFreqOld = 3;
-float InLevel = 0;
-
-const int myInput = AUDIO_INPUT_LINEIN;
-
-float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
-{
-  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
-}
-Bounce OnOff = Bounce(Tap1, 30 );
-Bounce BoostOnOff = Bounce(Tap2, 30);
-
-void setup() {
-  AudioMemory(100);
-  InLevel = float(EEPROM.read(0)/255.0);
-  dc2.amplitude(1, 20);
-  sgtl5000_1.enable();  // Enable the audio shield
-  sgtl5000_1.inputSelect(myInput);
-  sgtl5000_1.volume(0.8);
-  sgtl5000_1.lineInLevel(5);   // 1,33Vp-p
-  sgtl5000_1.lineOutLevel(13); // 3.16Vp-p
-  fft1024_1.windowFunction(AudioWindowHanning1024);
-
-  pinMode(ledPin1, OUTPUT);
-  pinMode(ledPin2, OUTPUT);
-  pinMode(ledPin3, OUTPUT);
-  pinMode(Tap1, INPUT);
-  pinMode(Tap2, INPUT);
-  mixer3.gain(0, 1);
-  mixer3.gain(1, 0);
-  mixer4.gain(0, 0);
-  mixer4.gain(1, 0);
-  mixer4.gain(3, 1.65);
-  mixer1.gain(0, 1);    //24order filter
-  mixer1.gain(1, 1);
-  mixer1.gain(2, 1);
-  mixer1.gain(3, 0);
-  mixer2.gain(0, 1);    //12 order filter
-  mixer2.gain(1, 1);
-  mixer2.gain(2, 1);
-  mixer2.gain(3, 0);
-  sgtl5000_1.dacVolume (level);
-  sgtl5000_1.autoVolumeControl(2,0,0,0.7,50,100);  //maxGain,response,hard limit,threshold,attack, decay
-  sgtl5000_1.autoVolumeEnable();
-  Serial.begin(115200);
-  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
-  display.clearDisplay();
-  delay(100);
-}
-
-//Main loop
-void loop() {
-  OnOff.update();      //update the bounce
-  BoostOnOff.update();
-
-  // read the value from the sensor:
-  Pot1Value = analogRead(Pot1);    //Sense
-  Pot2Value = analogRead(Pot2);    //Resonance
-  Pot3Value = analogRead(Pot3);    //Freq
-  Pot4Value = analogRead(Pot4);    //Mode
-  Tap1Value = digitalRead(Tap1);   //On off
-  Tap2Value = digitalRead(Tap2);   //Mode/Tap
-  SW1Value = analogRead(SW1);      //Filter char
-  SW2Value = analogRead(SW2);      //Direction
-  CV1Value = analogRead(CV1);      //CV input
-  CV2Value = analogRead(CV2);      //EXP input
-
-  Pot1Value = mapfloat(Pot1Value, 0, 1023, 1, 0);        //Sense
-  Pot2Value = mapfloat(Pot2Value, 0, 1023, 2, 0.7);      //Resonance
-  GraphFreq = map(Pot3Value, 0, 1023, 90, 30);           //Moving point of Graph
-  Pot3Value = map(Pot3Value, 0, 1023, 1500, 150);        //Freq
-  Pot4Value = mapfloat(Pot4Value, 0, 1023, 10.0, 0.1);   //ModFreq
-  SW1Value = map(SW1Value, 0, 1023, 5, 0);               //Filter char
-  SW1Value = constrain(SW1Value, 1, 5);
-  SW2Value = map(SW2Value, 0, 1023, 5, 0);               //Direction
-  SW2Value = constrain(SW2Value, 1, 5);
-  CV1Value = map(CV1Value, 0, 1023, 10, 1);              //Octave CVinput
-  CV2Value = map(CV2Value, 0, 1023, 1500, 150);          //Freq expression pedal
-
-  buttonState0 = OnOff.read();
-  if (lastButtonState0 != buttonState0){
-      // only toggle the state if the new button state is HIGH
-      if (buttonState0 == LOW) {
-        ledStateONOFF = !ledStateONOFF;
-      }
-  }
-  buttonState1 = BoostOnOff.read();
-  if (lastButtonState1 != buttonState1){
-      // only toggle the state if the new button state is HIGH
-      if (buttonState1 == LOW) {
-        ledStateBOOST = !ledStateBOOST;
-      }
-  }
-
-    // set the outputs:
-  digitalWrite(ledPin1, ledStateONOFF);
-  lastButtonState0 = buttonState0;  //save readings to next round
-  lastButtonState1 = buttonState1;
-
-  //Sets the sense multiplication factor
-  if (SW2Value == 3)dc1.amplitude(Pot1Value);
-  else if (SW2Value == 5)dc1.amplitude(-Pot1Value);
-
-  //read the signal input peak
-  if (peak1.available())  peak = peak1.read();
-  if (peak2.available())  peak_2 = peak2.read();    //Output peak
-  if (peak3.available())  peak_3 = peak3.read();
-
-  if (modulationMode == 0){
-    analogWrite(ledPin2, peak_2*400);    //yellow LED
-    if (Pot4Value <= 5)filterOrder = 12;
-    else filterOrder = 24;
-    }
-  else analogWrite(ledPin2, (peak_3)*100);  //modulation active
-
-  if (CV1Value <1) octave = 6;  //Check if CVinput is active
-  else octave = CV1Value;
-
-  if (CV2Value <100) spanfreq = Pot3Value;  //Check if exp pedal is active
-  else spanfreq = CV2Value;
-
-  if (SW2Value == 3) movingfreq = peak*2 * spanfreq + spanfreq ;
-  if (SW2Value == 5) movingfreq = -peak *2* spanfreq + spanfreq ;
-  if (SW2Value == 1) movingfreq = spanfreq;    //not moving filter
-
-  filter1.frequency(movingfreq);
-  filter1.resonance(Pot2Value);
-  filter1.octaveControl(octave);
-  filter2.frequency(movingfreq);
-  filter2.resonance(Pot2Value);
-  filter2.octaveControl(octave);
-  filter3.frequency(movingfreq);
-  filter3.resonance(Pot2Value);
-  filter3.octaveControl(octave);
-  filter4.frequency(movingfreq);
-  filter4.resonance(Pot2Value);
-  filter4.octaveControl(octave);
-
-  waveform1.frequency(Pot4Value);
-
-if (!Tap2Value && (Tap2Value == Tap2ValueOld) && modulationMode == 0 && Tap2Pressed == 0){ //turn on modulation
-  Serial.print("TIME0\n");
-  Tap2Timer++;
-  if (Tap2Timer > 15){
-    mixer3.gain(0,0);
-    mixer3.gain(1,1);
-    modulationMode = 1;
-    analogWrite(ledPin2,255);
-    digitalWrite(ledPin3,HIGH);
-    Tap2Pressed = 1;
-  }
-}
-else if (!Tap2Value && (Tap2Value == Tap2ValueOld) && modulationMode == 1 && Tap2Pressed == 0){ //turn off modulation
-  Serial.print("TIME1\n");
-  Tap2Timer++;
-  if (Tap2Timer > 15){
-    mixer3.gain(0,1);
-    mixer3.gain(1,0);
-    modulationMode = 0;
-    analogWrite(ledPin2,255);
-    digitalWrite(ledPin3,LOW);
-    Tap2Pressed = 1;
-  }
-}
-else if (Tap2Value){
-  Tap2Timer = 0;
-  Tap2Pressed = 0;
-  }
-
-//BYPASS MODE
-  if (ledStateONOFF == 0){
-      mixer4.gain(0, 0);
-      mixer4.gain(1, 0);
-      mixer4.gain(2, 0);
-      mixer4.gain(3, 1.65);
-  }
-  else {
-      mixer4.gain(3, 0);  //Always turn off bypass signal
-    if (SW1Value == 3) {  //HP
-      if (filterOrder == 12) { //   12db/dec
-        mixer4.gain(0, 1.3);
-        mixer4.gain(1, 0);
-        mixer2.gain(0, 0);
-        mixer2.gain(1, 0);
-        mixer2.gain(2, 1);
-        }
-      else if (filterOrder == 24) {    //24db/dec
-        mixer4.gain(0, 0);
-        mixer4.gain(1, 1.3);
-        mixer1.gain(0, 0);
-        mixer1.gain(1, 0);
-        mixer1.gain(2, 1);
-      }
-    }
-    else if (SW1Value == 1) {  //BP
-       if (filterOrder == 12) { //   12db/dec
-        mixer4.gain(0, 1.3);
-        mixer4.gain(1, 0);
-        mixer2.gain(0, 0);
-        mixer2.gain(1, 1);
-        mixer2.gain(2, 0);
-        }
-      else if (filterOrder == 24) {    //24db/dec
-        mixer4.gain(0, 0);
-        mixer4.gain(1, 1.3);
-        mixer1.gain(0, 0);
-        mixer1.gain(1, 1);
-        mixer1.gain(2, 0);
-      }
-    }
-    else if (SW1Value == 5) { //LowPass
-       if (filterOrder == 12) { //   12db/dec
-        mixer4.gain(0, 1.3);
-        mixer4.gain(1, 0);
-        mixer2.gain(0, 1);
-        mixer2.gain(1, 0);
-        mixer2.gain(2, 0);
-        }
-      else if (filterOrder == 24) {    //24db/dec
-        mixer4.gain(0, 0);
-        mixer4.gain(1, 1.3);
-        mixer1.gain(0, 1);
-        mixer1.gain(1, 0);
-        mixer1.gain(2, 0);
-      }
-    }
-  }
-display.clearDisplay();
-if (!Tap1Value && (Tap1Value == Tap1ValueOld)){    //When Mode/tap is held down you can adjust the input gain of the input
-  Serial.print("TIME");
-  Tap1Timer++;
-  if (Tap1Timer > 15){
-    InLevel = analogRead(Pot1);
-    InLevel = mapfloat(InLevel,0,1023,1,0.2);
-    dc2.amplitude(InLevel,10);
-    delay(50);
-    EEPROM.write(0, InLevel*255);
-    analogWrite(ledPin2, 255);
-    //display.clearDisplay();
-    display.setTextSize(1);
-    display.setTextColor(WHITE);
-    display.setCursor(5, 10);
-    display.print("Input:");
-    display.print(InLevel);
-    display.display();
-  }
-}
-else if (Tap1Value){
-  Tap1Timer = 0;
-//  peak = peak1.read();   //read the signal output peak
-  if (peak == -1)(peak = 0);
-  analogWrite(ledPin2, peak*100);
-}
-if(fft1024_1.available()){        //Display FFT on screen
- // display.clearDisplay();
-  for (int i=0; i<42; i++) {
-    float fft = fft1024_1.read(i)*512;
-    //Serial.print(fft);
-    //Serial.print(",");
-    display.drawLine(i*3, 64, i*3, 64-fft, WHITE);
-    display.drawLine(i*3+1, 64, i*3+1, 64-fft, WHITE);
-    display.drawLine(i*3+2, 64, i*3+2, 64-fft, WHITE);
-  }
-}
-//  display.clearDisplay();
-  GraphFreq = movingfreq/15;
- if(SW1Value ==5){    //LP
-    display.drawLine(0, 32, GraphFreq-5, 32, WHITE);
-    display.drawLine(GraphFreq-5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
-    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq+5, 32, WHITE);
-    display.drawLine(GraphFreq+5, 32, GraphFreq+(48-filterOrder), 64, WHITE);
- }
- else if(SW1Value == 3){    //HP
-    display.drawLine(128, 32, GraphFreq+5, 32, WHITE);
-    display.drawLine(GraphFreq+5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
-    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq-5, 32, WHITE);
-    display.drawLine(GraphFreq-5, 32, GraphFreq-(48-filterOrder), 64, WHITE);
- }
-  else {    //BP
-    display.drawLine(GraphFreq-(48-filterOrder), 64, GraphFreq-5, 32, WHITE);
-    display.drawLine(GraphFreq+5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
-    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq-5, 32, WHITE);
-    display.drawLine(GraphFreq+5, 32, GraphFreq+(48-filterOrder), 64, WHITE);
- }
-  display.setTextSize(1);
-  display.setTextColor(WHITE);
-  display.setCursor(80, 10);
-  display.print("fc:");
-  display.print(movingfreq);
-  display.display();
-
-   Serial.print(" InLevel: ");
-   Serial.print(InLevel);
-   Serial.print(" Filterorder: ");
-   Serial.println(filterOrder);
-
-   Pot1ValueOld = Pot1Value;
-   Pot2ValueOld = Pot2Value;
-   Pot3ValueOld = Pot3Value;
-   Pot4ValueOld = Pot4Value;
-   SW1ValueOld = SW1Value;
-   SW2ValueOld = SW2Value;
-   Tap1ValueOld = Tap1Value;
-   Tap2ValueOld = Tap2Value;
-   CV1ValueOld = CV1Value;
-}
+/*
+FunkyFellow1_1.ino
+Filter effect using state variable filters.
+Thanks to Paul Stoffregen, www.PJRC.com, that made the great audio library fro Teensy! Plus all the other great stuff!
+This code can be loaded into a Teensy3.1/3.2 with a Audio sheild. Use a I2C 64x128 OLED screen to show the graphics.
+Hold the On/Off switch for 1 sek to edit the input gain with pot1.
+Activate sine modulation mode by holding Mode/tap button in 2 sek.
+All in all use the OpenEffectsBox from OnkartGromt.
+ */
+#include <EEPROM.h>
+#include <Bounce.h>
+#include <Audio.h>
+#include <Wire.h>
+#include <SPI.h>
+#include <SD.h>
+#include <SerialFlash.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+
+#define OLED_RESET 4
+Adafruit_SSD1306 display(OLED_RESET);
+
+// GUItool: begin automatically generated code
+AudioSynthWaveform       waveform1;      //xy=106,573
+AudioSynthWaveformDc     dc1;            //xy=109,473
+AudioInputI2S            i2s1;           //xy=140,314
+AudioSynthWaveformDc     dc2;            //xy=140.88888549804688,358.8888854980469
+AudioEffectMultiply      multiply2;      //xy=248,532
+AudioAnalyzePeak         peak3;          //xy=254,573
+AudioEffectMultiply      multiply3;      //xy=298.8888854980469,313.8888854980469
+AudioMixer4              mixer3;         //xy=393,492
+AudioFilterStateVariable filter1;        //xy=456,147
+AudioEffectMultiply      multiply1;      //xy=495,420
+AudioAnalyzePeak         peak1;          //xy=673,420
+AudioFilterStateVariable filter2;        //xy=759,151
+AudioFilterStateVariable filter3;        //xy=759,204
+AudioFilterStateVariable filter4;        //xy=759,257
+AudioMixer4              mixer2;         //xy=911,78
+AudioMixer4              mixer1;         //xy=911,216
+AudioMixer4              mixer4;         //xy=1187,295
+AudioAnalyzeFFT1024      fft1024_1;      //xy=1385,389
+AudioAnalyzePeak         peak2;          //xy=1394,297
+AudioOutputI2S           i2s2;           //xy=1394,342
+AudioConnection          patchCord1(waveform1, 0, multiply2, 1);
+AudioConnection          patchCord2(waveform1, peak3);
+AudioConnection          patchCord3(dc1, 0, multiply2, 0);
+AudioConnection          patchCord4(dc1, 0, mixer3, 0);
+AudioConnection          patchCord5(i2s1, 0, multiply3, 0);
+AudioConnection          patchCord6(dc2, 0, multiply3, 1);
+AudioConnection          patchCord7(multiply2, 0, mixer3, 1);
+AudioConnection          patchCord8(multiply3, 0, multiply1, 0);
+AudioConnection          patchCord9(multiply3, 0, filter1, 0);
+AudioConnection          patchCord10(multiply3, fft1024_1);
+AudioConnection          patchCord11(multiply3, 0, mixer4, 3);
+AudioConnection          patchCord12(mixer3, 0, multiply1, 1);
+AudioConnection          patchCord13(filter1, 0, filter2, 0);
+AudioConnection          patchCord14(filter1, 0, mixer2, 0);
+AudioConnection          patchCord15(filter1, 1, filter3, 0);
+AudioConnection          patchCord16(filter1, 1, mixer2, 1);
+AudioConnection          patchCord17(filter1, 2, filter4, 0);
+AudioConnection          patchCord18(filter1, 2, mixer2, 2);
+AudioConnection          patchCord19(multiply1, peak1);
+AudioConnection          patchCord20(multiply1, 0, filter1, 1);
+AudioConnection          patchCord21(multiply1, 0, filter2, 1);
+AudioConnection          patchCord22(multiply1, 0, filter3, 1);
+AudioConnection          patchCord23(multiply1, 0, filter4, 1);
+AudioConnection          patchCord24(filter2, 0, mixer1, 0);
+AudioConnection          patchCord25(filter3, 1, mixer1, 1);
+AudioConnection          patchCord26(filter4, 2, mixer1, 2);
+AudioConnection          patchCord27(mixer2, 0, mixer4, 0);
+AudioConnection          patchCord28(mixer1, 0, mixer4, 1);
+AudioConnection          patchCord29(mixer4, peak2);
+AudioConnection          patchCord30(mixer4, 0, i2s2, 0);
+AudioConnection          patchCord31(mixer4, 0, i2s2, 1);
+AudioControlSGTL5000     sgtl5000_1;     //xy=662.0000305175781,536.0000305175781
+// GUItool: end automatically generated code
+
+//Pinout board rev1
+int Pot1 = A6;    // select the input pin for the potentiometer
+int Pot2 = A3;    // select the input pin for the potentiometer
+int Pot3 = A2;    // select the input pin for the potentiometer
+int Pot4 = A1;    // select the input pin for the potentiometer
+int CV1 = A10;
+int CV2 = A11;
+
+int Tap1 = 0;
+int Tap2 = 1;
+
+int SW1 = A12;
+int SW2 = A13;
+
+int ledPin1 = 3;      // select the pin for the LEDonoff
+int ledPin2 = 4;      // select the pin for the LEDyellow
+int ledPin3 = 5;      // select the pin for the LEDmode/tap
+
+//Variables for values
+boolean Tap1Value = 0;
+boolean Tap2Value = 0;
+float Pot1Value = 0;
+float Pot2Value = 0;
+float Pot3Value = 0;
+float Pot4Value = 0;
+int SW1Value = 0;
+int SW2Value = 0;
+float CV1Value = 0;
+float CV2Value = 0;
+float Pot1ValueOld = 0;  // variable to store the previous value
+float Pot2ValueOld = 0;
+float Pot3ValueOld = 0;
+float Pot4ValueOld = 0;
+int SW1ValueOld = 0;
+int SW2ValueOld = 0;
+int Tap1ValueOld = 1;
+int Tap2ValueOld = 1;
+int CV1ValueOld = 0;
+int Tap1Timer = 0;
+int Tap2Timer = 0;
+float margin  = 0.1;
+int modulationMode = 0;
+boolean Tap2Pressed = 0;
+int filterOrder = 24;
+int GraphFreq = 0;
+float ffund = 0;
+
+// Variables
+int ledStateONOFF = LOW;         // the current state of the output pin
+int buttonState0;             // the current reading from the input pin
+int lastButtonState0 = LOW;   // the previous reading from the input pin
+int ledStateBOOST = LOW;         // the current state of the output pin
+int buttonState1;             // the current reading from the input pin
+int lastButtonState1 = LOW;   // the previous reading from the input pin
+
+unsigned long lastDebounceTime0 = 0;  // the last time the output pin was toggled
+unsigned long lastDebounceTime1 = 0;  // the last time the output pin was toggled
+unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers
+
+float peak = 0.0;
+float peak_2 = 0.0;
+float peak_3 =0.0;
+int spanfreq = 500;
+int offsetfreq = 201;
+int movingfreq = 500;
+int octave = 7;
+float level = 0.85;
+float modFreq = 3;
+float modFreqOld = 3;
+float InLevel = 0;
+
+const int myInput = AUDIO_INPUT_LINEIN;
+
+float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
+{
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+Bounce OnOff = Bounce(Tap1, 30 );
+Bounce BoostOnOff = Bounce(Tap2, 30);
+
+void setup() {
+  AudioMemory(100);
+  InLevel = float(EEPROM.read(0)/255.0);
+  dc2.amplitude(1, 20);
+  sgtl5000_1.enable();  // Enable the audio shield
+  sgtl5000_1.inputSelect(myInput);
+  sgtl5000_1.volume(0.8);
+  sgtl5000_1.lineInLevel(5);   // 1,33Vp-p
+  sgtl5000_1.lineOutLevel(13); // 3.16Vp-p
+  fft1024_1.windowFunction(AudioWindowHanning1024);
+
+  pinMode(ledPin1, OUTPUT);
+  pinMode(ledPin2, OUTPUT);
+  pinMode(ledPin3, OUTPUT);
+  pinMode(Tap1, INPUT);
+  pinMode(Tap2, INPUT);
+  mixer3.gain(0, 1);
+  mixer3.gain(1, 0);
+  mixer4.gain(0, 0);
+  mixer4.gain(1, 0);
+  mixer4.gain(3, 1.65);
+  mixer1.gain(0, 1);    //24order filter
+  mixer1.gain(1, 1);
+  mixer1.gain(2, 1);
+  mixer1.gain(3, 0);
+  mixer2.gain(0, 1);    //12 order filter
+  mixer2.gain(1, 1);
+  mixer2.gain(2, 1);
+  mixer2.gain(3, 0);
+  sgtl5000_1.dacVolume (level);
+  sgtl5000_1.autoVolumeControl(2,0,0,0.7,50,100);  //maxGain,response,hard limit,threshold,attack, decay
+  sgtl5000_1.autoVolumeEnable();
+  Serial.begin(115200);
+  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
+  display.clearDisplay();
+  delay(100);
+}
+
+//Main loop
+void loop() {
+  OnOff.update();      //update the bounce
+  BoostOnOff.update();
+
+  // read the value from the sensor:
+  Pot1Value = analogRead(Pot1);    //Sense
+  Pot2Value = analogRead(Pot2);    //Resonance
+  Pot3Value = analogRead(Pot3);    //Freq
+  Pot4Value = analogRead(Pot4);    //Mode
+  Tap1Value = digitalRead(Tap1);   //On off
+  Tap2Value = digitalRead(Tap2);   //Mode/Tap
+  SW1Value = analogRead(SW1);      //Filter char
+  SW2Value = analogRead(SW2);      //Direction
+  CV1Value = analogRead(CV1);      //CV input
+  CV2Value = analogRead(CV2);      //EXP input
+
+  Pot1Value = mapfloat(Pot1Value, 0, 1023, 1, 0);        //Sense
+  Pot2Value = mapfloat(Pot2Value, 0, 1023, 2, 0.7);      //Resonance
+  GraphFreq = map(Pot3Value, 0, 1023, 90, 30);           //Moving point of Graph
+  Pot3Value = map(Pot3Value, 0, 1023, 1500, 150);        //Freq
+  Pot4Value = mapfloat(Pot4Value, 0, 1023, 10.0, 0.1);   //ModFreq
+  SW1Value = map(SW1Value, 0, 1023, 5, 0);               //Filter char
+  SW1Value = constrain(SW1Value, 1, 5);
+  SW2Value = map(SW2Value, 0, 1023, 5, 0);               //Direction
+  SW2Value = constrain(SW2Value, 1, 5);
+  CV1Value = map(CV1Value, 0, 1023, 10, 1);              //Octave CVinput
+  CV2Value = map(CV2Value, 0, 1023, 1500, 150);          //Freq expression pedal
+
+  buttonState0 = OnOff.read();
+  if (lastButtonState0 != buttonState0){
+      // only toggle the state if the new button state is HIGH
+      if (buttonState0 == LOW) {
+        ledStateONOFF = !ledStateONOFF;
+      }
+  }
+  buttonState1 = BoostOnOff.read();
+  if (lastButtonState1 != buttonState1){
+      // only toggle the state if the new button state is HIGH
+      if (buttonState1 == LOW) {
+        ledStateBOOST = !ledStateBOOST;
+      }
+  }
+
+    // set the outputs:
+  digitalWrite(ledPin1, ledStateONOFF);
+  lastButtonState0 = buttonState0;  //save readings to next round
+  lastButtonState1 = buttonState1;
+
+  //Sets the sense multiplication factor
+  if (SW2Value == 3)dc1.amplitude(Pot1Value);
+  else if (SW2Value == 5)dc1.amplitude(-Pot1Value);
+
+  //read the signal input peak
+  if (peak1.available())  peak = peak1.read();
+  if (peak2.available())  peak_2 = peak2.read();    //Output peak
+  if (peak3.available())  peak_3 = peak3.read();
+
+  if (modulationMode == 0){
+    analogWrite(ledPin2, peak_2*400);    //yellow LED
+    if (Pot4Value <= 5)filterOrder = 12;
+    else filterOrder = 24;
+    }
+  else analogWrite(ledPin2, (peak_3)*100);  //modulation active
+
+  if (CV1Value <1) octave = 6;  //Check if CVinput is active
+  else octave = CV1Value;
+
+  if (CV2Value <100) spanfreq = Pot3Value;  //Check if exp pedal is active
+  else spanfreq = CV2Value;
+
+  if (SW2Value == 3) movingfreq = peak*2 * spanfreq + spanfreq ;
+  if (SW2Value == 5) movingfreq = -peak *2* spanfreq + spanfreq ;
+  if (SW2Value == 1) movingfreq = spanfreq;    //not moving filter
+
+  filter1.frequency(movingfreq);
+  filter1.resonance(Pot2Value);
+  filter1.octaveControl(octave);
+  filter2.frequency(movingfreq);
+  filter2.resonance(Pot2Value);
+  filter2.octaveControl(octave);
+  filter3.frequency(movingfreq);
+  filter3.resonance(Pot2Value);
+  filter3.octaveControl(octave);
+  filter4.frequency(movingfreq);
+  filter4.resonance(Pot2Value);
+  filter4.octaveControl(octave);
+
+  waveform1.frequency(Pot4Value);
+
+if (!Tap2Value && (Tap2Value == Tap2ValueOld) && modulationMode == 0 && Tap2Pressed == 0){ //turn on modulation
+  Serial.print("TIME0\n");
+  Tap2Timer++;
+  if (Tap2Timer > 15){
+    mixer3.gain(0,0);
+    mixer3.gain(1,1);
+    modulationMode = 1;
+    analogWrite(ledPin2,255);
+    digitalWrite(ledPin3,HIGH);
+    Tap2Pressed = 1;
+  }
+}
+else if (!Tap2Value && (Tap2Value == Tap2ValueOld) && modulationMode == 1 && Tap2Pressed == 0){ //turn off modulation
+  Serial.print("TIME1\n");
+  Tap2Timer++;
+  if (Tap2Timer > 15){
+    mixer3.gain(0,1);
+    mixer3.gain(1,0);
+    modulationMode = 0;
+    analogWrite(ledPin2,255);
+    digitalWrite(ledPin3,LOW);
+    Tap2Pressed = 1;
+  }
+}
+else if (Tap2Value){
+  Tap2Timer = 0;
+  Tap2Pressed = 0;
+  }
+
+//BYPASS MODE
+  if (ledStateONOFF == 0){
+      mixer4.gain(0, 0);
+      mixer4.gain(1, 0);
+      mixer4.gain(2, 0);
+      mixer4.gain(3, 1.65);
+  }
+  else {
+      mixer4.gain(3, 0);  //Always turn off bypass signal
+    if (SW1Value == 3) {  //HP
+      if (filterOrder == 12) { //   12db/dec
+        mixer4.gain(0, 1.3);
+        mixer4.gain(1, 0);
+        mixer2.gain(0, 0);
+        mixer2.gain(1, 0);
+        mixer2.gain(2, 1);
+        }
+      else if (filterOrder == 24) {    //24db/dec
+        mixer4.gain(0, 0);
+        mixer4.gain(1, 1.3);
+        mixer1.gain(0, 0);
+        mixer1.gain(1, 0);
+        mixer1.gain(2, 1);
+      }
+    }
+    else if (SW1Value == 1) {  //BP
+       if (filterOrder == 12) { //   12db/dec
+        mixer4.gain(0, 1.3);
+        mixer4.gain(1, 0);
+        mixer2.gain(0, 0);
+        mixer2.gain(1, 1);
+        mixer2.gain(2, 0);
+        }
+      else if (filterOrder == 24) {    //24db/dec
+        mixer4.gain(0, 0);
+        mixer4.gain(1, 1.3);
+        mixer1.gain(0, 0);
+        mixer1.gain(1, 1);
+        mixer1.gain(2, 0);
+      }
+    }
+    else if (SW1Value == 5) { //LowPass
+       if (filterOrder == 12) { //   12db/dec
+        mixer4.gain(0, 1.3);
+        mixer4.gain(1, 0);
+        mixer2.gain(0, 1);
+        mixer2.gain(1, 0);
+        mixer2.gain(2, 0);
+        }
+      else if (filterOrder == 24) {    //24db/dec
+        mixer4.gain(0, 0);
+        mixer4.gain(1, 1.3);
+        mixer1.gain(0, 1);
+        mixer1.gain(1, 0);
+        mixer1.gain(2, 0);
+      }
+    }
+  }
+display.clearDisplay();
+if (!Tap1Value && (Tap1Value == Tap1ValueOld)){    //When Mode/tap is held down you can adjust the input gain of the input
+  Serial.print("TIME");
+  Tap1Timer++;
+  if (Tap1Timer > 15){
+    InLevel = analogRead(Pot1);
+    InLevel = mapfloat(InLevel,0,1023,1,0.2);
+    dc2.amplitude(InLevel,10);
+    delay(50);
+    EEPROM.write(0, InLevel*255);
+    analogWrite(ledPin2, 255);
+    //display.clearDisplay();
+    display.setTextSize(1);
+    display.setTextColor(WHITE);
+    display.setCursor(5, 10);
+    display.print("Input:");
+    display.print(InLevel);
+    display.display();
+  }
+}
+else if (Tap1Value){
+  Tap1Timer = 0;
+//  peak = peak1.read();   //read the signal output peak
+  if (peak == -1)(peak = 0);
+  analogWrite(ledPin2, peak*100);
+}
+if(fft1024_1.available()){        //Display FFT on screen
+ // display.clearDisplay();
+  for (int i=0; i<42; i++) {
+    float fft = fft1024_1.read(i)*512;
+    //Serial.print(fft);
+    //Serial.print(",");
+    display.drawLine(i*3, 64, i*3, 64-fft, WHITE);
+    display.drawLine(i*3+1, 64, i*3+1, 64-fft, WHITE);
+    display.drawLine(i*3+2, 64, i*3+2, 64-fft, WHITE);
+  }
+}
+//  display.clearDisplay();
+  GraphFreq = movingfreq/15;
+ if(SW1Value ==5){    //LP
+    display.drawLine(0, 32, GraphFreq-5, 32, WHITE);
+    display.drawLine(GraphFreq-5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
+    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq+5, 32, WHITE);
+    display.drawLine(GraphFreq+5, 32, GraphFreq+(48-filterOrder), 64, WHITE);
+ }
+ else if(SW1Value == 3){    //HP
+    display.drawLine(128, 32, GraphFreq+5, 32, WHITE);
+    display.drawLine(GraphFreq+5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
+    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq-5, 32, WHITE);
+    display.drawLine(GraphFreq-5, 32, GraphFreq-(48-filterOrder), 64, WHITE);
+ }
+  else {    //BP
+    display.drawLine(GraphFreq-(48-filterOrder), 64, GraphFreq-5, 32, WHITE);
+    display.drawLine(GraphFreq+5, 32, GraphFreq, 35-Pot2Value*4, WHITE);
+    display.drawLine(GraphFreq, 35-Pot2Value*4, GraphFreq-5, 32, WHITE);
+    display.drawLine(GraphFreq+5, 32, GraphFreq+(48-filterOrder), 64, WHITE);
+ }
+  display.setTextSize(1);
+  display.setTextColor(WHITE);
+  display.setCursor(80, 10);
+  display.print("fc:");
+  display.print(movingfreq);
+  display.display();
+
+   Serial.print(" InLevel: ");
+   Serial.print(InLevel);
+   Serial.print(" Filterorder: ");
+   Serial.println(filterOrder);
+
+   Pot1ValueOld = Pot1Value;
+   Pot2ValueOld = Pot2Value;
+   Pot3ValueOld = Pot3Value;
+   Pot4ValueOld = Pot4Value;
+   SW1ValueOld = SW1Value;
+   SW2ValueOld = SW2Value;
+   Tap1ValueOld = Tap1Value;
+   Tap2ValueOld = Tap2Value;
+   CV1ValueOld = CV1Value;
+}


Apply fixes from polargraph

Apply fixes from polargraph

--- software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
+++ software/firmware/LogoBotWifiScribbler/LogoBotWifiScribbler.ino
@@ -6,8 +6,8 @@
 #include <Servo.h>

 Bot bot(MOTOR_L_PIN_1, MOTOR_L_PIN_2, MOTOR_L_PIN_3, MOTOR_L_PIN_4, MOTOR_R_PIN_1, MOTOR_R_PIN_2, MOTOR_R_PIN_3, MOTOR_R_PIN_4);
-CommandQueue cmdQ(20);
-String text = ""; // buffered text to "write" using the pen
+CommandQueue cmdQ(15);
+CommandQueue textQ(20);
 String cmd; // cmd received over serial - builds up char at a time

 void setup()
@@ -20,14 +20,14 @@
   bot.initBuzzer(BUZZER_PIN);
   //bot.lookAheadEnable(true);
   bot.playStartupJingle();
-  LogobotText::begin(cmdQ);
+  LogobotText::begin(textQ);
 }

 void loop()
 {
   // Parse Logo commands from Serial
   if (Serial.available()) {
-    char c = Serial.read();
+    char c = toupper(Serial.read());
     if (c == '\r' || c == '\n') {  // if found a line end
       if (cmd != "") {  // check the command isn't blank
         if (cmd == "STAT") { // handle status commands: execute immediately, no need to parse and/or queue
@@ -50,26 +50,28 @@
   // keep the bot moving (this triggers the stepper motors to move, so needs to be called frequently, i.e. >1KHz)
   bot.run();

-  // see if we can queue the next command to the bot...
-  // Needs to be a movement command and the bot movement queue must not be full
-  if (cmdQ.peekAtType() <= LOGO_MOVE_CMDS && !bot.isQFull()) {
-      // pop and process next command from queue
-      doLogoCommand(cmdQ.dequeue());
-
-  } else if (!bot.isBusy()) {  // See if the bot has finished whatever it's doing...
-    // see if we've got more text to write
-    if (text.length() > 0) {
-      // check if we're ready for another letter - need the queue to be empty as letters take a LOT of commands
-      if (bot.isQEmpty()) {
-        char c = text[0];  // grab the next character to write
-        text = text.substring(1);  // and remove the first character from the text writing buffer
-        LogobotText::writeChar(c, bot.state.x, bot.state.y);  // use the LogobotText library to write the letter
-      }
-    } else {
-      // pop and process next command from queue
-      doLogoCommand(cmdQ.dequeue());
+  // dequeue commands from textQ, then cmdQ
+  // textQ will be emptied before processing anything in cmdQ
+  if (dequeueFrom(textQ))
+    dequeueFrom(cmdQ);
+}
+
+static boolean dequeueFrom(CommandQueue q) {
+  if (!q.isEmpty()) {
+    // see if we can queue the next command to the bot...  two situations where we can dequeue:
+    //   1) if the next command is a movement command, and the bots motion queue isn't full
+    //   2) the bot has finished whatever it was doing
+    if (
+        ( q.peekAtType() <= LOGO_MOVE_CMDS && !bot.isQFull() )
+        ||
+        !bot.isBusy()
+    ) {
+        // dequeue and process next command - ultimately passing it over to the bot object for execution
+        doLogoCommand(q.dequeue());
     }
   }
+  // return true when this queue is empty
+  return q.isEmpty();
 }

 static void handleCollision(byte collisionData)
@@ -256,7 +258,6 @@
             break;
         case LOGO_CMD_SE:
             bot.emergencyStop();
-			text = "";
             break;
 		case LOGO_CMD_CS:
 			bot.resetPosition();
@@ -290,10 +291,13 @@
 }

 static void writeText(String s) {
-  // overwrite write text
-  text = s;
-  text.toUpperCase();
-
-  // reset current state
-  bot.resetPosition();
-}
+  if (s.length() > 0) {
+    char c = s[0];  // grab the next character to write
+
+    // put the rest of the command back at the beginning of the queue
+    cmdQ.insert(s.substring(1), LOGO_CMD_WT);
+
+    // use the LogobotText library to write the letter
+    LogobotText::writeChar(c, bot.state.x, bot.state.y);
+  }
+}


Warning fix

Warning fix

--- examples/Interrupt/Interrupt.ino
+++ examples/Interrupt/Interrupt.ino
@@ -34,7 +34,7 @@
 };

 Blink::Blink(int pin, int delay) :
-  state(LOW), pin(pin), delay(delay), Task()
+  Task(), state(LOW), pin(pin), delay(delay)
 {
 }


- use 128bit uuid's

- use 128bit uuid's

--- examples/ir_bridge/ir_bridge.ino
+++ examples/ir_bridge/ir_bridge.ino
@@ -31,9 +31,9 @@
 BLEPeripheral                    blePeripheral               = BLEPeripheral(BLE_REQ, BLE_RDY, BLE_RST);

 // create service and characteristics
-BLEService                       irService                   = BLEService("4952");
-BLEFixedLengthCharacteristic     irOutputCharacteristic      = BLEFixedLengthCharacteristic("4953", BLEWrite, sizeof(irValue));
-BLEFixedLengthCharacteristic     irInputCharacteristic       = BLEFixedLengthCharacteristic("4954", BLENotify, sizeof(irValue));
+BLEService                       irService                   = BLEService("00004952-0000-bbbb-0123-456789abcdef");
+BLEFixedLengthCharacteristic     irOutputCharacteristic      = BLEFixedLengthCharacteristic("00004953-0000-bbbb-0123-456789abcdef", BLEWrite, sizeof(irValue));
+BLEFixedLengthCharacteristic     irInputCharacteristic       = BLEFixedLengthCharacteristic("00004954-0000-bbbb-0123-456789abcdef", BLENotify, sizeof(irValue));

 void setup() {


- update reset pin

- update reset pin

--- examples/ir_bridge/ir_bridge.ino
+++ examples/ir_bridge/ir_bridge.ino
@@ -8,7 +8,7 @@
 // define pins (varies per shield/board)
 #define BLE_REQ     9
 #define BLE_RDY     8
-#define BLE_RST     4
+#define BLE_RST     7

 #define IR_SEND_PIN 13 // pin 3 on Uno
 #define IR_RECV_PIN 2


Encoder support!

Encoder support!

For my new "Blume Living" (room) lighting, I'm using a rotary encoder
with button. This adds support, and could be used to support general
button interaction to cycle between modes etc.
I set up a basic portfolio of different modes showcasing various things;
the encoder can be used to tweak mode settings. (Right now it only
tweaks hue/saturation, but it should really tweak different values based
on the mode.)
We now always set a new saveTarget if restoreFromSettings() is called
with loadEeprom=false.
Get rid of some really long lines to make the Arduino editor experience
suck less.
And while we're here (and wifi/openpixelcontrol/mdns work!!!), tweak a
few things with openpixelcontrol.

--- blume.ino
+++ blume.ino
@@ -6,7 +6,12 @@
 // Wiring is in a zig-zag pattern.
 #define ZIGZAG   false
 // Support text mode; currently 6-pixel height only.
-#define TEXTMODE true
+#define TEXTMODE false
+// Rotary encoder with button control.
+/*#define ENCODER true
+#define ENC_P1 22
+#define ENC_P2 23
+#define ENC_SW 21*/
 // POI: 18/1/false/false
 // STAFF: 50/1/false/false
 // CUCUMBER: 104/6/true/false
@@ -26,6 +31,7 @@
 // NIC'S BLUME: 40/6/true/false/false
 // BLUME DUBIOUS: 59/6/true/false/false
 // BLUME BEACON: 40/6/true/false/false
+// BLUME LIVING: 298?/1/false/false/false/true:22,23,sw=21 (APA_MHZ=1)

 #define DEBUG false

@@ -172,6 +178,61 @@
 // Stored frames of POV/light-painting image, used by mode 'P'
 // Each pixel is in 8-bit RRRGGGBB format
 byte ledFrames[NUM_LEDS * MAX_FRAMES];
+
+#if ENCODER
+#include <Encoder.h>
+Encoder encoder(ENC_P1, ENC_P2);
+// Is the encoder's swith currently pressed?
+volatile bool encoderPressed = false;
+// true when the main run loop should restoreSettings().
+// We can't call it directly; it crashes, probably due to
+// concurrency issues.
+volatile bool encoderNewSettingsPending = false;
+// Used when switch was pressed to turn on.
+volatile bool encoderClickDisabled = false;
+// Has the encoder knob moved during the current press?
+volatile bool encoderMovedDuringPress = false;
+// millis() when the encoder switch was pressed
+volatile long encoderPressTime = 0;
+// settings.brightness when the encoder switch was pressed
+volatile byte encoderPressInitialBrightness = 255;
+// Un-pressed encoder position
+volatile int32_t encoderPrimary = 0;
+// Pressed encoder position
+volatile int32_t encoderSecondary = 0;
+// Last raw encoder value, regardless of press state
+volatile int32_t lastEncoder = 0;
+portMUX_TYPE encoderMux = portMUX_INITIALIZER_UNLOCKED;
+#define ENCODER_DEBOUNCE_MS 100
+// How many milliseconds before a pending click becomes a
+// long-held press to change brightness
+#define ENCODER_LONG_PRESS 1000
+// After ENCODER_LONG_PRESS milliseconds, this additional time
+// reduces brightess by one level.
+#define ENCODER_MS_PER_BRIGHTNESS 10
+SavedSettings encoderModes[] = {
+  // Standard color mode with a warm yellow
+  { 255, 'C', 60, 255, 0, 0 },
+  // Small slow blobs
+  { 255, 'B', 14, 45, 45, 45 },
+  // Fire
+  { 255, 'Z', 16, 255, 139, 118 },
+  // Blue blobs
+  { 255, 'B', 38, 147, 43, 255 },
+  // Pulsing red
+  { 255, 'M', 0, 255, 47, 149 },
+  // Twinkle
+  { 255, 'Z', 0, 0, 124, 154 },
+  // Chasing blue
+  { 255, 'M', 168, 255, 51, 98 },
+  // Noise
+  { 255, 'Z', 0, 255, 201, 201 },
+  // Chasing rainbow
+  { 255, 'M', 168, 255, 149, 100 }
+};
+byte nextEncoderMode = 0;
+#endif // ENCODER
+

 #if TEXTMODE
 #include "Picopixel.h"
@@ -322,8 +383,15 @@
   opcServer.setClientConnectedCallback(cbOpcClientConnected);
   opcServer.setClientDisconnectedCallback(cbOpcClientDisconnected);
   opcServer.begin();
-  opcServer.mDNSBegin("Blume-ESP32-OPC");
-#endif
+  opcServer.mDNSBegin("blume");
+#endif
+
+#if ENCODER
+  pinMode(ENC_SW, INPUT_PULLUP);
+  attachInterrupt(digitalPinToInterrupt(ENC_SW), encoderSwitchHandler, CHANGE);
+  // Make sure we're in sync with current switch state.
+  encoderSwitchHandler();
+#endif // ENCODER

   pinMode(DATA_PIN_0, OUTPUT);
   pinMode(CLOCK_PIN_0, OUTPUT);
@@ -414,6 +482,12 @@
 void loop() {
   lastFrameDuration = millis() - lastFrameTime;
   lastFrameTime += lastFrameDuration;
+#if ENCODER
+  if (encoderNewSettingsPending) {
+    encoderNewSettingsPending = false;
+    restoreFromSettings(false);
+  }
+#endif
 #ifdef ESP32_OPC
   if (!lastOpc || lastOpc < millis() - OPC_DISPLAY_TIMEOUT) {
 #else
@@ -430,6 +504,11 @@
 #ifdef ESP32_OPC
   opcServer.process();
 #endif
+#if ENCODER
+  portENTER_CRITICAL(&encoderMux);
+  checkEncoder();
+  portEXIT_CRITICAL(&encoderMux);
+#endif // ENCODER
   do {
     // show() at least once,
     FastLED.show();
@@ -602,14 +681,8 @@
     }
 #endif
   }
-
-  /*Serial.print(len);
-  Serial.print(F(" -> "));*/
   // We have new settings! Apply them.
-  if (restoreFromSettings(false)) {
-    // Plan to save this if we don't get any more data
-    saveTarget = millis() + EEPROM_SAVE_TIMEOUT_MS;
-  }
+  restoreFromSettings(false);
 }

 void checkSave() {
@@ -642,7 +715,7 @@
     if (settings.mode == 'T') {
       EEPROM.get(eepromStart + sizeof(settings), text);
     }
-#endif
+#endif // TEXTMODE
   }
 #if DEBUG
   Serial.print(F("settings: "));
@@ -658,6 +731,11 @@
   Serial.print(',');
   Serial.println(settings.c2);
 #endif
+#if ENCODER
+  // New mode: reset encoder values.
+  encoderPrimary = 0;
+  encoderSecondary = 0;
+#endif // ENCODER

   FastLED.setBrightness(settings.brightness);
   if (settings.mode == 'C') {
@@ -686,12 +764,15 @@
     Serial.print(F("Unknown mode: "));
     Serial.println(settings.mode);
 #endif
-    return false;
-  }
-  return true;
+  }
+  if (!loadEeprom) {
+    // Plan to save this if we don't get any more data
+    saveTarget = millis() + EEPROM_SAVE_TIMEOUT_MS;
+  }
 }

 void runMode() {
+  FastLED.setBrightness(settings.brightness);
   if (settings.mode == 'M') {
     runMovement(false);
   } else if (settings.mode == 'Z') {
@@ -761,7 +842,8 @@
         abs(float(i) - position - dimension));
     CRGB color;
     if (rainbow) {
-      color = CHSV(int(float(settings.hue) + distance * size) % 256, settings.saturation, 255);
+      color = CHSV(int(float(settings.hue) + distance * size) % 256,
+                   settings.saturation, 255);
     } else {
       byte value;
       float intensity = size / 2.0 - distance;
@@ -804,7 +886,8 @@
   }
 }

-// Positions should really be bytes, but we're about to do arithmetic with them that wants negative results.
+// Positions should really be uint16_ts,
+// but we're about to do arithmetic with them that wants negative results.
 float distance(float pos1, float pos2, float dimensionSize) {
   float distance = abs(pos1 - pos2);
   while (distance > dimensionSize) distance -= dimensionSize;
@@ -862,8 +945,10 @@
   bool allowZero = WIDTH > 1 || HEIGHT > 1;
   for (byte c = RED; c <= BLUE; c++) {
     if (!steps[c]) {
-      xIncrement[c] = (float)(random(allowZero ? 0 : WIDTH * settings.hue / 2, WIDTH * settings.hue) + 100) / 50000.0;
-      yIncrement[c] = (float)(random(allowZero ? 0 : HEIGHT * settings.hue / 2, HEIGHT * settings.hue) + 100) / 50000.0;
+      xIncrement[c] = (float)(random(allowZero ? 0 : WIDTH * settings.hue / 2,
+                                     WIDTH * settings.hue) + 100) / 50000.0;
+      yIncrement[c] = (float)(random(allowZero ? 0 : HEIGHT * settings.hue / 2,
+                                     HEIGHT * settings.hue) + 100) / 50000.0;
       if (random(2)) {
         xIncrement[c] *= -1;
       }
@@ -885,7 +970,8 @@

 void oneRandom(uint16_t i) {
   bool rainbow = settings.c1 > 100;
-  byte _size = mapRange(settings.c2 > 100 ? settings.c2 - 101 : settings.c2, 0, 100, 0, 255);
+  byte _size = mapRange(settings.c2 > 100 ? settings.c2 - 101 :
+                        settings.c2, 0, 100, 0, 255);
   leds[i] = CHSV(
     rainbow ?
       settings.hue + random8(_size) :
@@ -908,16 +994,11 @@

 #ifdef ESP32_OPC
 void cbOpcMessage(uint8_t channel, uint8_t command, uint16_t length, uint8_t* data) {
-  /*Serial.print("chn:");
-  Serial.print(channel);
-  Serial.print("cmd:");
-  Serial.print(command);
-  Serial.print("len:");
-  Serial.println(length);*/
   memcpy(leds, data, min(length, sizeof(leds)));
   lastOpc = millis();
   opcCount++;
-  FastLED.setBrightness(15);
+  // Maximize brightness; pixel data knows no brightness level
+  FastLED.setBrightness(255);
 }

 // Callback when a client is connected
@@ -932,3 +1013,97 @@
   Serial.println(opcClient.ipAddress);
 }
 #endif
+
+#if ENCODER
+void checkEncoder() {
+  // Get "raw" encoder value
+  int32_t val = encoder.read();
+  // First, check if we're in a long press, which overrides any
+  // encoder movement.
+  if (encoderPressed &&
+      !encoderMovedDuringPress &&
+      millis() > encoderPressTime + ENCODER_LONG_PRESS) {
+    // We're in the middle of a long press; reduce brightness accordingly.
+    settings.brightness = max(
+      0,
+      (int)encoderPressInitialBrightness -
+        (int)(millis() - encoderPressTime - ENCODER_LONG_PRESS) /
+        ENCODER_MS_PER_BRIGHTNESS);
+#if DEBUG
+  Serial.print("NewBright! ");
+  Serial.print(encoderPressInitialBrightness);
+  Serial.print(" => ");
+  Serial.print(settings.brightness);
+  Serial.print("   ");
+  Serial.print(millis());
+  Serial.print(',');
+  Serial.println(encoderPressTime);
+#endif
+  // We're not in a long press; did the encoder move?
+  } else if (val != lastEncoder) {
+    // If brightness is zero, probably due to a long press,
+    // turn back on given this new interaction.
+    if (settings.brightness == 0) {
+      settings.brightness = 255;
+    }
+    if (encoderPressed) {
+      encoderMovedDuringPress = true;
+      encoderSecondary += val - lastEncoder;
+      settings.saturation += val - lastEncoder;
+    } else {
+      encoderPrimary += val - lastEncoder;
+      settings.hue += val - lastEncoder;
+    }
+    encoderNewSettingsPending = true;
+    lastEncoder = val;
+#if DEBUG
+    Serial.print("Encoder change: ");
+    Serial.print(encoderPrimary);
+    Serial.print(',');
+    Serial.print(encoderSecondary);
+    Serial.print(',');
+    Serial.println(encoderPressed);
+#endif
+  }
+}
+void encoderSwitchHandler() {
+  portENTER_CRITICAL_ISR(&encoderMux);
+#if DEBUG
+  Serial.print("Switch! ");
+  Serial.println(!digitalRead(ENC_SW));
+#endif
+  if (!digitalRead(ENC_SW) != encoderPressed) {
+    encoderPressed = !encoderPressed;
+    long ms = millis();
+    if (encoderPressed) {
+      // If brightness is zero, probably due to a long press,
+      // turn back on given this new interaction.
+      if (settings.brightness == 0) {
+        settings.brightness = 255;
+        // Also, make sure this interaction will never register
+        // as a click, though it could register as other stuff.
+        encoderClickDisabled = true;
+      } else {
+        encoderClickDisabled = false;
+      }
+      encoderMovedDuringPress = false;
+      encoderPressTime = ms;
+      encoderPressInitialBrightness = settings.brightness;
+    } else if (!encoderMovedDuringPress &&
+               !encoderClickDisabled &&
+               ms > encoderPressTime + ENCODER_DEBOUNCE_MS &&
+               ms <= encoderPressTime + ENCODER_LONG_PRESS) {
+#if DEBUG
+      Serial.print("Click! New mode: ");
+      Serial.println(nextEncoderMode);
+#endif
+      settings = encoderModes[nextEncoderMode];
+      nextEncoderMode = (nextEncoderMode + 1) %
+        (sizeof(encoderModes) / sizeof(SavedSettings));
+      encoderNewSettingsPending = true;
+    }
+  }
+  checkEncoder();
+  portEXIT_CRITICAL_ISR(&encoderMux);
+}
+#endif // ENCODER