C2 DriveByWire is an alternative version of C2 controls. Both need to be updated with current sensing feedback from ThrottleLogger.

error: pathspec 'Elcano_C2_DriveByWire.ino' did not match any file(s) known to git

--- Elcano_C2_DriveByWire.ino
+++ Elcano_C2_DriveByWire.ino
@@ -0,0 +1,687 @@
+/*
+Elcano Contol Module C2: Instrument panel controls and LEDs.
+This routine handles simple drive-by-wire, as well as handing control over to the
+computer based on the state of the enable switches.
+*/
+#define MEGA
+#define TEST_MODE
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifdef MEGA
+#include "IO_Mega.h"
+#else
+#include "IO_2009.h"
+#endif
+
+/*
+
+There are four principle states. "Enable" is considered a generic state that encompasses the
+three switches for Throttle, Brake and Steer. The four main states have additional substates
+corresponding to the state of these three systems. The system can simultaneaous be in mixed states,
+e.g. "Cruise Go" on Throttle and Brakes and "Manual Go" on Steering.
+When Cruise is enabled on a system, "Joystick Motion" means major motion in that axis:
+Left to right for Steer, Forward for Throttle, Reverse for Brake. Minor joystick motions will
+not take an enabled system into manual mode, but major motion will.
+
+MS: Manual Stop State:  Stop LED On, Cruise LED Off,
+  Throttle Off, Brakes Off,  Steer responds to joystick but not to computer.
+  Joystick is centered.
+  Enable Off.
+
+CS: Cruise Stop State:  Stop LED On, Cruise LED On,
+  Throttle Off, Brakes Off,  Steer responds to computer.
+  Joystick is centered.
+  Enable On.
+
+MG: Manual Go State:  Stop LED Off, Cruise LED Off,
+  Throttle, Brakes, Steer respond to joystick but not to computer.
+
+CG:Cruisel Go State:  Stop LED Off, Cruise LED On,
+  Throttle, Brakes, Steer respond to computer.
+  Joystick is centered.
+  Enable On.
+
+There are five controls that can transition between states:
+Cruise button.
+  MS -> MS; CS -> CG; MG -> CG; CG -> CG.
+Joystick motion
+  MS -> MG; CS -> MG; MG -> MG; CG -> MG.
+Enable Switch On
+  MS -> CS; CS N/A; MG -> MG; CG N/A.
+Enable Switch Off
+  MS N/A; CS -> MS; MG -> MG; CG -> MG.
+Stop button
+  MS -> MS; CS -> CS; MG -> MS; CG -> CS.
+E-stop
+  MS -> MS; CS -> CS; MG -> MS; CG -> CS. E-stop also removes power to the traction motor.
+If the E-stop button has been pushed, transition to MG or CG is blocked until
+power is restored. Restoring power is done by turning the key or pressing
+the remote E-stop button (RC4) a second time. There is a dead zone of several seconds between the
+first button push and the second push, allowing the vehicle to come to a stop.
+
+States:  */
+  const int ManualStop = 0;
+  const int CruiseStop = 1;
+  const int ManualGo = 3;
+  const int CruiseGo = 4;
+
+
+
+volatile int Stop = TRUE;
+volatile unsigned long TimeOfStopButton_ms;
+volatile int Cruise = FALSE;
+volatile unsigned long TimeOfCruiseButton_ms;
+const int PauseTime_ms = 4000;
+unsigned long TimeOfReverseButton_ms;
+int Forward;
+
+const int Full = 255;   // fully on for PWM signals
+const int Off = 0;
+const int FullThrottle =  179;   // 3.5 V
+const int MinimumThrottle = 39;  // Throttle has no effect until 0.75 V
+const int FullBrake = 255;
+const int MinimumBrake = 127;
+const int HardLeft = 127;
+const int HalfLeft = 159;
+const int Straight = 191;
+const int HalfRight = 223;
+const int HardRight = 255;
+/*  Servo range is 50 mm for brake, 100 mm for steering.
+    Servo is fully retracted on a pulse width of 2 ms;
+    fully extended at 1 ms and centered at 1.5 ms.
+    There is a deadband of 8 us.
+    At 12v, servo operating speed is 56mm/s with no load or
+    35 mm/s at maximum load.
+
+    The Arduino PWM signal is at 490 Hz or 2.04 ms.
+    0 is always off; 255 always on. One step is 7.92 us.
+
+*/
+
+  const int Motor = 0;
+  const int Brakes = 1;
+  const int Steering = 2;
+  struct _Instruments
+  {
+     int Enabled;  // whether cruise control is enabled.
+     int State;
+     int StickMoved;  // bool
+     int Joystick;   // position of stick
+     int Position;  // last commanded
+     int QuiescentCurrent;  // Nominally 120 counts
+     int CurrentDraw;  // In counts, with 1 Amp = 12 counts
+     int CurrentLimit;  // In counts
+     // One count from analog input is about 5mV from ACS758lcb050U
+     // The ACS758 has sensitivity of 60 mA/V
+  } Instrument[3];
+ /*---------------------------------------------------------------------------------------*/
+void setup()
+{
+        pinMode(ReverseButton, INPUT);
+        pinMode(CruiseReverse, INPUT);
+        pinMode(StopButton, INPUT);  // via interrupt
+        pinMode(CruiseButton, INPUT); // via interrupt
+        pinMode(EnableThrottle, INPUT);
+        pinMode(EnableBrake, INPUT);
+        pinMode(EnableSteer, INPUT);
+        pinMode(StopLED, OUTPUT);
+        pinMode(CruiseLED, OUTPUT);
+        pinMode(Throttle, OUTPUT);
+        pinMode(DiskBrake, OUTPUT);
+        pinMode(Steer, OUTPUT);
+        pinMode(Reverse, OUTPUT);
+        pinMode(ReverseLED, OUTPUT);
+        pinMode(AccelerateJoystick, INPUT);
+        pinMode(SteerJoystick, INPUT);
+        pinMode(JoystickCenter, INPUT);
+        pinMode(CruiseThrottle, INPUT);
+        pinMode(CruiseBrake, INPUT);
+        pinMode(CruiseSteer, INPUT);
+#ifdef MEGA
+        pinMode(Current36V, INPUT);
+        pinMode(CurrentBrake, INPUT);
+        pinMode(CurrentSteer, INPUT);
+        pinMode(LED1, OUTPUT);
+        pinMode(LED3, OUTPUT);
+        pinMode(LED4, OUTPUT);
+        pinMode(LED5, OUTPUT);
+        pinMode(LED6, OUTPUT);
+        pinMode(LED7, OUTPUT);
+        pinMode(LED8, OUTPUT);
+        initialize();
+        attachInterrupt(0, CruiseRC1Pressed, RISING);
+        attachInterrupt(1, StopRC2Pressed, RISING);
+        attachInterrupt(3, EStopPressed, FALLING);
+        attachInterrupt(4, StopPressed, RISING);
+        attachInterrupt(5, CruisePressed, RISING);
+#else
+        initialize();
+        attachInterrupt(0, StopPressed, FALLING);
+        attachInterrupt(1, CruisePressed, FALLING);
+#endif
+}
+
+/*---------------------------------------------------------------------------------------*/
+void initialize()
+{
+        Halt();
+       // assume that vehicle always stops with brakes on and wheels straight.
+       // Otherwise, there is a possibility of blowing a fuse if servos try to
+       // get to this state too quickly.
+        analogWrite( Steer, Straight);
+        Instrument[Steering].Position = Straight;
+        digitalWrite( StopLED, HIGH);
+        digitalWrite( CruiseLED, LOW);
+        Instrument[Motor].State = ManualStop;
+        Instrument[Brakes].State = ManualStop;
+        Instrument[Steering].State = ManualStop;
+        Instrument[Motor].Joystick = Off;
+        Instrument[Brakes].Joystick = Off;
+        Instrument[Steering].Joystick = Straight;
+        Instrument[Motor].CurrentLimit = 230;  // about 20A
+        Instrument[Brakes].CurrentLimit = 55;  // about 5A
+        Instrument[Steering].CurrentLimit = 55;
+        TimeOfStopButton_ms = 0;
+        TimeOfCruiseButton_ms = 0;
+        TimeOfReverseButton_ms = 0;
+        Forward = TRUE;
+        // Wait for everything to settle down
+        delay(2000);  // 2 second
+        // Read quiesent state of current sensors.
+        Instrument[Brakes].CurrentDraw =
+        Instrument[Brakes].QuiescentCurrent = analogRead(CurrentBrake);
+        Instrument[Steering].CurrentDraw =
+        Instrument[Steering].QuiescentCurrent = analogRead(CurrentSteer);
+        Instrument[Motor].CurrentDraw =
+        Instrument[Motor].QuiescentCurrent = analogRead(Current36V);
+
+}
+/*---------------------------------------------------------------------------------------*/
+/*---------------------------------------------------------------------------------------
+ CruisePressed is called by an interrupt
+ */
+void CruisePressed()
+{
+    TimeOfCruiseButton_ms = millis();
+    Cruise = TRUE;
+}
+void CruiseRC1Pressed()
+{
+    TimeOfCruiseButton_ms = millis();
+    Cruise = TRUE;
+}
+/*---------------------------------------------------------------------------------------
+ StopPressed is called by an interrupt
+ */
+void StopPressed()
+{
+    Halt();
+    TimeOfStopButton_ms = millis();
+    Stop = TRUE;
+}
+void StopRC2Pressed()
+{
+    Halt();
+    TimeOfStopButton_ms = millis();
+    Stop = TRUE;
+}
+void EStopPressed()
+{
+    Halt();
+    TimeOfStopButton_ms = millis();
+    Stop = TRUE;
+}
+/*---------------------------------------------------------------------------------------*/
+// Bring the vehicle to a stop.
+// Stop may be called from an interrupt or from the loop.
+void Halt()
+{
+   analogWrite(Throttle, Off);
+   analogWrite(DiskBrake, FullBrake);
+   Instrument[Motor].Position = Off;
+   Instrument[Brakes].Position = FullBrake;
+   digitalWrite(StopLED, HIGH);
+}
+
+/*---------------------------------------------------------------------------------------*/
+void loop()
+{
+  unsigned long TimeSinceCmd_ms = 0;     // radians
+  const unsigned long MaxSilence = 2000;  // ms
+  int TimeNow = millis();
+  int NextLoopTime_ms = TimeNow + 100;
+
+#ifdef TEST_MODE
+//  testSwitches();
+//  testRamp();
+    testQuick();
+
+#else  // not TEST_MODE
+
+  JoystickMotion();
+  Instrument[Motor].Enabled = digitalRead(EnableThrottle);
+  Instrument[Brakes].Enabled = digitalRead(EnableBrake);
+  Instrument[Steering].Enabled = digitalRead(EnableSteer);
+  StateTransition(Motor);
+  StateTransition(Brakes);
+  StateTransition(Steering);
+
+  if (Instrument[Motor].State == ManualGo)
+  {
+   analogWrite(Throttle, Instrument[Motor].Joystick);
+   Instrument[Motor].Position = Instrument[Motor].Joystick;
+  }
+  else if (Instrument[Motor].State == CruiseGo)
+  {
+    Instrument[Motor].Position = analogRead(CruiseThrottle) / 4;
+    analogWrite(Throttle, Instrument[Motor].Position);
+  }
+  else
+  {
+    Instrument[Motor].Position = MinimumThrottle;
+    analogWrite(Throttle, Instrument[Motor].Position);
+  }
+
+  if (Instrument[Brakes].State == ManualGo)
+  {
+   analogWrite(DiskBrake, Instrument[Brakes].Joystick);
+   Instrument[Brakes].Position = Instrument[Brakes].Joystick;
+  }
+  else if (Instrument[Brakes].State == CruiseGo)
+  {
+    Instrument[Brakes].Position = analogRead(CruiseBrake) / 4;
+    analogWrite(DiskBrake, Instrument[Brakes].Position);
+  }
+  else
+  {
+    Instrument[Brakes].Position = FullBrake;
+    analogWrite(DiskBrake, Instrument[Brakes].Position);
+  }
+
+   if (Instrument[Steering].State == ManualGo)
+  {
+   analogWrite(Steer, Instrument[Steering].Joystick);
+   Instrument[Steering].Position = Instrument[Steering].Joystick;
+  }
+  else if (Instrument[Steering].State == CruiseGo)
+  {
+    Instrument[Steering].Position = analogRead(CruiseSteer) / 4;
+    analogWrite(Steer, Instrument[Steering].Position);
+  }
+   if (Stop)
+     digitalWrite(StopLED, HIGH);
+   else
+     digitalWrite(StopLED, LOW);
+   if (TimeNow > TimeOfCruiseButton_ms + 400 &&
+   (Instrument[Motor].StickMoved || Instrument[Brakes].StickMoved || Instrument[Steering].StickMoved)
+       Cruise = FALSE;
+   if (!Instrument[Motor].Enabled && !Instrument[Motor].Enabled && !Instrument[Motor].Enabled)
+       Cruise = False
+   if (Cruise)
+     digitalWrite(CruiseLED, HIGH);
+   else
+     digitalWrite(CruiseLED, LOW);
+
+  checkReverse();
+  do  //  Delay so that loop is not faster than 10 Hz.
+  {
+    TimeNow = millis();
+  } while (TimeNow < NextLoopTime_ms);
+
+
+#endif  // TEST_MODE
+}
+/*---------------------------------------------------------------------------------------*/
+void JoystickMotion()
+{
+  int stick;
+  int center;
+  const int deadBandLow = 32;  // out of 1023
+  const int deadBandHigh = 32;
+  center = analogRead(JoystickCenter);
+  int tinyDown = center - deadBandLow;
+  int tinyUp = center + deadBandHigh;
+
+    if (Stop && (millis() < TimeOfStopButton_ms + PauseTime_ms))
+    {
+      Instrument[Motor].StickMoved = FALSE;
+      Instrument[Brakes].StickMoved = FALSE;
+      Instrument[Steering].StickMoved = FALSE;
+      return;
+    }
+    stick = analogRead(AccelerateJoystick);
+    if (stick <= tinyUp)
+    {
+      Instrument[Motor].Joystick = 0;
+      Instrument[Motor].StickMoved = FALSE;
+    }
+    else
+    {
+      Instrument[Motor].Joystick = 255 * (stick - tinyUp) / (1023 - tinyUp);
+      Instrument[Motor].StickMoved =  TRUE;
+      Stop = FALSE;
+    }
+
+    if (stick >= tinyDown)
+    {
+      Instrument[Brakes].Joystick = 0;
+      Instrument[Brakes].StickMoved =  FALSE;
+    }
+    else
+    {
+      Instrument[Brakes].Joystick = MinimumBrake + (FullBrake - MinimumBrake) * (-stick + tinyDown) / tinyDown;
+      Instrument[Brakes].StickMoved =  TRUE;
+      Stop = FALSE;
+    }
+
+    stick = analogRead(SteerJoystick);
+    if (stick > tinyDown && stick <= tinyUp)
+    {
+      Instrument[Steering].Joystick = Straight;
+      Instrument[Steering].StickMoved =  FALSE;
+    }
+    else if (stick > tinyUp)
+    {
+      Instrument[Steering].Joystick = Straight + (HardRight - Straight) * (stick - tinyUp) / (1023 - tinyUp);
+      Instrument[Steering].StickMoved =  TRUE;
+      Stop = FALSE;
+    }
+    else
+    {
+      Instrument[Steering].Joystick = Straight + (Straight - HardLeft) * (-stick + tinyDown) / tinyDown;
+      Instrument[Steering].StickMoved = TRUE;
+      Stop = FALSE;
+    }
+}
+/*---------------------------------------------------------------------------------------*/
+void StateTransition( int system)
+{
+  unsigned long Time_ms = millis();
+  switch(Instrument[system].State)
+  {
+    case ManualStop:
+    if (TimeOfStopButton_ms + PauseTime_ms > Time_ms)
+      break;
+      if (Instrument[system].Enabled)
+      {
+        Instrument[system].State = CruiseStop;
+        break;
+      }
+//  if (joystick motion) set state.
+    if (Instrument[system].StickMoved)
+    {
+      Instrument[system].State = ManualGo;
+    }
+    break;
+
+    case ManualGo:
+    if (Stop)
+    {
+      Instrument[system].State = ManualStop;
+      break;
+    }
+    if (Cruise)
+    {
+      Instrument[system].State = CruiseGo;
+      break;
+      // respond to joystick
+    }
+    break;
+
+    case CruiseStop:
+    if (TimeOfStopButton_ms + PauseTime_ms > Time_ms)
+      break;
+    if (Instrument[system].StickMoved)
+    {
+       Instrument[system].State = ManualGo;
+       break;
+    }
+    if (!Instrument[system].Enabled)
+    {
+      Instrument[system].State = ManualStop;
+      break;
+    }
+    if (Cruise)
+    {
+      Instrument[system].State = CruiseGo;
+    }
+    break;
+
+    case CruiseGo:
+    if (Stop)
+    {
+      Instrument[system].State = CruiseStop;
+      break;
+    }
+    if (Instrument[system].StickMoved)
+    {
+      Instrument[system].State = ManualGo;
+      break;
+    }
+    if (!Instrument[system].Enabled)
+    {
+      Instrument[system].State = ManualGo;
+      break;
+    }
+    break;
+  }
+}
+/*---------------------------------------------------------------------------------------*/
+void  checkReverse()
+{
+  unsigned long TimeNow;
+  int ReversePushed;
+
+  if (Instrument[Motor].State == ManualStop)
+ {
+   ReversePushed = digitalRead(ReverseButton);
+   if (ReversePushed)
+   {
+     TimeNow = millis();
+     if (TimeNow > TimeOfReverseButton_ms + 2000)
+     {
+         TimeOfReverseButton_ms = TimeNow;
+         Forward = !Forward;
+     }
+   }
+  digitalWrite(ReverseLED, !Forward);
+  digitalWrite(Reverse, !Forward);
+ }
+   if (Instrument[Motor].State == CruiseStop || Instrument[Motor].State == CruiseGo)
+   {
+     Forward = !digitalRead(CruiseReverse);
+     digitalWrite(ReverseLED, !Forward);
+     digitalWrite(Reverse, !Forward);
+   }
+}
+
+
+/***********************************************************
+                        TEST ROUTINES
+ ***********************************************************/
+
+
+#ifdef TEST_MODE
+
+/*---------------------------------------------------------------------------------------*/
+void testRamp()
+{
+  // test passed for brakes and steering 5/21/11.
+  // Computer commanded braking, steering and throttle works!
+
+    int i, throttle;
+    unsigned int count = 0;
+
+//  write_all (LOW);
+//  delay (1000);
+//  for (i = MinimumThrottle; i <= MinimumThrottle+5; i++)
+//  {
+//      ramp(Throttle, i);
+//  }
+//  write_all (HIGH);
+//  delay (1000);
+//  for (i = MinimumThrottle+5; i >= MinimumThrottle; i--)
+//  {
+//      ramp(Throttle, i);
+//  }
+  write_all (HIGH);
+  delay (1000);
+
+   write_all (LOW);
+   delay (1000);
+   FlashMorse (count++);
+
+  for (i = MinimumBrake; i <= FullBrake; i++)
+  {
+      ramp(DiskBrake, i);
+  }
+  write_all (HIGH);
+  delay (1000);
+  for (i = FullBrake; i >= MinimumBrake; i--)
+  {
+      ramp(DiskBrake, i);
+  }
+
+   write_all (LOW);
+   delay (1000);
+   for (i = Straight; i <= HardRight; i++)
+   {
+      ramp(Steer, i);
+   }
+    write_all (HIGH);
+  delay (1000);
+  for (i = HardRight; i >= Straight; i--)
+  {
+      ramp(Steer, i);
+  }
+   write_all (LOW);
+
+  for (i = MinimumBrake; i <= FullBrake; i++)
+  {
+      ramp(DiskBrake, i);
+  }
+  write_all (HIGH);
+  delay (1000);
+  for (i = FullBrake; i >= MinimumBrake; i--)
+  {
+      ramp(DiskBrake, i);
+  }
+
+   delay (1000);
+   for (i = Straight; i <= HardLeft; i++)
+   {
+      ramp(Steer, i);
+   }
+    write_all (HIGH);
+
+
+  delay (1000);
+  for (i = HardLeft; i >= Straight; i--)
+  {
+      ramp(Steer, i);
+  }
+}
+/*---------------------------------------------------------------------------------------*/
+void testSwitches()
+{
+  // test failed 5/2/11.  Panel LEDs do not light.
+  int SwThrottle, SwBrake, SwSteer;
+  SwThrottle = digitalRead(EnableThrottle);
+  SwBrake = digitalRead(EnableBrake);
+  SwSteer = digitalRead(EnableSteer);
+  digitalWrite( StopLED, SwBrake);
+  digitalWrite( CruiseLED, SwThrottle);
+  digitalWrite( ReverseLED, SwSteer);
+}
+/*---------------------------------------------------------------------------------------*/
+// testQuick: fast operation of brakes and steering to measure peak power demand
+void testQuick()
+{
+  int i, steer, brake;
+  for (i = 0; i < 5; i++)
+  {
+     steer = Straight + i * (HalfRight - Straight)/4;
+     analogWrite( Steer, steer);
+     brake = MinimumBrake + i * (FullBrake - MinimumBrake)/4;
+     analogWrite( DiskBrake, brake);
+   }
+  for (i = 5; i >= 0; i--)
+  {
+     steer = Straight + i * (HalfRight - Straight)/4;
+     analogWrite( Steer, steer);
+     brake = MinimumBrake + i * (FullBrake - MinimumBrake)/4;
+     analogWrite( DiskBrake, brake);
+   }
+
+}
+
+/*---------------------------------------------------------------------------------------*/
+void write_all( int state)
+{
+      digitalWrite( StopLED, state);
+      digitalWrite( CruiseLED, state);
+      digitalWrite( ReverseLED, state);
+}
+/*---------------------------------------------------------------------------------------*/
+void ramp (int channel, int state)
+{
+   analogWrite( channel, state);
+   delay(100);
+
+}
+/*---------------------------------------------------------------------------------------
+Flash a number in Morse Code
+1  . ----
+2  ..---
+3  ...--
+4  ....-
+5  .....
+6  -....
+7  --...
+8  ---..
+9  ----.
+0  -----
+*/
+#define BASE 300
+#define DOT BASE
+#define DASH (4*BASE)
+#define BIT_SPACE (2*BASE)
+#define NUMBER_SPACE (10*BASE)
+void FlashMorse (unsigned int number)
+{
+  unsigned int quotient, remainder;
+  unsigned int i;
+  quotient = number / 10;
+  remainder = number % 10;
+  if (quotient != 0)
+    FlashMorse (quotient);
+  if (remainder <= 5)
+  {
+    for (i = 0; i < remainder; i++)
+      Flash(DOT);
+    for (; i < 5; i++)
+      Flash(DASH);
+  }
+  else
+  {
+    for (i = 5; i < remainder; i++)
+      Flash(DASH);
+    for (; i < 10; i++)
+      Flash(DOT);
+   }
+   digitalWrite( ReverseLED, LOW);
+   delay (NUMBER_SPACE);
+
+}
+void Flash(int DashDot)
+{
+  digitalWrite( ReverseLED, LOW);
+  delay (BIT_SPACE);
+  digitalWrite( ReverseLED, HIGH);
+  delay (DashDot);
+}
+#endif  // TEST_MODE
+


adding example

adding example

This example program writes text, draws a line, draws a rectangle, and
fills in another rectangle. Then it blinks one pixel. It should be a
good starting point for a first project.

error: pathspec 'firmware/examples/RGBmatrixPanelCPLD-demo.ino' did not match any file(s) known to git

--- firmware/examples/RGBmatrixPanelCPLD-demo.ino
+++ firmware/examples/RGBmatrixPanelCPLD-demo.ino
@@ -0,0 +1,41 @@
+/*
+
+This demo shows off some of the functionality of the
+RGBmatrixPanelCPLD library. Its usage is similar to
+the RGBmatrixPanel library.
+
+Be sure to include the following libraries
+* RGBmatrixPanelCPLD
+* SparkIntervalTimer
+* Adafruit_mfGFX
+
+*/
+
+RGBmatrixPanelCPLD display(32, 32);
+
+void setup() {
+    display.begin();
+
+    display.setCursor(0,0);
+    display.setTextColor(display.Color444(0x3,0x2,0xF));
+    display.write('P');
+    display.write('H');
+    display.write('O');
+    display.write('T');
+    display.write('O');
+    display.write('N');
+
+    display.drawLine(0,16,16,16,display.Color444(0xF,0x0,0x0));
+    display.fillRect(4,18,4,4,display.Color444(0x0,0x0,0xF));
+    display.drawRect(16,20,16,6,display.Color444(0x0,0xF,0x0));
+}
+
+void loop() {
+    static bool isOn = true;
+    if (isOn) {
+        display.drawPixel(2,30,display.Color444(0xF,0xF,0xF));
+    } else {
+        display.drawPixel(2,30,display.Color444(0x0,0x0,0x0));
+    }
+    isOn = !isOn;
+}


hall_sensor_test : Simple test program to read the hall effect sensor

error: pathspec 'hall_sensor_test/hall_sensor_test.ino' did not match any file(s) known to git

--- hall_sensor_test/hall_sensor_test.ino
+++ hall_sensor_test/hall_sensor_test.ino
@@ -0,0 +1,18 @@
+/*
+  A simple test program to read the value of a hall effect sensor
+  Part used is Honeywell SS461C - Farnell part # 181-1311
+*/
+
+int analogPin = 0;  // the pint that the hall sensor is connected to
+int val = 0;        // a var to store the sensor value in
+
+void setup()
+{
+  Serial.begin(9600);  // serial setup
+}
+
+void loop()
+{
+  val = analogRead(analogPin);  // read the sensor value
+  Serial.println(val);          // print the value to the serial port
+}


Steering servo via a micros() timer

Steering servo via a micros() timer

error: pathspec 'current-test-program/servo_via_timer.ino' did not match any file(s) known to git

--- current-test-program/servo_via_timer.ino
+++ current-test-program/servo_via_timer.ino
@@ -0,0 +1,41 @@
+#include <Servo.h>
+
+Servo servo1;
+
+int SERVO1_MIN = 1250;
+int SERVO1_MAX = 2000;
+unsigned long SERVO1_DURATION_MS = 1200;
+unsigned long servo1_timestep_micros;
+unsigned long servo1_next_time_micros;
+int servo1_value;
+unsigned long INITIAL_DELAY_MS = 500;
+
+
+void setup() {
+  servo1.attach(11);
+  pinMode(13, OUTPUT);
+  servo1_timestep_micros = (SERVO1_DURATION_MS * 1000) / (SERVO1_MAX - SERVO1_MIN);
+  servo1_value = SERVO1_MIN;
+  servo1.writeMicroseconds(servo1_value);
+  servo1_next_time_micros = micros() + 1000 * INITIAL_DELAY_MS;
+}
+
+
+void perhaps_update_servo1() {
+  if (micros() > servo1_next_time_micros) {
+    servo1_value += 1;
+    if (servo1_value > SERVO1_MAX) {
+      // delay(1000);
+      // servo1_value = SERVO1_MIN;
+      // servo1_next_time_micros = micros();
+      servo1.detach();
+    }
+    servo1_next_time_micros += servo1_timestep_micros;
+    servo1.writeMicroseconds(servo1_value);
+  }
+}
+
+
+void loop() {
+  perhaps_update_servo1();
+}


Add a DMX send example

Add a DMX send example

error: pathspec 'examples/TeensyDMXSend/TeensyDMXSend.ino' did not match any file(s) known to git

--- examples/TeensyDMXSend/TeensyDMXSend.ino
+++ examples/TeensyDMXSend/TeensyDMXSend.ino
@@ -0,0 +1,28 @@
+#include <TeensyDmx.h>
+
+#define DMX_REDE 2
+
+byte DMXVal[] = {50};
+
+// This isn't required for DMX sending, but the code currently requires it.
+struct RDMINIT rdmData {
+  "TeensyDMX v0.1",
+  "Teensyduino",
+  1,  // Device ID
+  "DMX Node",
+  1,  // The DMX footprint
+  0,  // The DMX startAddress - only used for RDM
+  0,  // Additional commands length for RDM
+  0   // Definition of additional commands
+};
+
+TeensyDmx Dmx(Serial1, &rdmData, DMX_REDE);
+
+void setup() {
+  Dmx.setMode(TeensyDmx::DMX_OUT);
+}
+
+void loop() {
+  Dmx.setChannels(0,DMXVal,1);
+  Dmx.loop();
+}


refined redboard and xbee firmware

refined redboard and xbee firmware

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/DrewMeyersCUboulder/UPOD_Bridge.git/'


Fix compilation error

Fix compilation error

--- hardware/msp430/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino
+++ hardware/msp430/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino
@@ -26,10 +26,6 @@
 {
   // Open serial communications and wait for port to open:
   Serial.begin(9600);
-  while (!Serial) {
-    ; // wait for serial port to connect. Needed for Leonardo only
-  }
-

   Serial.println("Goodnight moon!");


adding arduino sources

adding arduino sources

error: pathspec 'arduino/FileBreaker.ino' did not match any file(s) known to git

--- arduino/FileBreaker.ino
+++ arduino/FileBreaker.ino
@@ -0,0 +1,277 @@
+//* FileBreaker
+//*
+//* V1.2
+//*
+//* Enero de 2017
+//* Preparado por:
+//*      Talleres de Electrónica y Delineación
+//*      Centro de Asistencia a la Investigación
+//*      Talleres de Apoyo a la Investigación
+//*      Universidad Complutense de Madrid.
+//*
+
+
+// Includes
+#include <LiquidCrystal.h>      //Se incluye la librería para el control de la pantalla LCD
+#include <Bounce2.h>            //Librería Bounce2 para eliminar transitorios en botones de entrada
+#include <elapsedMillis.h>      //Librería para cálculo de tiempo en loop
+
+// Constantes
+#define PIN_DIRECCION 7         //Pin de la placa con el que se controla el sentido de giro del motor
+#define PIN_MOVIMIENTO 9        //Pin de la placa con el que se controla la velocidad de giro del motor
+#define PIN_LED 2               //Pin de la placa al que se ha conectado el PIN_LED
+#define PIN_LECTURA A0          //Pin donde se conecta la LDR para lectura del haz
+
+#define BOTON_A 12              //Botón A conectado a E/S digital 12
+#define BOTON_B 13              //Botón B conectado a E/S digital 13
+
+// Variables globales
+char cDato = 0;                 //Variable en la que se almacena lo enviado desde el ordenador
+int iVelocidad = 0;             //Variable en la que se almacena la última velocidad seleccionada
+int iLectura = 0;               //Variable en la que se almacena la lectura del canal de luz
+int iIteracion = 0;             //Variable que almacena el numero de veces iIteraciontidas que se detecta la fresa introducida para detectar si se ha roto
+int iMinimo = 1024;             //Variable donde se almacena el valor de luz con la fresa introducida en la calibracion
+int iMaximo = 0;                //Variable donde se almacena el valor de luz con la fresa extraída en la calibracion
+int iUmbral = 0;                //Umbral que se calculará por distancia Max Min en Calibración
+int iVueltas = 0;               //Indica el número de ciclos de entrada de la fresa por experimento
+unsigned int iPeriodo = 20000;  //Tiempo máximo esperable entre cambios de estado en la inserción de la fresa. Utilizado en loop
+                                //Inicializamos a un tiempo mayor que el obtenido por observación en la velocidad más lenta 10% (15sg)
+                                //para que no detecte rotura en el calibrado.
+bool bMotorOn = false;          //Al inicio el motor está parado.
+bool bCalibrando = true;        //Al inicio queremos calibrar.
+bool bEstadoFresa = false;      //Booleano para detectar cambio de estado en la fresa
+bool bGirando = false;          //Cuando recibo velocidad del PC, activo flag para empezar a comparar tiempos. Antes no puedo.
+
+const int aiPeriodos[10] = {15000,6420,3950,3090,2290,1930,1770,1580,1250,1200}; // Constante (periodos en ms para cada velocidad)
+                                                                                // que usamos para cargar los valores de iPeriodo en func. motor.
+#define C_INC_PERIODO 0.20      //Porcentaje en que incrementamos el periodo de una revolución para detectar rotura
+#define C_UMBRAL      0.80      //Porcentaje en que incrementamos el periodo de una revolución para detectar rotura
+
+
+//Instancias iniciales
+LiquidCrystal lcd(10, 8, 6, 5, 4, 3);   // Inicialización del LCD
+Bounce boton_a = Bounce();              // Inicialización de Antirrebotes para boton A y B
+Bounce boton_b = Bounce();
+elapsedMillis emTiempo;                 // Inicialización del contador de tiempo
+
+void motor (int iNuevaVelocidad)        //Función que cambia la velocidad de giro del motor
+{
+  digitalWrite(PIN_DIRECCION, HIGH);                                  //Indicamos dirección
+  analogWrite (PIN_MOVIMIENTO, map(iNuevaVelocidad, 0, 100, 0, 255)); // Ponemos salida proporcional a Pololu
+  if (iNuevaVelocidad==0) {
+    iPeriodo = 20000;
+  }
+  else
+  {
+    iPeriodo=aiPeriodos[(iNuevaVelocidad/10)-1]*(1+C_INC_PERIODO);    //Cargamos el nuevo periodo
+  }
+}
+
+
+void lcd_velocidad(int iNuevaVelocidad) //Función que indica la nueva velocidad
+{
+
+  lcd.setCursor(0, 1);                                                //Pinta la velocidad seleccionada, para evitar pausas, un solo print
+  switch (iNuevaVelocidad)
+  {
+    case 0:  lcd.print("  Velocidad:   0% "); break;
+    case 10: lcd.print("  Velocidad:  10% "); break;
+    case 20: lcd.print("  Velocidad:  20% "); break;
+    case 30: lcd.print("  Velocidad:  30% "); break;
+    case 40: lcd.print("  Velocidad:  40% "); break;
+    case 50: lcd.print("  Velocidad:  50% "); break;
+    case 60: lcd.print("  Velocidad:  60% "); break;
+    case 70: lcd.print("  Velocidad:  70% "); break;
+    case 80: lcd.print("  Velocidad:  80% "); break;
+    case 90: lcd.print("  Velocidad:  90% "); break;
+    case 100: lcd.print("  Velocidad: 100% "); break;
+  }
+}
+
+
+void lcd_umbrales(int iMin, int iLec,int iMax)                        //Función para indicar los umbrales en pantalla
+{
+      lcd.setCursor(1,3);
+      lcd.print(iMin);
+      lcd.print("    ");
+      lcd.setCursor(6,3);
+
+      if (iLec==0){
+        lcd.print("-------");
+
+      }
+      else
+      {
+        lcd.print("- ");
+        lcd.print(iLec);
+        lcd.print("    ");
+      }
+
+      lcd.setCursor(13,3);
+      lcd.print("- ");
+      lcd.print(iMax);
+      lcd.print("    ");
+}
+
+void setup()                        //Funcion setup, ejecutada al inicio una sóla vez.
+{
+  lcd.begin(20, 4);                 // Configuración del tipo de LCD: Columnas, líneas
+  Serial.begin(9600);               // Configuración de la velocidad del puerto serie.
+  pinMode(PIN_LED, OUTPUT);         //PIN_LED declarado como salida
+  digitalWrite(PIN_LED, HIGH);      //PIN_LED encendido
+  pinMode(BOTON_A, INPUT_PULLUP);   //BOTON_A con pullup interno activado
+  pinMode(BOTON_B, INPUT_PULLUP);   //BOTON_B con pullup interno activado
+  boton_a.attach(BOTON_A);          //Unimos una instancia del antirrebotes al boton_A
+  boton_b.attach(BOTON_B);          //Unimos una instancia del antirrebotes al boton_B
+  boton_a.interval(5);              //Fijamos el tiempo de desacople en 5ms al boton_A...
+  boton_b.interval(5);              //...y el boton_B
+
+  lcd.setCursor(0, 0);              //Escritura de presentación del LCD
+  lcd.print("    FileBreakeR     ");
+  lcd.setCursor(0, 1);
+  lcd.print("  V1.2 Enero 2017   ");
+  lcd.setCursor(0, 4);
+  lcd.print("U.Complutense Madrid");
+  delay(1000);
+  lcd.clear();
+
+  lcd.setCursor(0, 0);              //Inicia secuencia de calibración del LCD
+  lcd.print("    Calibracion     ");
+  lcd.setCursor(0, 1);
+  lcd.print("Boton A: Girar/Parar");
+  lcd.setCursor(0, 2);
+  lcd.print(" Boton B: Terminar  ");
+
+  while (bCalibrando) {
+    boton_a.update();               //Actualizamos el antirrebotes.
+    boton_b.update();
+
+    if (boton_a.fell()) {           //En el flanco de bajada del botón A
+      if(bMotorOn==false) {         //Si el motor estaba parado...
+        motor(10);                  //...arranca al mínimo
+      }
+      else                          //Si estaba encendido, lo paro.
+      {
+        motor(0);
+      }
+
+      if (bMotorOn) {               //Actualizamos el flag.
+        bMotorOn=false;
+      }
+      else
+      {
+        bMotorOn=true;
+      }
+
+    }
+
+    if (boton_b.fell()) {           //Han pulsado el botón B (flanco bajada)
+      motor(0);                     //Se para el motor
+      bMotorOn=false;
+      bCalibrando=false;            //Marcamos salida del bucle
+    }
+
+    //Código para acumular máximo y mínimo:
+
+    iLectura = analogRead(PIN_LECTURA);
+
+    if (iLectura<iMinimo) {
+      iMinimo=iLectura;
+    }
+
+    if (iLectura>iMaximo) {
+      iMaximo=iLectura;
+    }
+
+    if (bMotorOn==true){
+      lcd_umbrales(iMinimo, iLectura, iMaximo);
+    }
+  }
+
+  iUmbral=iMinimo+((iMaximo-iMinimo)*C_UMBRAL); //Calculamos el umbral de detección para loop
+  lcd.clear();
+  lcd.setCursor(0, 1);                          //Pasamos el control a loop
+  lcd.print(" Esperando comando");
+  lcd_umbrales(iMinimo, 0, iMaximo);            //Imprimo sólo máximo y mínimo
+
+  iLectura =  analogRead(PIN_LECTURA);          //Dejamos en consonancia el booleano de estado de la fresa
+
+  if (iLectura < iUmbral)                       //Fresa introducida
+  {
+    lcd.setCursor(9,3);                         //Indicamos el estado introducido de la fresa
+    lcd.print("__");
+    bEstadoFresa=true;
+  }
+  else
+  {
+    lcd.setCursor(9,3);                         //Indicamos el estado introducido de la fresa
+    lcd.print("^^");
+    bEstadoFresa=false;
+  }
+
+  emTiempo=0;                                   //Inicializamos el contador de tiempo.
+
+}
+
+void loop()
+{
+
+  if (Serial.available() > 0)          //Si hay comando remoto, se actúa
+  {
+    cDato = Serial.read();
+    switch (cDato)
+    {
+      lcd.setCursor(0,0);             //Borramos mensaje de rotura detectada, por si es segunda ejecución después de detectar fresa rota.
+      lcd.print(iUmbral); //"                    ");
+      case '0': motor(0); lcd_velocidad(0); bGirando = false; break;
+      case '1': motor(10); lcd_velocidad(10); bGirando = true; break;
+      case '2': motor(20); lcd_velocidad(20); bGirando = true; break;
+      case '3': motor(30); lcd_velocidad(30); bGirando = true; break;
+      case '4': motor(40); lcd_velocidad(40); bGirando = true; break;
+      case '5': motor(50); lcd_velocidad(50); bGirando = true; break;
+      case '6': motor(60); lcd_velocidad(60); bGirando = true; break;
+      case '7': motor(70); lcd_velocidad(70); bGirando = true; break;
+      case '8': motor(80); lcd_velocidad(80); bGirando = true; break;
+      case '9': motor(90); lcd_velocidad(90); bGirando = true; break;
+      case 'a': motor(100); lcd_velocidad(100); bGirando = true; break;
+    }
+    emTiempo=0;                         //Reseteamos contador de rotura de fresa.
+  }
+
+  iLectura =  analogRead(PIN_LECTURA);  //Envio de cada medida tomada del canal de luz por el puerto serie
+  // Sólo para depuración, no descomentar: Serial.println(iLectura);
+
+  if (iLectura < iUmbral) // Fresa introducida
+  {
+    lcd.setCursor(9,3);
+    lcd.print("__");
+    if (bEstadoFresa==false) {
+      bEstadoFresa=true;                //Indicamos el estado introducido de la fresa
+      emTiempo=0;                       //Reseteamos contador de rotura de fresa.
+    }
+  }
+
+  if (iLectura > iUmbral) // Fresa extraída
+  {
+    lcd.setCursor(9,3);
+    lcd.print("^^");
+    if (bEstadoFresa==true) {
+      bEstadoFresa=false;               //Indicamos el estado introducido de la fresa
+      emTiempo=0;                       //Reseteamos contador de rotura de fresa.
+    }
+  }
+
+  if (bGirando==true) {                 //Si hemos superado el tiempo de guarda, estando en giro
+    if (emTiempo > iPeriodo) {
+      lcd.setCursor(0,0);               //Entonces la fresa está rota
+      lcd.print("  Rotura detectada  ");
+      Serial.print('r');                //Informamos al PC.
+      motor(0);
+      lcd_velocidad(0);
+      bGirando = false;                 //Paramos el motor, pero se puede volver a emitir comando desde el PC.
+    }
+  }
+
+}
+
+


one typo fixed

one typo fixed

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JackBDu/robot-tour-guide.git/'


Adding ability to specify which node to send to, and define which colour you want to use in the animation (if applicable)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/hooroo/moteino_build_lights.git/'


add test code

add test code

error: pathspec 'control-scheme/test_serial/test_serial.ino' did not match any file(s) known to git

--- control-scheme/test_serial/test_serial.ino
+++ control-scheme/test_serial/test_serial.ino
@@ -0,0 +1,13 @@
+void setup() {
+  Serial.begin(9600);
+}
+
+void loop() {
+  int s[] = {1, 2, 3, 4, 10, 11, 12, 13, 14, 15, 19, 20, 21};
+
+  for(int i=0; i<13; i++)
+  {
+    Serial.println(s[i]);
+    delay(2000);
+  }
+}


added motor_test.ino

added motor_test.ino

error: pathspec 'daily' did not match any file(s) known to git
error: pathspec 'code/Day' did not match any file(s) known to git
error: pathspec '2/motor_test/motor_test.ino' did not match any file(s) known to git


Fixed removed reference

Fixed removed reference

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/dltn/tortellini.git/'


Add Airboard example

Add Airboard example

error: pathspec 'examples/Boards_WiFi/TheAirBoard_WiFly/TheAirBoard_WiFly.ino' did not match any file(s) known to git

--- examples/Boards_WiFi/TheAirBoard_WiFly/TheAirBoard_WiFly.ino
+++ examples/Boards_WiFi/TheAirBoard_WiFly/TheAirBoard_WiFly.ino
@@ -0,0 +1,68 @@
+/**************************************************************
+ * Blynk is a platform with iOS and Android apps to control
+ * Arduino, Raspberry Pi and the likes over the Internet.
+ * You can easily build graphic interfaces for all your
+ * projects by simply dragging and dropping widgets.
+ *
+ *   Downloads, docs, tutorials: http://www.blynk.cc
+ *   Blynk community:            http://community.blynk.cc
+ *   Social networks:            http://www.fb.com/blynkapp
+ *                               http://twitter.com/blynk_app
+ *
+ * Blynk library is licensed under MIT license
+ * This example code is in public domain.
+ *
+ **************************************************************
+ * This example shows how to use AirBoard + RN-XV WiFly module
+ * to connect your project to Blynk.
+ *
+ * For this example you need WiFlyHQ library:
+ *   https://github.com/harlequin-tech/WiFlyHQ
+ *
+ * Note: Be sure to read this: http://www.theairboard.cc/quick-start/
+ *       WiFly firmware version 4.41 or later is preferred.
+ *
+ * Change WiFi ssid, pass, and Blynk auth token to run :)
+ * Feel free to apply it to any other example. It's simple!
+ *
+ **************************************************************/
+
+#include <SoftwareSerial.h>
+SoftwareSerial DebugSerial(10, 11); // RX, TX
+#define BLYNK_PRINT DebugSerial     // Comment this out to disable prints and save space
+
+#include <TheAirBoard.h>
+#include <WiFlyHQ.h>
+#include <BlynkSimpleWiFly.h>
+
+// You should get Auth Token in the Blynk App.
+// Go to the Project Settings (nut icon).
+char auth[] = "YourAuthToken";
+
+#define WiFlySerial Serial
+WiFly wifly;
+
+void setup()
+{
+  DebugSerial.begin(9600);  // Set console baud rate
+  delay(10);
+  WiFlySerial.begin(9600);  // Set your RN-XV baud rate
+  delay(10);
+
+  // Bind WiFly driver to the serial
+  if (!wifly.begin(&WiFlySerial)) {
+    BLYNK_FATAL("Failed to start wifly");
+  }
+
+  // You can try increasing baud rate:
+  //wifly.setBaud(115200);
+  //WiFlySerial.begin(115200);
+
+  Blynk.begin(auth, wifly, "ssid", "pass");
+}
+
+void loop()
+{
+  Blynk.run();
+}
+


global speed 180, turn speed 150

global speed 180, turn speed 150

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Electroscholars/LineFollower.git/'


Create SerialPrint.ino

Create SerialPrint.ino

error: pathspec 'src/SerialPrint/SerialPrint.ino' did not match any file(s) known to git

--- src/SerialPrint/SerialPrint.ino
+++ src/SerialPrint/SerialPrint.ino
@@ -0,0 +1 @@
+


Kapitola: Začíname s robotom

Kapitola: Začíname s robotom

error: pathspec 'Programy/02_Spomaľovanie' did not match any file(s) known to git
error: pathspec 'a' did not match any file(s) known to git
error: pathspec 'zrýchľovanie.ino' did not match any file(s) known to git


Add alternate light scheme

Add alternate light scheme

error: pathspec 'arduino_neopixel/ALTERNATIVE_PATTERNS/ALTERNATIVE_PATTERNS.ino' did not match any file(s) known to git

--- arduino_neopixel/ALTERNATIVE_PATTERNS/ALTERNATIVE_PATTERNS.ino
+++ arduino_neopixel/ALTERNATIVE_PATTERNS/ALTERNATIVE_PATTERNS.ino
@@ -0,0 +1,148 @@
+// Skateboard Neopixel Program
+// Controls 2*26 sets of neopixels on the bottom of my DIY electric skateboard
+// Used an Arduino Nano to control the lights to save logic level conversion on the Pi Zero and worrying about task management
+// Wiimote 'A' button triggers Pi that then triggers Arduino inputs that then turn on the lights
+
+#include <Adafruit_NeoPixel.h>
+#ifdef __AVR__
+  #include <avr/power.h>
+#endif
+
+#define PIN 6
+#define BUTTON 7
+#define INTERRUPT_PIN 2
+
+Adafruit_NeoPixel strip = Adafruit_NeoPixel(26, PIN, NEO_GRB + NEO_KHZ800);
+
+void setup() {
+  strip.begin();
+  strip.show();
+  pinMode(BUTTON, INPUT);
+  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), ISRturn_off, RISING);
+  }
+
+void loop() {
+  int value = 0;
+  int but_val = 0;
+  blank();
+  while (true){
+    but_val = digitalRead(BUTTON);
+    if (but_val == 1){
+        sequence();
+      }
+    if (but_val == 0){
+        blank();
+      }
+    }
+  }
+
+void ISRturn_off(){
+  blank();
+  }
+
+void colorWipe(uint32_t c, uint8_t wait) {
+  for(int i = (strip.numPixels()-1); i >= 0; i = i - 1) {
+    strip.setPixelColor(i, c);
+    strip.show();
+    delay(wait);
+    }
+  }
+
+void sequence(){
+  colorWipe(strip.Color(255, 0, 0), 25);
+  colorWipe(strip.Color(0, 255, 0), 25);
+  colorWipe(strip.Color(0, 0, 255), 25);
+
+  for(int i = 0; i <=4; i++){
+    theaterChase(strip.Color(127, 127, 127), 25); // White
+    theaterChase(strip.Color(127, 0, 0), 25); // Red
+    theaterChase(strip.Color(0, 0, 127), 25); // Blue
+  }
+  rainbow(20);
+  rainbowCycle(20);
+  theaterChaseRainbow(25);
+
+  }
+
+void blank(){
+  colorWipe(strip.Color(0, 0, 0), 25);
+  }
+
+/////// ADAFRUIT PRESET PATTERNS BELOW//////////
+
+
+void rainbow(uint8_t wait) {
+  uint16_t i, j;
+
+  for(j=0; j<256; j++) {
+    for(i=0; i<strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel((i+j) & 255));
+    }
+    strip.show();
+    delay(wait);
+  }
+}
+
+// Slightly different, this makes the rainbow equally distributed throughout
+void rainbowCycle(uint8_t wait) {
+  uint16_t i, j;
+
+  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
+    for(i=0; i< strip.numPixels(); i++) {
+      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
+    }
+    strip.show();
+    delay(wait);
+  }
+}
+
+//Theatre-style crawling lights.
+void theaterChase(uint32_t c, uint8_t wait) {
+  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
+    for (int q=0; q < 3; q++) {
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, c);    //turn every third pixel on
+      }
+      strip.show();
+
+      delay(wait);
+
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, 0);        //turn every third pixel off
+      }
+    }
+  }
+}
+
+//Theatre-style crawling lights with rainbow effect
+void theaterChaseRainbow(uint8_t wait) {
+  for (int j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
+    for (int q=0; q < 3; q++) {
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, Wheel( (i+j) % 255));    //turn every third pixel on
+      }
+      strip.show();
+
+      delay(wait);
+
+      for (uint16_t i=0; i < strip.numPixels(); i=i+3) {
+        strip.setPixelColor(i+q, 0);        //turn every third pixel off
+      }
+    }
+  }
+}
+
+// Input a value 0 to 255 to get a color value.
+// The colours are a transition r - g - b - back to r.
+uint32_t Wheel(byte WheelPos) {
+  WheelPos = 255 - WheelPos;
+  if(WheelPos < 85) {
+    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
+  }
+  if(WheelPos < 170) {
+    WheelPos -= 85;
+    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
+  }
+  WheelPos -= 170;
+  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
+}


