Copy and Adapt https://gist.github.com/krhoyt/2fe97bbbda9db36ea234 to Industruino.

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

--- Industruino-stomp/Industruino-stomp.ino
+++ Industruino-stomp/Industruino-stomp.ino
@@ -0,0 +1,298 @@
+// Libraries
+#include <SPI.h>
+#include <EthernetIndustruino.h>
+#define W5500_ETHERNET_SHIELD
+
+// Defines
+// Used for connectivity parameters
+#define ENDPOINT "192.168.1.35"
+#define LOGIN    " "
+#define PASSCODE " "
+#define PORT     61613
+#define TOPIC    "/topic/heart"
+#define ZEROBYTE (uint8_t)0x00
+
+// Constants for STOMP
+const int DISCONNECTED = 0;
+const int CONNECTING = 1;
+const int CONNECTED = 2;
+const int WAITING = 3;
+const int SUBSCRIBING = 4;
+const int SUBSCRIBED = 5;
+const int SENDING = 6;
+const int SENT = 7;
+const int DISCONNECTING = 8;
+const int STOP = 9;
+
+// Global
+int       counter;
+int       state;
+String    session;
+EthernetClient client; //Ethernet client mode
+byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
+IPAddress ip(192, 168, 1, 21);
+
+// Setup
+void setup()
+{
+  // Initially disconnected
+  state = DISCONNECTED;
+
+  //Setup of Ethernet module chip select lines
+  pinMode(10, OUTPUT);
+  pinMode(6, OUTPUT);
+  pinMode(4, OUTPUT);
+  digitalWrite(10, LOW);
+  digitalWrite(6, HIGH);
+  digitalWrite(4, HIGH);
+
+  delay(5000); //wait 5 seconds to make sure Ethernet is running.
+
+  // Serial for debugging
+  Serial.begin( 9600 );
+
+  // start the Ethernet connection:
+  if (Ethernet.begin(mac) == 0) {
+
+    Serial.println("Failed to configure Ethernet using DHCP");
+    // no point in carrying on, so do nothing forevermore:
+    // try to congifure using IP address instead of DHCP:
+    Ethernet.begin(mac, ip);
+
+  }
+  // give the Ethernet shield a second to initialize:
+  delay(1000);
+  Serial.println("starting..");
+
+}
+
+// Loop
+void loop()
+{
+  int    start;
+  String body;
+  String frame;
+  String response;
+
+  // If disconnected
+  if( state == DISCONNECTED )
+  {
+    // Connect to server
+    if( client.connect( ENDPOINT, PORT ) )
+    {
+      // Set connecting state
+      state = CONNECTING;
+      Serial.println( "Connecting..." );
+    } else {
+      // Problem connecting
+      Serial.println( "Not connected" );
+    }
+  // Connected to server
+  } else if( state == CONNECTING ) {
+    // Initiate STOMP connection
+    client.println( "CONNECT" );
+    client.println( "accept-version:1.2" );
+    client.print( "host:" );
+    client.println( ENDPOINT );
+    client.print( "login:" );
+    client.println( LOGIN );
+    client.print( "passcode:" );
+    client.println( PASSCODE );
+    client.println();
+    client.write( ZEROBYTE );
+
+    // Waiting for response
+    Serial.println( "Connect header sent..." );
+    state = WAITING;
+  // Connected to STOMP broker
+  } else if( state == CONNECTED ) {
+    // Subscribe to specified destination
+    client.println( "SUBSCRIBE" );
+    client.print( "id:" );
+    client.println( session );
+    client.print( "destination:" );
+    client.println( TOPIC );
+    client.println( "receipt:subscribed" );
+    client.println();
+    client.write( ZEROBYTE);
+
+    // Subscribing to topic
+    Serial.println( "Subscribing to topic..." );
+    state = SUBSCRIBING;
+  } else if( state == SUBSCRIBED ) {
+    counter = counter + 1;
+    body = String( counter );
+
+    client.println( "SEND" );
+    client.print( "destination:" );
+    client.println( TOPIC );
+    client.println( "content-type:text/plain" );
+    client.print( "content-length:" );
+    client.println( body.length() );
+    client.print( "receipt:message-" );
+    client.println( counter );
+    client.println();
+    client.print( body );
+    client.write( (ZEROBYTE);
+
+    state = SENDING;
+    Serial.println( "Sending message..." );
+  } else if( state == SENT ) {
+    body = String( counter );
+
+    client.println( "DISCONNECT" );
+    client.print( "receipt:disconnect-" );
+    client.println( body );
+    client.write( (ZEROBYTE);
+
+    state = DISCONNECTING;
+    Serial.println( "Disconnecting..." );
+  }
+
+  // Incoming data from broker
+  if( client.available() > 0 )
+  {
+    response = client.readStringUntil( 0x0 );
+
+    Serial.print( "*** Response Start (" );
+    Serial.print( response.length() );
+    Serial.println( ") ***" );
+    Serial.println( response );
+    Serial.println( "*** Response End ***" );
+
+    if( response.length() > 0 )
+    {
+      frame = getValue( response, 0, "\n" );
+
+      if( frame == "CONNECTED" )
+      {
+        // Get session for later reference
+        session = getHeader( response, "session" );
+        Serial.print( "Session: " );
+        Serial.println( session );
+
+        // Set state
+        state = CONNECTED;
+        Serial.println( "Connected." );
+      } else if( frame == "MESSAGE" ) {
+        body = getValue( response, 1, "\n\n" );
+
+        Serial.print( "Message: " );
+        Serial.println( body );
+      } else if( frame == "RECEIPT" ) {
+        if( state == SUBSCRIBING )
+        {
+          state = SUBSCRIBED;
+          Serial.println( "Subscribed." );
+        } else if( state == SENDING ) {
+          state = SENT;
+          Serial.println( "Sent." );
+
+          delay( 1000 );
+        } else if( state == DISCONNECTING ) {
+          Serial.println( "Disconnected." );
+
+          client.stop();
+          Serial.println( "Connection closed." );
+          state = STOP;
+        }
+      }
+    }
+
+    // Read last null byte
+    client.read();
+  }
+}
+
+// Count the number of parts in a string
+// Used to help replace lack of split
+int count( String content, String delimeter )
+{
+  int count = 0;
+  int end;
+  int start = 0;
+
+  // Count occurances of delimeter
+  do {
+    end = content.indexOf( delimeter, start );
+    start = end + 1;
+    count = count + 1;
+  } while( end > 0 );
+
+  // Return occurance count
+  return count;
+}
+
+// Reads response for specific header
+// Extracts and returns header value
+String getHeader( String content, String header )
+{
+  int    parts;
+  int    start;
+  String line;
+  String prefix;
+  String result;
+
+  // How many lines in response
+  parts = count( content, "\n" );
+
+  // Start on line after frame line
+  // Look for header prefix match
+  for( int p = 1; p < parts; p++ )
+  {
+    // Header line
+    // Split into parts
+    line = getValue( content, p, "\n" );
+    prefix = getValue( line, 0, ":" );
+
+    // If prefix matches
+    if( prefix == header )
+    {
+      // Get value for header
+      start = line.indexOf( ":" ) + 1;
+      result = line.substring( start );
+      break;
+    }
+  }
+
+  // Return result
+  return result;
+}
+
+// Get a specific section of a string
+// Based on delimeters
+// Used to replace lack of split
+String getValue( String content, int part, String delimeter )
+{
+  int    end;
+  int    start = 0;
+  String result;
+
+  // Iterate past unwanted values
+  for( int count = 0; count < part; count++ )
+  {
+    end = content.indexOf( delimeter, start );
+    start = end + delimeter.length();
+  }
+
+  // Get next occurance of delimeter
+  // May return -1 if not found
+  end = content.indexOf( delimeter, start );
+
+  // If no more occurances
+  if( end == -1 )
+  {
+    // Must be last value in content
+    // Parse out remainder
+    result = content.substring( start );
+  } else {
+    // Otherwise parse out segment of content
+    result = content.substring( start, end );
+  }
+
+  // Clean off white space
+  result.trim();
+
+  // Return resulting content
+  return result;
+}


Tilt sensor

Tilt sensor

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

--- Project_8/Project_8.ino
+++ Project_8/Project_8.ino
@@ -0,0 +1,34 @@
+const int switchPin = 8;
+unsigned long previousTime = 0;
+int switchState = 0;
+int prevSwitchState = 0;
+int led = 2;
+long interval = 10000;
+
+void setup() {
+  for (int i = 2; i < 8; i++) {
+    pinMode(i, OUTPUT);
+  }
+  pinMode(switchPin, INPUT);
+}
+
+void loop() {
+  unsigned long currentTime = millis();
+  if (currentTime - previousTime > interval) {
+    previousTime = currentTime;
+    digitalWrite(led, HIGH);
+    led++;
+    if (led == 7) {
+
+    }
+  }
+  switchState = digitalRead(switchPin);
+  if (switchState != prevSwitchState) {
+    for (int i = 2; i < 8; i++) {
+      digitalWrite(i, LOW);
+    }
+    led = 2;
+    previousTime = currentTime;
+  }
+  prevSwitchState = switchState;
+}


Tweaks. Is better.

Tweaks. Is better.

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


Added SoftwareSerialDemo.ino, which uses pins 7 and 8 as Receive and Transmit to/from an external serial interface.

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

--- examples/SoftwareSerialDemo/SoftwareSerialDemo.ino
+++ examples/SoftwareSerialDemo/SoftwareSerialDemo.ino
@@ -0,0 +1,85 @@
+/*
+   Code to detect pulses from the PulseSensor,
+   using an interrupt service routine and
+   using SoftwareSerial for Serial output.
+
+   See https://www.pulsesensor.com
+
+   Copyright World Famous Electronics LLC - see LICENSE
+   Contributors:
+     Joel Murphy, https://pulsesensor.com
+     Yury Gitman, https://pulsesensor.com
+     Bradford Needham, @bneedhamia, https://bluepapertech.com
+
+   Licensed under the MIT License, a copy of which
+   should have been included with this software.
+
+   This software is not intended for medical use.
+*/
+
+#include <PulseSensorPlayground.h>
+#include <SoftwareSerial.h>
+
+const int OUTPUT_TYPE = PROCESSING_VISUALIZER;
+
+/*
+     PIN_RX = Serial Receive pin (input into Arduino)
+     PIN_TX = Serial Transmit pin (output from Arduino)
+
+     In most cases, you'll want to wire the Arduino PIN_RX
+     to the TRANSMIT pin of the external serial device,
+     and the Arduino PIN_TX to the RECEIVE pin of the
+     external device.
+*/
+const int PIN_RX = 7;
+const int PIN_TX = 8;
+
+const int PIN_INPUT = A0;
+const int PIN_BLINK = 13;    // Pin 13 is the on-board LED
+const int PIN_FADE = 5;      // must be a pin that supports PWM. Can't be pin 3 or 11 (see ISR()).
+
+/*
+   Our software serial controller.
+ */
+SoftwareSerial ourSerial(PIN_RX, PIN_TX);
+
+PulseSensorPlayground pulseSensor;
+
+void setup() {
+
+  ourSerial.begin(115200);
+
+  // Configure the PulseSensor manager.
+  pulseSensor.analogInput(PIN_INPUT);
+  pulseSensor.blinkOnPulse(PIN_BLINK);
+  pulseSensor.fadeOnPulse(PIN_FADE);
+  pulseSensor.setSerial(ourSerial);
+  pulseSensor.setOutputType(OUTPUT_TYPE);
+
+  if (!pulseSensor.begin()) {
+    /*
+     * PulseSensor initialization failed,
+     * likely because our particular Arduino platform interrupts
+     * aren't supported yet.
+     *
+     * If your Sketch hangs here, try ProcessEverySample.ino
+     */
+    for(;;) {
+      // Flash the led to show things didn't work.
+      digitalWrite(PIN_BLINK, LOW);
+      delay(50);
+      digitalWrite(PIN_BLINK, HIGH);
+      delay(50);
+    }
+  }
+}
+
+void loop() {
+  delay(20);
+
+  pulseSensor.outputSample();
+
+  if (pulseSensor.sawStartOfBeat()) {
+    pulseSensor.outputBeat();
+  }
+}


Examples Adding example for non-blocking publish routine

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

--- examples/publishNonBlocking/publishNonBlocking.ino
+++ examples/publishNonBlocking/publishNonBlocking.ino
@@ -0,0 +1,69 @@
+/******************************************
+ *
+ * This example works for both Industrial and STEM users.
+ * If you are using the old educational platform,
+ * please consider to migrate your account to a STEM plan
+ *
+ * ****************************************/
+
+/****************************************
+ * Include Libraries
+ ****************************************/
+#include "UbidotsESPMQTT.h"
+
+/****************************************
+ * Define Constants
+ ****************************************/
+#define TOKEN "...."     // Your Ubidots TOKEN
+#define WIFINAME "...."  // Your SSID
+#define WIFIPASS "...."  // Your Wifi Pass
+
+Ubidots client(TOKEN);
+
+/****************************************
+ * Auxiliar Functions
+ ****************************************/
+
+void callback(char* topic, byte* payload, unsigned int length) {
+  Serial.print("Message arrived [");
+  Serial.print(topic);
+  Serial.print("] ");
+  for (int i = 0; i < length; i++) {
+    Serial.print((char)payload[i]);
+  }
+  Serial.println();
+}
+
+/****************************************
+ * Main Functions
+ ****************************************/
+
+void setup() {
+  // put your setup code here, to run once:
+  Serial.begin(115200);
+  client.setDebug(true);  // Pass a true or false bool value to activate debug messages
+  client.wifiConnection(WIFINAME, WIFIPASS);
+  client.begin(callback);
+}
+
+void loop() {
+  // put your main code here, to run repeatedly:
+  if (!client.connected()) {
+    bool conn = client.connect();
+    while (!conn) {
+      Serial.print(".");
+      delay(500);
+      conn = client.connect();
+    }
+  }
+
+  // Publish values to 2 different data sources
+
+  client.add("stuff", 10.2);  // Insert your variable Labels and the value to be sent
+  client.ubidotsPublish("source1");
+  client.add("stuff", 10.2);
+  client.add("more-stuff", 120.2);
+  client.ubidotsPublish("source2");
+  client.loop();
+  delay(5000);
+}


Just trying to get this in the repo

Just trying to get this in the repo

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

--- interrupt_driven_rgb.ino
+++ interrupt_driven_rgb.ino
@@ -0,0 +1,344 @@
+// #include <avr/sleep.h>
+// #include <pitches.h>
+
+#include <SPI.h>
+#include <Time.h>
+// #include <EEPROM.h>
+#include <Ucglib.h>
+#include <TinyGPS++.h>
+#include <Streaming.h>
+#include <TimedEvent.h>
+#include <ButtonEvent.h>
+#include <FiniteStateMachine.h>
+
+#define OLED_MOSI 11
+#define OLED_CLK 13
+#define OLED_CS 10
+#define OLED_DC 3
+#define OLED_RESET 2
+
+#define GET_FIX_TIMER 1
+#define READ_LOCATION_TIMER 2
+
+#define LAT_INDEX 0
+#define LNG_INDEX 1
+
+#define arraySize(a) (sizeof(a) / sizeof(a[0]))
+
+const uint8_t buttonPin = 2;
+// const uint8_t id_address = 0;
+const double threshold = 0.01;
+// unsigned long start = 0;
+double distanceTo;
+double course;
+uint8_t waypoint_index = 0;
+
+const double waypoint[][2] = {
+  { 36.139670, -96.004777 },
+  { 36.139777, -96.003538 },
+  { 36.140135, -96.004070 },
+};
+
+// U8GLIB_SSD1351_128X128_HICOLOR oled(OLED_CS, OLED_DC, OLED_RESET);
+Ucglib_SSD1351_18x128x128_HWSPI oled(OLED_DC, OLED_CS, OLED_RESET);
+
+TinyGPSPlus gps;
+
+// TinyGPSCustom ack_command(gps, "PMTK001", 1);
+// TinyGPSCustom ack_response(gps, "PMTK001", 2);
+// TinyGPSCustom awake(gps, "PMTK010", 1);
+
+State GetFix       = State(enterGetFix, updateGetFix, exitGetFix);
+State ReadLocation = State(enterReadLocation, updateReadLocation, exitReadLocation);
+State SleepModules = State(enterSleepModules, updateSleepModules, NULL);
+State SleepNow     = State(updateSleepNow);
+State WakeModules  = State(enterWakeModules, updateWakeModules, NULL);
+State NextWaypoint = State(enterNextWaypoint, updateNextWaypoint, NULL);
+State LastWaypoint = State(updateLastWaypoint);
+State GPSFailure   = State(enterGPSFailure, NULL, NULL);
+
+FSM stateMachine = FSM(GetFix);
+
+// void pictureLoop(void (draw)()) {
+//   oled.firstPage();
+//   do {
+//     draw();
+//   } while(oled.nextPage());
+// }
+
+void onDown(ButtonInformation* sender) { /* do nothing here */ }
+
+void onUp(ButtonInformation* sender) { /* do nothing here */ }
+
+void onDouble(ButtonInformation* sender) { /* do nothing here */ }
+
+void onHold(ButtonInformation* sender) {
+  if(millis() < 6000) {
+    // reset waypoint index
+  } else {
+    stateMachine.transitionTo(NextWaypoint);
+  }
+}
+
+void gpsFailure(TimerInformation* sender) {
+  if(gps.charsProcessed() < 10)
+    stateMachine.transitionTo(GPSFailure);
+}
+
+void initiateSleep(TimerInformation* sender) {
+  stateMachine.transitionTo(SleepModules);
+}
+
+void drawTitle(const __FlashStringHelper *ifsh) {
+  oled.undoClipRange();
+  oled.clearScreen();
+
+  oled.setColor(0, 0, 255);
+  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
+
+  oled.setFont(ucg_font_7x13Br);
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(5, 14);
+  oled << ifsh;
+}
+
+// States
+
+void enterGetFix() {
+  drawTitle(F("Aquiring Fix"));
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("Please wait...");
+
+  int width = oled.getStrWidth("0 satellites");
+  oled.setClipRange(0, oled.getHeight() - 12, width, 12);
+
+  TimedEvent.start(GET_FIX_TIMER);
+}
+
+void updateGetFix() {
+  if(gps.location.isValid())
+    stateMachine.transitionTo(ReadLocation);
+
+  oled.setColor(255, 255, 255);
+
+  oled.setPrintPos(0, oled.getHeight() + oled.getFontDescent());
+  oled << gps.satellites.value() << F(" satellites");
+}
+
+void exitGetFix() {
+  TimedEvent.stop(GET_FIX_TIMER);
+}
+
+void enterReadLocation() {
+  drawTitle(F("Directions"));
+  oled.setClipRange(0, 22, oled.getWidth(), oled.getHeight() - 22);
+
+  TimedEvent.start(READ_LOCATION_TIMER);
+}
+
+void updateReadLocation() {
+  if(gps.location.isUpdated() && gps.location.age() < 200) {
+    distanceTo =
+      TinyGPSPlus::distanceBetween(
+        gps.location.lat(),
+        gps.location.lng(),
+        waypoint[waypoint_index][LAT_INDEX],
+        waypoint[waypoint_index][LNG_INDEX]
+      ) * _GPS_MILES_PER_METER;
+    course =
+      TinyGPSPlus::courseTo(
+        gps.location.lat(),
+        gps.location.lng(),
+        waypoint[waypoint_index][LAT_INDEX],
+        waypoint[waypoint_index][LNG_INDEX]
+      );
+
+    if(distanceTo < threshold)
+      stateMachine.transitionTo(NextWaypoint);
+  }
+
+  if((gps.date.isUpdated() && gps.date.age() < 200) || (gps.time.isUpdated() && gps.time.age() < 200)) {
+    setTime(
+      gps.time.hour(),
+      gps.time.minute(),
+      gps.time.second(),
+      gps.date.day(),
+      gps.date.month(),
+      gps.date.year()
+    );
+    adjustTime(-6 * SECS_PER_HOUR);
+  }
+
+  drawReadLocation();
+}
+
+void exitReadLocation() {
+  TimedEvent.stop(READ_LOCATION_TIMER);
+}
+
+void enterSleepModules() {
+  drawTitle(F("Going to Sleep"));
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("Please wait...");
+}
+
+void updateSleepModules() {
+}
+
+void updateSleepNow() {
+}
+
+void enterWakeModules() {
+  ;
+}
+
+void updateWakeModules() {
+  drawWakeModules();
+}
+
+void enterNextWaypoint() {
+  ;
+}
+
+void updateNextWaypoint() {
+  drawNextWaypoint();
+}
+
+void updateLastWaypoint() {
+  drawLastWaypoint();
+}
+
+void enterGPSFailure() {
+  drawGPSFailure();
+}
+
+void drawReadLocation() {
+  char datetime[24];
+  char status[24];
+
+  sprintf(datetime, "%d-%02d-%02d    %02d:%02d:%02d", year(), month(), day(), hourFormat12(), minute(), second());
+  sprintf(status, "%2d satellites", gps.satellites.value());
+
+  oled.setFont(ucg_font_7x13Br);
+
+  oled.setColor(0, 0, 255);
+  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
+
+
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(5, 15);
+  oled << F("Directions");
+
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(0, 22);
+  oled << datetime;
+
+  oled.setFont(ucg_font_7x13Br);
+
+  oled.setPrintPos(0, oled.getHeight() / 2 - 20);
+  oled << distanceTo << F(" miles");
+
+  oled.setPrintPos(0, oled.getHeight() / 2 + 20);
+  oled << TinyGPSPlus::cardinal(course);
+
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setPrintPos(0, oled.getHeight() - (oled.getFontDescent() + 12));
+  oled << status;
+
+  oled.setPrintPos(0, oled.getHeight() - (oled.getFontDescent() + 24));
+  oled << F("hdop: ") << gps.hdop.value() << F(" WP: ") << (waypoint_index + 1) << '/' << arraySize(waypoint);
+}
+
+void drawSleepModules() {
+  oled.clearScreen();
+  oled.setColor(0, 0, 255);
+  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
+
+  oled.setFont(ucg_font_7x13Br);
+
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(5, 15);
+  oled << F("Sleep Modules");
+}
+
+void drawSleepNow() {
+  ;
+}
+
+void drawWakeModules() {
+  ;
+}
+
+void drawNextWaypoint() {
+  oled.clearScreen();
+  oled.setColor(0, 0, 255);
+  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
+
+  oled.setFont(ucg_font_7x13Br);
+
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(5, 15);
+  oled << F("Next Waypoint");
+}
+
+void drawLastWaypoint() {
+  ;
+}
+
+void drawGPSFailure() {
+  oled.clearScreen();
+  oled.setColor(0, 0, 255);
+  oled.drawRFrame(0, 0, oled.getWidth(), 20, 3);
+
+  oled.setFont(ucg_font_7x13Br);
+
+  oled.setColor(255, 255, 255);
+  oled.setPrintPos(5, 15);
+  oled << F("GPS Failure");
+
+  oled.setFont(ucg_font_fixed_v0r);
+
+  oled.setColor(255, 255, 0);
+  oled.setPrintPos(0, oled.getHeight() / 2);
+  oled << F("No data from GPS!");
+}
+
+void setup() {
+  ButtonEvent.addButton(
+    buttonPin,
+    onDown,
+    onUp,
+    onHold,
+    5000,
+    onDouble,
+    200
+  );
+
+  TimedEvent.addTimer(GET_FIX_TIMER, 5000, gpsFailure);
+  TimedEvent.addTimer(READ_LOCATION_TIMER, 60000, initiateSleep);
+
+  Serial3.begin(9600);
+  delay(1000);
+  Serial3.println(F("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"));
+  Serial3.println(F("$PMTK220,200*2C"));
+
+  oled.begin(UCG_FONT_MODE_SOLID);
+  oled.setColor(1, 0, 0, 0);
+  oled.clearScreen();
+}
+
+void loop() {
+  while(Serial3.available()) gps << Serial3.read();
+  TimedEvent.loop();
+  ButtonEvent.loop();
+  stateMachine.update();
+}


new TempSensor Device.

new TempSensor Device.

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/mathertel/Dose.git/'


setting poscomp

setting poscomp

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/'


Made sound sensor work

Made sound sensor work

used for start

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

--- arduino/soundSensor.ino
+++ arduino/soundSensor.ino
@@ -0,0 +1,34 @@
+
+int sensorPin = A0;
+int ledPin = 13;
+int sensorValue = 0;
+bool robotOn = false;
+
+void setup() {
+  // declare the ledPin as an OUTPUT:
+  pinMode(ledPin, OUTPUT);
+  pinMode(sensorPin, INPUT);
+  Serial.begin(112500);
+}
+
+void soundStart(){
+
+  sensorValue = analogRead(sensorPin);
+  Serial.println("Sensor Value: " + (String)sensorValue);
+  Serial.print( "  RobotOn: " +  (String)robotOn) ;
+  delay(100);
+
+    if(sensorValue > 500) {
+      robotOn = true;
+    }
+    while(robotOn){
+      for(int i = 0; i <100; i++){
+       digitalWrite(ledPin, HIGH);
+       Serial.println( "RobotOn: TRUE") ;
+      }
+    }
+
+}
+void loop() {
+ soundStart();
+}


Update Titan16_3DOF.ino

Update Titan16_3DOF.ino

added an else statement for debugging

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


Add Simple ACS712 reader

Add Simple ACS712 reader

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/'


Add arduino directory and working sketch file to project

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

--- arduino/arduino_sketch/arduino_sketch.ino
+++ arduino/arduino_sketch/arduino_sketch.ino
@@ -0,0 +1,326 @@
+//Created by Ryan Staatz
+
+//Arduino JSON library: https://github.com/bblanchon/ArduinoJson
+#include <ArduinoJson.h>
+#include <Servo.h>
+
+//Sets the baud rate of the Arduino
+const long BAUD_RATE = 115200;
+
+//Receiver input timeout in microseconds
+const int PULSE_TIMEOUT = 44100;
+
+//Pulse threshold values for receiver input for cutover between auto and manual control
+const int CUTOVER_MIN = 900;
+const int CUTOVER_MAX = 1500;
+
+//Pulse threshold values for receiver input for servos and motor
+const int RECEIVER_MIN = 750;
+const int RECEIVER_MAX = 1800;
+
+//Sets the character array (max) length for serial input
+const int numChars = 300;
+
+//This array stores Json characters read from serial input
+char receivedJson[numChars];
+
+//All valid input/output must start/end with the corresponding char
+char startMarker = '@';
+char endMarker = '#';
+
+//Determines if new Json data has been collected from serial input for processing
+boolean newData = false;
+
+//Determines if the plane is controlled manually (remote control) or via autopilot (phone)
+boolean manualControl = false;
+
+//Determines if the cutover pin can use interrupts
+boolean cutoverInterrupt = false;
+
+//Stores the pin value for each receiver input
+int aileronIn = -1;
+int elevatorIn = -1;
+int rudderIn = -1;
+int throttleIn = -1;
+int cutoverIn = -1;
+
+//Servos (including the motor)
+Servo aileron;
+Servo elevator;
+Servo rudder;
+Servo throttle;
+
+void setup() {
+  Serial.begin(BAUD_RATE);  //Set the baud rate
+  while (!Serial) {}  //Wait for serial port to connect
+  sendJson("status", "ready");  //Inform serial interface that Arduino is ready
+}
+
+void loop() {
+  readSerialJsonText();
+  processJsonText();
+  readReceiverInput();
+}
+
+//Reads json serial input and stores input in a char array
+//Most of this method code is taken from: https://forum.arduino.cc/index.php?topic=288234.0
+void readSerialJsonText() {
+  static boolean receiveInProgress = false;  //Determines if a char received via serial input belongs to the current json input char array
+  static int index = 0;  //Index for storing the most recently received serial input in the correct place in the input char array
+  char charIn;  //Char being currently read from serial input
+
+  //Only attempt to read data when serial input is available
+  while (Serial.available() > 0 && newData == false) {
+    charIn = Serial.read();
+
+    if (receiveInProgress == true) {
+      if (charIn != endMarker) {
+        receivedJson[index] = charIn;
+        index++;
+        if (index >= numChars) {
+          index = numChars - 1;
+          sendJson("error", "Serial buffer overflow");
+        }
+      }
+      else {
+        receivedJson[index] = '\0'; // terminate the string
+        receiveInProgress = false;
+        index = 0;
+        newData = true;
+      }
+
+    } else if (charIn == startMarker) {
+      receiveInProgress = true;
+    }
+  }
+}
+
+//Example JSON strings below:
+//@{"manualControl":false, "config":{"throttle":10, "elevator":9, "aileron":8, "rudder":7, "aileronIn":6, "elevatorIn":5, "rudderIn":4, "throttleIn":3, "cutoverIn":2, "cutoverInterrupt":true}, "throttle":120, "elevator":100, "aileron":90, "rudder":75}#
+//@{"aileron": 90}#
+void processJsonText() {
+  if (newData == true) {
+    StaticJsonBuffer<numChars> jsonBuffer;
+    JsonObject& root = jsonBuffer.parseObject(receivedJson);
+
+    //If the JSON object failed to parse, inform the serial interface and return
+    if (!root.success()) {
+      sendJson("error", "Parsing JSON failed");
+      newData = false;
+      return;
+    }
+
+    //If status is requested, send status check response
+    if (root.containsKey("request")) {
+      const char* request = root["request"];
+      if (strcmp(request, "status") == 0) sendJson("status", "ready");
+    }
+
+    //Enable or disable manual control
+    if (root.containsKey("manualControl")) {
+      manualControl = (boolean) root["manualControl"];
+      if (manualControl) {
+        sendJson("manualControl", true);
+      } else {
+        sendJson("manualControl", false);
+      }
+    }
+
+    //Assigns pin numbers to the motor, servos, and receiver inputs based on the received JSON
+    if (root.containsKey("config")) {
+      JsonObject& config = root["config"];
+      if (config.containsKey("aileron")) {
+        int aileronPin = (int) config["aileron"];
+        aileron.attach(aileronPin);
+      }
+      if (config.containsKey("elevator")) {
+        int elevatorPin = (int) config["elevator"];
+        elevator.attach(elevatorPin);
+      }
+      if (config.containsKey("rudder")) {
+        int rudderPin = (int) config["rudder"];
+        rudder.attach(rudderPin);
+      }
+      if (config.containsKey("throttle")) {
+        int throttlePin = (int) config["throttle"];
+        throttle.attach(throttlePin);
+      }
+      if (config.containsKey("aileronIn")) {
+        aileronIn = (int) config["aileronIn"];
+        pinMode(aileronIn, INPUT);
+      }
+      if (config.containsKey("elevatorIn")) {
+        elevatorIn = (int) config["elevatorIn"];
+        pinMode(elevatorIn, INPUT);
+      }
+      if (config.containsKey("rudderIn")) {
+        rudderIn = (int) config["rudderIn"];
+        pinMode(rudderIn, INPUT);
+      }
+      if (config.containsKey("throttleIn")) {
+        throttleIn = (int) config["throttleIn"];
+        pinMode(throttleIn, INPUT);
+      }
+      if (config.containsKey("cutoverIn")) {
+        cutoverIn = (int) config["cutoverIn"];
+        pinMode(cutoverIn, INPUT);
+      }
+      //Configures an interrupt service routine for listening for the cutover signal from the receiver
+      if (config.containsKey("cutoverInterrupt")) {
+        if (cutoverIn != -1) {
+          cutoverInterrupt = (boolean) config["cutoverInterrupt"];
+          attachInterrupt(digitalPinToInterrupt(cutoverIn), listenForCutover, CHANGE);
+        } else {
+          sendJson("error", "Unassigned cutover pin");
+        }
+      }
+    }
+
+    //If autopilot is enabled, set the servo values according to the received JSON
+    if (!manualControl) {
+      if (root.containsKey("aileron")) {
+        if (aileron.attached()) {
+          int aileronValue = root["aileron"];
+          aileron.write(aileronValue);
+          sendJson("aileron", aileronValue);
+        } else {
+          sendJson("error", "Unassigned aileron pin");
+        }
+      }
+
+      if (root.containsKey("elevator")) {
+        if (elevator.attached()) {
+          int elevatorValue = root["elevator"];
+          elevator.write(elevatorValue);
+          sendJson("elevator", elevatorValue);
+        } else {
+          sendJson("error", "Unassigned elevator pin");
+        }
+      }
+
+      if (root.containsKey("rudder")) {
+        if (rudder.attached()) {
+          int rudderValue = root["rudder"];
+          rudder.write(rudderValue);
+          sendJson("rudder", rudderValue);
+        } else {
+          sendJson("error", "Unassigned rudder pin");
+        }
+      }
+
+      if (root.containsKey("throttle")) {
+        if (throttle.attached()) {
+          int throttleValue = root["throttle"];
+          throttle.write(throttleValue);
+          sendJson("throttle", throttleValue);
+        } else {
+          sendJson("error", "Unassigned throttle pin");
+        }
+      }
+    }
+    newData = false;
+  }
+}
+
+//TODO prevent process from hanging if receiver is out of range and no interrupt is in place
+//Listens for cutover input to switch between manual (receiver) and autopilot (phone) mode
+void listenForCutover() {
+  if (cutoverIn != -1) {
+    long pulse = pulseIn(cutoverIn, HIGH, PULSE_TIMEOUT);
+    if (pulse != 0) {
+      if (pulse < CUTOVER_MIN) {
+        manualControl = false;
+        sendJson("manualControl", false);
+      } else if (pulse > CUTOVER_MAX) {
+        manualControl = true;
+        sendJson("manualControl", true);
+      }
+    }
+  }
+}
+
+//Reads receiver input and writes translated values to servos
+void readReceiverInput() {
+  if (!cutoverInterrupt) listenForCutover();  //If there is no cutover interrupt already running, listen for cutover without an interrupt
+  //Only read servo inputs if manual control is enabled
+  if (manualControl) {
+    if (throttle.attached()) {
+      if (throttleIn != -1) {
+        long pulse = pulseIn(throttleIn, HIGH, PULSE_TIMEOUT);
+        if (pulse != 0) {
+          int servoPosition = constrain(map(pulse, RECEIVER_MIN, RECEIVER_MAX, 0, 180), 0, 180);
+          throttle.write(servoPosition);
+          sendJson("rudder", servoPosition);         }
+      }
+    } else {
+      sendJson("error", "Unassigned throttle pin");
+    }
+
+    if (elevator.attached()) {
+      if (elevatorIn != -1) {
+        long pulse = pulseIn(elevatorIn, HIGH, PULSE_TIMEOUT);
+        if (pulse != 0) {
+          int servoPosition = constrain(map(pulse, RECEIVER_MIN, RECEIVER_MAX, 0, 180), 0, 180);
+          elevator.write(servoPosition);
+          sendJson("rudder", servoPosition);         }
+      }
+    } else {
+      sendJson("error", "Unassigned elevator pin");
+    }
+
+    if (aileron.attached()) {
+      if (aileronIn != -1) {
+        long pulse = pulseIn(aileronIn, HIGH, PULSE_TIMEOUT);
+        if (pulse != 0) {
+          int servoPosition = constrain(map(pulse, RECEIVER_MIN, RECEIVER_MAX, 0, 180), 0, 180);
+          aileron.write(servoPosition);
+          sendJson("rudder", servoPosition);         }
+      }
+    } else {
+      sendJson("error", "Unassigned aileron pin");
+    }
+
+    if (rudder.attached()) {
+      if (rudderIn != -1) {
+        long pulse = pulseIn(rudderIn, HIGH, PULSE_TIMEOUT);
+        if (pulse != 0) {
+          int servoPosition = constrain(map(pulse, RECEIVER_MIN, RECEIVER_MAX, 0, 180), 0, 180);
+          rudder.write(servoPosition);
+          sendJson("rudder", servoPosition);
+        }
+      }
+    } else {
+      sendJson("error", "Unassigned rudder pin");
+    }
+  }
+}
+
+//Takes a key (text) value (boolean) pair and sends them as JSON over the serial interface
+void sendJson(const char key[], boolean value) {
+  StaticJsonBuffer<numChars> jsonBuffer;
+  JsonObject& root = jsonBuffer.createObject();
+  root[key] = value;
+  Serial.print(startMarker);
+  root.printTo(Serial);
+  Serial.println(endMarker);
+}
+
+//Takes a key value (char array) pair and sends them as JSON over the serial interface
+void sendJson(const char key[], const char value[]) {
+  StaticJsonBuffer<numChars> jsonBuffer;
+  JsonObject& root = jsonBuffer.createObject();
+  root[key] = value;
+  Serial.print(startMarker);
+  root.printTo(Serial);
+  Serial.println(endMarker);
+}
+
+//Takes a key (text) value (int) pair and sends them as JSON over the serial interface
+void sendJson(const char key[], int value) {
+  StaticJsonBuffer<numChars> jsonBuffer;
+  JsonObject& root = jsonBuffer.createObject();
+  root[key] = value;
+  Serial.print(startMarker);
+  root.printTo(Serial);
+  Serial.println(endMarker);
+}


typos

typos

--- projects/ask/stm32f1init/stm32f1init.ino
+++ projects/ask/stm32f1init/stm32f1init.ino
@@ -9,8 +9,8 @@

 #include "ParitySerial.h"

-// The LED, if used, will blink at approx the following rate on 16 MHz ATmega:
-// 0.5 Hz = trying to connect, 1 Hz = programming, 5 Hz = error, steady = done
+// the LED, if used, will blink at approx the following rate on 16 MHz ATmega:
+// 0.25 Hz = trying to connect, 1 Hz = programming, 5 Hz = error, steady = done

 #define LED_PIN     13      // Arduino Dig.13, AVR port B.5, ATMega328 pin.13
 #define RESET_PIN   5       // Arduino Dig.5, AVR port D.5, ATMega328 pin.11
@@ -24,7 +24,7 @@

 #define SPEED       1       // relative CPU speed for use in busy loops

-#else // probably a STM32F103 running at 64 or 72 MHz, with hardware serial
+#else // probably an STM32F103 running at 64 or 72 MHz, with hardware serial

 #ifdef ARDUINO_STM_NUCLEO_F103RB
 #define Log         Serial1
@@ -46,7 +46,7 @@
 #endif // __AVR_ATmega328P__

 // only uncomment one of the boot loaders mentioned below (or add your own)
-// see etc/bin2h.c for the utility code used to make these include files
+// see ./etc/bin2h.c for the utility code used to make these include files

 //#define BOOT_LOADER "boot-maplemini-v20.h"
 #define BOOT_LOADER "boot-usbSerial-v01.h"


WIP..

WIP..

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/wintersandroid/lego-display-sequencer.git/'


Initial Arduino Code

Initial Arduino Code

Added skeleton for client Arduino. Also working on server rasp pi.

Time = 2 hours

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

--- Arduino/Client/Client.ino
+++ Arduino/Client/Client.ino
@@ -0,0 +1,69 @@
+/*****************************************************************
+
+
+*****************************************************************/
+
+// Libraries
+#include <SoftwareSerial.h>
+
+// Constants
+#define COMMAND_CHAR  '+'
+#define BAUD_RATE     38400
+#define S_READY       'Y'
+#define S_BUSY        'N'
+
+// Create Objects
+SoftwareSerial XBee(2, 3);
+
+// Variables
+char rChar;
+bool canWrite = false;
+
+// Function Prototypes
+void runCommand();
+void readCommand();
+
+// Setup - Run once at startup
+void setup()
+{
+  // Initialize Serial Interfaces
+  XBee.begin(BAUD_RATE);
+  Serial.begin(BAUD_RATE);
+}
+
+void loop()
+{
+  if (Serial.available())
+  {
+
+  }
+
+  if (XBee.available())
+  {
+    rChar = XBee.read();
+    if (rChar == COMMAND_CHAR) readCommand();
+  }
+}
+
+void runCommand()
+{
+
+}
+
+void readCommand()
+{
+  rChar = XBee.read();
+  switch (rChar)
+  {
+    case S_READY:
+      canWrite = true;
+      break;
+    case S_BUSY:
+      canWrite = false;
+      break;
+    default:
+      Serial.println("Error. Not a valid command");
+      break;
+  }
+}
+


Create mirror_and_fade_ends.ino

Create mirror_and_fade_ends.ino

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

--- mirror_and_fade_ends.ino
+++ mirror_and_fade_ends.ino
@@ -0,0 +1,76 @@
+/****************************************************************
+mirror display and faded out ends of strip
+This example shows one basic way to mirror the display on
+a strip.  It also fades out the ends of the strip to black.
+
+This example fades the ends over 7 pixels.
+
+
+Marc Miller, Feb 2021
+****************************************************************/
+
+#include "FastLED.h"
+
+#define LED_TYPE      LPD8806
+#define COLOR_ORDER   GRB
+#define DATA_PIN      11
+#define CLOCK_PIN     13  // delete for clockless pixel types
+#define NUM_LEDS      32
+uint8_t BRIGHTNESS = 255;
+CRGB leds[NUM_LEDS];
+
+
+//===============================================================
+void setup() {
+  Serial.begin(115200);
+  delay(2000);  // safety start up delay
+  //FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
+  FastLED.addLeds<LED_TYPE, DATA_PIN, CLOCK_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
+  FastLED.setBrightness(BRIGHTNESS);
+  FastLED.clear();
+  FastLED.show();
+  Serial.println("\nSetup done.\n");
+}
+
+//===============================================================
+void loop() {
+
+  // fill first half the strip with a rainbow
+  fill_rainbow( leds, NUM_LEDS / 2, (millis() / 50) );
+
+  // mirror data
+  mirror();
+
+  // fade ends by X number of pixels
+  fadeEnds(7);
+
+  // update the display
+  FastLED.show();
+
+} // end_main_loop
+
+
+
+//---------------------------------------------------------------
+// mirror data to the other half
+void mirror() {
+  for (uint8_t i = 0; i < NUM_LEDS / 2; i++) {
+    leds[NUM_LEDS - 1 - i] = leds[i];
+  }
+}
+
+
+//---------------------------------------------------------------
+// fade both ends of strip over X number of pixels
+void fadeEnds(uint8_t fadeOver) {
+  uint8_t fadePP = 255 / fadeOver;  // fade per pixel
+  for (uint8_t i = 0; i < fadeOver + 1; i++) {
+    uint8_t fadeAmmount = (255 - (fadePP * i));
+    leds[i].fadeToBlackBy(fadeAmmount);
+    leds[NUM_LEDS - 1 - i].fadeToBlackBy(fadeAmmount);
+  }
+}
+
+
+//---------------------------------------------------------------
+


Fixed bug in hardware serial declaration

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


voltage creator, i.e. any voltage between 0..5 V on pin 9

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

--- Testsystem/Testsystem03/Voltage/Voltage.ino
+++ Testsystem/Testsystem03/Voltage/Voltage.ino
@@ -0,0 +1,48 @@
+
+int voltagePin = 9;
+int voltageValue = 0;
+byte voltageTargetValue = 0;
+
+#define MAX_VOLTAGE 50
+
+void setup()
+{
+  pinMode(voltagePin, OUTPUT);
+  Serial.begin(9600);
+  Serial.println("Ready... enter: + -");
+}
+
+void checkSerial()
+{
+  if(Serial.available())
+  {
+    byte character = (char)Serial.read();
+    if(character == '+')
+      voltageValue += 1;
+    else if(character == '-')
+      voltageValue -= 1;
+
+    if(voltageValue < 0)
+      voltageValue = 0;
+    else if(voltageValue > MAX_VOLTAGE)
+      voltageValue = MAX_VOLTAGE;
+
+    voltageTargetValue = map(voltageValue, 0, MAX_VOLTAGE, 0, 255);
+
+    Serial.print("New Voltage: ");
+    Serial.print(voltageTargetValue);
+    Serial.print("  ");
+    Serial.print(voltageValue/10.f);
+    Serial.println("V");
+  }
+}
+
+void loop()
+{
+  checkSerial();
+
+  analogWrite(voltagePin, voltageTargetValue);
+
+  delay(30);
+}
+


This fixes a lot of bugs gcn_controller_v5 had...

... and gcn_controller_v5 is now no longer going to be updated.

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

--- gcn_controller_v6/gcn_controller_v6.ino
+++ gcn_controller_v6/gcn_controller_v6.ino
@@ -0,0 +1,1030 @@
+// This project uses 4 8-bit shift register, such as 74HC595 or HCF4094, in cascading format
+/*
+  GCN Controller for Arduino UNO by WhatAboutGaming NOTE: THIS CODE HAD TO BE MODIFIED TO WORK WITH MEGA 2560 BECAUSE UNO RAN OUT OF RAM, THIS CODE NEEDS TO BE OPTIMIZED TO SAVE RAM, I DON'T KNOW WHERE TO EVEN START TO OPTIMIZE THE CODE, TO ME, EVERYTHING LOOKS FINE BUT I'M A NOOB
+  For use in the Twitch.TV stream TwitchTriesToPlay.
+  https://www.twitch.tv/twitchtriestoplay
+  https://github.com/WhatAboutGaming/Twitch-Plays-Stuff
+
+  Reference:
+  http://www.int03.co.uk/crema/hardware/gamecube/gc-control.html
+  http://www.seas.upenn.edu/~gland/gamecube.html
+  https://nintenduino.wordpress.com/documentation/controller-reference/
+  https://nintenduino.files.wordpress.com/2013/12/untitled.png
+  https://nintenduino.files.wordpress.com/2013/12/protocolv1-0.png
+  https://github.com/NicoHood/Nintendo
+  https://github.com/dekuNukem/gc3ds
+*/
+
+/*
+  PINOUTS
+
+
+  Protoboard Side|SR Bit      |Variable Name |GCN Controller Side
+  13 LEFT        |22 and 23   |axisY         |Analog Axis Y // Done
+  14 LEFT        |20 and 21   |axisX         |Analog Axis X // Done
+  15 LEFT        |18 and 19   |axisCx        |Axis C X // Done
+  16 LEFT        |16 and 17   |axisCy        |Axis C Y // Done
+  6  LEFT        |7           |buttonDDown   |D-Down // Done
+  5  LEFT        |6           |buttonDLeft   |D-Left // Done
+  8  LEFT        |8           |axisLTrigger  |L Analog Trigger // Done
+  7  LEFT        |10          |buttonLTrigger|L Digital Trigger // Done
+  10 LEFT        |0           |buttonTurbo   |Turbo (Bootleg Controller Button) // Done
+  11 LEFT        |24          |buttonMode    |Mode (Bootleg Controller Button) // Done
+  12 LEFT        |3           |buttonStart   |Start // Done
+  4  RIGHT       |9           |axisRTrigger  |R Analog Trigger // Done
+  3  LEFT        |4           |buttonDUp     |D-Up // Done
+  4  LEFT        |5           |buttonDRight  |D-Right // Done
+  5  RIGHT       |15          |buttonB       |B // Done
+  3  RIGHT       |11          |buttonRTrigger|R Digital Trigger // Done
+  6  RIGHT       |12          |buttonY       |Y // Done
+  8  RIGHT       |13          |buttonX       |X // Done
+  7  RIGHT       |14          |buttonA       |A // Done
+  10 RIGHT       |2           |buttonZ       |Z // Done
+  9  RIGHT       |1           |buttonMacro   |Macro (Bootleg Controller Button) // Done
+  9  LEFT        |A0 (Not SR) |motorInput    |Motor
+  11 RIGHT       |A1 (Not SR) |turboLed      |Turbo LED (Bootleg Controller Function)
+  12 RIGHT       |A2 (Not SR) |macroLed      |Macro LED (Bootleg Controller Function)
+  SR = Shift Register
+*/
+
+#define bootLed 13
+
+#define latchPin 2  // HCF4094/74HC595 Latch/Strobe Input
+#define dataPin 3   // HCF4094/74HC595 Data Input
+#define clockPin 4  // HCF4094/74HC595 Clock Input
+
+/*
+  #define buttonLTrigger 0 // Left 7 // Bit
+  #define buttonRTrigger 1 // Right 3 // Bit
+  #define buttonZ 2 // Right 10 // Bit
+  #define buttonStart 3 // Left 12 // Bit
+
+  #define buttonY 4 // Right 6 // Bit
+  #define buttonX 5 // Right 8 // Bit
+  #define buttonB 6 // Right 5 // Bit
+  #define buttonA 7 // Right 7 // Bit
+
+  #define axisLTrigger 8 // Left 8 // Bit
+  #define axisRTrigger 9 // Right 4 // Bit
+  #define buttonMacro 10 // Right 9 // Bit
+  #define buttonTurbo 11 // Left 10 // Bit
+
+  #define buttonDUp 12 // Left 3 // Bit
+  #define buttonDDown 13 // Left 6 // Bit
+  #define buttonDRight 14 // Left 4 // Bit
+  #define buttonDLeft 15 // Left 5 // Bit
+
+  #define axisXHalf 16 // Left 14
+  #define axisXFull 17 // Left 14 // Both are part of the same byte
+
+  #define axisYHalf 18 // Left 13
+  #define axisYFull 19 // Left 13 // Both are part of the same byte
+
+  #define axisCxHalf 20 // left 15
+  #define axisCxFull 21 // left 15 // Both are part of the same byte
+
+  #define axisCyHalf 22 // Left 16
+  #define axisCyFull 23 // Left 16 // Both are part of the same byte
+
+  #define buttonMode 24 // Left 11 // Bit
+*/
+#define buttonTurbo 0  // Left 10 // Bit
+#define buttonMacro 1  // Right 9 // Bit
+#define buttonZ 2      // Right 10 // Bit
+#define buttonStart 3  // Left 12 // Bit
+
+#define buttonDUp 4     // Left 3 // Bit
+#define buttonDRight 5  // Left 4 // Bit
+#define buttonDLeft 6   // Left 5 // Bit
+#define buttonDDown 7   // Left 6 // Bit
+
+#define axisLTrigger 8     // Left 8 // Bit
+#define axisRTrigger 9     // Right 4 // Bit
+#define buttonLTrigger 10  // Left 7 // Bit
+#define buttonRTrigger 11  // Right 3 // Bit
+
+#define buttonY 12  // Right 6 // Bit
+#define buttonX 13  // Right 8 // Bit
+#define buttonA 14  // Right 7 // Bit
+#define buttonB 15  // Right 5 // Bit
+
+#define axisCxHalf 18  // Left 14
+#define axisCxFull 19  // Left 14 // Both are part of the same byte
+
+#define axisCyHalf 16  // Left 13
+#define axisCyFull 17  // Left 13 // Both are part of the same byte
+
+#define axisXHalf 20  // left 15
+#define axisXFull 21  // left 15 // Both are part of the same byte
+
+#define axisYHalf 22  // Left 16
+#define axisYFull 23  // Left 16 // Both are part of the same byte
+
+#define buttonMode 24  // Left 11 // Bit
+/*
+  serial_rx_buffer[0] = 0x01; //  Preamble
+  serial_rx_buffer[1] = 0x00; //  Digital L Trigger, Digital R Trigger, Z, Start, Y, X, B, A
+  serial_rx_buffer[2] = 0x00; //  Analog L Trigger, Analog R Trigger, Macro (Bootleg), Turbo (Bootleg), DUp, DDown, DRight, DLeft
+  serial_rx_buffer[3] = 0x7F; //  Analog X Axis
+  serial_rx_buffer[4] = 0x7F; //  Analog Y Axis
+  serial_rx_buffer[5] = 0x7F; //  C X Axis
+  serial_rx_buffer[6] = 0x7F; //  C Y Axis
+  serial_rx_buffer[7] = 0x00; //  Mode (Bootleg), Buffer Array Element 7  //  All other bits in this Buffer Array Element are unused
+  serial_rx_buffer[8] = 0x00; //  Unused
+  serial_rx_buffer[9] = 0x00; //  Delay Byte 2
+  serial_rx_buffer[10] = 0x00; // Delay Byte 1
+  serial_rx_buffer[11] = 0x01; // Postamble
+*/
+/////////////////////////////////
+
+const unsigned int startingMacroIndex = 0x04;
+const unsigned int endingMacroIndex = 0x64;
+const unsigned int macroBufferSize = endingMacroIndex - startingMacroIndex;
+const unsigned int startingMacroMetadataIndex = endingMacroIndex + 1;
+const unsigned int endingMacroMetadataIndex = startingMacroMetadataIndex + macroBufferSize;
+const unsigned int macroMetadataSize = endingMacroMetadataIndex - startingMacroMetadataIndex;  // Using define on these variables for some reason was making it return wrong values
+//const unsigned int macroMetadataSize = macroBufferSize;
+
+unsigned int macroIndex = 0;
+unsigned int currentMacroIndexRunning = 0;
+unsigned int macroInputsToRun = 0;
+unsigned int loopMacro = 0;    //0 = Don't loop, 1 = loop
+unsigned int timesToLoop = 0;  //0 = Loop indefinitely, >0 = loop n times
+unsigned int loopCounter = 0;
+unsigned int howManyInnerLoopsMacroHas = 0;  //This variable is used to tell if the macro has inner loops (eg: a+b,[wait b]255) and how many there are // 0 = There are NO inner loops !0 = There are n inner loops, where n is this variable
+unsigned int macroMetadataIndex = 0;
+unsigned int isInnerLoop = 0;
+
+#define motorInput A0  // Left 9
+#define turboLed A1    // Right 11
+#define macroLed A2    // Right 12
+
+// Left 9 = Motor Input = A0
+// Right 11 = Turbo LED = A1
+// Right 12 = Macro LED = A2
+
+const bool defaultStatus[] = { HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW, LOW, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH };
+bool inputStatus[] = { HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW, LOW, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH, LOW, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH };
+//uint8_t commandArray[] = {buttonLTrigger, buttonRTrigger, buttonZ, buttonStart, buttonY, buttonX, buttonB, buttonA, axisLTrigger, axisRTrigger, buttonMacro, buttonTurbo, buttonDUp, buttonDDown, buttonDRight, buttonDLeft, axisXHalf, axisXFull, axisYHalf, axisYFull, axisCxHalf, axisCxFull, axisCyHalf, axisCyHalf, buttonMode, 25, 26, 27, 28, 29, 30, 31};
+unsigned int commandArray[] = { buttonTurbo, buttonMacro, buttonZ, buttonStart, buttonDUp, buttonDRight, buttonDLeft, buttonDDown, axisLTrigger, axisRTrigger, buttonLTrigger, buttonRTrigger, buttonY, buttonX, buttonA, buttonB, axisCyHalf, axisCyFull, axisCxHalf, axisCxFull, axisXHalf, axisXFull, axisYHalf, axisYHalf, buttonMode, 25, 26, 27, 28, 29, 30, 31 };
+unsigned int motorArray[] = { motorInput, turboLed, macroLed };  // Motor, Turbo LED, Macro LED
+
+bool isInputting = false;
+bool isInputtingDelayed = false;
+
+bool didInputChange = false;
+
+uint32_t inputDelay = 0;
+uint32_t previousInputDelay = 0;
+
+uint32_t baudRate = 500000;
+
+uint8_t serial_rx_buffer[12];
+uint8_t current_macro_input[12];
+uint8_t old_macro_input[12];
+uint8_t macro_buffer[macroBufferSize][12];
+uint8_t inner_loop_metadata[macroMetadataSize][12];  // Contains informations such as how many times to repeat a portion of a macro, and where to start and end
+uint32_t controller = 0;
+
+void setup() {
+  pinMode(bootLed, OUTPUT);
+  digitalWrite(bootLed, HIGH);
+  Serial.begin(baudRate);
+
+  pinMode(motorInput, INPUT);
+  pinMode(turboLed, INPUT);
+  pinMode(macroLed, INPUT);
+
+  pinMode(latchPin, OUTPUT);
+  pinMode(dataPin, OUTPUT);
+  pinMode(clockPin, OUTPUT);
+
+  digitalWrite(latchPin, LOW);
+  for (int8_t i = 31; i >= 0; i--) {
+    digitalWrite(clockPin, LOW);
+    digitalWrite(dataPin, defaultStatus[i]);
+    digitalWrite(clockPin, HIGH);
+  }
+  digitalWrite(latchPin, HIGH);
+
+  // Press the buttons X, Y and Start for 2 to 3 seconds to reset the controller,
+  // this is a built in controller feature to make it easier to reset analog sticks and
+  // triggers without having to unplug the controller, thanks Nintendo, this feature is very useful!
+  inputStatus[buttonX] = LOW;
+  inputStatus[buttonY] = LOW;
+  inputStatus[buttonStart] = LOW;
+
+  digitalWrite(latchPin, LOW);
+  for (int8_t i = 31; i >= 0; i--) {
+    digitalWrite(clockPin, LOW);
+    digitalWrite(dataPin, inputStatus[i]);
+    digitalWrite(clockPin, HIGH);
+  }
+  digitalWrite(latchPin, HIGH);
+
+  delay(2000);  // Change this if the controller takes longer to reset
+
+  // Now we release the buttons X, Y and Start after 2 to 3 seconds have passed
+  inputStatus[buttonX] = HIGH;
+  inputStatus[buttonY] = HIGH;
+  inputStatus[buttonStart] = HIGH;
+
+  digitalWrite(latchPin, LOW);
+  for (int8_t i = 31; i >= 0; i--) {
+    digitalWrite(clockPin, LOW);
+    digitalWrite(dataPin, inputStatus[i]);
+    digitalWrite(clockPin, HIGH);
+  }
+  digitalWrite(latchPin, HIGH);
+
+  //  Reset everything
+  serial_rx_buffer[0] = 0x00;
+  serial_rx_buffer[1] = 0x00;
+  serial_rx_buffer[2] = 0x00;
+  serial_rx_buffer[3] = 0x7F;
+  serial_rx_buffer[4] = 0x7F;
+  serial_rx_buffer[5] = 0x7F;
+  serial_rx_buffer[6] = 0x7F;
+  serial_rx_buffer[7] = 0x00;
+  serial_rx_buffer[8] = 0x00;
+  serial_rx_buffer[9] = 0x00;
+  serial_rx_buffer[10] = 0x00;
+  serial_rx_buffer[11] = 0x00;
+
+  current_macro_input[0] = 0x00;
+  current_macro_input[1] = 0x00;
+  current_macro_input[2] = 0x00;
+  current_macro_input[3] = 0x7F;
+  current_macro_input[4] = 0x7F;
+  current_macro_input[5] = 0x7F;
+  current_macro_input[6] = 0x7F;
+  current_macro_input[7] = 0x00;
+  current_macro_input[8] = 0x00;
+  current_macro_input[9] = 0x00;
+  current_macro_input[10] = 0x00;
+  current_macro_input[11] = 0x00;
+
+  old_macro_input[0] = 0x00;
+  old_macro_input[1] = 0x00;
+  old_macro_input[2] = 0x00;
+  old_macro_input[3] = 0x7F;
+  old_macro_input[4] = 0x7F;
+  old_macro_input[5] = 0x7F;
+  old_macro_input[6] = 0x7F;
+  old_macro_input[7] = 0x00;
+  old_macro_input[8] = 0x00;
+  old_macro_input[9] = 0x00;
+  old_macro_input[10] = 0x00;
+  old_macro_input[11] = 0x00;
+  digitalWrite(bootLed, LOW);
+}
+
+void loop() {
+  if (Serial.available() > 0) {
+    controller = Serial.readBytes(serial_rx_buffer, sizeof(serial_rx_buffer)) && 0xFF;
+    //  Set Start Byte (Preamble Byte) and End Byte (Postamble Byte)
+    //  1 == 0x01
+    if ((serial_rx_buffer[0] == 0x01) && (serial_rx_buffer[11] == 0x01)) {
+      for (uint8_t currentInputIndex = 0; currentInputIndex < sizeof(serial_rx_buffer); currentInputIndex++) {
+        current_macro_input[currentInputIndex] = serial_rx_buffer[currentInputIndex];
+      }
+      // Make the button presses actually work
+      macroIndex = 0;
+      currentMacroIndexRunning = 0;
+      macroInputsToRun = 0;
+      loopMacro = 0;
+      timesToLoop = 0;
+      loopCounter = 0;
+      howManyInnerLoopsMacroHas = 0;
+      macroMetadataIndex = 0;
+      isInnerLoop = 0;
+      isInputting = true;
+      isInputtingDelayed = false;
+      previousInputDelay = millis();
+    }
+    if ((serial_rx_buffer[0] >= startingMacroIndex) && (serial_rx_buffer[11] >= startingMacroIndex)) {
+      if ((serial_rx_buffer[0] < endingMacroIndex) && (serial_rx_buffer[11] < endingMacroIndex)) {
+        if (serial_rx_buffer[0] == serial_rx_buffer[11]) {
+          // Stop the current loop when we receive a new macro
+          macroIndex = 0;
+          currentMacroIndexRunning = 0;
+          macroInputsToRun = 0;
+          loopMacro = 0;
+          timesToLoop = 0;
+          loopCounter = 0;
+          howManyInnerLoopsMacroHas = 0;
+          macroMetadataIndex = 0;
+          isInnerLoop = 0;
+          //isInputting = false;
+          isInputtingDelayed = false;
+          macroIndex = serial_rx_buffer[0] - startingMacroIndex;
+          for (uint8_t macroInputIndex = 0; macroInputIndex < sizeof(serial_rx_buffer); macroInputIndex++) {
+            macro_buffer[macroIndex][macroInputIndex] = serial_rx_buffer[macroInputIndex];
+          }
+        }
+      }
+    }
+    if ((serial_rx_buffer[0] == endingMacroIndex) && (serial_rx_buffer[11] == endingMacroIndex)) {
+      // Stop the current loop when we receive a new macro setter (The thing that tells how a macro should be executed, if it should loop, how many inputs it has to iterate through)
+      macroIndex = 0;
+      currentMacroIndexRunning = 0;
+      macroInputsToRun = 0;
+      loopMacro = 0;
+      timesToLoop = 0;
+      loopCounter = 0;
+      howManyInnerLoopsMacroHas = 0;
+      macroMetadataIndex = 0;
+      isInnerLoop = 0;
+      isInputtingDelayed = false;
+      isInputting = false;
+      macroInputsToRun = serial_rx_buffer[1];
+      loopMacro = serial_rx_buffer[2];
+      currentMacroIndexRunning = serial_rx_buffer[3];
+      timesToLoop = serial_rx_buffer[4];  // Times to repeat, if <=0, it'll not repeat, if >0, it'll repeat n times, so in this case, gramatically speaking, timesToLoop and times to repeat are different things (does this make sense?), so the max amount of times it can loop is 256, the amount of times it can repeat is 255, the first iteration is not a repetition (Repeat input? Repeated input?) (Again, does this makes sense?)
+      loopCounter = serial_rx_buffer[5];
+      howManyInnerLoopsMacroHas = serial_rx_buffer[6];  // >0 if there are, <=0 if there aren't
+      macroMetadataIndex = serial_rx_buffer[7];
+      isInnerLoop = serial_rx_buffer[8];
+      if (howManyInnerLoopsMacroHas > 0) {
+        macroMetadataIndex = 0;
+        // Check if the first inner loop metadata is valid, if it is, use that, if not, disregard and don't do anything (how many inputs that shout be executed, and how many times the inner block should be repeated)
+        if (inner_loop_metadata[0][1] > 0 && inner_loop_metadata[0][3] > 0) {
+          if (inner_loop_metadata[0][6] < inner_loop_metadata[0][7]) {
+            // Accept inner loop metadata if first inner loop metadata is valid
+            macroMetadataIndex = 0;
+            for (uint8_t macroMetadataIndexInner = 0; macroMetadataIndexInner < howManyInnerLoopsMacroHas; macroMetadataIndexInner++) {
+              inner_loop_metadata[macroMetadataIndexInner][2] = 0;  // Reset current input index for inner loop
+              inner_loop_metadata[macroMetadataIndexInner][4] = 0;  // Reset current repeat counter for inner loop
+            }
+          }
+        }
+        if (inner_loop_metadata[0][6] >= inner_loop_metadata[0][7]) {
+          // Clear all inner loop metadata if first inner loop metadata is invalid
+          macroMetadataIndex = 0;
+          howManyInnerLoopsMacroHas = 0;
+          for (uint8_t macroMetadataIndexInner = 0; macroMetadataIndexInner < macroMetadataSize; macroMetadataIndexInner++) {
+            for (uint8_t innerLoopMetadataIndex = 0; innerLoopMetadataIndex < sizeof(inner_loop_metadata[0]); innerLoopMetadataIndex++) {
+              inner_loop_metadata[macroMetadataIndexInner][innerLoopMetadataIndex] = 0;
+            }
+          }
+          isInnerLoop = 0;
+        }
+        if (inner_loop_metadata[0][1] <= 0 || inner_loop_metadata[0][3] <= 0) {
+          // Clear all inner loop metadata if first inner loop metadata is invalid
+          macroMetadataIndex = 0;
+          howManyInnerLoopsMacroHas = 0;
+          for (uint8_t macroMetadataIndexInner = 0; macroMetadataIndexInner < macroMetadataSize; macroMetadataIndexInner++) {
+            for (uint8_t innerLoopMetadataIndex = 0; innerLoopMetadataIndex < sizeof(inner_loop_metadata[0]); innerLoopMetadataIndex++) {
+              inner_loop_metadata[macroMetadataIndexInner][innerLoopMetadataIndex] = 0;
+            }
+          }
+          isInnerLoop = 0;
+        }
+        if (howManyInnerLoopsMacroHas > 0) {
+          // If we entered this block, that means we still have to test the other inner loops
+          unsigned int howManyInnerLoopsMacroHasInternalTesting = 0;
+          bool countValidInnerLoops = true;
+          //unsigned int whereDoesTheNextInnerLoopStart = 0; // Not used yet (should definitely be used (Now that I think about it, it's completely optional) )
+          unsigned int whereDoesTheCurrentInnerLoopStart = 0;  // Used
+          //unsigned int whereDoesTheCurrentInnerLoopEnd = 0; // Not used yet (can be used, but not really necessary?)
+          unsigned int howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop = 0;  // Used (should definitely be used (Now that I think about it, it's completely optional) )
+
+          unsigned int whereDoesTheNextPreviousInnerLoopStart = 0;  // Used (should definitely be used (Now that I think about it, it's completely optional) ) // Confusing name is confusing
+          //unsigned int whereDoesThePreviousInnerLoopStart = 0; // Not used yet (can be used, but not really necessary?)
+          unsigned int whereDoesThePreviousInnerLoopEnd = 0;  // Used
+          //unsigned int howManyInnerLoopsShouldBeExecutedAfterThePreviousInnerLoop = 0; // Not used yet (should definitely be used (Now that I think about it, it's completely optional) )
+          for (uint8_t macroMetadataIndexInner = 0; macroMetadataIndexInner < howManyInnerLoopsMacroHas; macroMetadataIndexInner++) {
+            if (inner_loop_metadata[macroMetadataIndexInner][1] > 0 && inner_loop_metadata[macroMetadataIndexInner][3] > 0) {
+              if (inner_loop_metadata[macroMetadataIndexInner][6] < inner_loop_metadata[macroMetadataIndexInner][7]) {
+                // Valid
+                //whereDoesTheNextInnerLoopStart = inner_loop_metadata[macroMetadataIndexInner][5];
+                whereDoesTheCurrentInnerLoopStart = inner_loop_metadata[macroMetadataIndexInner][6];
+                //whereDoesTheCurrentInnerLoopEnd = inner_loop_metadata[macroMetadataIndexInner][7];
+                howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop = inner_loop_metadata[macroMetadataIndexInner][8];
+                if (countValidInnerLoops == false) {
+                }
+                if (countValidInnerLoops == true) {
+                  if (macroMetadataIndexInner <= 0) {
+                    if (whereDoesThePreviousInnerLoopEnd <= 0) {
+                      if (howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop > 0) {
+                        // Very simple logic, less maths to apply and will likely work fine, if there are more than 0 inner loops left, then we count the inner loop
+                        howManyInnerLoopsMacroHasInternalTesting++;  // Increment the counter but don't end yet
+                      }
+                      if (howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop <= 0) {
+                        // Very simple logic, less maths to apply and will likely work fine, if there are 0 or less than 0 inner loops left, then end here
+                        howManyInnerLoopsMacroHasInternalTesting++;  // But this one has to count too
+                        countValidInnerLoops = false;                // Then stop counting right after
+                      }
+                      // It's safe to ignore this
+                      //howManyInnerLoopsMacroHasInternalTesting++;  // Do not increment this counter here?
+                      /*
+                      if (whereDoesTheNextPreviousInnerLoopStart == whereDoesTheCurrentInnerLoopStart) {
+                        // This is correct, but should also be ignored
+                        countValidInnerLoops = false;
+                      }
+                      */
+                      /*
+                      if (whereDoesTheNextPreviousInnerLoopStart != whereDoesTheCurrentInnerLoopStart) {
+                        // This should be ignored tho
+                        howManyInnerLoopsMacroHasInternalTesting++;
+                      }
+                      */
+                    }
+                    if (whereDoesThePreviousInnerLoopEnd > 0) {
+                      // This is definitely invalid (should never happen, and will probably never happen)
+                      countValidInnerLoops = false;
+                    }
+                    // Something happens here but only if it's the first inner loop metadata
+                  }
+                  if (macroMetadataIndexInner > 0) {
+                    if (whereDoesThePreviousInnerLoopEnd <= 0) {
+                      // This is definitely invalid (or it ends here (?) )
+                      countValidInnerLoops = false;
+                    }
+                    if (whereDoesThePreviousInnerLoopEnd > 0) {
+                      // Might be valid (?)
+                      if (whereDoesThePreviousInnerLoopEnd <= whereDoesTheCurrentInnerLoopStart) {
+                        if (whereDoesTheNextPreviousInnerLoopStart == whereDoesTheCurrentInnerLoopStart) {
+                          if (howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop > 0) {
+                            // Very simple logic, less maths to apply and will likely work fine, if there are more than 0 inner loops left, then we count the inner loop
+                            howManyInnerLoopsMacroHasInternalTesting++;  // Increment the counter but don't end yet
+                          }
+                          if (howManyInnerLoopsShouldBeExecutedAfterTheCurrentInnerLoop <= 0) {
+                            // Very simple logic, less maths to apply and will likely work fine, if there are 0 or less than 0 inner loops left, then end here
+                            howManyInnerLoopsMacroHasInternalTesting++;  // But this one has to count too
+                            countValidInnerLoops = false;                // Then stop counting right after
+                          }
+                        }
+                        if (whereDoesTheNextPreviousInnerLoopStart != whereDoesTheCurrentInnerLoopStart) {
+                          countValidInnerLoops = false;
+                        }
+                      }
+                      if (whereDoesThePreviousInnerLoopEnd > whereDoesTheCurrentInnerLoopStart) {
+                        countValidInnerLoops = false;
+                      }
+                    }
+                    // Something else happens here
+                  }
+                }
+                if (countValidInnerLoops == false) {
+                }
+                whereDoesTheNextPreviousInnerLoopStart = inner_loop_metadata[macroMetadataIndexInner][5];
+                //whereDoesThePreviousInnerLoopStart = inner_loop_metadata[macroMetadataIndexInner][6];
+                whereDoesThePreviousInnerLoopEnd = inner_loop_metadata[macroMetadataIndexInner][7];
+                //howManyInnerLoopsShouldBeExecutedAfterThePreviousInnerLoop = inner_loop_metadata[macroMetadataIndexInner][8];
+              }
+              if (inner_loop_metadata[macroMetadataIndexInner][6] >= inner_loop_metadata[macroMetadataIndexInner][7]) {
+                // Invalid
+                countValidInnerLoops = false;
+              }
+            }
+            if (inner_loop_metadata[macroMetadataIndexInner][1] <= 0 && inner_loop_metadata[macroMetadataIndexInner][3] <= 0) {
+              if (inner_loop_metadata[macroMetadataIndexInner][6] < inner_loop_metadata[macroMetadataIndexInner][7]) {
+                // Invalid
+                countValidInnerLoops = false;
+              }
+              if (inner_loop_metadata[macroMetadataIndexInner][6] >= inner_loop_metadata[macroMetadataIndexInner][7]) {
+                // Invalid
+                countValidInnerLoops = false;
+              }
+            }
+            //inner_loop_metadata[macroMetadataIndexInner][2] = 0;  // Reset current input index for inner loop
+            //inner_loop_metadata[macroMetadataIndexInner][4] = 0;  // Reset current repeat counter for inner loop
+          }
+          howManyInnerLoopsMacroHas = howManyInnerLoopsMacroHasInternalTesting;
+        }
+        if (howManyInnerLoopsMacroHas <= 0) {
+          // No further testing needed
+          isInnerLoop = 0;
+        }
+      }
+      if (howManyInnerLoopsMacroHas <= 0) {
+        isInnerLoop = 0;
+      }
+    }
+    if ((serial_rx_buffer[0] >= startingMacroMetadataIndex) && (serial_rx_buffer[11] >= startingMacroMetadataIndex)) {
+      if ((serial_rx_buffer[0] < endingMacroMetadataIndex) && (serial_rx_buffer[11] < endingMacroMetadataIndex)) {
+        if (serial_rx_buffer[0] == serial_rx_buffer[11]) {
+          // Stop the current loop when we receive a new macro inner loop metadata
+          macroIndex = 0;
+          currentMacroIndexRunning = 0;
+          macroInputsToRun = 0;
+          loopMacro = 0;
+          timesToLoop = 0;
+          loopCounter = 0;
+          howManyInnerLoopsMacroHas = 0;
+          macroMetadataIndex = 0;
+          isInnerLoop = 0;
+          //isInputting = false;
+          isInputtingDelayed = false;
+          macroMetadataIndex = serial_rx_buffer[0] - startingMacroMetadataIndex;
+          /*
+            inner_loop_metadata[macroMetadataIndex][0] = 0; // Preamble
+            inner_loop_metadata[macroMetadataIndex][1] = 0; // Inputs to execute (number of inputs that should be executed in this inner loop)
+            inner_loop_metadata[macroMetadataIndex][2] = 0; // Current input index
+            inner_loop_metadata[macroMetadataIndex][3] = 0; // Times to repeat (number of times this inner loop should be executed, before going to the next inner loop, if any)
+            inner_loop_metadata[macroMetadataIndex][4] = 0; // Repeat counter (number of times this inner loop was executed)
+            inner_loop_metadata[macroMetadataIndex][5] = 0; // Where is the next inner loop's first input (index 0 input for the next inner loop, aka the index for the input in the macro_buffer array) (Continue normally if value is 0, or do nothing if there are no more inputs to be executed) // Current unused, apply logic to this // Is this really needed? (maybe as a failsafe?) (I will not use this variable for anything because I'm scared it'll break things during an actual run)
+            inner_loop_metadata[macroMetadataIndex][6] = 0; // Where to start (index of the starting input) (Inclusive)
+            inner_loop_metadata[macroMetadataIndex][7] = 0; // Where to end (index of the ending input) (Inclusive)
+            inner_loop_metadata[macroMetadataIndex][8] = 0; // How many inner loops that should be executed after this (if <=0, don't execute inner loops any inner loops after this, and move on as normal, if there are normal inputs to be exeucuted, execute those, if there's nothing else to do, go back to the beginning of the larger loop, if > 0, execute n inner loops after this) // Currently unused, apply logic to this // Is this really needed? (maybe as a failsafe?) (I will not use this variable for anything because I'm scared it'll break things during an actual run)
+            inner_loop_metadata[macroMetadataIndex][9] = 0; // Unused?
+            inner_loop_metadata[macroMetadataIndex][10] = 0; // Unused?
+            inner_loop_metadata[macroMetadataIndex][11] = 0; // Postamble
+          */
+          for (uint8_t macroInputMetadataIndex = 0; macroInputMetadataIndex < sizeof(serial_rx_buffer); macroInputMetadataIndex++) {
+            inner_loop_metadata[macroMetadataIndex][macroInputMetadataIndex] = serial_rx_buffer[macroInputMetadataIndex];
+          }
+        }
+      }
+    }
+  }
+  runMacro();
+  pressButtons();
+}  // Close Loop Function
+
+void runMacro() {
+  if (isInputting == false) {
+    if (macroInputsToRun > 0) {
+      if (macroInputsToRun > currentMacroIndexRunning) {
+        if (loopCounter <= timesToLoop) {
+          for (uint8_t currentInputIndex = 0; currentInputIndex < sizeof(serial_rx_buffer); currentInputIndex++) {
+            current_macro_input[currentInputIndex] = macro_buffer[currentMacroIndexRunning][currentInputIndex];
+          }
+          // Make the button presses actually work
+          isInputting = true;
+          previousInputDelay = millis();
+        }
+      }
+      if (currentMacroIndexRunning < macroInputsToRun) {
+        if (howManyInnerLoopsMacroHas <= 0) {
+          isInnerLoop = 0;
+          currentMacroIndexRunning++;
+        }
+        if (howManyInnerLoopsMacroHas > 0 && howManyInnerLoopsMacroHas <= macroMetadataIndex) {
+          isInnerLoop = 0;
+          currentMacroIndexRunning++;
+        }
+        if (howManyInnerLoopsMacroHas > 0 && howManyInnerLoopsMacroHas > macroMetadataIndex) {
+          for (uint8_t innerLoopMetadataIndex = 0; innerLoopMetadataIndex < sizeof(inner_loop_metadata[macroMetadataIndex]); innerLoopMetadataIndex++) {
+            Serial.write(inner_loop_metadata[macroMetadataIndex][innerLoopMetadataIndex]);
+          }
+          bool incrementCurrentMacroIndexRunningAgain = true;
+          if (currentMacroIndexRunning < inner_loop_metadata[macroMetadataIndex][6] || currentMacroIndexRunning > inner_loop_metadata[macroMetadataIndex][7]) {
+            isInnerLoop = 0;
+            // Increment normally until it enters an inner loop
+            if (incrementCurrentMacroIndexRunningAgain == true) {
+              currentMacroIndexRunning++;
+              inner_loop_metadata[macroMetadataIndex][2] = currentMacroIndexRunning;
+              incrementCurrentMacroIndexRunningAgain = false;
+            }
+            if (currentMacroIndexRunning == inner_loop_metadata[macroMetadataIndex][6] && currentMacroIndexRunning <= inner_loop_metadata[macroMetadataIndex][7]) {
+              isInnerLoop = 1;
+            }
+          }
+          if (currentMacroIndexRunning >= inner_loop_metadata[macroMetadataIndex][6] && currentMacroIndexRunning <= inner_loop_metadata[macroMetadataIndex][7]) {
+            if (currentMacroIndexRunning >= inner_loop_metadata[macroMetadataIndex][7]) {
+              isInnerLoop = 1;
+              if (incrementCurrentMacroIndexRunningAgain == true) {
+                //currentMacroIndexRunning = inner_loop_metadata[macroMetadataIndex][6]; // Return to the beginning of the inner loop
+                //incrementCurrentMacroIndexRunningAgain = false;
+                if (inner_loop_metadata[macroMetadataIndex][4] < inner_loop_metadata[macroMetadataIndex][3]) {
+                  inner_loop_metadata[macroMetadataIndex][4]++;
+                }
+                if (inner_loop_metadata[macroMetadataIndex][4] < inner_loop_metadata[macroMetadataIndex][3]) {
+                  currentMacroIndexRunning = inner_loop_metadata[macroMetadataIndex][6];  // Return to the beginning of the inner loop
+                  inner_loop_metadata[macroMetadataIndex][2] = currentMacroIndexRunning;
+                  incrementCurrentMacroIndexRunningAgain = false;
+                }
+                if (inner_loop_metadata[macroMetadataIndex][4] >= inner_loop_metadata[macroMetadataIndex][3]) {
+                  inner_loop_metadata[macroMetadataIndex][4] = 0;
+                  macroMetadataIndex++;
+                }
+              }
+            }
+            isInnerLoop = 1;
+            if (incrementCurrentMacroIndexRunningAgain == true) {
+              currentMacroIndexRunning++;
+              inner_loop_metadata[macroMetadataIndex][2] = currentMacroIndexRunning;
+              incrementCurrentMacroIndexRunningAgain = false;
+            }
+          }
+          //currentMacroIndexRunning++;
+          for (uint8_t innerLoopMetadataIndex = 0; innerLoopMetadataIndex < sizeof(inner_loop_metadata[macroMetadataIndex]); innerLoopMetadataIndex++) {
+            Serial.write(inner_loop_metadata[macroMetadataIndex][innerLoopMetadataIndex]);
+          }
+        }
+        if (howManyInnerLoopsMacroHas > 0 && howManyInnerLoopsMacroHas <= macroMetadataIndex) {
+          //isInnerLoop = 0;
+          //currentMacroIndexRunning++;
+        }
+      }
+      if (loopMacro > 0) {
+        if (currentMacroIndexRunning >= macroInputsToRun) {
+          currentMacroIndexRunning = 0;
+          if (howManyInnerLoopsMacroHas <= 0) {
+            //macroMetadataIndex = 0;
+          }
+          if (howManyInnerLoopsMacroHas > 0) {
+            macroMetadataIndex = 0;
+          }
+          if (timesToLoop > 0 && loopCounter <= timesToLoop) {
+            // Sending this block for redundancy sake, will comment this block if something goes wrong (it shouldn't)
+            Serial.write(endingMacroIndex);
+            Serial.write(macroInputsToRun);
+            Serial.write(loopMacro);
+            Serial.write(currentMacroIndexRunning);
+            Serial.write(timesToLoop);
+            Serial.write(loopCounter);
+            Serial.write(howManyInnerLoopsMacroHas);
+            Serial.write(macroMetadataIndex);
+            Serial.write(isInnerLoop);
+            Serial.write(0x00);
+            Serial.write(0x00);
+            Serial.write(endingMacroIndex);
+            loopCounter++;
+            Serial.write(endingMacroIndex);
+            Serial.write(macroInputsToRun);
+            Serial.write(loopMacro);
+            Serial.write(currentMacroIndexRunning);
+            Serial.write(timesToLoop);
+            Serial.write(loopCounter);
+            Serial.write(howManyInnerLoopsMacroHas);
+            Serial.write(macroMetadataIndex);
+            Serial.write(isInnerLoop);
+            Serial.write(0x00);
+            Serial.write(0x00);
+            Serial.write(endingMacroIndex);
+          }
+        }
+      }
+    }
+  }
+}
+
+void pressButtons() {
+  if (isInputtingDelayed == false) {
+    //  Define input delay (If Buffer Array Element 9 and 10 !=0)
+    inputDelay = (uint32_t)current_macro_input[9] << 8 | (uint32_t)current_macro_input[10];
+  }
+  if (isInputting == true) {
+    didInputChange = false;
+    // Send the controller data back so it can be used to display controller information on the overlay
+    for (uint8_t currentByteIndex = 0; currentByteIndex < sizeof(current_macro_input); currentByteIndex++) {
+      if (current_macro_input[currentByteIndex] != old_macro_input[currentByteIndex]) {
+        didInputChange = true;
+      }
+      old_macro_input[currentByteIndex] = current_macro_input[currentByteIndex];
+    }
+    if (didInputChange == true) {
+      if (macroInputsToRun > 0) {
+        // This block is used to tell the backend where in the macro chain the current macro input is
+        Serial.write(endingMacroIndex);
+        Serial.write(macroInputsToRun);
+        Serial.write(loopMacro);
+        Serial.write(currentMacroIndexRunning);
+        Serial.write(timesToLoop);
+        Serial.write(loopCounter);
+        Serial.write(howManyInnerLoopsMacroHas);
+        Serial.write(macroMetadataIndex);
+        Serial.write(isInnerLoop);
+        Serial.write(0x00);
+        Serial.write(0x00);
+        Serial.write(endingMacroIndex);
+      }
+      for (uint8_t currentByteIndex = 0; currentByteIndex < sizeof(current_macro_input); currentByteIndex++) {
+        // Send only data back if it has changed, I don't know how to do this without having two loops
+        Serial.write(current_macro_input[currentByteIndex]);
+      }
+    }
+    Serial.flush();
+    //  Press Button
+
+    //  First 8 buttons, Buffer Array Element 1
+    //  Digital L Trigger, Digital R Trigger, Z, Start, Y, X, B, A
+    inputStatus[buttonLTrigger] = !(current_macro_input[1] & B00000001);
+    inputStatus[buttonRTrigger] = !(current_macro_input[1] & B00000010);
+    inputStatus[buttonZ] = !(current_macro_input[1] & B00000100);
+    inputStatus[buttonStart] = !(current_macro_input[1] & B00001000);
+    inputStatus[buttonY] = !(current_macro_input[1] & B00010000);
+    inputStatus[buttonX] = !(current_macro_input[1] & B00100000);
+    inputStatus[buttonB] = !(current_macro_input[1] & B01000000);
+    inputStatus[buttonA] = !(current_macro_input[1] & B10000000);
+
+    //  Second 8 buttons, Buffer Array Element 2
+    //  Analog L Trigger, Analog R Trigger, Macro (Bootleg), Turbo (Bootleg), DUp, DDown, DRight, DLeft
+    //  Analog R and L Triggers have to be inverted (invert the logic level)
+    inputStatus[axisLTrigger] = (current_macro_input[2] & B00000001);
+    inputStatus[axisRTrigger] = (current_macro_input[2] & B00000010);
+    inputStatus[buttonMacro] = !(current_macro_input[2] & B00000100);
+    inputStatus[buttonTurbo] = !(current_macro_input[2] & B00001000);
+    inputStatus[buttonDUp] = !(current_macro_input[2] & B00010000);
+    inputStatus[buttonDDown] = !(current_macro_input[2] & B00100000);
+    inputStatus[buttonDRight] = !(current_macro_input[2] & B01000000);
+    inputStatus[buttonDLeft] = !(current_macro_input[2] & B10000000);
+
+    //  4 Axis, Buffer Array Elements 3, 4, 5, 6
+    //  X, Y, CX, CY
+
+    //X STICK
+    if (current_macro_input[3] > 127) {
+      // Push X Stick to Right
+      inputStatus[axisXHalf] = HIGH;
+      inputStatus[axisXFull] = HIGH;
+    }
+    if (current_macro_input[3] < 127) {
+      // Push X Stick to Left
+      inputStatus[axisXHalf] = LOW;
+      inputStatus[axisXFull] = LOW;
+    }
+    if (current_macro_input[3] == 127) {
+      // Keep X Stick Centered
+      inputStatus[axisXHalf] = HIGH;
+      inputStatus[axisXFull] = LOW;
+    }
+    //Y STICK
+    if (current_macro_input[4] > 127) {
+      // Push Y Stick to Up
+      inputStatus[axisYHalf] = LOW;
+      inputStatus[axisYFull] = LOW;
+    }
+    if (current_macro_input[4] < 127) {
+      // Push Y Stick to Down
+      inputStatus[axisYHalf] = HIGH;
+      inputStatus[axisYFull] = HIGH;
+    }
+    if (current_macro_input[4] == 127) {
+      // Keep Y Stick Centered
+      inputStatus[axisYHalf] = HIGH;
+      inputStatus[axisYFull] = LOW;
+    }
+    //CX STICK
+    if (current_macro_input[5] > 127) {
+      // Push CX Stick to Right
+      inputStatus[axisCxHalf] = HIGH;
+      inputStatus[axisCxFull] = HIGH;
+    }
+    if (current_macro_input[5] < 127) {
+      // Push CX Stick to Left
+      inputStatus[axisCxHalf] = LOW;
+      inputStatus[axisCxFull] = LOW;
+    }
+    if (current_macro_input[5] == 127) {
+      // Keep CX Stick Centered
+      inputStatus[axisCxHalf] = HIGH;
+      inputStatus[axisCxFull] = LOW;
+    }
+    //CY STICK
+    if (current_macro_input[6] > 127) {
+      // Push CY Stick to Down
+      inputStatus[axisCyHalf] = LOW;
+      inputStatus[axisCyFull] = LOW;
+    }
+    if (current_macro_input[6] < 127) {
+      // Push CY Stick to Up
+      inputStatus[axisCyHalf] = HIGH;
+      inputStatus[axisCyFull] = HIGH;
+    }
+    if (current_macro_input[6] == 127) {
+      // Keep CY Stick Centered
+      inputStatus[axisCyHalf] = HIGH;
+      inputStatus[axisCyFull] = LOW;
+    }
+    //  Mode (Bootleg), Buffer Array Element 7
+    //  All other bits in this Buffer Array Element are unused
+    inputStatus[buttonMode] = !(current_macro_input[7] & B00000001);
+
+    digitalWrite(latchPin, LOW);
+    for (int8_t i = 31; i >= 0; i--) {
+      digitalWrite(clockPin, LOW);
+      digitalWrite(dataPin, inputStatus[i]);
+      digitalWrite(clockPin, HIGH);
+    }
+    digitalWrite(latchPin, HIGH);
+
+    //  Buffer Array Element 8 is unused in this code, but is existing in case changes are needed
+
+    //  Buffer Array Elements 9 and 10 are used to tell the Arduino how long commands are executed, on a delay ranging from 1-65535ms
+    if (inputDelay != 0) {
+      isInputtingDelayed = true;
+      //  The block below executes Soft Delay for holding the buttons down
+      if (isInputtingDelayed == true) {
+        if (millis() - previousInputDelay >= inputDelay) {
+          //  Now we need to stop the Soft Delay
+
+          //  Reset everything
+          serial_rx_buffer[0] = 0x00;
+          serial_rx_buffer[1] = 0x00;
+          serial_rx_buffer[2] = 0x00;
+          serial_rx_buffer[3] = 0x7F;
+          serial_rx_buffer[4] = 0x7F;
+          serial_rx_buffer[5] = 0x7F;
+          serial_rx_buffer[6] = 0x7F;
+          serial_rx_buffer[7] = 0x00;
+          serial_rx_buffer[8] = 0x00;
+          serial_rx_buffer[9] = 0x00;
+          serial_rx_buffer[10] = 0x00;
+          serial_rx_buffer[11] = 0x00;
+
+          current_macro_input[0] = 0x00;
+          current_macro_input[1] = 0x00;
+          current_macro_input[2] = 0x00;
+          current_macro_input[3] = 0x7F;
+          current_macro_input[4] = 0x7F;
+          current_macro_input[5] = 0x7F;
+          current_macro_input[6] = 0x7F;
+          current_macro_input[7] = 0x00;
+          current_macro_input[8] = 0x00;
+          current_macro_input[9] = 0x00;
+          current_macro_input[10] = 0x00;
+          current_macro_input[11] = 0x00;
+
+          didInputChange = false;
+
+          // Send the controller data back so it can be used to display controller information on the overlay
+          for (uint8_t currentByteIndex = 0; currentByteIndex < sizeof(current_macro_input); currentByteIndex++) {
+            if (current_macro_input[currentByteIndex] != old_macro_input[currentByteIndex]) {
+              didInputChange = true;
+            }
+            old_macro_input[currentByteIndex] = current_macro_input[currentByteIndex];
+          }
+          if (didInputChange == true) {
+            if (macroInputsToRun > 0) {
+              // This block is used to tell the backend where in the macro chain the current macro input is
+              Serial.write(endingMacroIndex);
+              Serial.write(macroInputsToRun);
+              Serial.write(loopMacro);
+              Serial.write(currentMacroIndexRunning);
+              Serial.write(timesToLoop);
+              Serial.write(loopCounter);
+              Serial.write(howManyInnerLoopsMacroHas);
+              Serial.write(macroMetadataIndex);
+              Serial.write(isInnerLoop);
+              Serial.write(0x00);
+              Serial.write(0x00);
+              Serial.write(endingMacroIndex);
+            }
+            if (loopMacro <= 0) {
+              if (currentMacroIndexRunning == macroInputsToRun) {
+                for (uint8_t currentByteIndex = 0; currentByteIndex < sizeof(current_macro_input); currentByteIndex++) {
+                  // Send only data back if it has changed, I don't know how to do this without having two loops
+                  Serial.write(current_macro_input[currentByteIndex]);
+                }
+              }
+            }
+            if (loopMacro > 0) {
+              if (loopCounter > timesToLoop) {
+                for (uint8_t currentByteIndex = 0; currentByteIndex < sizeof(current_macro_input); currentByteIndex++) {
+                  // Send only data back if it has changed, I don't know how to do this without having two loops
+                  Serial.write(current_macro_input[currentByteIndex]);
+                }
+              }
+            }
+          }
+          Serial.flush();
+          //  First 8 buttons, Buffer Array Element 1
+          //  Digital L Trigger, Digital R Trigger, Z, Start, Y, X, B, A
+          inputStatus[buttonLTrigger] = !(current_macro_input[1] & B00000001);
+          inputStatus[buttonRTrigger] = !(current_macro_input[1] & B00000010);
+          inputStatus[buttonZ] = !(current_macro_input[1] & B00000100);
+          inputStatus[buttonStart] = !(current_macro_input[1] & B00001000);
+          inputStatus[buttonY] = !(current_macro_input[1] & B00010000);
+          inputStatus[buttonX] = !(current_macro_input[1] & B00100000);
+          inputStatus[buttonB] = !(current_macro_input[1] & B01000000);
+          inputStatus[buttonA] = !(current_macro_input[1] & B10000000);
+
+          //  Second 8 buttons, Buffer Array Element 2
+          //  Analog L Trigger, Analog R Trigger, Macro (Bootleg), Turbo (Bootleg), DUp, DDown, DRight, DLeft
+          //  Analog R and L Triggers have to be inverted (invert the logic level)
+          inputStatus[axisLTrigger] = (current_macro_input[2] & B00000001);
+          inputStatus[axisRTrigger] = (current_macro_input[2] & B00000010);
+          inputStatus[buttonMacro] = !(current_macro_input[2] & B00000100);
+          inputStatus[buttonTurbo] = !(current_macro_input[2] & B00001000);
+          inputStatus[buttonDUp] = !(current_macro_input[2] & B00010000);
+          inputStatus[buttonDDown] = !(current_macro_input[2] & B00100000);
+          inputStatus[buttonDRight] = !(current_macro_input[2] & B01000000);
+          inputStatus[buttonDLeft] = !(current_macro_input[2] & B10000000);
+
+          //  4 Axis, Buffer Array Elements 3, 4, 5, 6
+          //  X, Y, CX, CY
+
+          //X STICK
+          if (current_macro_input[3] > 127) {
+            // Push X Stick to Right
+            inputStatus[axisXHalf] = HIGH;
+            inputStatus[axisXFull] = HIGH;
+          }
+          if (current_macro_input[3] < 127) {
+            // Push X Stick to Left
+            inputStatus[axisXHalf] = LOW;
+            inputStatus[axisXFull] = LOW;
+          }
+          if (current_macro_input[3] == 127) {
+            // Keep X Stick Centered
+            inputStatus[axisXHalf] = HIGH;
+            inputStatus[axisXFull] = LOW;
+          }
+          //Y STICK
+          if (current_macro_input[4] > 127) {
+            // Push Y Stick to Up
+            inputStatus[axisYHalf] = LOW;
+            inputStatus[axisYFull] = LOW;
+          }
+          if (current_macro_input[4] < 127) {
+            // Push Y Stick to Down
+            inputStatus[axisYHalf] = HIGH;
+            inputStatus[axisYFull] = HIGH;
+          }
+          if (current_macro_input[4] == 127) {
+            // Keep Y Stick Centered
+            inputStatus[axisYHalf] = HIGH;
+            inputStatus[axisYFull] = LOW;
+          }
+          //CX STICK
+          if (current_macro_input[5] > 127) {
+            // Push CX Stick to Right
+            inputStatus[axisCxHalf] = HIGH;
+            inputStatus[axisCxFull] = HIGH;
+          }
+          if (current_macro_input[5] < 127) {
+            // Push CX Stick to Left
+            inputStatus[axisCxHalf] = LOW;
+            inputStatus[axisCxFull] = LOW;
+          }
+          if (current_macro_input[5] == 127) {
+            // Keep CX Stick Centered
+            inputStatus[axisCxHalf] = HIGH;
+            inputStatus[axisCxFull] = LOW;
+          }
+          //CY STICK
+          if (current_macro_input[6] > 127) {
+            // Push CY Stick to Down
+            inputStatus[axisCyHalf] = LOW;
+            inputStatus[axisCyFull] = LOW;
+          }
+          if (current_macro_input[6] < 127) {
+            // Push CY Stick to Up
+            inputStatus[axisCyHalf] = HIGH;
+            inputStatus[axisCyFull] = HIGH;
+          }
+          if (current_macro_input[6] == 127) {
+            // Keep CY Stick Centered
+            inputStatus[axisCyHalf] = HIGH;
+            inputStatus[axisCyFull] = LOW;
+          }
+          //  Mode (Bootleg), Buffer Array Element 7
+          //  All other bits in this Buffer Array Element are unused
+          inputStatus[buttonMode] = !(current_macro_input[7] & B00000001);
+          // Sometimes buttons are considered as released by the console between inputs, the pieces of code below will hopefully make it so buttons are only released at the end of the final iteration of a loopable macro, or released at the final input of a non-loopable macro, or released at the end of a basic input
+          if (loopMacro <= 0) {
+            if (currentMacroIndexRunning == macroInputsToRun) {
+              // Reset all variables related to macro to stop the arduino from running useless code
+              macroIndex = 0;
+              macroInputsToRun = 0;
+              loopMacro = 0;
+              currentMacroIndexRunning = 0;
+              timesToLoop = 0;
+              loopCounter = 0;
+              howManyInnerLoopsMacroHas = 0;
+              macroMetadataIndex = 0;
+              isInnerLoop = 0;
+              digitalWrite(latchPin, LOW);
+              for (int8_t i = 31; i >= 0; i--) {
+                digitalWrite(clockPin, LOW);
+                digitalWrite(dataPin, inputStatus[i]);
+                digitalWrite(clockPin, HIGH);
+              }
+              digitalWrite(latchPin, HIGH);
+            }
+          }
+          if (loopMacro > 0) {
+            if (loopCounter > timesToLoop) {
+              // Reset all variables related to macro to stop the arduino from running useless code
+              macroIndex = 0;
+              macroInputsToRun = 0;
+              loopMacro = 0;
+              currentMacroIndexRunning = 0;
+              timesToLoop = 0;
+              loopCounter = 0;
+              howManyInnerLoopsMacroHas = 0;
+              macroMetadataIndex = 0;
+              isInnerLoop = 0;
+              digitalWrite(latchPin, LOW);
+              for (int8_t i = 31; i >= 0; i--) {
+                digitalWrite(clockPin, LOW);
+                digitalWrite(dataPin, inputStatus[i]);
+                digitalWrite(clockPin, HIGH);
+              }
+              digitalWrite(latchPin, HIGH);
+            }
+          }
+          //  Buffer Array Element 8 is unused in this code, but is existing in case changes are needed
+          isInputtingDelayed = false;
+          isInputting = false;
+          previousInputDelay += inputDelay;
+          inputDelay = 0;
+        }
+      }
+    }
+  }
+}


Update to use thermocouple look up.  Remove old Arduino 1.0.5 calls and replace with latest for BLE.

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/FirstBuild/pizzaduino.git/'


ok, we better immediately set the start

ok, we better immediately set the start


Added IRBeacon navigation test. Not tested

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

--- Tests/IRBeacon_navigation_test/IRBeacon_navigation_test.ino
+++ Tests/IRBeacon_navigation_test/IRBeacon_navigation_test.ino
@@ -0,0 +1,63 @@
+#include <Servo.h>
+
+const int IR_BEACON_L_PIN  = A0;
+const int IR_BEACON_R_PIN = A1;
+const int SERVO_L_PIN = 13;
+const int SERVO_R_PIN = 12;
+
+// Constants for servo
+Servo servoRight;
+Servo servoLeft;
+int servoLeftForward = 1550;
+int servoLeftBackward = 1450;
+int servoRightForward = 1450;
+int servoRightBackward = 1550;
+
+const float analogConversionFactor = 5.0 / 1024.0;
+float irBeaconLeftVal, irBeaconRightVal, tmpSum, irBeaconMeanValue;
+float leftSum, rightSum;
+void setup() {
+  Serial.begin(9600);
+  pinMode(IR_BEACON_L_PIN, INPUT);
+  pinMode(IR_BEACON_R_PIN,INPUT);
+  servoLeft.attach(SERVO_L_PIN);
+  servoRight.attach(SERVO_R_PIN);
+
+  leftSum = rightSum = 0;
+}
+
+void loop() {
+  irBeaconLeftVal  = analogRead(IR_BEACON_L_PIN) * analogConversionFactor;
+  irBeaconRightVal = analogRead(IR_BEACON_R_PIN) * analogConversionFactor;
+
+  if(irBeaconLeftVal == 0 && irBeaconRightVal > 0) {
+    leftSum++;
+  } else if(irBeaconRightVal == 0 && irBeaconLeftVal > 0) {
+    rightSum++;
+  } else if(irBeaconRightVal == 0 && irBeaconLeftVal == 0){
+    leftSum = rightSum = 0;
+  }
+
+  if(leftSum < rightSum){
+    turnRight(servoLeft,servoRight);
+  } else if (leftSum > rightSum){
+    turnLeft(servoLeft,servoRight);
+  } else { //leftSum == rightSum
+    moveForward(servoLeft,servoRight);
+  }
+  delay(100);
+}
+
+void turnLeft(Servo servoLeft, Servo servoRight){
+  servoLeft.writeMicroseconds(servoRightBackward);
+  servoRight.writeMicroseconds(servoLeftForward);
+}
+void turnRight(Servo servoLeft, Servo servoRight){
+  servoLeft.writeMicroseconds(servoLeftBackward);
+  servoRight.writeMicroseconds(servoRightForward);
+}
+void moveForward(Servo servoLeft, Servo servoRight){
+  servoLeft.writeMicroseconds(servoLeftForward);
+  servoRight.writeMicroseconds(servoRightForward);
+}
+


sketches: Add vidor-arduino-logo

sketches: Add vidor-arduino-logo

error: pathspec 'Sketches/vidor-arduino-logo/vidor-arduino-logo/vidor-arduino-logo.ino' did not match any file(s) known to git

--- Sketches/vidor-arduino-logo/vidor-arduino-logo/vidor-arduino-logo.ino
+++ Sketches/vidor-arduino-logo/vidor-arduino-logo/vidor-arduino-logo.ino
@@ -0,0 +1,61 @@
+#include "VidorGraphics.h"
+#include "Vidor_GFX.h"
+
+Vidor_GFX  vdgfx;
+
+void setup() {
+  Serial.begin(9600);
+
+  // wait for the serial monitor to open,
+  // if you are powering the board from a USB charger remove the next line
+  while (!Serial);
+
+  // Initialize the FPGA
+  if (!FPGA.begin()) {
+    Serial.println("Initialization failed!");
+    while (1) {}
+  }
+
+  delay(4000);
+}
+
+void loop()
+{
+  int count = 0;
+
+  /**
+  *  Draw an Arduino logo
+  */
+
+  // Fill the screen with a white background
+  vdgfx.fillRect(0,0,640,480,vdgfx.White());
+
+  /**
+  *  The library allows drawing some basic elements to the view, like circles, rectangles, lines
+  */
+
+  vdgfx.fillCircle(225,225,100 ,vdgfx.lightBlue());
+  vdgfx.fillCircle(415,225,100 ,vdgfx.lightBlue());
+  vdgfx.fillCircle(225,225,90 ,vdgfx.White());
+  vdgfx.fillCircle(415,225,90 ,vdgfx.White());
+  vdgfx.fillRect(175,220,100,10 ,vdgfx.lightBlue());
+  vdgfx.fillRect(365,220,100,10 ,vdgfx.lightBlue());
+  vdgfx.fillRect(410,175,10,100 ,vdgfx.lightBlue());
+
+  /**
+  *  To draw a text we can use the classic functions like write() and print()
+  *  Text size, color and position can be changed using the .text subclass
+  */
+  vdgfx.text.setCursor(150,375);
+  vdgfx.text.setAlpha(255);
+  vdgfx.text.setSize(3);
+  vdgfx.text.setColor(vdgfx.lightBlue());
+  vdgfx.println("ARDUINO");
+  vdgfx.text.setCursor(480,145);
+  vdgfx.text.setSize(1);
+  vdgfx.println("TM");
+
+  while (1) {
+    Serial.println(count++);
+  }
+}