Add touch calibration diagnostic sketch

Add touch calibration diagnostic sketch

error: pathspec 'examples/arduino/diag_ard_touch_calib/diag_ard_touch_calib.ino' did not match any file(s) known to git

--- examples/arduino/diag_ard_touch_calib/diag_ard_touch_calib.ino
+++ examples/arduino/diag_ard_touch_calib/diag_ard_touch_calib.ino
@@ -0,0 +1,940 @@
+//
+// GUIslice Library Examples
+// - Calvin Hass
+// - https://www.impulseadventure.com/elec/guislice-gui.html
+// - https://github.com/ImpulseAdventure/GUIslice
+// - TFT Diagnostic (Arduino): Touch Calibration
+//   - This sketch is intended to run on resistive displays only
+//   - Please refer to the touch configuration guide for details:
+//     https://github.com/ImpulseAdventure/GUIslice/wiki/Configure-Touch-Support
+//
+// ARDUINO NOTES:
+// - GUIslice_config must be edited to match the pinout connections
+//   between the Arduino CPU and the display controller (eg. ADAGFX_PIN_*).
+//
+
+#include "GUIslice.h"
+#include "GUIslice_drv.h"
+
+// Check configuration settings
+#if defined(DRV_TOUCH_NONE)
+  #error "Calibration requires a touch driver but DRV_TOUCH_NONE was set"
+#elif !defined(DRV_TOUCH_ADA_STMPE610) && !defined(DRV_TOUCH_ADA_SIMPLE) && !defined(DRV_TOUCH_XPT2046)
+  #error "Calibration only supported for resistive touch displays"
+#endif
+
+// Import optional libraries
+#if defined(DRV_DISP_ADAGFX_MCUFRIEND)
+  // Import MCUFRIEND to support ID reporting
+  #include <MCUFRIEND_kbv.h>
+  extern MCUFRIEND_kbv m_disp;
+#endif
+
+// ------------------------------------------------------------
+// Additional configuration:
+// ------------------------------------------------------------
+
+// Uncomment the following line to display additional debug info
+//#define DEBUG_CALIB
+
+// Select method used for averaging
+// - Uncomment one of the following lines
+#define CALC_BASIC_AVG  // Simple average
+//#define CALC_EXP_AVG  // Exponential moving average [not yet supported]
+
+// ------------------------------------------------------------
+
+
+// Defines for resources
+enum { E_FONT_TXT };
+
+#define MAX_STR 60
+
+bool  m_bQuit = false; // Quit flag (unused)
+
+// State machine settings
+typedef enum {
+  STATE_CAL_UNDEF = 0,
+  STATE_CAL_START_MSG,
+  STATE_CAPT_TL_MSG,
+  STATE_CAPT_TL_DO,
+  STATE_CAPT_TR_MSG,
+  STATE_CAPT_TR_DO,
+  STATE_CAPT_BL_MSG,
+  STATE_CAPT_BL_DO,
+  STATE_CAPT_BR_MSG,
+  STATE_CAPT_BR_DO,
+  STATE_CAPT_ROT,
+  STATE_CAPT_ROT_TL_MSG,
+  STATE_CAPT_ROT_TL_DO,
+  STATE_CAL_REPORT,
+  STATE_CAL_DONE_MSG,
+  STATE_CAL_DONE_END,
+  STATE_CAL_SET,
+  STATE_TEST_MSG,
+  STATE_TEST_DO,
+  STATE_CAL_REDO_MSG,
+  STATE_ROTATE_MSG,
+  STATE_ROTATE_DO
+} teState;
+teState m_eState = STATE_CAL_START_MSG;
+
+// Definitions for calibration points
+typedef enum {
+  POINT_TL = 0,
+  POINT_TR,
+  POINT_BL,
+  POINT_BR,
+  POINT_TL_ROT,
+  POINT_TEST,
+  POINT__NUM,
+} teCalibPt;
+teCalibPt   m_eCalibPt = POINT_TL;
+
+typedef enum {
+  E_ROT_NORMAL = 0,
+  E_ROT_REVERSE,
+  E_ROT_SWAP,
+  E_ROT_NONE,
+  E_ROT_UNDEF
+} teRotSpecial;
+teRotSpecial m_eRotSpecial = E_ROT_UNDEF;
+
+typedef struct {
+  bool          bXLeft;
+  bool          bYTop;
+  const char*   acStr;
+  teState       eStateDo;
+  teState       eStateNxt;
+} tsCalibStage;
+
+// Define calibration sequence
+tsCalibStage m_asCalibStage[5] = {
+  {true, true, "Capture TL",STATE_CAPT_TL_DO,STATE_CAPT_TR_MSG},
+  {false,true, "Capture TR",STATE_CAPT_TR_DO,STATE_CAPT_BL_MSG},
+  {true, false,"Capture BL",STATE_CAPT_BL_DO,STATE_CAPT_BR_MSG},
+  {false,false,"Capture BR",STATE_CAPT_BR_DO,STATE_CAPT_ROT},
+  {true, true, "Capture TL (Rotated)",STATE_CAPT_ROT_TL_DO,STATE_CAL_REPORT},
+};
+
+
+teState     m_eStateOld = STATE_CAL_UNDEF;
+bool        m_bStateBegin = true;
+
+// Define calibration target display
+#define TARGET_MARGIN 10
+#define TARGET_SIZE   10
+
+// Calibration data
+int16_t   m_nTouchXMin;
+int16_t   m_nTouchXMax;
+int16_t   m_nTouchYMin;
+int16_t   m_nTouchYMax;
+int16_t   m_nTouchZMin;
+int16_t   m_nTouchZMax;
+
+int m_anTouchXPeak[POINT__NUM];
+int m_anTouchYPeak[POINT__NUM];
+
+// Storage for touch averaging
+int32_t m_nPointBufX = 0;
+int32_t m_nPointBufY = 0;
+uint16_t m_nPointBufCnt = 0;
+
+
+
+// For exponential averaging, define the time constant
+// and precision used in the calculation.
+#define EXP_AVG_NUMER 6
+#define EXP_AVG_DENOM 10
+#define EXP_AVG_FIXPT 8
+
+// Define the tolerance in detecting the rotated display
+// - Setting a value of 10 means that it will attempt to
+//   locate a calibration point within 10% of the rotated click
+#define DET_ROT_TOLER_PCT 10
+
+int16_t m_nPointFinalX = -1;
+int16_t m_nPointFinalY = -1;
+
+// Reset to calibration defaults from configuration
+// - These values will be overwritten after calibration
+uint16_t m_nTouchCalXMin = ADATOUCH_X_MIN;
+uint16_t m_nTouchCalXMax = ADATOUCH_X_MAX;
+uint16_t m_nTouchCalYMin = ADATOUCH_Y_MIN;
+uint16_t m_nTouchCalYMax = ADATOUCH_Y_MAX;
+// Corner readings before adjusting for offsets
+uint16_t m_nTouchCalXMinRaw;
+uint16_t m_nTouchCalXMaxRaw;
+uint16_t m_nTouchCalYMinRaw;
+uint16_t m_nTouchCalYMaxRaw;
+// Preserve reading ranges
+int16_t m_nTouchCalXRngRaw;
+int16_t m_nTouchCalYRngRaw;
+
+
+
+bool m_bTouchCoordValid = false;
+
+char m_acTxt[MAX_STR];
+
+// Define GUI display elements
+gslc_tsRect m_rLblX = (gslc_tsRect) { 40, 60, 50, 10 };
+gslc_tsRect m_rCurX = (gslc_tsRect) { 100, 60, 30, 10 };
+gslc_tsRect m_rRngX = (gslc_tsRect) { 140, 60, 65, 10 };
+
+gslc_tsRect m_rLblY = (gslc_tsRect) { 40, 80, 50, 10 };
+gslc_tsRect m_rCurY = (gslc_tsRect) { 100, 80, 30, 10 };
+gslc_tsRect m_rRngY = (gslc_tsRect) { 140, 80, 65, 10 };
+
+gslc_tsRect m_rLblZ = (gslc_tsRect) { 40, 100, 50, 10 };
+gslc_tsRect m_rCurZ = (gslc_tsRect) { 100, 100, 30, 10 };
+gslc_tsRect m_rRngZ = (gslc_tsRect) { 140, 100, 65, 10 };
+
+gslc_tsRect m_rLblStatus = (gslc_tsRect) { 30, 20, 110, 10 };
+gslc_tsRect m_rCurStatus = (gslc_tsRect) { 100, 20, 120, 10 };
+
+gslc_tsRect m_rReport = (gslc_tsRect) { 40, 60, 140, 10 };
+
+
+// Instantiate the GUI
+#define MAX_FONT                1
+
+gslc_tsGui                  m_gui;
+gslc_tsDriver               m_drv;
+gslc_tsFont                 m_asFont[MAX_FONT];
+
+gslc_tsFont*                m_pFont = NULL;
+
+// Define debug message function
+static int16_t DebugOut(char ch) { Serial.write(ch); return 0; }
+
+void ResetCalib()
+{
+  // Reset the calibration ranges to enable min/max determination
+  m_nTouchCalXMin = 9999;
+  m_nTouchCalXMax = 0;
+  m_nTouchCalYMin = 9999;
+  m_nTouchCalYMax = 0;
+
+  for (int nInd = 0; nInd < POINT__NUM; nInd++) {
+    m_anTouchXPeak[nInd] = 0;
+    m_anTouchYPeak[nInd] = 0;
+  }
+
+  m_eRotSpecial = E_ROT_UNDEF;
+}
+
+void ResetMax()
+{
+  m_nTouchXMin = 9999;
+  m_nTouchXMax = 0;
+  m_nTouchYMin = 9999;
+  m_nTouchYMax = 0;
+  m_nTouchZMin = 9999;
+  m_nTouchZMax = 0;
+
+  m_bTouchCoordValid = false;
+}
+
+void DrawBackground()
+{
+  gslc_tsRect rBack = (gslc_tsRect) { 0, 0, 0, 0 };
+  rBack.w = m_gui.nDispW;
+  rBack.h = m_gui.nDispH;
+  gslc_DrawFillRect(&m_gui, rBack, GSLC_COL_BLACK);
+}
+
+void DrawBackgroundStart()
+{
+  int16_t nPosX = m_rReport.x;
+  int16_t nPosY = m_rReport.y;
+  gslc_DrvDrawTxt(&m_gui, nPosX, nPosY + 00, m_pFont, "In the following pages, use", GSLC_TXT_DEFAULT, GSLC_COL_WHITE, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, nPosX, nPosY + 10, m_pFont, "a point/stylus to touch the", GSLC_TXT_DEFAULT, GSLC_COL_WHITE, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, nPosX, nPosY + 20, m_pFont, "crosshairs in each corner", GSLC_TXT_DEFAULT, GSLC_COL_WHITE, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, nPosX, nPosY + 30, m_pFont, "as indicated for >3 secs.", GSLC_TXT_DEFAULT, GSLC_COL_WHITE, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, nPosX, nPosY + 60, m_pFont, "Click to start", GSLC_TXT_DEFAULT, GSLC_COL_BLUE, GSLC_COL_BLACK);
+}
+
+void DrawPageCoords()
+{
+  gslc_DrvDrawTxt(&m_gui, m_rLblX.x, m_rLblX.y, m_pFont, "X:", GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rLblY.x, m_rLblY.y, m_pFont, "Y:", GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rLblZ.x, m_rLblZ.y, m_pFont, "Z:", GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+}
+
+
+void RedrawStatus(const char* pStatus)
+{
+  gslc_DrvDrawTxt(&m_gui, m_rLblStatus.x, m_rLblStatus.y, m_pFont, "Status:", GSLC_TXT_DEFAULT, GSLC_COL_WHITE, GSLC_COL_BLACK);
+
+  gslc_DrawFillRect(&m_gui, m_rCurStatus, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rCurStatus.x, m_rCurStatus.y, m_pFont, pStatus, GSLC_TXT_DEFAULT, GSLC_COL_PURPLE, GSLC_COL_BLACK);
+}
+
+void DrawTarget(int16_t nX, int16_t nY, uint16_t nSize, gslc_tsColor nColOut, gslc_tsColor nColIn)
+{
+  gslc_tsRect rRect;
+  rRect.x = nX - nSize;
+  rRect.y = nY - nSize;
+  rRect.w = nSize * 2;
+  rRect.h = nSize * 2;
+  gslc_DrawFrameRect(&m_gui, rRect, nColOut);
+  gslc_DrawLine(&m_gui, nX - (nSize / 2), nY, nX + (nSize / 2) - 1, nY, nColIn);
+  gslc_DrawLine(&m_gui, nX, nY - (nSize / 2), nX, nY + (nSize / 2) - 1, nColIn);
+}
+
+// This function updates the coordinate text
+// - Background redraw is used to limit the update area
+void RedrawCoords(int16_t nTouchX, int16_t nTouchY, uint16_t nTouchZ)
+{
+  // X
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u" : "-", nTouchX);
+  gslc_DrawFillRect(&m_gui, m_rCurX, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rCurX.x, m_rCurX.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u..%u" : "-", m_nTouchXMin, m_nTouchXMax);
+  gslc_DrawFillRect(&m_gui, m_rRngX, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rRngX.x, m_rRngX.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_BLUE, GSLC_COL_BLACK);
+
+  // Y
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u" : "-", nTouchY);
+  gslc_DrawFillRect(&m_gui, m_rCurY, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rCurY.x, m_rCurY.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u..%u" : "-", m_nTouchYMin, m_nTouchYMax);
+  gslc_DrawFillRect(&m_gui, m_rRngY, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rRngY.x, m_rRngY.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_BLUE, GSLC_COL_BLACK);
+
+  // Z
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u" : "-", nTouchZ);
+  gslc_DrawFillRect(&m_gui, m_rCurZ, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rCurZ.x, m_rCurZ.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, (m_bTouchCoordValid) ? "%u..%u" : "-", m_nTouchZMin, m_nTouchZMax);
+  gslc_DrawFillRect(&m_gui, m_rRngZ, GSLC_COL_BLACK);
+  gslc_DrvDrawTxt(&m_gui, m_rRngZ.x, m_rRngZ.y, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_BLUE, GSLC_COL_BLACK);
+}
+
+
+void DrawTracer(int16_t nTouchX, int16_t nTouchY)
+{
+  // Render marker
+  gslc_DrawSetPixel(&m_gui, nTouchX, nTouchY, GSLC_COL_RED);
+}
+
+void ResetDatapoints()
+{
+  m_nPointBufX = 0;
+  m_nPointBufY = 0;
+  m_nPointBufCnt = 0;
+}
+
+void AddDatapoint(int16_t nTouchX, int16_t nTouchY)
+{
+  #if defined(CALC_EXP_AVG)
+    // Exponential moving average
+    m_nPointBufX = ((EXP_AVG_NUMER)* m_nPointBufX / EXP_AVG_DENOM) + (EXP_AVG_FIXPT * (EXP_AVG_DENOM - EXP_AVG_NUMER) * nTouchX / EXP_AVG_DENOM);
+    m_nPointBufY = ((EXP_AVG_NUMER)* m_nPointBufY / EXP_AVG_DENOM) + (EXP_AVG_FIXPT * (EXP_AVG_DENOM - EXP_AVG_NUMER) * nTouchY / EXP_AVG_DENOM);
+    m_nPointBufCnt++;
+    #if defined(DEBUG_CALIB)
+      snprintf(m_acTxt, MAX_STR, "AddDatapoint(EXP): (%d,%d) => (%ld,%ld)", nTouchX, nTouchY, m_nPointBufX, m_nPointBufY);
+      GSLC_DEBUG_PRINT("%s\n", m_acTxt);
+    #endif // DEBUG_CALIB
+  #elif defined(CALC_BASIC_AVG)
+    // Simple averaging
+    // - Avoid integer overflow
+    if (m_nPointBufCnt < 10000) {
+      m_nPointBufX += nTouchX;
+      m_nPointBufY += nTouchY;
+      m_nPointBufCnt++;
+      #if defined(DEBUG_CALIB)
+        snprintf(m_acTxt, MAX_STR, "AddDatapoint(BASIC): (%d,%d) => (%ld,%ld,%d)", nTouchX, nTouchY, m_nPointBufX, m_nPointBufY, m_nPointBufCnt);
+        GSLC_DEBUG_PRINT("%s\n", m_acTxt);
+      #endif // DEBUG_CALIB
+    }
+  #endif
+}
+
+void CalcDatapoint(teCalibPt ePoint)
+{
+  #if defined(CALC_EXP_AVG)
+    m_nPointFinalX = m_nPointBufX / EXP_AVG_FIXPT;
+    m_nPointFinalY = m_nPointBufY / EXP_AVG_FIXPT;
+  #elif defined(CALC_BASIC_AVG)
+    if (m_nPointBufCnt > 0) {
+      m_nPointFinalX = m_nPointBufX / m_nPointBufCnt;
+      m_nPointFinalY = m_nPointBufY / m_nPointBufCnt;
+    }
+  #endif
+
+  // Record the final value in the corresponding touch point
+  m_anTouchXPeak[ePoint] = m_nPointFinalX;
+  m_anTouchYPeak[ePoint] = m_nPointFinalY;
+
+}
+
+void CalcMaxCoords(int16_t nTouchX, int16_t nTouchY, uint16_t nTouchZ)
+{
+  // Capture maximums (for current step)
+  m_nTouchXMin = (nTouchX < m_nTouchXMin) ? nTouchX : m_nTouchXMin;
+  m_nTouchXMax = (nTouchX > m_nTouchXMax) ? nTouchX : m_nTouchXMax;
+  m_nTouchYMin = (nTouchY < m_nTouchYMin) ? nTouchY : m_nTouchYMin;
+  m_nTouchYMax = (nTouchY > m_nTouchYMax) ? nTouchY : m_nTouchYMax;
+  m_nTouchZMin = (nTouchZ < m_nTouchZMin) ? nTouchZ : m_nTouchZMin;
+  m_nTouchZMax = (nTouchZ > m_nTouchZMax) ? nTouchZ : m_nTouchZMax;
+}
+
+
+void CalcCalib()
+{
+  float   fSx, fSy;
+  int16_t nXMin, nXMax, nYMin, nYMax;
+  int16_t nXd, nYd;
+  int16_t nPixXd, nPixYd;
+
+  // Calculate calibration ranges based on averaging of raw target values
+  // - Assume calibration was done in native orientation
+  // - Assume pins XP/XM/YP/YM have been assigned correctly
+  m_nTouchCalXMinRaw = (m_anTouchXPeak[POINT_TL] + m_anTouchXPeak[POINT_BL]) / 2;
+  m_nTouchCalXMaxRaw = (m_anTouchXPeak[POINT_TR] + m_anTouchXPeak[POINT_BR]) / 2;
+  m_nTouchCalYMinRaw = (m_anTouchYPeak[POINT_TL] + m_anTouchYPeak[POINT_TR]) / 2;
+  m_nTouchCalYMaxRaw = (m_anTouchYPeak[POINT_BL] + m_anTouchYPeak[POINT_BR]) / 2;
+
+  m_nTouchCalXRngRaw = m_nTouchCalXMaxRaw - m_nTouchCalXMinRaw;
+  m_nTouchCalYRngRaw = m_nTouchCalYMaxRaw - m_nTouchCalYMinRaw;
+  m_nTouchCalXRngRaw = abs(m_nTouchCalXRngRaw);
+  m_nTouchCalYRngRaw = abs(m_nTouchCalYRngRaw);
+
+  // Apply correction factor for targets not at corners
+
+  #if defined(DEBUG_CALIB)
+    // Report raw calibration range prior to adjustment
+    GSLC_DEBUG_PRINT("CALIB: Range(raw) nXMin=%d nYmin=%d nXMax=%d nYMax=%d\n",
+      m_nTouchCalXMinRaw, m_nTouchCalYMinRaw, m_nTouchCalXMaxRaw, m_nTouchCalYMaxRaw);
+  #endif // DEBUG_CALIB
+
+
+  // Calculate the range in touch readings & range in pixel coordinates
+  nXd = (m_nTouchCalXMaxRaw - m_nTouchCalXMinRaw);
+  nYd = (m_nTouchCalYMaxRaw - m_nTouchCalYMinRaw);
+  nPixXd = (m_gui.nDisp0W - 2 * TARGET_MARGIN);
+  nPixYd = (m_gui.nDisp0H - 2 * TARGET_MARGIN);
+
+  // Determine mapping slope
+  fSx = (float)nXd / (float)nPixXd;
+  fSy = (float)nYd / (float)nPixYd;
+
+  // Extrapolate range in touch readings (at corners)
+  nXMin = m_nTouchCalXMinRaw - (fSx * TARGET_MARGIN);
+  nYMin = m_nTouchCalYMinRaw - (fSy * TARGET_MARGIN);
+  nXMax = m_nTouchCalXMaxRaw + (fSx * TARGET_MARGIN);
+  nYMax = m_nTouchCalYMaxRaw + (fSy * TARGET_MARGIN);
+
+  // Assign the adjusted calibration ranges
+  m_nTouchCalXMin = nXMin;
+  m_nTouchCalYMin = nYMin;
+  m_nTouchCalXMax = nXMax;
+  m_nTouchCalYMax = nYMax;
+
+  GSLC_DEBUG_PRINT("CALIB: Range(adj) nXMin=%d nYmin=%d nXMax=%d nYMax=%d\n",
+    m_nTouchCalXMin, m_nTouchCalYMin, m_nTouchCalXMax, m_nTouchCalYMax);
+
+}
+
+teCalibPt FindClosestPt(int16_t nX, int16_t nY)
+{
+  teCalibPt ePoint = POINT_TEST;
+  int16_t nDeltaMinX, nDeltaMaxX, nDeltaMinY, nDeltaMaxY;
+  /*
+    nDeltaMinX = abs(m_nTouchCalXMin - nX);
+    nDeltaMaxX = abs(m_nTouchCalXMax - nX);
+    nDeltaMinY = abs(m_nTouchCalYMin - nY);
+    nDeltaMaxY = abs(m_nTouchCalYMax - nY);
+  */
+  nDeltaMinX = m_nTouchCalXMinRaw - nX;
+  nDeltaMaxX = m_nTouchCalXMaxRaw - nX;
+  nDeltaMinY = m_nTouchCalYMinRaw - nY;
+  nDeltaMaxY = m_nTouchCalYMaxRaw - nY;
+  nDeltaMinX = abs(nDeltaMinX);
+  nDeltaMaxX = abs(nDeltaMaxX);
+  nDeltaMinY = abs(nDeltaMinY);
+  nDeltaMaxY = abs(nDeltaMaxY);
+
+  // Calculate tolerance for corner detection
+  int16_t nTolerX;
+  int16_t nTolerY;
+  nTolerX = m_nTouchCalXRngRaw * DET_ROT_TOLER_PCT / 100;
+  nTolerY = m_nTouchCalYRngRaw * DET_ROT_TOLER_PCT / 100;
+
+  #ifdef DEBUG_CALIB
+    GSLC_DEBUG_PRINT("ROT_FIND: calib_raw MinX=%d MaxX=%d MinY=%d MaxY=%d\n",
+      m_nTouchCalXMinRaw, m_nTouchCalXMaxRaw, m_nTouchCalYMinRaw, m_nTouchCalYMaxRaw);
+    GSLC_DEBUG_PRINT("ROT_FIND: rotate    X=%d Y=%d\n", nX, nY);
+    GSLC_DEBUG_PRINT("ROT_FIND: tolerance X=%d Y=%d\n", nTolerX, nTolerY);
+    GSLC_DEBUG_PRINT("ROT_FIND: delta     MinX= %d MaxX= %d MinY= %d MaxY= %d\n",
+      nDeltaMinX, nDeltaMaxX, nDeltaMinY, nDeltaMaxY);
+  #endif
+
+  // Locate nearest calibration point that is within the tolerance zone
+  if ((nDeltaMinX < nDeltaMaxX) && (nDeltaMinX < nTolerX)) {
+    if ((nDeltaMinY < nDeltaMaxY) && (nDeltaMinY < nTolerY)) {
+      ePoint = POINT_TL;
+    }
+    else if ((nDeltaMaxY < nDeltaMinY) && (nDeltaMaxY < nTolerY)) {
+      ePoint = POINT_BL;
+    }
+    else {
+      #ifdef DEBUG_CALIB
+        GSLC_DEBUG_PRINT("ROT_FIND: Closest not found: X close, Y far\n", "");
+      #endif // DEBUG_CALIB
+    }
+  }
+  else if ((nDeltaMaxX < nDeltaMinX) && (nDeltaMaxX < nTolerX)) {
+    if ((nDeltaMinY < nDeltaMaxY) && (nDeltaMinY < nTolerY)) {
+      ePoint = POINT_TR;
+    }
+    else if ((nDeltaMaxY < nDeltaMinY) && (nDeltaMaxY < nTolerY)) {
+      ePoint = POINT_BR;
+    }
+    else {
+      #ifdef DEBUG_CALIB
+        GSLC_DEBUG_PRINT("ROT_FIND: Closest not found: X far, Y close\n", "");
+      #endif // DEBUG_CALIB
+    }
+  }
+  else {
+    #ifdef DEBUG_CALIB
+      GSLC_DEBUG_PRINT("ROT_FIND: Closest not found: X far, Y far\n", "");
+    #endif // DEBUG_CALIB
+  }
+
+  #ifdef DEBUG_CALIB
+    if (ePoint != POINT_TEST) {
+      GSLC_DEBUG_PRINT("ROT_FIND: Closest found: [%d]\n", ePoint);
+    }
+  #endif // DEBUG_CALIB
+
+  return ePoint;
+}
+
+// Perform additional check to infer screen behavior as a
+// result of screen rotation. The additional calibrattion
+// point in ROTATE=1 mode enables us to see whether the
+// display rotates as expected or whether the rotation direction
+// is reversed and requires additional configuration.
+void CalcCalibRotate()
+{
+  m_eRotSpecial = E_ROT_UNDEF;
+
+  // Is the remapped POINT_ROT_TL in the top-right corner? (near POINT_TR?)
+  // Determine which of the four raw calibration points were closest to
+  // rotated point. Depending on which point was detected, we can infer
+  // how the display must have been rotated. This enables us to determine
+  // if we need additional configuration to handle the various rotation modes.
+  teCalibPt ePtClosest = FindClosestPt(m_anTouchXPeak[POINT_TL_ROT], m_anTouchYPeak[POINT_TL_ROT]);
+
+  switch (ePtClosest) {
+  case POINT_TL:
+    // No change! Display doesn't support rotation
+    // NOTE: This case is expected on certain displays, but GUIslice
+    //       does not currently disable rotation in this mode. For now
+    //       users should not call GuiRotate() on these displays.
+    m_eRotSpecial = E_ROT_NONE;
+    break;
+  case POINT_TR:
+    // Normal expected rotation
+    GSLC_DEBUG_PRINT("CALIB: Detected normal rotation\n", "");
+    m_eRotSpecial = E_ROT_NORMAL;
+    break;
+  case POINT_BL:
+    // Reversed rotation
+    // NOTE: This case is not expected to be encountered and is not
+    //       currently supported by GUIslice. However, if users report
+    //       encountering displays with this case, support will be added.
+    GSLC_DEBUG_PRINT("WARN: Detected reversed rotation. Please file GitHub issue.\n", "");
+    m_eRotSpecial = E_ROT_REVERSE;
+    break;
+  case POINT_BR:
+    // Unusual (swapped) rotation
+    // NOTE: This case is not expected to be encountered and will not
+    //       be handled by GUIslice
+    GSLC_DEBUG_PRINT("ERROR: Detected unusual swapped rotation. Please file GitHub issue.\n", "");
+    m_eRotSpecial = E_ROT_SWAP;
+    break;
+  case POINT_TEST:
+  default:
+    // No match found?
+    GSLC_DEBUG_PRINT("ERROR: Could not detect rotation. Please retry calibration.\n", "");
+    m_eRotSpecial = E_ROT_UNDEF;
+    break;
+  }
+
+}
+
+void ReportCalibResult()
+{
+  GSLC_DEBUG_PRINT("\n\n", "");
+  GSLC_DEBUG_PRINT("Recommended calibration settings are shown below.\n", "");
+  GSLC_DEBUG_PRINT("- Copy and paste these lines into your GUIslice config file\n", "");
+  GSLC_DEBUG_PRINT("  over top of the existing ADATOUCH_X/Y_MIN/MAX settings.\n", "");
+  GSLC_DEBUG_PRINT("\n", "");
+
+  GSLC_DEBUG_PRINT("---\n", "");
+
+  // Report the display's native dimensions
+  char acDim[12] = "";
+  snprintf(acDim, 12, "[%ux%u]", m_gui.nDisp0W, m_gui.nDisp0H);
+
+  // NOTE: Only need to handle resistive touch display modes
+  #if defined(DRV_TOUCH_ADA_SIMPLE)
+    GSLC_DEBUG_PRINT("  // DRV_TOUCH_ADA_SIMPLE %s: ", acDim);
+    #if defined(DRV_DISP_ADAGFX_MCUFRIEND)
+      // For MCUFRIEND displays, report the ID
+      snprintf(m_acTxt, MAX_STR, "(MCUFRIEND ID=0x%04X)", m_disp.readID());
+      GSLC_DEBUG_PRINT("%s ", m_acTxt);
+    #endif
+    // Report the pin wiring to the 4-wire resistive interface
+    GSLC_DEBUG_PRINT("(XP=%u,XM=A%d,YP=A%d,YM=%u) ", ADATOUCH_PIN_XP, (ADATOUCH_PIN_XM - A0), (ADATOUCH_PIN_YP - A0), ADATOUCH_PIN_YM);
+    GSLC_DEBUG_PRINT("\n", "");
+  #elif defined(DRV_TOUCH_ADA_STMPE610)
+    GSLC_DEBUG_PRINT("  // DRV_TOUCH_ADA_STMPE610 %s:\n", acDim);
+  #elif defined(DRV_TOUCH_ADA_XPT2046)
+    GSLC_DEBUG_PRINT("  // DRV_TOUCH_ADA_XPT2046 %s:\n", acDim);
+  #endif // DRV_TOUCH_ADA_*
+
+  GSLC_DEBUG_PRINT("  #define ADATOUCH_X_MIN    %u\n", m_nTouchCalXMin);
+  GSLC_DEBUG_PRINT("  #define ADATOUCH_Y_MIN    %u\n", m_nTouchCalYMin);
+  GSLC_DEBUG_PRINT("  #define ADATOUCH_X_MAX    %u\n", m_nTouchCalXMax);
+  GSLC_DEBUG_PRINT("  #define ADATOUCH_Y_MAX    %u\n", m_nTouchCalYMax);
+
+  // Check for unexpected rotation behavior
+  switch (m_eRotSpecial) {
+  case E_ROT_NORMAL:
+    // No need to add special config
+    break;
+  case E_ROT_REVERSE:
+    GSLC_DEBUG_PRINT("  #define GSLC_ROTATE_SPECIAL %d // Reversed Rotation\n", m_eRotSpecial);
+    break;
+  case E_ROT_SWAP:
+    GSLC_DEBUG_PRINT("  #define GSLC_ROTATE_SPECIAL %d // Swapped Rotation\n", m_eRotSpecial);
+    break;
+  case E_ROT_NONE:
+    GSLC_DEBUG_PRINT("  #define GSLC_ROTATE_SPECIAL %d // No Rotation supported\n", m_eRotSpecial);
+    break;
+  case E_ROT_UNDEF:
+  default:
+    GSLC_DEBUG_PRINT("  // NOTE: Rotation type not detected properly\n", "");
+    break;
+  }
+  GSLC_DEBUG_PRINT("---\n", "");
+
+  if ((m_eRotSpecial == E_ROT_REVERSE) || (m_eRotSpecial == E_ROT_SWAP)) {
+    GSLC_DEBUG_PRINT("*** Please file a GitHub issue to add support for this mode\n", "");
+  }
+
+  GSLC_DEBUG_PRINT("\n", "");
+
+}
+
+void DrawCalibResult()
+{
+  snprintf(m_acTxt, MAX_STR, "ADATOUCH_X_MIN: %u", m_nTouchCalXMin);
+  gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 00, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, "ADATOUCH_U_MIN: %u", m_nTouchCalYMin);
+  gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 20, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, "ADATOUCH_X_MAX: %u", m_nTouchCalXMax);
+  gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 40, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+  snprintf(m_acTxt, MAX_STR, "ADATOUCH_Y_MAX: %u", m_nTouchCalYMax);
+  gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 60, m_pFont, m_acTxt, GSLC_TXT_DEFAULT, GSLC_COL_YELLOW, GSLC_COL_BLACK);
+
+  if ((m_eRotSpecial == E_ROT_REVERSE) || (m_eRotSpecial == E_ROT_SWAP)) {
+    gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 100, m_pFont, "ERROR: See serial log", GSLC_TXT_DEFAULT, GSLC_COL_RED, GSLC_COL_BLACK);
+  }
+  else if (m_eRotSpecial == E_ROT_NONE) {
+    gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 100, m_pFont, "No rotation supported", GSLC_TXT_DEFAULT, GSLC_COL_RED, GSLC_COL_BLACK);
+  }
+  else if (m_eRotSpecial == E_ROT_UNDEF) {
+    gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 100, m_pFont, "ERROR: Could not detect rotation", GSLC_TXT_DEFAULT, GSLC_COL_RED, GSLC_COL_BLACK);
+  }
+  else if (m_eRotSpecial == E_ROT_NORMAL) {
+    gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 100, m_pFont, "Rotation detected OK", GSLC_TXT_DEFAULT, GSLC_COL_GREEN, GSLC_COL_BLACK);
+  }
+
+  gslc_DrvDrawTxt(&m_gui, m_rReport.x, m_rReport.y + 140, m_pFont, "Click to continue", GSLC_TXT_DEFAULT, GSLC_COL_BLUE, GSLC_COL_BLACK);
+}
+
+// Implement State Machine
+void DoFsm(bool bTouchDown, bool bTouchUp, int16_t nTouchX, int16_t nTouchY, uint16_t nTouchZ)
+{
+  // Save state
+  m_eStateOld = m_eState;
+  tsCalibStage sCalibStage;
+
+  // Determine which calibration point we are handling
+  switch (m_eState) {
+  case STATE_CAPT_TL_MSG:
+  case STATE_CAPT_TL_DO:
+    m_eCalibPt = POINT_TL;
+    break;
+  case STATE_CAPT_TR_MSG:
+  case STATE_CAPT_TR_DO:
+    m_eCalibPt = POINT_TR;
+    break;
+  case STATE_CAPT_BL_MSG:
+  case STATE_CAPT_BL_DO:
+    m_eCalibPt = POINT_BL;
+    break;
+  case STATE_CAPT_BR_MSG:
+  case STATE_CAPT_BR_DO:
+    m_eCalibPt = POINT_BR;
+    break;
+  case STATE_CAPT_ROT_TL_MSG:
+  case STATE_CAPT_ROT_TL_DO:
+    m_eCalibPt = POINT_TL_ROT;
+    break;
+
+  default:
+    m_eCalibPt = POINT_TEST;
+    break;
+  } // m_eState
+
+  // Handle state machine
+  switch (m_eState) {
+
+  case STATE_CAL_START_MSG:
+    if (m_bStateBegin) {
+      RedrawStatus("GUIslice Calibration");
+      DrawBackgroundStart();
+      ResetDatapoints();
+    }
+    // Need to disable any touch remapping during calibration
+    gslc_SetTouchRemapEn(&m_gui, false);
+    if (bTouchUp) { m_eState = STATE_CAPT_TL_MSG; }
+    break;
+
+  case STATE_CAPT_TL_MSG:
+  case STATE_CAPT_TR_MSG:
+  case STATE_CAPT_BL_MSG:
+  case STATE_CAPT_BR_MSG:
+  case STATE_CAPT_ROT_TL_MSG:
+    sCalibStage = m_asCalibStage[m_eCalibPt];
+    if (m_bStateBegin) {
+      DrawBackground();
+      RedrawStatus(sCalibStage.acStr);
+      ResetMax();
+      ResetDatapoints();
+      DrawPageCoords();
+      m_bTouchCoordValid = false;
+      RedrawCoords(0, 0, 0);
+    }
+    DrawTarget(sCalibStage.bXLeft ? TARGET_MARGIN : (m_gui.nDispW - TARGET_MARGIN),
+      sCalibStage.bYTop ? TARGET_MARGIN : (m_gui.nDispH - TARGET_MARGIN),
+      TARGET_SIZE, GSLC_COL_GREEN, GSLC_COL_GREEN_LT2);
+    if (bTouchDown) { m_eState = sCalibStage.eStateDo; }
+    break;
+
+  case STATE_CAPT_TL_DO:
+  case STATE_CAPT_TR_DO:
+  case STATE_CAPT_BL_DO:
+  case STATE_CAPT_BR_DO:
+  case STATE_CAPT_ROT_TL_DO:
+    sCalibStage = m_asCalibStage[m_eCalibPt];
+    if (bTouchDown) {
+      CalcMaxCoords(nTouchX, nTouchY, nTouchZ);
+      RedrawCoords(nTouchX, nTouchY, nTouchZ);
+      AddDatapoint(nTouchX, nTouchY);
+    }
+    if (bTouchUp) {
+      CalcDatapoint(m_eCalibPt);
+      GSLC_DEBUG_PRINT("%s: X=%d Y=%d Cnt=%u\n", sCalibStage.acStr, m_nPointFinalX, m_nPointFinalY, m_nPointBufCnt);
+      m_eState = sCalibStage.eStateNxt;
+    }
+    break;
+
+  case STATE_CAPT_ROT:
+    // Calculate calibration
+    CalcCalib();
+
+    GSLC_DEBUG_PRINT("\nCALIB: Rotate\n", "");
+
+    // Reset the background
+    DrawBackground();
+
+    // Rotate the display to ROTATE=1
+    //
+    // This step detects how the display rotation behaves (ie. rotates clockwise or
+    // counter-clockwise) by asking for an additional calibration point
+    // after rotating the display between orientation 0 to orientation 1.
+    // Depending on the quadrant that the user selects in this final step,
+    // a determination can be made as to the rotation direction and
+    // an additional rotation config setting can be reported.
+    gslc_GuiRotate(&m_gui, 1);
+
+    m_eState = STATE_CAPT_ROT_TL_MSG;
+    break;
+
+  case STATE_CAL_REPORT:
+    // Redraw to cleanup markers
+    DrawBackground();
+
+    if (m_bStateBegin) {
+      RedrawStatus("Calibrate Done");
+    }
+    m_bTouchCoordValid = false;
+
+    // Calculate the calibration settings based on the
+    // rotated orientation (ROTATE=1).
+    CalcCalibRotate();
+
+    ReportCalibResult();
+    DrawCalibResult();
+
+    m_eState = STATE_CAL_DONE_MSG;
+    break;
+
+  case STATE_CAL_DONE_MSG:
+    if (bTouchDown) { m_eState = STATE_CAL_DONE_END; }
+    break;
+  case STATE_CAL_DONE_END:
+    if (bTouchUp) { m_eState = STATE_CAL_SET; }
+    break;
+
+  case STATE_CAL_SET:
+    GSLC_DEBUG_PRINT("\nCALIB: Apply calibration\n", "");
+
+    // Assign the new touch calibration
+    gslc_SetTouchRemapCal(&m_gui, m_nTouchCalXMin, m_nTouchCalXMax, m_nTouchCalYMin, m_nTouchCalYMax);
+    gslc_SetTouchRemapEn(&m_gui, true);
+
+    m_eState = STATE_TEST_MSG;
+    break;
+
+  case STATE_TEST_MSG:
+    // Reset the background
+    DrawBackground();
+    DrawPageCoords();
+
+    snprintf(m_acTxt, MAX_STR, "Test Rotate=%u", m_gui.nRotation);
+    RedrawStatus(m_acTxt);
+
+    m_eCalibPt = POINT_TEST;
+
+    // Clear stats
+    ResetMax();
+    m_bTouchCoordValid = false;
+    RedrawCoords(0, 0, 0);
+
+    m_eState = STATE_TEST_DO;
+    break;
+
+  case STATE_TEST_DO:
+    if (bTouchDown) {
+      CalcMaxCoords(nTouchX, nTouchY, nTouchZ);
+      RedrawCoords(nTouchX, nTouchY, nTouchZ);
+      DrawTracer(nTouchX, nTouchY);
+    }
+    else if (bTouchUp) {
+      m_eState = STATE_ROTATE_MSG;
+    }
+    break;
+
+  case STATE_CAL_REDO_MSG:
+    break;
+
+  case STATE_ROTATE_MSG:
+    m_eState = STATE_ROTATE_DO;
+    break;
+
+  case STATE_ROTATE_DO:
+    ResetMax();
+
+    // Increment the current rotation by one step
+    gslc_GuiRotate(&m_gui, (m_gui.nRotation + 1) % 4);
+
+    m_eState = STATE_TEST_MSG;
+    break;
+
+  default:
+    break;
+  } // case(m_eState)
+
+  // Are we going to enter a new state?
+  // - This is used to limit certain behavior to state entry
+  m_bStateBegin = (m_eState != m_eStateOld);
+}
+
+
+void setup()
+{
+  // Initialize debug output
+  Serial.begin(9600);
+  gslc_InitDebug(&DebugOut);
+  //delay(1000);  // NOTE: Some devices require a delay after Serial.begin() before serial port can be used
+
+  // Initialize
+  // - Basic init without support for GUI elements
+  if (!gslc_Init(&m_gui, &m_drv, NULL, 0, m_asFont, MAX_FONT)) { return; }
+
+  // Use default font
+  if (!gslc_FontAdd(&m_gui, E_FONT_TXT, GSLC_FONTREF_PTR, NULL, 1)) { return; }
+  m_pFont = gslc_FontGet(&m_gui, E_FONT_TXT);
+
+  // Force orientation to native rotation for calibration purposes
+  gslc_GuiRotate(&m_gui, 0);
+
+  // Initialize calibration and display
+  DrawBackground();
+  ResetCalib();
+  ResetMax();
+
+  // Report initialization settings
+  GSLC_DEBUG_PRINT("\n=== Touch Calibration ===\n\n", "");
+  GSLC_DEBUG_PRINT("CALIB: Config defaults: XMin=%u XMax=%u YMin=%u YMax=%u\n",
+    ADATOUCH_X_MIN, ADATOUCH_X_MAX, ADATOUCH_Y_MIN, ADATOUCH_Y_MAX);
+  #if defined(CALC_EXP_AVG)
+    GSLC_DEBUG_PRINT("CALIB: Averaging mode: EXP\n", "");
+  #elif defined(CALC_BASIC_AVG)
+    GSLC_DEBUG_PRINT("CALIB: Averaging mode: BASIC\n", "");
+  #endif
+  GSLC_DEBUG_PRINT("\n", "");
+}
+
+void loop()
+{
+  int16_t               nTouchX = 0;
+  int16_t               nTouchY = 0;
+  uint16_t              nTouchZ = 0;
+  bool                  bTouchEvent = false;
+  gslc_teInputRawEvent  eInputEvent = GSLC_INPUT_NONE;
+  int16_t               nInputVal = 0;
+
+  // Perform touch tracking
+  bTouchEvent = gslc_GetTouch(&m_gui, &nTouchX, &nTouchY, &nTouchZ, &eInputEvent, &nInputVal);
+
+  if (eInputEvent != GSLC_INPUT_TOUCH) {
+    // Just in case we received another type of event
+    bTouchEvent = false;
+  }
+  else {
+    // Set the flag indicating that we have at least one
+    // valid reading. This just affects our display.
+    m_bTouchCoordValid = true;
+  }
+
+  // Detect transition events
+  bool bTouchDown = (bTouchEvent && (nTouchZ > 0));
+  bool bTouchUp = (bTouchEvent && (nTouchZ == 0));
+
+  // Step through the FSM
+  DoFsm(bTouchDown, bTouchUp, nTouchX, nTouchY, nTouchZ);
+
+  // Slow down updates
+  delay(10);
+
+  // In a real program, we would detect the button press and take an action.
+  // For this Arduino demo, we will pretend to exit by emulating it with an
+  // infinite loop. Note that interrupts are not disabled so that any debug
+  // messages via Serial have an opportunity to be transmitted.
+  if (m_bQuit) {
+    gslc_Quit(&m_gui);
+    while (1) {}
+  }
+}


started estim

started estim

error: pathspec 'Mod/E-Stim/TCDS__BASIC_/TCDS__BASIC_.ino' did not match any file(s) known to git

--- Mod/E-Stim/TCDS__BASIC_/TCDS__BASIC_.ino
+++ Mod/E-Stim/TCDS__BASIC_/TCDS__BASIC_.ino
@@ -0,0 +1,54 @@
+/* Snow Crash: TcDS
+
+
+based mostly off blinkwithoutdelay:
+ created 2005
+ by David A. Mellis
+ modified 8 Feb 2010
+ by Paul Stoffregen
+
+ This example code is in the public domain.
+ */
+
+// constants won't change. Used here to
+// set pin numbers:
+const int ledPin =  11;      // the number of the LED pin
+
+// Variables will change:
+int ledState = LOW;             // ledState used to set the LED
+long previousMillis = 0;        // will store last time LED was updated
+
+// the follow variables is a long because the time, measured in miliseconds,
+// will quickly become a bigger number than can be stored in an int.
+long interval =20;           // interval at which to blink (milliseconds)
+
+void setup() {
+  // set the digital pin as output:
+  pinMode(ledPin, OUTPUT);
+}
+
+void loop()
+{
+  // here is where you'd put code that needs to be running all the time.
+
+  // check to see if it's time to blink the LED; that is, if the
+  // difference between the current time and last time you blinked
+  // the LED is bigger than the interval at which you want to
+  // blink the LED.
+  unsigned long currentMillis = millis();
+
+  if(currentMillis - previousMillis > interval) {
+    // save the last time you blinked the LED
+    previousMillis = currentMillis;
+
+    // if the LED is off turn it on and vice-versa:
+    if (ledState == LOW)
+      ledState = HIGH;
+    else
+      ledState = LOW;
+
+    // set the LED with the ledState of the variable:
+    digitalWrite(ledPin, ledState);
+  }
+}
+


Add the sketch to count step on the electronic rule. This software is missing counts...

error: pathspec 'Arduino/Electronic_rule/src/sketch.ino' did not match any file(s) known to git

--- Arduino/Electronic_rule/src/sketch.ino
+++ Arduino/Electronic_rule/src/sketch.ino
@@ -0,0 +1,108 @@
+
+// Copyright (c) 2013 Nautilabs
+// https://github.com/baptistelabat/robokite
+
+// Using example in http://code.google.com/p/arduino-pinchangeint/wiki/Usage
+
+#include <PinChangeInt.h>
+
+//Parts of code taken from http://playground.arduino.cc/Main/RotaryEncoders J.Carter(of Earth)
+
+// 'threshold' is the De-bounce Adjustment factor for the Rotary Encoder.
+//
+// The threshold value I'm using limits it to 100 half pulses a second
+//
+// My encoder has 12 pulses per 360deg rotation and the specs say
+// it is rated at a maximum of 100rpm.
+//
+// This threshold will permit my encoder to reach 250rpm so if it was connected
+// to a motor instead of a manually operated knob I
+// might possibly need to adjust it to 25000. However, this threshold
+// value is working perfectly for my situation
+//
+volatile unsigned long threshold = 10000;
+
+// 'rotaryHalfSteps' is the counter of half-steps. The actual
+// number of steps will be equal to rotaryHalfSteps / 2
+//
+volatile long rotaryHalfSteps = 0;
+
+// Working variables for the interrupt routines
+//
+volatile unsigned long int0time = 0;
+volatile unsigned long int1time = 0;
+volatile uint8_t int0signal = 0;
+volatile uint8_t int1signal = 0;
+volatile uint8_t int0history = 0;
+volatile uint8_t int1history = 0;
+
+uint8_t latest_interrupted_pin;
+uint8_t interrupt_count[20]={0}; // 20 possible arduino pins
+
+void int0()
+	{
+	if ( micros() - int0time < threshold )
+		return;
+	int0history = int0signal;
+	int0signal = bitRead(PIND,2);
+	if ( int0history==int0signal )
+		return;
+	int0time = micros();
+	if ( int0signal == int1signal )
+		rotaryHalfSteps++;
+	else
+		rotaryHalfSteps--;
+	}
+
+void int1()
+	{
+	if ( micros() - int1time < threshold )
+		return;
+	int1history = int1signal;
+	int1signal = bitRead(PIND,3);
+	if ( int1history==int1signal )
+		return;
+	int1time = micros();
+	}
+void reset()
+{
+ rotaryHaflSteps = 0;
+ }
+
+void setup() {
+  pinMode(2, INPUT);
+  digitalWrite(2, HIGH);
+  PCintPort::attachInterrupt(2, &int0, CHANGE);
+  pinMode(3, INPUT);
+  digitalWrite(3, HIGH);
+  PCintPort::attachInterrupt(3, &int1, CHANGE);
+
+  // Pin used to get absolute position
+  pinMode(4, INPUT);
+  digitalWrite(4, HIGH);
+  PCintPort::attachInterrupt(4, &reset, CHANGE);
+  Serial.begin(115200);
+  Serial.println("---------------------------------------");
+}
+
+uint8_t i;
+
+void loop() {
+  long actualRotaryTicks = (rotaryHalfSteps / 2);
+  Serial.println(actualRotaryTicks, DEC);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+


Añadido sketch de lectura de la EEPROM

Añadido sketch de lectura de la EEPROM

error: pathspec 'test/dump_EEPROM/dump_EEPROM.ino' did not match any file(s) known to git

--- test/dump_EEPROM/dump_EEPROM.ino
+++ test/dump_EEPROM/dump_EEPROM.ino
@@ -0,0 +1,262 @@
+// --------------------------------------
+// Habilitar la EEPROM
+//
+
+#include <Wire.h>
+
+#define GPIO 0x20
+#define MEM 0x50
+
+#define CONFIG 0x30
+#define ENABLER 0x2D
+
+#define PASS1 0x43
+#define PASS2 0x4D
+#define PASS3 0x53
+
+#define VALUE 0x02
+#define RESET_CMD 0x02
+
+
+void turnUpEEPROM() {
+  //Serial.print("\nActivando la EEPROM...");
+
+  Wire.beginTransmission(GPIO);
+  Wire.write((byte)ENABLER);
+  Wire.write((byte)PASS1);
+  Wire.write((byte)PASS2);
+  Wire.write((byte)PASS3);
+  Wire.write((byte)VALUE);
+  int error = Wire.endTransmission();
+
+  /*if (error == 0) {
+    Serial.println(" OK");
+  } else {
+    Serial.print("COD ERROR: ");
+    Serial.println(error);
+  }*/
+
+}
+
+void reset() {
+  //Serial.print("\nReseteando...");
+
+  Wire.beginTransmission(GPIO);
+  Wire.write((byte)CONFIG);
+  Wire.write((byte)RESET_CMD);
+  int error = Wire.endTransmission();
+  /*if(error==0){
+    Serial.println(" OK");
+  }else{
+    Serial.print("COD ERROR: ");
+    Serial.println(error);
+  }*/
+}
+
+int save(unsigned int dir, byte data) {
+  //Serial.print("\nGuardando en la EEPROM...");
+
+
+  byte high = dir / 256;
+  byte low = dir % 256;
+
+  /*Serial.print(" -> Escribiendo en la direccion: ");
+  Serial.print("0x");
+  Serial.print(high,HEX);
+  Serial.print(" 0x");
+  Serial.print(low,HEX);
+  Serial.print(" ...");*/
+
+  Wire.beginTransmission(MEM);
+  Wire.write((byte)high);
+  Wire.write((byte)low);
+  Wire.write(data);
+  int error = Wire.endTransmission();
+
+
+  return error;
+
+}
+
+
+int save(unsigned int dir, char* data) {
+  //Serial.print("\nGuardando en la EEPROM...");
+
+
+  byte high = dir / 256;
+  byte low = dir % 256;
+
+  /*Serial.print("Escribiendo en la direccion: ");
+  Serial.print("0x");
+  Serial.print(high,HEX);
+  Serial.print(" 0x");
+  Serial.println(low,HEX);*/
+
+  Wire.beginTransmission(MEM);
+  Wire.write((byte)high);
+  Wire.write((byte)low);
+  Wire.write(data);
+  int error = Wire.endTransmission();
+
+  return error;
+
+}
+
+
+byte read(unsigned int dir) {
+  byte rdata = 242;
+
+  byte high = dir / 256;
+  byte low = dir % 256;
+
+  /*Serial.print("Leyendo en la direccion: ");
+  Serial.print("0x");
+  Serial.print(high,HEX);
+  Serial.print(" 0x");
+  Serial.println(low,HEX);
+
+  Serial.print("\Leyendo de la EEPROM...");*/
+
+  Wire.beginTransmission(MEM);
+  Wire.write((byte)high);
+  Wire.write((byte)low);
+  int error = Wire.endTransmission();
+
+  Wire.requestFrom(MEM, 1);
+  if (Wire.available()) {
+    rdata = Wire.read();
+  }
+
+  /*if(error==0){
+    Serial.println(" OK");
+  }else{
+    Serial.print("COD ERROR: ");
+    Serial.println(error);
+  }*/
+
+  return rdata;
+
+}
+
+void read2(unsigned int dir,byte* rdata, int len) {
+
+  byte high = dir / 256;
+  byte low = dir % 256;
+
+  /*Serial.print("Leyendo en la direccion: ");
+  Serial.print("0x");
+  Serial.print(high,HEX);
+  Serial.print(" 0x");
+  Serial.println(low,HEX);
+
+  Serial.print("\Leyendo de la EEPROM...");*/
+
+  Wire.beginTransmission(MEM);
+  Wire.write((byte)high);
+  Wire.write((byte)low);
+  int error = Wire.endTransmission();
+
+  Wire.requestFrom(MEM, len);
+  int c = 0;
+  for ( c = 0; c < len; c++ ) {
+    if (Wire.available()) {
+      rdata[c] = Wire.read();
+    }
+  }
+
+  /*if(error==0){
+    Serial.println(" OK");
+  }else{
+    Serial.print("COD ERROR: ");
+    Serial.println(error);
+  }*/
+
+}
+
+
+void setup()
+{
+  Wire.begin();
+
+  Serial.begin(9600);
+  while (!Serial);
+
+}
+
+
+void loop()
+{
+
+  Serial.println("INICIO\n\n");
+
+  unsigned int i = 0;
+
+
+  for(i=0; i< 32768;i++){
+
+    if( (i%16)==0 ){
+      Serial.print("\n0x");
+      if(i<16){
+        Serial.print("0");
+      }
+      if(i<256){
+        Serial.print("0");
+      }
+      if(i<4096){
+        Serial.print("0");
+      }
+      Serial.print(i,HEX);
+      Serial.print(" - ");
+    }
+
+    byte hola = read(i);
+
+     if(hola<16){
+       Serial.print("0");
+     }
+
+     //int hola = save(i,(byte)48);
+     Serial.print(hola,HEX);
+     Serial.print(" ");
+  }
+
+
+
+
+
+  /*int prueba = 0;
+  unsigned int i=11560;
+  while(prueba==0){
+
+    if( (i%16)==0 ){
+      Serial.print("\n0x");
+      if(i<16){
+        Serial.print("0");
+      }
+      if(i<256){
+        Serial.print("0");
+      }
+      if(i<4096){
+        Serial.print("0");
+      }
+      Serial.print(i,HEX);
+      Serial.print(" - ");
+    }
+
+
+    prueba = save(i,(byte)48);
+    Serial.print(prueba);
+    Serial.print(" ");
+    i++;
+  }*/
+
+
+  Serial.println("\n======================= HEMOS ACABADO ==================================");
+  /* for(byte i=1; i<24; i++){
+     jeje = read(0,i);
+     delay(2000);
+     Serial.println(jeje);
+   }*/
+
+  delay(200000);
+}


Add files via upload

Add files via upload

This contains the functional and accurate rack and pinion depth measurement code

error: pathspec 'Main_Code/AccurateServo.ino' did not match any file(s) known to git

--- Main_Code/AccurateServo.ino
+++ Main_Code/AccurateServo.ino
@@ -0,0 +1,71 @@
+#include <Servo.h>
+int servoPin = 5;
+Servo servo;
+
+boolean saltFlag = false;
+void setup(){
+  servo.attach(5);
+  servo.write(180);
+  Serial.begin(9600);
+}
+
+void loop(){
+Serial.println("MEASURED DEPTH" + (String)measureDepthAccurately());
+delay(5000);
+}
+double measureDepthAccurately(){
+  double depth = measureDepth();
+  delay(3000);
+  if((depth <= 4.4 && depth >= 2.2)){
+    return depth;
+  }else{
+    while(!(depth <= 4.4 && depth >= 2.2)){
+      depth = measureDepth();
+      delay(5000);
+    }
+    return depth;
+  }
+}
+  int salinityPin = A0;
+  int limitSwitch = A1;
+
+ double measureDepth(){
+   int flag = 0;
+   int limitflag = 0;
+   int servoAngle = 180;
+   int topOfWater = 180;
+   servo.write(servoAngle);
+
+   while(limitflag==0){
+
+    Serial.println("salt : " + (String)analogRead(A0) + "topOfWater: " + (String)topOfWater +" ServoAngle: " + (String)servoAngle  + " " + (topOfWater-servoAngle)*(6.0*3.14159/360.0));
+
+     if(analogRead(limitSwitch) >= 500){
+       Serial.println("Bottom hit at theta = " + (String)servoAngle);
+       limitflag = 1;
+       servo.write(180);
+       return((topOfWater-servoAngle)*(6.0*3.14159/360.0));
+     }
+
+     servo.write(servoAngle);
+     if(flag == 0 && analogRead(salinityPin)>25 && servoAngle<110){
+       Serial.println("Water hit at theta = " + (String) servoAngle);
+
+       topOfWater = servoAngle;
+       flag = 1;
+
+     }
+     if(analogRead(salinityPin)>=50){
+       saltFlag = true;
+     }
+     servoAngle = ((servoAngle -1));
+     if(servoAngle<=0){
+      servoAngle = 180;
+     }
+
+      delay(50);
+
+   }
+
+
+ }


Changing Sensor-rcv-ucg

Changing Sensor-rcv-ucg

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JulianNicholls/Arduino.git/'


read calibration coefficients

read calibration coefficients

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/wsnook/farm.git/'


Add simple interrupt test script

Add simple interrupt test script

error: pathspec 'arduino/interrupt_test/interrupt_test.ino' did not match any file(s) known to git

--- arduino/interrupt_test/interrupt_test.ino
+++ arduino/interrupt_test/interrupt_test.ino
@@ -0,0 +1,51 @@
+/****************************************************************************************************************************\
+ *
+ * Arduino interrupt tests, as simple and understandable as possible.
+ * © Aapo Rista 2017, MIT license
+ * Tested with Wemos ESP8266 D1 Mini PRO
+ * https://www.wemos.cc/product/d1-mini-pro.html
+ *
+\*************************************************************************************************************************/
+
+// const byte interruptPin = 2; // D4 on Wemos ESP8266
+const byte interruptPin = D4; // If the board is correctly set in Arduino IDE, you can use D1, D2 etc. directly
+volatile byte interruptCounter = 0;
+int numberOfInterrupts = 0;
+int state = 0;
+
+void setup() {
+  Serial.begin(115200);
+  Serial.println();
+  Serial.println("Start");
+  // pinMode(interruptPin, INPUT_PULLUP);
+  // Only one interrupt type can be attached to a GPIO pin at a time
+  // attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
+  // attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, RISING);
+  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, CHANGE);
+}
+
+void handleInterrupt() {
+  interruptCounter++;
+  state = digitalRead(interruptPin);
+}
+
+void loop() {
+
+  if(interruptCounter>0){
+
+      interruptCounter--;
+      numberOfInterrupts++;
+
+      Serial.print("Interrupt ");
+      if (state == 1) {
+        Serial.print(" RISING");
+      } else {
+        Serial.print("FALLING");
+      }
+      Serial.print(" at ");
+      Serial.print(millis());
+      Serial.print(" ms uptime. Total: ");
+      Serial.println(numberOfInterrupts);
+  }
+
+}


ESP.restart() with wifi and mqtt

ESP.restart() with wifi and mqtt

error: pathspec '_14-mqtt-reconnect-with-reset/_14-mqtt-reconnect-with-reset.ino' did not match any file(s) known to git

--- _14-mqtt-reconnect-with-reset/_14-mqtt-reconnect-with-reset.ino
+++ _14-mqtt-reconnect-with-reset/_14-mqtt-reconnect-with-reset.ino
@@ -0,0 +1,104 @@
+
+#include <ESP8266WiFi.h>
+#include <PubSubClient.h>
+#include "/usr/local/src/ap_setting.h"
+
+
+char* topic   = "/30/Status/MQTT";
+char* subtopic = "inTopic";
+char* hellotopic = "HELLO";
+
+IPAddress server(192, 168, 10, 138);
+WiFiClient wifiClient;
+PubSubClient client(server, 1883, callback, wifiClient);
+
+long lastMsg = 0;
+char msg[50];
+int value = 0;
+long lastReconnectAttempt = 0;
+int resetCountforMqttReconnect = 0;
+
+void setup() {
+  Serial.begin(115200);
+  setup_wifi();
+}
+
+void setup_wifi() {
+  delay(20);
+  Serial.println();
+  Serial.print("Connecting to ");
+  Serial.println(ssid);
+
+  WiFi.mode(WIFI_STA);
+  WiFi.begin(ssid, password);
+
+  int Attempt = 0;
+  while (WiFi.status() != WL_CONNECTED) {
+    delay(100);
+    Attempt++;
+    Serial.print(".");
+    if (Attempt == 100)
+    {
+      Serial.println();
+      Serial.println("Could not connect to WIFI");
+      ESP.restart();
+      delay(2000);
+    }
+  }
+
+  Serial.println("");
+  Serial.println("WiFi connected");
+  Serial.println("IP address: ");
+  Serial.println(WiFi.localIP());
+}
+
+void callback(char* topic, byte* payload, unsigned int length) {
+
+}
+
+boolean reconnect() {
+  if (!client.connected()) {
+    if (client.connect("arduinoClient")) {
+      client.publish(hellotopic, "hello world");
+      client.subscribe(subtopic);
+    }
+  }
+  return client.connected();
+}
+
+void loop()
+{
+  if (WiFi.status() == WL_CONNECTED) {
+    if (!client.connected()) {
+      long now = millis();
+      if (now - lastReconnectAttempt > 1000) {
+        Serial.print("failed, rc=");
+        Serial.println(client.state());
+        Serial.println("MQTT disconnected....");
+        lastReconnectAttempt = now;
+        resetCountforMqttReconnect++;
+        if ( resetCountforMqttReconnect == 100 ) {
+          Serial.println();
+          Serial.println("Could not connect to mqtt");
+          ESP.restart();
+          delay(2000);
+        }
+        if (reconnect()) {
+          Serial.println("MQTT connected....");
+          lastReconnectAttempt = 0;
+          resetCountforMqttReconnect = 0;
+        }
+      }
+    }  else {
+      long now = millis();
+      if (now - lastMsg > 30000) {
+        lastMsg = now;
+        Serial.println(client.state());
+        client.publish(topic, "on");
+      }
+      client.loop();
+    }
+  } else {
+    setup_wifi();
+  }
+}


ADD: BLE example

ADD: BLE example

error: pathspec 'examples/BoardWithBLE/BoardWithBLE.ino' did not match any file(s) known to git

--- examples/BoardWithBLE/BoardWithBLE.ino
+++ examples/BoardWithBLE/BoardWithBLE.ino
@@ -0,0 +1,25 @@
+#include <DSPI.h>
+#include <OpenBCI_32bit_Library.h>
+#include <OpenBCI_32Bit_Library_Definitions.h>
+
+void setup() {
+  // Bring up the OpenBCI Board
+  board.begin();
+  // Put it in BLE mode
+  board.setBoardMode(board.BOARD_MODE_BLE);
+}
+
+void loop() {
+  if (board.streaming) {
+    if (board.channelDataAvailable) {
+      // Read from the ADS(s), store data, set channelDataAvailable flag to false
+      board.updateChannelData();
+      // Send that channel data
+      board.sendChannelData();
+    }
+  }
+  // Check the serial ports for new data
+  if (board.hasDataSerial0()) board.processChar(board.getCharSerial0());
+  if (board.hasDataSerial1()) board.processChar(board.getCharSerial1());
+  board.loop();
+}


add DIJN test.ino sketch

add DIJN test.ino sketch

error: pathspec 'examples/DIJN/test/test.ino' did not match any file(s) known to git

--- examples/DIJN/test/test.ino
+++ examples/DIJN/test/test.ino
@@ -0,0 +1,25 @@
+/// @dir test
+/// Simple node-alive check, sends out one test packet per second.
+// 2013-02-02 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
+
+#include <JeeLib.h>
+
+byte counter;
+
+void setup () {
+  // this is node 1 in net group 100 on the 868 MHz band
+  rf12_initialize(1, RF12_868MHZ, 100);
+}
+
+void loop () {
+  // standard idiom for waiting until we can send a new packet
+  while (!rf12_canSend())
+    rf12_recvDone();
+  // actual packet send: broadcast to all, current counter, 1 byte long
+  rf12_sendStart(0, &counter, 1);
+
+  // next time, the counter will be one higher (it'll wrap from 255 to 0)
+  ++counter;
+  // let one second pass before sending out the next packet
+  delay(1000);
+}


Create naive.ino

Create naive.ino

error: pathspec 'PySerial/Naive_sketch_and_pyserial/naive.ino' did not match any file(s) known to git

--- PySerial/Naive_sketch_and_pyserial/naive.ino
+++ PySerial/Naive_sketch_and_pyserial/naive.ino
@@ -0,0 +1,8 @@
+void setup() {
+  Serial.begin(115200);
+}
+
+void loop() {
+  Serial.println(analogRead(A0));
+  delay(1000);
+}


Create Code.ino

Create Code.ino

error: pathspec 'Slide' did not match any file(s) known to git
error: pathspec 'Potentiometer/Code.ino' did not match any file(s) known to git


start adding Arduino sketches to j2mod

start adding Arduino sketches to j2mod

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/malleblas/j2mod.git/'


this seems to work thnks to hagen

this seems to work thnks to hagen

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/trinamic/T-Bone.git/'


Fix heat array and cleared logging

Fix heat array and cleared logging

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/c-dante/glowbrella.git/'