From a5c43777be0202cb25f4f36cc0b4184436b40ae3 Mon Sep 17 00:00:00 2001
From: nrs1g15 <nrs1g15@soton.ac.uk>
Date: Fri, 26 Jul 2019 16:16:01 +0100
Subject: [PATCH] Moved unused firmwares to legacy folder

---
 .../sufst-can-sd-xbee/sufst-can-sd-xbee.ino   | 1638 +++++++++++++++++
 .../.idea/codeStyles/Project.xml              |   76 +
 .../.idea/codeStyles/codeStyleConfig.xml      |    5 +
 .../sufst-openlogger/.idea/misc.xml           |    6 +
 .../sufst-openlogger/.idea/modules.xml        |    8 +
 .../.idea/sufst-openlogger.iml                |    8 +
 .../sufst-openlogger/.idea/vcs.xml            |    7 +
 .../sufst-openlogger/.idea/workspace.xml      |  329 ++++
 Legacy-firmware/sufst-openlogger/buffer.cpp   |  135 ++
 Legacy-firmware/sufst-openlogger/buffer.h     |   42 +
 .../sufst-openlogger/openLogger.cpp           |  433 +++++
 Legacy-firmware/sufst-openlogger/openLogger.h |   53 +
 .../sufst-openlogger/sufst-openlogger.ino     |   21 +
 .../.idea/codeStyles/Project.xml              |   60 +
 .../.idea/codeStyles/codeStyleConfig.xml      |    5 +
 .../.idea/misc.xml                            |    6 +
 .../.idea/modules.xml                         |    8 +
 .../.idea/sufst-openlogger_controller.iml     |    8 +
 .../sufst-openlogger_controller/.idea/vcs.xml |    6 +
 .../.idea/workspace.xml                       |  410 +++++
 .../sufst-openlogger_controller/buffer.cpp    |  142 ++
 .../sufst-openlogger_controller/buffer.h      |   48 +
 .../sufst-openlogger_controller/can.cpp       |  321 ++++
 .../sufst-openlogger_controller/can.h         |   69 +
 .../sufst-openlogger_controller/ecuCan.cpp    |  280 +++
 .../sufst-openlogger_controller/ecuCan.h      |   38 +
 .../ecuOpenloggerTags.h                       |   19 +
 .../openLoggerController.cpp                  |  296 +++
 .../openLoggerController.h                    |   49 +
 .../sufst-openlogger_controller.ino           |   64 +
 30 files changed, 4590 insertions(+)
 create mode 100644 Legacy-firmware/sufst-can-sd-xbee/sufst-can-sd-xbee.ino
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/codeStyles/Project.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/codeStyles/codeStyleConfig.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/misc.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/modules.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/sufst-openlogger.iml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/vcs.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/.idea/workspace.xml
 create mode 100644 Legacy-firmware/sufst-openlogger/buffer.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger/buffer.h
 create mode 100644 Legacy-firmware/sufst-openlogger/openLogger.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger/openLogger.h
 create mode 100644 Legacy-firmware/sufst-openlogger/sufst-openlogger.ino
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/Project.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/codeStyleConfig.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/misc.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/modules.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/sufst-openlogger_controller.iml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/vcs.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/.idea/workspace.xml
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/buffer.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/buffer.h
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/can.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/can.h
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/ecuCan.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/ecuCan.h
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/ecuOpenloggerTags.h
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/openLoggerController.cpp
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/openLoggerController.h
 create mode 100644 Legacy-firmware/sufst-openlogger_controller/sufst-openlogger_controller.ino

diff --git a/Legacy-firmware/sufst-can-sd-xbee/sufst-can-sd-xbee.ino b/Legacy-firmware/sufst-can-sd-xbee/sufst-can-sd-xbee.ino
new file mode 100644
index 0000000..0d9a240
--- /dev/null
+++ b/Legacy-firmware/sufst-can-sd-xbee/sufst-can-sd-xbee.ino
@@ -0,0 +1,1638 @@
+// Watchdog 
+#include <avr/wdt.h>
+
+/*                      TABLE OF CONTENTS                     */
+/*                  1. START OF MODULES CONFIG                */
+/*                  2. START OF DEBUG                         */
+/*                  3. COMPILER NOTICES                       */
+/*                  4. SHAFT SPEED                            */
+/*                  5. SD                                     */
+/*                  6. XBee                                   */
+/*                  7. CAN                                    */
+/*                  8. FUNCTION PROTOTYPES                    */
+/*                  9. FUNCTION POINTERS                      */
+/*                  10. SHAFT FUNCTIONS                       */
+/*                  11. ECU FUNCTIONS                         */
+/*                  12. CAN FUNCTIONS                         */
+/*                  13. TIMER FUNCTIONS                       */
+/*                  14. SD FUNCTIONS                          */
+/*                  15. XBee FUNCTIONS                        */
+/*                  16. ARDUINO FUNCTIONS (SETUP AND LOOP)    */
+
+
+/***************** START OF MODULES CONFIG *********************/
+#define SD_ENABLED 1
+
+// TODO: ADD XBEE BUFFERS
+#define XBEE_ENABLED 0
+
+#define SHAFT_SPEED_SENSOR_ENABLED 0
+
+#define EMULATE_ECU 0
+
+#define ECU_ATTACHED_ENABLED 1
+
+#define RPM_LEDS_ENABLED 0
+
+/***************** START OF DEBUG *********************/
+#define DEBUG_CAN_RX 0
+#define DEBUG_CAN_RX_MINIMAL 0
+
+#define DEBUG_CAN_TX 0
+#define DEBUG_CAN_TX_MINIMAL 0
+#define DEBUG_CAN_TX_REQS 0
+
+#define DEBUG_ECU_CAN 0
+#define DEBUG_ECU_CAN_MINIMAL 0
+
+#define DEBUG_SD 0
+#define DEBUG_SD_MINIMAL 1
+#define SD_SERIAL_PRINT_BLOCK_WRITES 1
+
+#define DEBUG_SHAFT_SPEED 0
+/***************** END OF DEBUG ********************/
+
+/***************** START OF COMPLIER NOTICES *********************/
+#if EMULATE_ECU
+#pragma message "Emulate ECU Enabled"
+#endif //EMULATE_ECU
+
+#if ECU_ATTACHED_ENABLED
+#pragma message "ECU Attached Enabled"
+#endif //ECU_ATTACHED_ENABLED
+
+#if DEBUG_CAN_RX
+#pragma message "Can Rx Debug Enabled"
+#endif //DEBUG_CAN_RX
+
+#if DEBUG_CAN_RX_MINIMAL
+#pragma message "Can Rx Minimal Debug Enabled"
+#endif //DEBUG_CAN_RX_MINIMAL
+
+#if DEBUG_CAN_TX
+#pragma message "Can Tx Debug Enabled"
+#endif //DEBUG_CAN_TX
+
+#if DEBUG_CAN_TX_MINIMAL
+#pragma message "Can Tx Minimal Debug Enabled"
+#endif //DEBUG_CAN_TX_MINIMAL
+
+#if DEBUG_CAN_TX_REQS
+#pragma message "Can Tx Requests Debug Enabled"
+#endif //DEBUG_CAN_TX_REQS
+
+#if DEBUG_ECU_CAN
+#pragma message "ECU Debug Enabled"
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+#pragma message "ECU Minimal Debug Enabled"
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+#if DEBUG_SD
+#pragma message "SD Debug Enabled"
+#endif //DEBUG_SD
+
+#if DEBUG_SD_MINIMAL
+#pragma message "SD Minimal Debug Enabled"
+#endif //DEBUG_SD_MINIMAL
+
+#if SD_ENABLED
+#pragma message "SD Enabled"
+#endif //SD_ENABLED
+
+#if XBEE_ENABLED
+#pragma message "Xbee Enabled"
+#endif //XBEE_ENABLED
+
+#if SHAFT_SPEED_SENSOR_ENABLED
+#pragma message "Shaft Speed Sensor Enabled"
+#endif // SHAFT_SPEED_SENSOR_ENABLED
+
+#if DEBUG_SHAFT_SPEED
+#pragma message "Shaft Speed Debug Enabled"
+#endif //DEBUG_SHAFT_SPEED
+
+#if SD_SERIAL_PRINT_BLOCK_WRITES
+#pragma message "SD Serial Printing Block Writes Info Enabled"
+#endif //SD_SERIAL_PRINT_BLOCK_WRITES
+
+#if RPM_LEDS_ENABLED
+#pragma message "RPM LEDs Enabled"
+#endif //RPM_LEDS_ENABLED
+/***************** END OF COMPLIER NOTICES *********************/
+
+/***************** START OF SHAFT SPEED *********************/
+#if SHAFT_SPEED_SENSOR_ENABLED
+
+#define SHAFT_SPEED_SENSOR_PIN A15
+
+#define SHAFT_HARDWARE_TIMER_NR 5
+
+#define SHAFT_SPEED_THRESHOLD_VALUE 2
+
+#define SHAFT_CALC_FREQUENCY_RATE_FREQ 10000
+
+volatile float shaftLastCalcFrequency = 0.0;
+
+#endif //SHAFT_SPEED_SENSOR_ENABLED
+/***************** END OF SHAFT SPEED *********************/
+
+/***************** START OF RPM LEDS **********************/
+#if RPM_LEDS_ENABLED
+#define RPM1_PIN 0
+#define RPM2_PIN 1
+#define RPM3_PIN 2
+#define RPM4_PIN 3
+#define RPM5_PIN 4
+#define UPSHIT_PIN 5 //CHANGED XBEE CTS AND RTS PIN care
+
+#define RED1_THRESHOLD 6000 // below this, time to downshit
+#define RED2_THRESHOLD 8000
+#define GREEN1_THRESHOLD 10000
+#define GREEN2_THRESHOLD 11000
+#define GREEN3_THRESHOLD 12000
+#define UPSHIT_THRESHOLD 13000 //above this, time to upshit
+
+
+uint16_t g_RPM = 0;
+
+#endif // RPM_LEDS_ENABLED
+/***************** END OF RPM LEDS **********************/
+/***************** START OF SD *********************/
+#if SD_ENABLED
+
+#define SD_WRITE_BUFFER_LEN 3
+
+#define SD_WRITE_FREQUENCY 10
+#define SD_HARDWARE_TIMER_NR 4
+
+#define SD_CS_PIN 8
+
+#include <SdFat.h>
+
+typedef struct {
+    uint16_t blockHead;
+    // Writing 512 bytes per write gives fastest performance due to
+    // least overheads.
+    uint8_t block[512];
+} sdBlockTemplate;
+
+static sdBlockTemplate sdWriteBuffer[SD_WRITE_BUFFER_LEN];
+
+uint16_t sdWriteBufferHead = 0;
+uint16_t sdWriteBufferTail = 0;
+
+SdFat sd;
+SdFile file;
+
+uint8_t sdCardStatus = 0;
+
+#if ECU_ATTACHED_ENABLED
+
+#define ECU_SD_START_BYTE 0x8C
+#define ECU_SD_END_BYTE 0xA7
+
+#endif //ECU_ATTACHED_ENABLED
+
+#endif // SD_ENABLED
+
+/***************** END OF SD *********************/
+
+/***************** START OF XBEE *********************/
+#if XBEE_ENABLED
+
+#define XBEE_USE_OWN_TX_BUFFER 1
+
+#define XBEE_CTS_PIN            6
+#define XBEE_RTS_PIN            7
+
+#define XBEE_CAN_NO_REC_PERIOD_BEFORE_TRANSMIT_MS 2
+
+#include "XBee.h"
+
+XBee xbee;
+
+XBeeAddress64 xbeeAddress64(0x0013A200, 0x410AC922);
+Tx64Request xbeeTx64Request(xbeeAddress64, 0, 0);
+
+#endif // XBEE_ENABLED
+
+/***************** END OF XBEE *********************/
+
+/***************** START OF CAN *********************/
+// CAN_INT_PIN MUST BE 2
+#define CAN_INT_PIN 2
+#define CAN_CS_PIN 10
+
+#define CAN_RX_BUFFER_LEN 128
+#define CAN_TX_BUFFER_LEN 64
+
+#define CAN_RESET_DEVICE_ON_TIMEOUT 0
+#define CAN_NO_MSG_TIMEOUT_RESET_MS 10000
+
+#define CAN_TX_RETRY_LIMIT 5
+
+
+#include <mcp_can.h>
+#include <mcp_can_dfs.h>
+
+typedef struct {
+    union {
+        uint16_t id;
+        // if id is 0x2001 then idByte[0] is 0x01 and idByte[1] is 0x20
+        // due to the endianness of the system
+        uint8_t idByte[2];
+    };
+    uint8_t len;
+
+    union {
+        uint8_t data[8];
+        uint16_t data16[4];
+        uint32_t data32[2];
+        float dataFl[2];
+    };
+
+} CanMsgTemplate;
+
+// Can Rx Buffer
+static CanMsgTemplate canRxBuffer[CAN_RX_BUFFER_LEN];
+volatile uint8_t canRxBufferHead = 0;
+volatile uint8_t canRxBufferTail = 0;
+
+// Can Tx Buffer
+static CanMsgTemplate canTxBuffer[CAN_TX_BUFFER_LEN];
+volatile uint8_t canTxBufferHead = 0;
+volatile uint8_t canTxBufferTail = 0;
+
+// Can instance
+MCP_CAN can;
+
+// Keep track of the last time we received a can msg
+volatile unsigned long lastCanMsgRecTimeMs = 0;
+unsigned long currMs = 0;
+
+/***************** END OF CAN *********************/
+
+/***************** START OF FUNCTION PROTOS *********************/
+// ECU
+#if ECU_ATTACHED_ENABLED
+
+static uint8_t ecuCanMsg0x2000(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2001(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2002(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2003(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2004(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2005(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2006(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2007(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2008(CanMsgTemplate *canMsg);
+
+static uint8_t ecuCanMsg0x2009(CanMsgTemplate *canMsg);
+
+#if SD_ENABLED
+
+uint8_t ecuAddToSdWriteRequest(CanMsgTemplate *canMsg);
+
+#endif // SD_ENABLED
+
+#endif // ECU_ATTACHED_ENABLED
+
+// CAN
+uint8_t canSaveMsg();
+
+void canAddTxRequest(uint16_t id, void *data, uint8_t lenBytes);
+
+void canBeginExtInterrupt();
+
+uint8_t canParseRxMsg(CanMsgTemplate *canMsg);
+
+uint8_t canProcessRx();
+
+uint8_t canProcessTx();
+
+void canNoActivityResetDevice();
+
+// TIMERS
+#if SD_ENABLED || EMULATE_ECU || SHAFT_SPEED_SENSOR_ENABLED
+
+void timerBegin(uint16_t freq);
+
+static uint8_t timerSetupTimer3Using256Prescal(uint16_t freq);
+
+static uint8_t timerSetupTimer4Using256Prescal(uint16_t freq);
+
+static uint8_t timerSetupTimer5Using256Prescal(uint16_t freq);
+
+#endif // SD_ENABLED || EMULATE_ECU
+
+// SD
+#if SD_ENABLED
+
+uint8_t sdBegin();
+
+uint8_t sdWriteBufferBlocks();
+
+uint8_t sdAddToWriteBlocks(void *pPayload, uint8_t payloadLen);
+
+uint8_t sdProcessWrite();
+
+#endif // SD_ENABLED
+
+// XBEE
+#if XBEE_ENABLED
+uint8_t canTransmitRxToXbee()
+#endif //XBEE_ENABLED
+
+/***************** END OF FUNCTION PROTOS *********************/
+
+
+/***************** START OF FUNCTIONS PTRS *********************/
+// CAN
+#define CAN_ECU_MSG_0x2000_FUNC ecuCanMsg0x2000
+#define CAN_ECU_MSG_0x2001_FUNC ecuCanMsg0x2001
+#define CAN_ECU_MSG_0x2002_FUNC ecuCanMsg0x2002
+#define CAN_ECU_MSG_0x2003_FUNC ecuCanMsg0x2003
+#define CAN_ECU_MSG_0x2004_FUNC ecuCanMsg0x2004
+#define CAN_ECU_MSG_0x2005_FUNC ecuCanMsg0x2005
+#define CAN_ECU_MSG_0x2006_FUNC ecuCanMsg0x2006
+#define CAN_ECU_MSG_0x2007_FUNC ecuCanMsg0x2007
+#define CAN_ECU_MSG_0x2008_FUNC ecuCanMsg0x2008
+#define CAN_ECU_MSG_0x2009_FUNC ecuCanMsg0x2009
+
+#define CAN_ECU_NUMBER_CAN_IDS  10
+
+// ECU can messages function pointers for calling the corresponding function when that msg is seen.
+// Used in function canParseRxMsg. 
+uint8_t
+(*ecuCanFuncPtrs[CAN_ECU_NUMBER_CAN_IDS])(CanMsgTemplate *) = {CAN_ECU_MSG_0x2000_FUNC, CAN_ECU_MSG_0x2001_FUNC,
+                                                               CAN_ECU_MSG_0x2002_FUNC,
+                                                               CAN_ECU_MSG_0x2003_FUNC,
+                                                               CAN_ECU_MSG_0x2004_FUNC, CAN_ECU_MSG_0x2005_FUNC,
+                                                               CAN_ECU_MSG_0x2006_FUNC,
+                                                               CAN_ECU_MSG_0x2007_FUNC, CAN_ECU_MSG_0x2008_FUNC,
+                                                               CAN_ECU_MSG_0x2009_FUNC};
+
+
+// TIMERS
+#if SD_ENABLED || EMULATE_ECU || SHAFT_SPEED_SENSOR_ENABLED
+
+#define HARDWARE_TIMER_0_BEGIN_FUNC NULL
+#define HARDWARE_TIMER_1_BEGIN_FUNC NULL
+#define HARDWARE_TIMER_2_BEGIN_FUNC NULL
+#define HARDWARE_TIMER_3_BEGIN_FUNC timerSetupTimer3Using256Prescal
+#define HARDWARE_TIMER_4_BEGIN_FUNC timerSetupTimer4Using256Prescal
+#define HARDWARE_TIMER_5_BEGIN_FUNC timerSetupTimer5Using256Prescal
+
+// Array of pointers for calling the corresponding hardware timer setup function from the selected
+// hardtimer number passed to timerBegin
+uint8_t (*timerBeginFuncPtrs[6])(uint16_t)
+= {
+HARDWARE_TIMER_0_BEGIN_FUNC, HARDWARE_TIMER_1_BEGIN_FUNC, HARDWARE_TIMER_2_BEGIN_FUNC,
+HARDWARE_TIMER_3_BEGIN_FUNC, HARDWARE_TIMER_4_BEGIN_FUNC, HARDWARE_TIMER_5_BEGIN_FUNC};
+
+#endif // SD_ENABLED || EMULATE_ECU || SHAFT_SPEED_SENSOR_ENABLED
+/***************** END OF FUNCTIONS PTRS *********************/
+
+/***************** START OF SHAFT FUNCTIONS *********************/
+#if SHAFT_SPEED_SENSOR_ENABLED
+
+static void shaftCheckThreshold() {
+    volatile uint16_t shaftVal = analogRead(SHAFT_SPEED_SENSOR_PIN);
+
+    //Serial.print("SH ");
+    //Serial.println(shaftVal);
+
+    volatile uint8_t shaftThresholdPassed = (shaftVal > SHAFT_SPEED_THRESHOLD_VALUE) ? 1 : 0;
+
+    volatile static uint8_t shaftLastSeenThreshold = 0;
+
+    volatile static unsigned long shaftLastPulseDetectedMs = 0;
+
+    volatile static float shaftPrevCalcFrequencies[4] = {0, 0, 0, 0};
+
+    if (shaftThresholdPassed) {
+        if (!shaftLastSeenThreshold) {
+            unsigned long currMs = millis();
+
+            memcpy(shaftPrevCalcFrequencies, &(shaftPrevCalcFrequencies[1]), 4);
+            memcpy(&(shaftPrevCalcFrequencies[1]), &(shaftPrevCalcFrequencies[2]), 4);
+            memcpy(&(shaftPrevCalcFrequencies[2]), &(shaftPrevCalcFrequencies[3]), 4);
+
+            shaftPrevCalcFrequencies[3] = 1000.0 / (currMs - shaftLastPulseDetectedMs);
+
+            //Serial.print("FREQ ");
+            Serial.println(shaftPrevCalcFrequencies[3]);
+
+            shaftLastCalcFrequency =
+                    (shaftPrevCalcFrequencies[0] + shaftPrevCalcFrequencies[1] + shaftPrevCalcFrequencies[2] +
+                     shaftPrevCalcFrequencies[3]) / 4;
+
+#if DEBUG_SHAFT_SPEED
+            //Serial.print("SHAFT : FREQ CALC ");
+            //Serial.println(shaftLastCalcFrequency);
+#endif // DEBUG_SHAFT_SPEED
+
+            shaftLastPulseDetectedMs = currMs;
+            shaftLastSeenThreshold = 1;
+        }
+    } else {
+        if (shaftLastSeenThreshold) {
+            shaftLastSeenThreshold = 0;
+        }
+    }
+}
+
+#endif // SHAFT_SPEED_SENSOR_ENABLED
+
+/***************** END OF SHAFT FUNCTIONS *********************/
+
+/***************** START OF ECU FUNCTIONS *********************/
+#if SD_ENABLED
+
+uint8_t ecuAddToSdWriteRequest(CanMsgTemplate *canMsg) {
+
+    uint8_t ecuSdStartByte = ECU_SD_START_BYTE;
+
+    uint8_t ecuSdEndByte = ECU_SD_END_BYTE;
+
+    if (sdCardStatus) {
+        uint8_t retVal = sdAddToWriteBlocks(&ecuSdStartByte, 1);
+        retVal = sdAddToWriteBlocks(&(canMsg->idByte[0]), 1);
+        retVal = sdAddToWriteBlocks(&(canMsg->data), 8);
+    }
+
+    return 1;
+}
+
+#endif // SD_ENABLED
+
+static uint8_t ecuCanMsg0x2000(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2000 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2000");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t rpm = canMsg->data16[0];
+#if RPM_LEDS_ENABLED
+    g_RPM = rpm;
+#endif
+
+    uint16_t tpsPerc = canMsg->data16[1];
+    uint16_t waterTempC = canMsg->data16[2];
+    uint16_t airTempC = canMsg->data16[3];
+
+    Serial.println(tpsPerc);
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2001(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2001 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2001");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t mainifoldPresKpa = canMsg->data16[0];
+    uint16_t lambdax1000 = canMsg->data16[1];
+    uint16_t speedKphx10 = canMsg->data16[2];
+    uint16_t oilPressKpa = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2002(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2002 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2002");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t fuelPressKpa = canMsg->data16[0];
+    uint16_t oilTempC = canMsg->data16[1];
+    uint16_t batteryVx10 = canMsg->data16[2];
+    uint16_t fuelComsumLpHrx10 = canMsg->data16[3];
+
+
+    // Serial.println((float)(batteryVx10 / 10.0));
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2003(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2003 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2003");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t currentGear = canMsg->data16[0];
+    uint16_t advanceDegx10 = canMsg->data16[1];
+    uint16_t injectionTimeMsx100 = canMsg->data16[2];
+    uint16_t fuelComsumLp100kMx10 = canMsg->data16[3];
+
+    Serial.println(currentGear);
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2004(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2004 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2004");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t ana1mV = canMsg->data16[0];
+    uint16_t ana2mV = canMsg->data16[1];
+    uint16_t ana3mV = canMsg->data16[2];
+    uint16_t camAdvanceDegx10 = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2005(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2005 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2005");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t camTargDegx10 = canMsg->data16[0];
+    uint16_t camPwmPercx10 = canMsg->data16[1];
+    uint16_t crankErrorsNr = canMsg->data16[2];
+    uint16_t camErrorsNr = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2006(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2006 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2006");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t cam2AdvDegx10 = canMsg->data16[0];
+    uint16_t cam2TargDegx10 = canMsg->data16[1];
+    uint16_t cam2PwmPercx10 = canMsg->data16[2];
+    uint16_t external5VmV = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2007(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2007 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2007");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t injDutyCyclePerc = canMsg->data16[0];
+    uint16_t lambdaPidTargPercx10 = canMsg->data16[1];
+    uint16_t lambdaPidAdjPercx10 = canMsg->data16[2];
+    uint16_t ecuSwitchesBitField = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2008(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2008 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2008");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t rdSpeedKphx10 = canMsg->data16[0];
+    uint16_t rUdSpeedKphx10 = canMsg->data16[1];
+    uint16_t ldSpeedKphx10 = canMsg->data16[2];
+    uint16_t lUdSpeedKphx10 = canMsg->data16[3];
+
+#if SD_ENABLED
+    ecuAddToSdWriteRequest(canMsg);
+#endif // SD_ENABLED
+
+    return 1;
+}
+
+static uint8_t ecuCanMsg0x2009(CanMsgTemplate *canMsg) {
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2009 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2008");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    //uint16_t rightLambdax1000 = canMsg->data16[0];
+
+    return 1;
+}
+
+/***************** END OF ECU FUNCTIONS *********************/
+
+/***************** START OF CAN FUNCTIONS *********************/
+
+uint8_t canSaveMsg() {
+    if (digitalRead(CAN_INT_PIN)) {
+        return 0;
+    }
+
+    union {
+        uint8_t id[4];
+        uint32_t id32;
+    } uid;
+
+    if (can.checkReceive() != CAN_MSGAVAIL) {
+        return 0;
+    }
+
+    CanMsgTemplate *currCanRxBufferSlot = &(canRxBuffer[canRxBufferHead]);
+
+    if (can.readMsgBuf(&(currCanRxBufferSlot->len), currCanRxBufferSlot->data) != CAN_OK) {
+        return 0;
+    }
+
+    uid.id32 = can.getCanId();
+
+    currCanRxBufferSlot->id = (uid.id[1] << 8) | uid.id[0];
+
+    canRxBufferHead = (canRxBufferHead + 1) % CAN_RX_BUFFER_LEN;
+
+#if DEBUG_CAN_RX
+    Serial.print("CAN SV RX: ");
+
+    Serial.print(currCanRxBufferSlot->id, HEX);
+    Serial.print(" : ");
+    for(uint8_t i = 0; i < 7; i++) {
+        Serial.print(currCanRxBufferSlot->data[i]);
+        Serial.print(", ");
+    }
+    Serial.println(currCanRxBufferSlot->data[7]);
+#endif // DEBUG_CAN_RX
+
+#if DEBUG_CAN_RX
+    Serial.print("CAN SV RX: HEAD AT ");
+    Serial.println(canRxBufferHead);
+#endif // DEBUG_CAN_RX
+
+    if (canRxBufferHead == canRxBufferTail) {
+        canRxBufferTail = (canRxBufferTail + 1) % CAN_RX_BUFFER_LEN;
+
+#if DEBUG_CAN_RX || DEBUG_CAN_RX_MINIMAL
+        Serial.println("CAN SV RX: BUFFER FULL");
+#endif // DEBUG_CAN_RX
+
+#if DEBUG_CAN_RX
+        Serial.print("CAN SV RX: TAIL AT ");
+        Serial.println(canRxBufferTail);
+#endif // DEBUG_CAN_RX
+    }
+
+    return 1;
+}
+
+void canAddTxRequest(uint16_t id, void *data, uint8_t lenBytes) {
+    data = (uint8_t *) data;
+
+    CanMsgTemplate *currCanTxBufferSlot = &(canTxBuffer[canTxBufferHead]);
+
+    if (NULL == data) {
+        return;
+    }
+
+    noInterrupts();
+    currCanTxBufferSlot->id = id;
+
+    currCanTxBufferSlot->len = lenBytes;
+
+    memcpy(currCanTxBufferSlot->data, data, lenBytes);
+
+    interrupts();
+
+#if DEBUG_CAN_TX_REQS
+    Serial.print("CAN TX ADD: ");
+    Serial.print(currCanTxBufferSlot->id, HEX);
+    Serial.print(" : ");
+    for(uint8_t i = 0; i < 7; i++) {
+      Serial.print(currCanTxBufferSlot->data[i], HEX);
+      Serial.print(", ");
+    }
+    Serial.println(currCanTxBufferSlot->data[7], HEX);
+#endif // DEBUG_CAN_TX_REQS
+
+    noInterrupts();
+    canTxBufferHead = (canTxBufferHead + 1) % CAN_TX_BUFFER_LEN;
+    interrupts();
+
+    noInterrupts();
+    if (canTxBufferHead == canTxBufferTail) {
+        canTxBufferTail = (canTxBufferTail + 1) % CAN_TX_BUFFER_LEN;
+
+#if DEBUG_CAN_TX || DEBUG_CAN_TX_MINIMAL
+        Serial.println("CAN TX BUFFER FULL");
+#endif // DEBUG_CAN_TX
+    }
+    interrupts();
+
+}
+
+// External interrupt currently only designed to work with atmega 2560
+#if !defined(__AVR_ATmega2560__)
+#error "PLATFORM NOT SUPPORTED CURRENTLY"
+#endif // !defined(atmega2560)
+
+#if CAN_INT_PIN != 2
+#error "CAN_INT_PIN CHANGED FROM 2"
+#endif //CAN_INT_PIN != 2
+
+void canBeginExtInterrupt() {
+    noInterrupts();
+
+    // On the mega 2560 pin 2 is external interrupt 4
+    EIMSK &= ~(1 << INT4);
+
+    EICRB &= ~(1 << ISC41);
+    //EICRB &= ~(1 << ISC40);
+
+    EIMSK |= (1 << INT4);
+
+    interrupts();
+}
+
+ISR(INT4_vect) {
+
+        noInterrupts();
+
+        lastCanMsgRecTimeMs = millis();
+
+        canSaveMsg();
+
+        interrupts();
+}
+
+uint8_t canParseRxMsg(CanMsgTemplate *canMsg) {
+    if ((canMsg->id >= 0x2000) && (canMsg->id <= 0x200A)) {
+        // canMsg->idByte[0] holds the 0x01 in 0x2001 received can msg
+        // We use the sub byte of the can ecu msg to determine the corresonding function
+        // This removes the need for a long if statement giving significant performance boosts
+        return (*ecuCanFuncPtrs[canMsg->idByte[0]])(canMsg);
+    }
+
+
+    return 0;
+}
+
+uint8_t canProcessRx() {
+    uint8_t retVal = 0;
+
+    noInterrupts();
+    canSaveMsg();
+
+    CanMsgTemplate *currCanRxBufferSlot = &(canRxBuffer[canRxBufferTail]);
+    interrupts();
+
+    noInterrupts();
+    while (canRxBufferTail != canRxBufferHead) {
+
+#if DEBUG_CAN_RX
+        Serial.print("CAN RX: ");
+
+        Serial.print(currCanRxBufferSlot->id, HEX);
+        Serial.print(" : ");
+        for(uint8_t i = 0; i < 7; i++) {
+          Serial.print(currCanRxBufferSlot->data[i]);
+          Serial.print(", ");
+        }
+        Serial.println(currCanRxBufferSlot->data[7]);
+#endif // DEBUG_CAN_RX
+
+#if DEBUG_CAN_RX_MINIMAL
+        Serial.print("CAN PRO RX : ");
+        Serial.println(currCanRxBufferSlot->id, HEX);
+#endif // DEBUG_CAN_RX_MINIMAL
+
+        retVal = canParseRxMsg(currCanRxBufferSlot);
+
+        canRxBufferTail = (canRxBufferTail + 1) % CAN_RX_BUFFER_LEN;
+
+#if DEBUG_CAN_RX || DEBUG_CAN_RX_MINIMAL
+        Serial.print("CAN PRO RX: TAIL AT ");
+        Serial.println(canRxBufferTail);
+#endif // DEBUG_CAN_RX || DEBUG_CAN_RX_MINIMAL
+
+        currCanRxBufferSlot = &(canRxBuffer[canRxBufferTail]);
+
+        // This may seem dumb but this allows any pending interrupts to be serviced safely
+        // just before we start another loop. Otherwise if we stay in this loop too long without
+        // servicing any interrupts we might miss one.
+        interrupts();
+        noInterrupts();
+    }
+    interrupts();
+
+    return retVal;
+}
+
+uint8_t canProcessTx() {
+
+    noInterrupts();
+    CanMsgTemplate *currCanTxBufferSlot = &(canTxBuffer[canTxBufferTail]);
+
+    uint8_t retVal = 0;
+
+    while (canTxBufferTail != canTxBufferHead) {
+
+#if DEBUG_CAN_TX
+        Serial.print("CAN TX: ");
+        Serial.print(currCanTxBufferSlot->id, HEX);
+        Serial.print(" : ");
+        for(uint8_t i = 0; i < (currCanTxBufferSlot->len - 1); i++) {
+          Serial.print(currCanTxBufferSlot->data[i]);
+          Serial.print(", ");
+        }
+        Serial.println(currCanTxBufferSlot->data[currCanTxBufferSlot->len - 1]);
+#endif // DEBUG_CAN_TX
+
+#if DEBUG_CAN_TX_MINIMAL
+        Serial.print("CAN TX : ");
+        Serial.println(currCanTxBufferSlot->id, HEX);
+#endif // DEBUG_CAN_TX_MINIMAL
+
+        uint8_t canTxWasSuccessful = 0;
+
+        for (uint8_t i = 0; i < CAN_TX_RETRY_LIMIT; i++) {
+            if (can.sendMsgBuf(currCanTxBufferSlot->id, 1, currCanTxBufferSlot->len,
+                               currCanTxBufferSlot->data, true) == CAN_OK) {
+
+                canTxBufferTail = (canTxBufferTail + 1) % CAN_TX_BUFFER_LEN;
+
+                currCanTxBufferSlot = &(canTxBuffer[canTxBufferTail]);
+
+                canTxWasSuccessful = 1;
+
+                retVal = 1;
+
+                break;
+            } else {
+
+                retVal = 0;
+            }
+        }
+
+        if (!canTxWasSuccessful) {
+
+#if DEBUG_CAN_TX || DEBUG_CAN_TX_MINIMAL
+            Serial.println("CAN TX: TX FAILED");
+#endif // DEBUG_CAN_TX || DEBUG_CAN_TX_MINIMAL
+
+            canTxBufferTail = (canTxBufferTail + 1) % CAN_TX_BUFFER_LEN;
+
+            currCanTxBufferSlot = &(canTxBuffer[canTxBufferTail]);
+        }
+
+        // This may seem dumb but this allows any pending interrupts to be serviced safely
+        // just before we start another loop. Otherwise if we stay in this loop too long without
+        // servicing any interrupts we might miss one.
+        interrupts();
+        noInterrupts();
+    }
+
+    interrupts();
+
+    return retVal;
+}
+
+void canNoActivityResetDevice() {
+    Serial.println("CAN ERROR : RESETTING DEVICE");
+    Serial.flush();
+
+#if SD_ENABLED
+
+    uint8_t payload[10] = {0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};
+
+    sdAddToWriteBlocks(payload, 10);
+
+    sdWriteBufferBlocks();
+
+#endif //SD_ENABLED
+
+    // Enabled watchdog timer to reset device as we will not pat it
+    wdt_enable(WDTO_15MS);
+
+    while (true);
+
+}
+
+/***************** END OF CAN FUNCTIONS *********************/
+
+/***************** START OF TIMER FUNCTIONS *********************/
+#if SD_ENABLED || EMULATE_ECU || SHAFT_SPEED_SENSOR_ENABLED
+
+// Hardware timers currently only designed to work with atmega 2560
+#if !defined(__AVR_ATmega2560__)
+#error "PLATFORM NOT SUPPORTED CURRENTLY"
+#endif // !defined(atmega2560)
+
+/*
+ * FOR REFERENCE:
+ * 
+ * The defines here such as TCCR3A are defined in AVR backend files 
+ * Hence, they are not defined anywhere 
+ * 
+ */
+
+static uint8_t timerSetupTimer3Using256Prescal(uint16_t freq) {
+    if ((freq < 1) || (freq > 62500)) {
+        return 0;
+    }
+    noInterrupts();
+
+    TCCR3A = 0;
+    TCCR3B = 0;
+    TCNT3 = 0;
+
+    // F_CPU is passed to the compilier by arduino so we do not defined it ourselves
+    // but we can access it
+    OCR3A = (uint16_t)(F_CPU / (256 * freq));
+
+    // 256 Prescaler
+    TCCR3B |= (1 << WGM32);
+    TCCR3B |= (1 << CS32);
+
+    // Enable timer
+    TIMSK3 |= (1 << OCIE3A);
+
+    interrupts();
+
+    return 1;
+}
+
+static uint8_t timerSetupTimer4Using256Prescal(uint16_t freq) {
+    if ((freq < 1) || (freq > 62500)) {
+        return 0;
+    }
+
+    noInterrupts();
+
+    TCCR4A = 0;
+    TCCR4B = 0;
+    TCNT4 = 0;
+
+    // F_CPU is passed to the compilier by arduino so we do not defined it ourselves
+    // but we can access it
+    OCR4A = (uint16_t)(F_CPU / (256 * freq));
+
+    // 256 Prescaler
+    TCCR4B |= (1 << WGM42);
+    TCCR4B |= (1 << CS42);
+
+    // Enable timer
+    TIMSK4 |= (1 << OCIE4A);
+
+    interrupts();
+
+    return 1;
+}
+
+static uint8_t timerSetupTimer5Using256Prescal(uint16_t freq) {
+    if ((freq < 1) || (freq > 62500)) {
+        return 0;
+    }
+
+    noInterrupts();
+
+    TCCR5A = 0;
+    TCCR5B = 0;
+    TCNT5 = 0;
+
+    // F_CPU is passed to the compilier by arduino so we do not defined it ourselves
+    // but we can access it
+    OCR5A = (uint16_t)(F_CPU / (256 * freq));
+
+    // 256 Prescaler
+    TCCR5B |= (1 << WGM52);
+    TCCR5B |= (1 << CS52);
+
+    // Enable timer
+    TIMSK5 |= (1 << OCIE5A);
+
+    interrupts();
+
+    return 1;
+}
+
+uint8_t timerBegin(uint16_t freq, uint8_t hwTimerNr) {
+    return (*timerBeginFuncPtrs[hwTimerNr])(freq);
+}
+
+ISR(TIMER3_COMPA_vect) {
+#if EMULATE_ECU
+        uint16_t data[4] = { 0xFFBB, 0xAA88, 0x7799, 0xCCFF };
+
+        canAddTxRequest(0x2000, data, 8);
+        canAddTxRequest(0x2001, data, 8);
+        canAddTxRequest(0x2002, data, 8);
+        canAddTxRequest(0x2003, data, 8);
+        canAddTxRequest(0x2004, data, 8);
+        canAddTxRequest(0x2005, data, 8);
+        canAddTxRequest(0x2006, data, 8);
+
+#endif //EMULATE_ECU
+}
+
+ISR(TIMER4_COMPA_vect) {
+#if RPM_LEDS_ENABLED
+        if (rpmBlueFlashFlag){
+            rpmBlueFlashFlag = ~rpmBlueFlashFlag;
+        }
+
+#endif // RPM_LEDS_ENABLED
+}
+
+ISR(TIMER5_COMPA_vect) {
+#if SHAFT_SPEED_SENSOR_ENABLED
+
+        shaftCheckThreshold();
+
+#endif // SHAFT_SPEED_SENSOR_ENABLED
+}
+
+#endif // SD_ENABLED || EMULATE_ECU || SHAFT_SPEED_SENSOR_ENABLED
+/***************** END OF TIMER FUNCTIONS *********************/
+
+/***************** START OF SD FUNCTIONS *********************/
+#if SD_ENABLED
+
+uint8_t sdBegin() {
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+    Serial.println("SD: STARTING SD SERIAL");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+    noInterrupts();
+
+    if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(10))) {
+        Serial.print("SD: ERROR ");
+        Serial.println(sd.card()->errorCode(), HEX);
+
+        sd.card()->spiStop();
+        interrupts();
+        return 0;
+    }
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+    Serial.println("SD: STARTED SD SERIAL");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+    if (sd.exists("DATA.BIN")) {
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+        Serial.println("SD: FILE EXISTS - REMOVING");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+        if (!sd.remove("DATA.BIN")) {
+            Serial.print("SD: ERROR ");
+            Serial.println(sd.card()->errorCode(), HEX);
+
+            sd.card()->spiStop();
+            interrupts();
+            return 0;
+        }
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+        Serial.println("SD: REMOVED FILE");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+    }
+
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+    Serial.println("SD: OPENING FILE");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+    if (!file.open("DATA.BIN", O_WRITE | O_CREAT)) {
+        Serial.print("SD: ERROR ");
+        Serial.println(sd.card()->errorCode(), HEX);
+
+        sd.card()->spiStop();
+        interrupts();
+        return 0;
+    }
+
+    sd.card()->spiStop();
+    interrupts();
+
+    Serial.println("SD: OPEN FOR WRITES");
+    Serial.println("SD: !!IMPORTANT NOTICE!!");
+    Serial.println("SD: SEND 's' TO STOP WRITES");
+    Serial.println("SD: REMOVING SD WITHOUT STOPPING WRITES WILL CORRUPT DATA LOG FILE!");
+
+    sdCardStatus = 1;
+
+    return 1;
+}
+
+uint8_t sdProcessWrite() {
+
+    if (Serial.available()) {
+
+        char sdReceivedByte = Serial.read();
+
+        if (sdReceivedByte == 's') {
+
+            if (!sdCardStatus) {
+
+                Serial.println("SD: WRITES ALREADY STOPPED");
+                return 0;
+            }
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+            Serial.println("SD: SHUTTING DOWN");
+            Serial.flush();
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+            noInterrupts();
+            sd.card()->spiStart();
+            sd.card()->writeStop();
+
+            if (!file.close()) {
+                Serial.print("SD: ERROR ");
+                Serial.println(sd.card()->errorCode(), HEX);
+                sd.card()->spiStop();
+                interrupts();
+
+                Serial.println("SD: FAILED TO STOP WRITES");
+                Serial.println("SD: TRY 's' AGAIN");
+                return 0;
+            }
+
+            sd.card()->spiStop();
+
+            sdCardStatus = 0;
+
+            interrupts();
+
+            Serial.println("SD: WRITES STOPPED");
+
+        } else if (sdReceivedByte == 'g') {
+
+            if (sdCardStatus) {
+                Serial.println("SD: ALREADY WRITING");
+                return 0;
+            }
+
+            while (!sdBegin()) {
+                Serial.println("SD: BEGIN FAIL");
+                delay(100);
+            }
+
+            sdCardStatus = 1;
+        }
+    } else {
+
+        if (!sdCardStatus) {
+            return 0;
+        }
+
+        noInterrupts();
+        if ((millis() - lastCanMsgRecTimeMs) > 2) {
+            interrupts();
+
+            if (sdWriteBufferTail != sdWriteBufferHead) {
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+                Serial.println("SD: WRITING BLOCK");
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+                sdWriteBufferBlocks();
+            }
+        }
+        interrupts();
+    }
+
+    return 1;
+}
+
+uint8_t sdAddToWriteBlocks(void *pPayload, uint8_t payloadLen) {
+
+#if DEBUG_SD || DEBUG_SD_MINIMAL
+    Serial.print("SD: REQ ");
+    Serial.println(payloadLen);
+
+    Serial.print("SD: BLOCK NR ");
+    Serial.println(sdWriteBufferHead);
+    Serial.flush();
+#endif //DEBUG_SD || DEBUG_SD_MINIMAL
+
+    sdBlockTemplate *sdCurrBlock = &(sdWriteBuffer[sdWriteBufferHead]);
+
+    uint16_t sdBytesLeftInCurrBlock = 512 - sdCurrBlock->blockHead;
+
+#if DEBUG_SD
+    Serial.print("SD: CURRENT BLOCK HEAD ");
+    Serial.println(sdCurrBlock->blockHead);
+
+    Serial.print("SD: BYTES LEFT IN BLOCK ");
+    Serial.println(sdBytesLeftInCurrBlock);
+    Serial.flush();
+#endif //DEBUG_SD
+
+    if ((payloadLen + sdCurrBlock->blockHead) <= 512) {
+        memcpy(&(sdCurrBlock->block[sdCurrBlock->blockHead]), pPayload, payloadLen);
+
+        sdCurrBlock->blockHead = sdCurrBlock->blockHead + payloadLen;
+
+#if DEBUG_SD
+        Serial.print("SD: WROTE TO CURR BLOCK ");
+        Serial.println(payloadLen);
+        Serial.flush();
+#endif //DEBUG_SD
+    } else {
+#if DEBUG_SD
+        Serial.print("SD: WR THIS AND NEXT BLOCK ");
+        Serial.println(payloadLen);
+        Serial.flush();
+#endif //DEBUG_SD
+
+        uint16_t sdBytesToAddThisBlock = sdBytesLeftInCurrBlock;
+        uint16_t sdBytesToAddNextBlock = payloadLen - sdBytesToAddThisBlock;
+
+#if DEBUG_SD
+        Serial.print("SD: WR THIS ");
+        Serial.println(sdBytesLeftInCurrBlock);
+        Serial.print("SD: WR NEXT ");
+        Serial.println(sdBytesToAddNextBlock);
+
+        Serial.flush();
+#endif //DEBUG_SD
+
+        memcpy(&(sdCurrBlock->block[sdCurrBlock->blockHead]), pPayload, sdBytesToAddThisBlock);
+
+        sdWriteBufferHead = (sdWriteBufferHead + 1) % SD_WRITE_BUFFER_LEN;
+
+        sdCurrBlock = &(sdWriteBuffer[sdWriteBufferHead]);
+
+        memcpy(&(sdCurrBlock->block), (uint8_t * )((pPayload + sdBytesToAddThisBlock) - 1), sdBytesToAddNextBlock);
+
+        sdCurrBlock->blockHead = sdBytesToAddNextBlock;
+
+#if DEBUG_SD
+        Serial.print("SD: WROTE TO CURR BLOCK ");
+        Serial.println(sdBytesToAddThisBlock);
+
+        Serial.print("SD: WROTE TO NEXT BLOCK ");
+        Serial.println(sdBytesToAddNextBlock);
+        Serial.flush();
+#endif //DEBUG_SD
+
+    }
+
+    return 1;
+}
+
+uint8_t sdWriteBufferBlocks() {
+
+    sdBlockTemplate *sdCurrBlock = &(sdWriteBuffer[sdWriteBufferTail]);
+
+    static uint8_t sdBlocksBeforeSync = 0;
+
+    static uint32_t sdTotalBlocksWrittenToCard = 0;
+
+    noInterrupts();
+    sd.card()->spiStart();
+
+    if (!(file.write(sdCurrBlock->block, 512))) {
+        return 0;
+    }
+
+    sd.card()->spiStop();
+    noInterrupts();
+
+    if (sdBlocksBeforeSync >= 2) {
+        noInterrupts();
+        sd.card()->spiStart();
+
+        file.flush();
+
+        sd.card()->spiStop();
+        noInterrupts();
+
+        sdBlocksBeforeSync = 0;
+    }
+
+#if SD_SERIAL_PRINT_BLOCK_WRITES
+    Serial.print("SD: BL WR ");
+    Serial.println(sdTotalBlocksWrittenToCard);
+#endif // SD_SERIAL_PRINT_BLOCK_WRITES
+
+    sdBlocksBeforeSync++;
+
+    sdCurrBlock->blockHead = 0;
+
+    sdTotalBlocksWrittenToCard++;
+
+    sdWriteBufferTail = (sdWriteBufferTail + 1) % SD_WRITE_BUFFER_LEN;
+
+
+    return 1;
+}
+
+#endif // SD_ENABLED
+/***************** END OF SD/EMULATE ECU FUNCTIONS *********************/
+
+/***************** START OF XBEE FUNCTIONS *********************/
+#if XBEE_ENABLED
+
+uint8_t canTransmitRxToXbee()
+{
+  if (digitalRead(XBEE_CTS_PIN)) {
+    return 0;
+  }
+
+  noInterrupts();
+  
+  while (canRxBufferTail != canRxBufferHead) {
+    
+    xbeeTx64Request.setPayload(canRxBuffer[canRxBufferTail].data);
+    xbeeTx64Request.setPayloadLength(canRxBuffer[canRxBufferTail].len);
+
+    xbee.send(xbeeTx64Request);
+
+    canRxBufferTail = (canRxBufferTail + 1) % CAN_RX_BUFFER_LEN;
+
+    if (digitalRead(XBEE_CTS_PIN)) {
+      interrupts();
+      return 0;
+    }
+
+    // This may seem dumb but this allows any pending interrupts to be serviced safely
+    // just before we start another loop. Otherwise if we stay in this loop too long without
+    // servicing any interrupts we might miss one.
+    interrupts();
+    noInterrupts();
+    
+  } 
+
+  interrupts();
+
+  return 1;
+}
+
+#endif //XBEE_ENABLED
+/***************** END OF XBEE FUNCTIONS *********************/
+/***************** START OF RPM LED FUNCTIONS *********************/
+
+/***************** END OF RPM LED FUNCTIONS *********************/
+#if RPM_LEDS_ENABLED
+
+void rpmBegin() {
+    pinMode(RPM1_PIN, OUTPUT);
+    pinMode(RPM2_PIN, OUTPUT);
+    pinMode(RPM3_PIN, OUTPUT);
+    pinMode(RPM4_PIN, OUTPUT);
+    pinMode(RPM5_PIN, OUTPUT);
+    timerBegin(4, 4);
+}
+
+void rpmProcessLEDS() {
+    //Use g_RPM to set LED INDICATORS
+    //for testing change rpm to tps for testing :)
+    if (g_RPM > RED1_THRESHOLD) //RED ONE
+    {
+        //TURN ON
+        digitalWrite(RPM1_PIN, 1);
+        //TURN OFF
+        digitalWrite(RPM2_PIN, 0);
+        digitalWrite(RPM3_PIN, 0);
+        digitalWrite(RPM4_PIN, 0);
+        digitalWrite(RPM5_PIN, 0);
+
+
+    } else if (g_RPM > RED2_THRESHOLD) { //RED TWO
+        //TURN ON
+        digitalWrite(RPM1_PIN, 1);
+        digitalWrite(RPM2_PIN, 1);
+        //TURN OFF
+        digitalWrite(RPM3_PIN, 0);
+        digitalWrite(RPM4_PIN, 0);
+        digitalWrite(RPM5_PIN, 0);
+        digitalWrite(UPSHIT_PIN, 0);
+    } else if (g_RPM > GREEN1_THRESHOLD) {
+        //TURN ON
+        digitalWrite(RPM1_PIN, 1);
+        digitalWrite(RPM2_PIN, 1);
+        digitalWrite(RPM3_PIN, 1);
+        //TURN OFF
+        digitalWrite(RPM4_PIN, 0);
+        digitalWrite(RPM5_PIN, 0);
+        digitalWrite(UPSHIT_PIN, 0);
+    } else if (g_RPM > GREEN2_THRESHOLD) {
+        //TURN ON
+        digitalWrite(RPM1_PIN, 1);
+        digitalWrite(RPM2_PIN, 1);
+        digitalWrite(RPM3_PIN, 1);
+        digitalWrite(RPM4_PIN, 1);
+        //TURN OFF
+        digitalWrite(RPM5_PIN, 0);
+        digitalWrite(UPSHIT_PIN, 0);
+
+    } else if (g_RPM > GREEN3_THRESHOLD) {
+        digitalWrite(RPM1_PIN, 1);
+        digitalWrite(RPM2_PIN, 1);
+        digitalWrite(RPM3_PIN, 1);
+        digitalWrite(RPM4_PIN, 1);
+        digitalWrite(RPM5_PIN, 1);
+        digitalWrite(UPSHIT_PIN, 0);
+
+
+    } else if (g_RPM > UPSHIT_THRESHOLD) {
+        if (rpmBlueFlashFlag) {
+            digitalWrite(UPSHIT_PIN, 1);
+        } else
+            digitalWrite(UPSHIT_PIN, 0);
+        digitalWrite(RPM1_PIN, 0);
+        digitalWrite(RPM2_PIN, 0);
+        digitalWrite(RPM3_PIN, 0);
+        digitalWrite(RPM4_PIN, 0);
+        digitalWrite(RPM5_PIN, 0);
+    }
+}
+
+#endif // RPM_LEDS_ENABLED
+
+/***************** START OF ARDUINO FUNCTIONS *********************/
+void setup() {
+    Serial.begin(230400);
+
+    Serial.println("~~~~ BEGIN PROGRAM ~~~~");
+
+    pinMode(CAN_INT_PIN, INPUT_PULLUP);
+
+    can.init_CS(CAN_CS_PIN);
+
+    while (can.begin(CAN_1000KBPS) != CAN_OK) {
+        Serial.println("CAN : INIT FAIL");
+        delay(100);
+    }
+
+//#if SD_ENABLED
+//    while (!sdBegin()) {
+//        Serial.println("SD: BEGIN FAIL");
+//        delay(100);
+//    }
+//#endif //SD_ENABLED
+
+#if SD_ENABLED
+    Serial.println("SD: SEND 'g' TO START WRITES");
+#endif //SD_ENABLED
+
+#if EMULATE_ECU
+    timerBegin(50, 3);
+#endif //EMULATE_CAN
+
+#if SHAFT_SPEED_SENSOR_ENABLED
+    timerBegin(1000, SHAFT_HARDWARE_TIMER_NR);
+#endif // SHAFT_SPEED_SENSOR_ENABLED
+
+#if XBEE_ENABLED
+    xbee.setSerial(Serial);
+
+    pinMode(XBEE_CTS_PIN, INPUT);
+
+    pinMode(XBEE_RTS_PIN, OUTPUT);
+
+    digitalWrite(XBEE_RTS_PIN, LOW);
+#endif //XBEE_ENABLED
+
+    canBeginExtInterrupt();
+
+    // Initial read to get current ms
+    lastCanMsgRecTimeMs = millis();
+
+    wdt_enable(WDTO_1S);
+}
+
+void loop() {
+    // put your main code here, to run repeatedly:
+
+    canProcessRx();
+    canProcessTx();
+
+#if SD_ENABLED
+    sdProcessWrite();
+#endif // SD_ENABLED
+
+    wdt_reset();
+
+}
diff --git a/Legacy-firmware/sufst-openlogger/.idea/codeStyles/Project.xml b/Legacy-firmware/sufst-openlogger/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..a7d5539
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/codeStyles/Project.xml
@@ -0,0 +1,76 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <Objective-C>
+      <option name="INDENT_NAMESPACE_MEMBERS" value="0" />
+      <option name="INDENT_C_STRUCT_MEMBERS" value="2" />
+      <option name="INDENT_CLASS_MEMBERS" value="2" />
+      <option name="INDENT_VISIBILITY_KEYWORDS" value="1" />
+      <option name="INDENT_INSIDE_CODE_BLOCK" value="2" />
+      <option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" />
+      <option name="KEEP_CASE_EXPRESSIONS_IN_ONE_LINE" value="true" />
+      <option name="FUNCTION_NON_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+      <option name="FUNCTION_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+      <option name="FUNCTION_PARAMETERS_WRAP" value="5" />
+      <option name="FUNCTION_CALL_ARGUMENTS_WRAP" value="5" />
+      <option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5" />
+      <option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true" />
+      <option name="CLASS_CONSTRUCTOR_INIT_LIST_WRAP" value="5" />
+      <option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" />
+      <option name="HEADER_GUARD_STYLE_PATTERN" value="${PROJECT_NAME}_${PROJECT_REL_PATH}_${FILE_NAME}_${EXT}_" />
+      <option name="NAMESPACES_NAMING_CONVENTION">
+        <value prefix="" style="SNAKE_CASE" suffix="" />
+      </option>
+      <option name="CLASSES_AND_STRUCTS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="ENUMS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="ENUMERATORS_NAMING_CONVENTION">
+        <value prefix="" style="SCREAMING_SNAKE_CASE" suffix="" />
+      </option>
+      <option name="TYPEDEFS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="UNIONS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="METHODS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="FIELDS_NAMING_CONVENTION">
+        <value prefix="" style="SNAKE_CASE" suffix="_" />
+      </option>
+      <option name="GLOBAL_FUNCTIONS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="GLOBAL_VARIABLES_NAMING_CONVENTION">
+        <value prefix="" style="SNAKE_CASE" suffix="" />
+      </option>
+      <option name="PARAMETERS_NAMING_CONVENTION">
+        <value prefix="" style="SNAKE_CASE" suffix="" />
+      </option>
+      <option name="LOCAL_VARIABLES_NAMING_CONVENTION">
+        <value prefix="" style="SNAKE_CASE" suffix="" />
+      </option>
+    </Objective-C>
+    <codeStyleSettings language="ObjectiveC">
+      <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
+      <option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
+      <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
+      <option name="BLANK_LINES_BEFORE_IMPORTS" value="0" />
+      <option name="BLANK_LINES_AFTER_IMPORTS" value="0" />
+      <option name="BLANK_LINES_AROUND_CLASS" value="0" />
+      <option name="BLANK_LINES_AROUND_METHOD" value="0" />
+      <option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
+      <option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false" />
+      <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
+      <option name="FOR_STATEMENT_WRAP" value="1" />
+      <option name="ASSIGNMENT_WRAP" value="1" />
+      <indentOptions>
+        <option name="INDENT_SIZE" value="2" />
+        <option name="CONTINUATION_INDENT_SIZE" value="4" />
+      </indentOptions>
+    </codeStyleSettings>
+  </code_scheme>
+</component>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/codeStyles/codeStyleConfig.xml b/Legacy-firmware/sufst-openlogger/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..a55e7a1
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
+  </state>
+</component>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/misc.xml b/Legacy-firmware/sufst-openlogger/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/modules.xml b/Legacy-firmware/sufst-openlogger/.idea/modules.xml
new file mode 100644
index 0000000..72d5b8a
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/sufst-openlogger.iml" filepath="$PROJECT_DIR$/.idea/sufst-openlogger.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/sufst-openlogger.iml b/Legacy-firmware/sufst-openlogger/.idea/sufst-openlogger.iml
new file mode 100644
index 0000000..bc2cd87
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/sufst-openlogger.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="CPP_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/vcs.xml b/Legacy-firmware/sufst-openlogger/.idea/vcs.xml
new file mode 100644
index 0000000..64713b8
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/vcs.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/.idea/workspace.xml b/Legacy-firmware/sufst-openlogger/.idea/workspace.xml
new file mode 100644
index 0000000..103382c
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/.idea/workspace.xml
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
+    <generated />
+  </component>
+  <component name="CMakeSettings">
+    <configurations>
+      <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
+    </configurations>
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="81322c4e-6adb-4223-9d00-22249012da89" name="Default Changelist" comment="">
+      <change afterPath="$PROJECT_DIR$/../../sufst-controller/daq.cpp" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/../../sufst-controller/daq.h" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/../../sufst-controller/sd.cpp" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/../../sufst-controller/sd.h" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-can-sd-xbee/sufst-can-sd-xbee.ino" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-controller/dashController.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/../../sufst-controller/dashController.cpp" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-controller/ecuCan.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/../../sufst-controller/ecuCan.cpp" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-controller/ecuOpenloggerTags.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-controller/openLoggerController.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-controller/openLoggerController.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/codeStyles/Project.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/codeStyles/codeStyleConfig.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/misc.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/modules.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/sufst-openlogger.iml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/vcs.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/.idea/workspace.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/buffer.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/buffer.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/openLogger.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/openLogger.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger/sufst-openlogger.ino" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/codeStyles/Project.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/codeStyles/codeStyleConfig.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/misc.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/modules.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/sufst-openlogger_controller.iml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/vcs.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/.idea/workspace.xml" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/buffer.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/buffer.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/can.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/can.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/ecuCan.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/ecuCan.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/ecuOpenloggerTags.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/openLoggerController.cpp" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/openLoggerController.h" beforeDir="false" />
+      <change beforePath="$PROJECT_DIR$/../../sufst-openlogger_controller/sufst-openlogger_controller.ino" beforeDir="false" />
+    </list>
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="ClangdSettings">
+    <option name="formatViaClangd" value="false" />
+  </component>
+  <component name="FavoritesManager">
+    <favorites_list name="sufst-openlogger" />
+  </component>
+  <component name="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/sufst-openlogger.ino">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="238">
+              <caret line="14" column="6" lean-forward="true" selection-start-line="14" selection-start-column="6" selection-end-line="14" selection-end-column="6" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/buffer.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="647">
+              <caret line="128" selection-start-line="128" selection-end-line="128" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/openLogger.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="1170">
+              <caret line="432" column="1" selection-start-line="432" selection-start-column="1" selection-end-line="432" selection-end-column="1" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/openLogger.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="442">
+              <caret line="26" selection-start-line="26" selection-end-line="26" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/buffer.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="527">
+              <caret line="31" column="5" selection-start-line="31" selection-start-column="5" selection-end-line="31" selection-end-column="5" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
+  </component>
+  <component name="FindInProjectRecents">
+    <findStrings>
+      <find>Read</find>
+      <find>Write</find>
+      <find>UartCir</find>
+      <find>1</find>
+      <find>Fast</find>
+      <find>sdUartByte</find>
+      <find>cirBuffer</find>
+      <find>SerialE</find>
+      <find>Begin</find>
+      <find>openloggerWriteBufferBlocks</find>
+      <find>cir</find>
+      <find>fast</find>
+      <find>start</find>
+      <find>begin</find>
+      <find>close</find>
+      <find>SERIAL</find>
+      <find>OPENLOGGER_INFO_WRITES_STARTED</find>
+      <find>OPENLOGGER_UART_STOP_BYTE</find>
+      <find>openloggerInformMaster</find>
+      <find>Serial</find>
+      <find>sdRx</find>
+      <find>uartTxBufferUsedCapacity</find>
+      <find>openloggerBeginSd</find>
+      <find>wdt</find>
+      <find>[</find>
+      <find>bein</find>
+      <find>unitSizeBytes</find>
+      <find>sdB</find>
+      <find>sdBufferUsedBytes</find>
+      <find>write</find>
+    </findStrings>
+    <replaceStrings>
+      <replace>DEBUG_OPENLOGGER</replace>
+      <replace>rxUartByte</replace>
+      <replace>uartStopByte</replace>
+      <replace>sdRxBufferUsedCapacity</replace>
+      <replace>unitSize</replace>
+    </replaceStrings>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/../.." />
+  </component>
+  <component name="IdeDocumentHistory">
+    <option name="CHANGED_PATHS">
+      <list>
+        <option value="$PROJECT_DIR$/circularBuffer.h" />
+        <option value="$PROJECT_DIR$/circularBuffer.cpp" />
+        <option value="$PROJECT_DIR$/sufst-openlogger.ino" />
+        <option value="$PROJECT_DIR$/buffer.h" />
+        <option value="$PROJECT_DIR$/openLogger.h" />
+        <option value="$PROJECT_DIR$/buffer.cpp" />
+        <option value="$PROJECT_DIR$/openLogger.cpp" />
+      </list>
+    </option>
+  </component>
+  <component name="OCFindUsagesOptions" text="true" ivars="false" properties="true" derivedClasses="false" />
+  <component name="ProjectFrameBounds">
+    <option name="x" value="-8" />
+    <option name="width" value="977" />
+    <option name="height" value="1038" />
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="true" />
+  <component name="ProjectView">
+    <navigator proportions="" version="1">
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="Scope" />
+      <pane id="ProjectPane">
+        <subPane>
+          <expand>
+            <path>
+              <item name="sufst-openlogger" type="b2602c69:ProjectViewProjectNode" />
+              <item name="sufst-openlogger" type="462c0819:PsiDirectoryNode" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
+    <property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$/../sufst-openlogger_controller" />
+    <property name="node.js.detected.package.eslint" value="true" />
+    <property name="node.js.detected.package.tslint" value="true" />
+    <property name="node.js.path.for.package.eslint" value="project" />
+    <property name="node.js.path.for.package.tslint" value="project" />
+    <property name="node.js.selected.package.eslint" value="(autodetect)" />
+    <property name="node.js.selected.package.tslint" value="(autodetect)" />
+    <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
+    <property name="nodejs_npm_path_reset_for_default_project" value="true" />
+    <property name="nodejs_package_manager_path" value="npm" />
+    <property name="run.code.analysis.last.selected.profile" value="pProject Default" />
+    <property name="settings.editor.selected.configurable" value="project.propVCSSupport.Mappings" />
+  </component>
+  <component name="RunDashboard">
+    <option name="ruleStates">
+      <list>
+        <RuleState>
+          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
+        </RuleState>
+        <RuleState>
+          <option name="name" value="StatusDashboardGroupingRule" />
+        </RuleState>
+      </list>
+    </option>
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="81322c4e-6adb-4223-9d00-22249012da89" name="Default Changelist" comment="" />
+      <created>1563140776084</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1563140776084</updated>
+      <workItem from="1563140777259" duration="246000" />
+      <workItem from="1563216461708" duration="10620000" />
+      <workItem from="1563385421018" duration="9848000" />
+      <workItem from="1563401015844" duration="2752000" />
+      <workItem from="1563476541945" duration="26985000" />
+      <workItem from="1564136510712" duration="2720000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TimeTrackingManager">
+    <option name="totallyTimeSpent" value="80706000" />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="-6" y="0" width="781" height="830" extended-state="0" />
+    <editor active="true" />
+    <layout>
+      <window_info content_ui="combo" id="Project" order="0" sideWeight="0.49426934" weight="0.40638003" />
+      <window_info id="Structure" order="1" sideWeight="0.5057307" side_tool="true" weight="0.40638003" />
+      <window_info id="Favorites" order="2" side_tool="true" weight="0.32916266" />
+      <window_info anchor="bottom" id="Message" order="0" />
+      <window_info anchor="bottom" id="Find" order="1" />
+      <window_info anchor="bottom" id="Run" order="2" />
+      <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
+      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
+      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
+      <window_info anchor="bottom" id="TODO" order="6" />
+      <window_info anchor="bottom" id="Database Changes" order="7" />
+      <window_info anchor="bottom" id="Version Control" order="8" />
+      <window_info anchor="bottom" id="Terminal" order="9" />
+      <window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
+      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
+      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
+      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
+      <window_info anchor="right" id="Database" order="3" />
+    </layout>
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="1" />
+  </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/circularBuffer.cpp" />
+    <entry file="file://$PROJECT_DIR$/circularBuffer.h" />
+    <entry file="file://$PROJECT_DIR$/buffer.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="647">
+          <caret line="128" selection-start-line="128" selection-end-line="128" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/buffer.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="527">
+          <caret line="31" column="5" selection-start-line="31" selection-start-column="5" selection-end-line="31" selection-end-column="5" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/sufst-openlogger.ino">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="238">
+          <caret line="14" column="6" lean-forward="true" selection-start-line="14" selection-start-column="6" selection-end-line="14" selection-end-column="6" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/openLogger.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="442">
+          <caret line="26" selection-start-line="26" selection-end-line="26" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/openLogger.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="1170">
+          <caret line="432" column="1" selection-start-line="432" selection-start-column="1" selection-end-line="432" selection-end-column="1" />
+        </state>
+      </provider>
+    </entry>
+  </component>
+  <component name="masterDetails">
+    <states>
+      <state key="ScopeChooserConfigurable.UI">
+        <settings>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+    </states>
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/buffer.cpp b/Legacy-firmware/sufst-openlogger/buffer.cpp
new file mode 100644
index 0000000..ad56e02
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/buffer.cpp
@@ -0,0 +1,135 @@
+//
+// Created by Sil on 7/19/2019.
+//
+
+#include "buffer.h"
+
+uint8_t cirBufferBegin(cirBuffer_handle cirBuff, void *data, uint16_t len, uint8_t unitSize)
+{
+
+    if (cirBuff == NULL) {
+        return 0;
+    }
+
+    if (data == NULL) {
+        return 0;
+    }
+
+    cirBuff->head = 0;
+    cirBuff->tail = 0;
+    cirBuff->capacity = len;
+    cirBuff->full = 0;
+    cirBuff->data = (uint8_t *) data;
+    cirBuff->unitSize = unitSize;
+
+    return 1;
+}
+
+uint16_t cirBufferAvailable(cirBuffer_handle cirBuff)
+{
+    if (!cirBuff->full) {
+        if (cirBuff->head >= cirBuff->tail) {
+            return (cirBuff->head - cirBuff->tail);
+        }
+        else {
+            return (cirBuff->capacity + cirBuff->head - cirBuff->tail);
+        }
+    }
+    else {
+        return cirBuff->capacity;
+    }
+}
+
+uint16_t cirBufferAvailableForWrite(cirBuffer_handle cirBuff)
+{
+    return cirBuff->capacity - cirBufferAvailable(cirBuff);
+}
+
+void cirBufferWrite(cirBuffer_handle cirBuff, void *unit)
+{
+
+
+    memcpy(&(cirBuff->data[cirBuff->head * cirBuff->unitSize]), unit, cirBuff->unitSize);
+
+    ++cirBuff->head &= (cirBuff->capacity - 1);
+
+    if (cirBuff->head == cirBuff->tail) {
+        cirBuff->full = 1;
+
+        ++cirBuff->tail &= (cirBuff->capacity - 1);
+    }
+}
+
+void cirBufferWriteBytes(cirBuffer_handle cirBuff, void *src, uint16_t len)
+{
+    uint16_t head = cirBuff->head;
+    uint16_t andOperator = cirBuff->capacity - 1;
+
+    uint16_t remainingBytes = cirBufferAvailableForWrite(cirBuff);
+
+    if ((remainingBytes + len) >= cirBuff->capacity) {
+        cirBuff->full = 1;
+    }
+
+    for (uint16_t i = 0; i < len; i++) {
+        cirBuff->data[head] = ((uint8_t *) src)[i];
+
+        ++head &= andOperator;
+    }
+
+    if (cirBuff->full) {
+        cirBuff->tail = (cirBuff->tail + (len - (cirBuff->capacity - remainingBytes))) & (cirBuff->capacity - 1);
+
+    }
+
+    cirBuff->head = head;
+    cirBuff->full = 0;
+}
+
+uint8_t *cirBufferExternalWrite(cirBuffer_handle cirBuff)
+{
+    uint8_t *head = &(cirBuff->data[cirBuff->head]);
+
+    ++cirBuff->head &= cirBuff->capacity - 1;
+
+    if (cirBuff->head == cirBuff->tail) {
+        cirBuff->full = 1;
+
+        ++cirBuff->tail &= (cirBuff->capacity - 1);
+    }
+
+    return head;
+}
+
+void cirBufferRead(cirBuffer_handle cirBuff, void *loc)
+{
+
+    memcpy(loc, &(cirBuff->data[cirBuff->tail * cirBuff->unitSize]), cirBuff->unitSize);
+
+    ++cirBuff->tail &= (cirBuff->capacity - 1);
+
+    cirBuff->full = 0;
+
+}
+
+void cirBufferReadBytes(cirBuffer_handle cirBuff, void *loc, uint16_t len)
+{
+    uint16_t tail = cirBuff->tail;
+    uint16_t andOperator = cirBuff->capacity - 1;
+
+    for (uint16_t i = 0; i < len; i++) {
+        ((uint8_t *) loc)[i] = cirBuff->data[tail];
+
+        ++tail &= andOperator;
+    }
+
+    cirBuff->tail = tail;
+    cirBuff->full = 0;
+}
+
+void cirBufferReset(cirBuffer_handle cirBuff)
+{
+    cirBuff->head = 0;
+    cirBuff->tail = 0;
+    cirBuff->full = 0;
+}
diff --git a/Legacy-firmware/sufst-openlogger/buffer.h b/Legacy-firmware/sufst-openlogger/buffer.h
new file mode 100644
index 0000000..f05bf2b
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/buffer.h
@@ -0,0 +1,42 @@
+//
+// Created by Sil on 7/19/2019.
+//
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include "Arduino.h"
+
+typedef struct CirBuffer
+{
+    uint16_t head;
+    uint16_t tail;
+    uint8_t full;
+    uint8_t *data;
+    uint16_t capacity;
+    uint8_t unitSize;
+};
+
+typedef CirBuffer *cirBuffer_handle;
+
+/*
+ * THE LEN OF THE BUFFER MUST BE A POWER OF 2
+ */
+
+uint8_t cirBufferBegin(cirBuffer_handle cirBuff, void *data, uint16_t len, uint8_t unitSize);
+
+uint16_t cirBufferAvailable(cirBuffer_handle cirBuff);
+
+uint16_t cirBufferAvailableForWrite(cirBuffer_handle cirBuff);
+
+void cirBufferWrite(cirBuffer_handle cirBuff, void *unit);
+
+uint8_t *cirBufferExternalWrite(cirBuffer_handle cirBuff);
+
+void cirBufferRead(cirBuffer_handle cirBuff, void *loc);
+
+void cirBufferReadBytes(cirBuffer_handle cirBuff, void *loc, uint16_t len);
+
+void cirBufferReset(cirBuffer_handle cirBuff);
+
+#endif //BUFFER_H
diff --git a/Legacy-firmware/sufst-openlogger/openLogger.cpp b/Legacy-firmware/sufst-openlogger/openLogger.cpp
new file mode 100644
index 0000000..a687d6c
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/openLogger.cpp
@@ -0,0 +1,433 @@
+//
+// Created by Sil on 14/07/2019.
+//
+
+#include "openLogger.h"
+
+#include <avr/wdt.h>
+#include <avr/interrupt.h>
+#include "buffer.h"
+
+#include <SdFat.h>
+
+SdFat sd;
+
+SdFile file;
+
+#if DEBUG_OPENLOGGER
+enum
+{
+    uartStartByte = 's',
+    uartStopByte = 'f'
+};
+
+enum
+{
+    uartTypeData = 'd',
+    uartTypeCommand = 'c',
+    uartTypeInfo = 'i'
+};
+
+enum
+{
+    uartCommandStartWrites = 'v',
+    uartCommandStopWrites = 'b'
+};
+
+enum
+{
+    uartInfoAlreadyRunning = '1',
+    uartInfoAlreadyIdle = '2',
+    uartInfoWritesStarted = '3',
+    uartInfoWritesStartError = '4',
+    uartInfoStopped = '5',
+    uartInfoStopError = '6',
+    uartInfoWriteError = '7',
+    uartInfoWritesNotStarted = '8'
+};
+#else
+enum
+{
+    uartStartByte = 's',
+    uartStopByte = 'f'
+};
+
+enum
+{
+    uartTypeData = 0,
+    uartTypeCommand,
+    uartTypeInfo
+};
+
+enum
+{
+    uartCommandStartWrites = 0,
+    uartCommandStopWrites
+};
+
+enum
+{
+    uartInfoAlreadyRunning = 0,
+    uartInfoAlreadyIdle,
+    uartInfoWritesStarted,
+    uartInfoWritesStartError,
+    uartInfoStopped,
+    uartInfoStopError,
+    uartInfoWriteError,
+    uartInfoWritesNotStarted
+};
+#endif // DEBUG_OPENLOGGER
+
+typedef enum
+{
+    idle = 0,
+    starting,
+    running,
+    stopping
+} OpenloggerState;
+
+typedef enum
+{
+    checkingForStart = 0,
+    checkingForType,
+    checkingForLength,
+    receivingData,
+    checkingForCommand
+} UartRxState;
+
+uint8_t openloggerBeginSd();
+
+void uartCheckingForStartByte();
+
+void uartCheckingForType();
+
+void uartCheckingForLength();
+
+void uartReceivingData();
+
+void uartCheckingForCommand();
+
+void openloggerIdle();
+
+void openloggerStarting();
+
+void openloggerRunning();
+
+void openloggerStopping();
+
+void openloggerInformMaster(uint8_t info);
+
+void watchdogBegin500ms();
+
+OpenloggerState openloggerState = idle;
+
+UartRxState uartRxState = checkingForStart;
+
+uint8_t sdBuffer[OPENLOGGER_WRITE_BUFFER_LEN];
+
+CirBuffer sdCirBuffer;
+
+void (*openloggerState_ptrs[4])(void) = {openloggerIdle, openloggerStarting, openloggerRunning, openloggerStopping};
+
+void
+(*uartRxState_ptrs[5])(void) = {uartCheckingForStartByte, uartCheckingForType, uartCheckingForLength, uartReceivingData,
+                                uartCheckingForCommand};
+
+volatile uint8_t uartExpectedDataLength = 0;
+
+uint8_t openloggerLastSeenCommand = 0;
+
+bool ledStatus = false;
+
+void serialEvent()
+{
+
+    wdt_reset();
+
+    uartRxState_ptrs[uartRxState]();
+}
+
+ISR(WDT_vect) {
+    uartRxState = checkingForStart;
+}
+
+void uartCheckingForStartByte()
+{
+
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING START ");
+    Serial.println((char) Serial.peek());
+#endif // DEBUG_OPENLOGGER
+
+    if (Serial.read() == uartStartByte) {
+        uartRxState = checkingForType;
+    }
+}
+
+void uartCheckingForType()
+{
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING FOR TYPE ");
+    Serial.println((char) Serial.peek());
+#endif // DEBUG_OPENLOGGER
+
+    if (Serial.peek() <= uartTypeInfo) {
+        uartRxState = (Serial.read() == uartTypeData) ? checkingForLength : checkingForCommand;
+    }
+}
+
+void uartCheckingForLength()
+{
+    if (openloggerState != running) {
+#if DEBUG_OPENLOGGER
+        Serial.println("OPLOG: NOT running");
+#endif // DEBUG_OPENLOGGER
+
+        openloggerInformMaster(uartInfoWritesNotStarted);
+
+        uartRxState = checkingForStart;
+
+        return;
+    }
+
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING LENGTH ");
+    Serial.println((char) Serial.peek());
+#endif // DEBUG_OPENLOGGER
+
+    if (Serial.peek() <= OPENLOGGER_WRITE_BUFFER_LEN) {
+        uartExpectedDataLength = Serial.read();
+
+        uartRxState = receivingData;
+    }
+    else {
+        uartRxState = checkingForStart;
+    }
+}
+
+void uartReceivingData()
+{
+    for (; uartExpectedDataLength > 0; uartExpectedDataLength--) {
+
+#if DEBUG_OPENLOGGER
+        Serial.print("OPLOG: LEFT ");
+        Serial.println(uartExpectedDataLength);
+#endif // DEBUG_OPENLOGGER
+
+        Serial.readBytes(cirBufferExternalWrite(&sdCirBuffer), 1);
+    }
+
+    uartRxState = checkingForStart;
+}
+
+void uartCheckingForCommand()
+{
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING COMMAND ");
+    Serial.println((char) Serial.peek());
+#endif // DEBUG_OPENLOGGER
+
+    openloggerState = (Serial.read() == uartCommandStartWrites) ? starting : stopping;
+
+    uartRxState = checkingForStart;
+}
+
+void openloggerIdle()
+{
+
+}
+
+void openloggerStarting()
+{
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: starting WRITES");
+#endif // DEBUG_OPENLOGGER
+
+    if (openloggerBeginSd()) {
+
+        if (!ledStatus) {
+            digitalWrite(5, HIGH);
+
+            ledStatus = true;
+        }
+
+        openloggerInformMaster(uartInfoWritesStarted);
+
+        openloggerState = running;
+    }
+    else {
+        openloggerInformMaster(uartInfoWritesStartError);
+
+        openloggerState = idle;
+    }
+}
+
+void openloggerRunning()
+{
+    static uint8_t sdPayload[OPENLOGGER_BYTES_PER_BLOCK_WRITE];
+
+    if (cirBufferAvailable(&sdCirBuffer) >= OPENLOGGER_BYTES_PER_BLOCK_WRITE) {
+
+#if DEBUG_OPENLOGGER
+        Serial.println("OPLOG: WRITING BLOCK");
+#endif // DEBUG_OPENLOGGER
+
+        static uint8_t sdBlocksWritten = 0;
+
+        cirBufferReadBytes(&sdCirBuffer, sdPayload, OPENLOGGER_BYTES_PER_BLOCK_WRITE);
+
+        if (!file.write(sdPayload, OPENLOGGER_BYTES_PER_BLOCK_WRITE)) {
+
+            openloggerInformMaster(uartInfoWriteError);
+
+            openloggerState = stopping;
+        }
+
+        sdBlocksWritten++;
+
+        if (sdBlocksWritten >= OPENLOGGER_BLOCKS_BEFORE_FLUSH) {
+            file.flush();
+
+            sdBlocksWritten = 0;
+        }
+    }
+}
+
+void openloggerStopping()
+{
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: stopping ");
+#endif // DEBUG_OPENLOGGER
+
+    if (file.close()) {
+
+        openloggerInformMaster(uartInfoStopped);
+    }
+    else {
+
+        openloggerInformMaster(uartInfoStopError);
+    }
+
+    openloggerState = idle;
+
+    if (ledStatus) {
+        digitalWrite(5, LOW);
+
+        ledStatus = false;
+    }
+
+}
+
+void openloggerProcess()
+{
+    openloggerState_ptrs[openloggerState]();
+}
+
+uint8_t openloggerBegin()
+{
+
+    Serial.begin(OPENLOGGER_SERIAL_BUAD_RATE);
+
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: BEGIN");
+
+    Serial.setTimeout((uint32_t)(-1));
+#endif // DEBUG_OPENLOGGER
+
+#if !DEBUG_OPENLOGGER
+    watchdogBegin500ms();
+#endif // !DEBUG_OPENLOGGER
+
+    pinMode(5, OUTPUT);
+
+    digitalWrite(5, LOW);
+
+    cirBufferBegin(&sdCirBuffer, sdBuffer, OPENLOGGER_WRITE_BUFFER_LEN, sizeof(uint8_t));
+
+    return 1;
+}
+
+void openloggerInformMaster(uint8_t info)
+{
+    Serial.write(uartStartByte);
+    Serial.write(uartTypeInfo);
+    Serial.write(info);
+    Serial.write(uartStopByte);
+}
+
+void watchdogBegin500ms()
+{
+    cli();
+
+    WDTCSR = (1 << WDCE) | (1 << WDE);
+    WDTCSR = 0;
+
+    WDTCSR = (1 << WDIE) | (1 << WDP2) | (1 << WDP0);
+
+    sei();
+}
+
+uint8_t openloggerBeginSd()
+{
+
+#if DEBUG_OPENLOGGER
+    Serial.println("SD: starting SD SERIAL");
+#endif //DEBUG_OPENLOGGER
+
+    noInterrupts();
+
+    if (!sd.begin(OPENLOGGER_CS_PIN, SD_SCK_MHZ(10))) {
+
+#if DEBUG_OPENLOGGER
+        Serial.print("SD: ERROR ");
+        Serial.println(sd.card()->errorCode(), HEX);
+#endif // DEBUG_OPENLOGGER
+
+        interrupts();
+        return 0;
+    }
+
+#if DEBUG_OPENLOGGER
+    Serial.println("SD: STARTED SD SERIAL");
+#endif //DEBUG_OPENLOGGER
+
+    if (sd.exists("DATA.BIN")) {
+
+#if DEBUG_OPENLOGGER
+        Serial.println("SD: FILE EXISTS - REMOVING");
+#endif //DEBUG_OPENLOGGER
+
+        if (!sd.remove("DATA.BIN")) {
+
+#if DEBUG_OPENLOGGER
+            Serial.print("SD: ERROR ");
+            Serial.println(sd.card()->errorCode(), HEX);
+#endif // DEBUG_OPENLOGGER
+
+            interrupts();
+            return 0;
+        }
+
+#if DEBUG_OPENLOGGER
+        Serial.println("SD: REMOVED FILE");
+#endif //DEBUG_OPENLOGGER
+    }
+
+#if DEBUG_OPENLOGGER
+    Serial.println("SD: OPENING FILE");
+#endif //DEBUG_OPENLOGGER
+
+    if (!file.open("DATA.BIN", O_WRITE | O_CREAT)) {
+#if DEBUG_OPENLOGGER
+        Serial.print("SD: ERROR ");
+        Serial.println(sd.card()->errorCode(), HEX);
+#endif // DEBUG_OPENLOGGER
+
+        interrupts();
+        return 0;
+    }
+
+    interrupts();
+
+    return 1;
+}
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger/openLogger.h b/Legacy-firmware/sufst-openlogger/openLogger.h
new file mode 100644
index 0000000..281500a
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/openLogger.h
@@ -0,0 +1,53 @@
+//
+// Created by Sil on 14/07/2019.
+//
+
+#ifndef SUFST_OPENLOGGER_INO_SDCARD_H
+#define SUFST_OPENLOGGER_INO_SDCARD_H
+
+#include "Arduino.h"
+
+#define DEBUG_OPENLOGGER 0
+
+#if DEBUG_OPENLOGGER
+
+#define OPENLOGGER_SERIAL_BUAD_RATE 115200
+
+#else
+
+#define OPENLOGGER_SERIAL_BUAD_RATE 115200
+
+#endif // DEBUG_OPENLOGGER
+
+#define OPENLOGGER_BYTES_PER_BLOCK_WRITE 128
+#define OPENLOGGER_WRITE_BUFFER_LEN OPENLOGGER_BYTES_PER_BLOCK_WRITE * 4
+#define OPENLOGGER_BLOCKS_BEFORE_FLUSH 4
+
+#define OPENLOGGER_CS_PIN 10
+
+/*
+ *
+ * There are three types of transactions: save this data, do this command or heres some info.
+ *
+ * STRUCTURE OF A VALID SD CARD UART SAVE THIS DATA TRANSACTION
+ *
+ * START BYTE | DATA TYPE | LENGTH BYTE | DATA BYTES | STOP BYTE
+ *
+ * STRUCTURE OF A VALID COMMAND TRANSACTION
+ *
+ * START BYTE | COMMAND TYPE | COMMAND BYTE | STOP BYTE
+ *
+ * STUCTURE OF VALID INFO TRANSACTION
+ *
+ * START BYTE | INFO TYPE | INFO BYTE | STOP BYTE
+ *
+ * If no rx has been received for more than 500ms the rx state is reset to checking for start byte
+ * This ensures the open logger does not get stuck in the middle of a transaction if the master stops sending data
+ *
+ */
+
+void openloggerProcess();
+
+uint8_t openloggerBegin();
+
+#endif //SUFST_OPENLOGGER_INO_SDCARD_H
diff --git a/Legacy-firmware/sufst-openlogger/sufst-openlogger.ino b/Legacy-firmware/sufst-openlogger/sufst-openlogger.ino
new file mode 100644
index 0000000..2cf83c8
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger/sufst-openlogger.ino
@@ -0,0 +1,21 @@
+
+#include "openLogger.h"
+
+void setup()
+{
+    // put your setup code here, to run once:
+
+    openloggerBegin();
+
+}
+
+void loop()
+{
+
+    /*
+     * ALL PROCESSES *MUST* BE NON BLOCKING
+     */
+
+    openloggerProcess();
+
+}
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/Project.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..1be0d30
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/Project.xml
@@ -0,0 +1,60 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <Objective-C>
+      <option name="INDENT_NAMESPACE_MEMBERS" value="0" />
+      <option name="KEEP_STRUCTURES_IN_ONE_LINE" value="true" />
+      <option name="KEEP_CASE_EXPRESSIONS_IN_ONE_LINE" value="true" />
+      <option name="NAMESPACE_BRACE_PLACEMENT" value="2" />
+      <option name="FUNCTION_BRACE_PLACEMENT" value="2" />
+      <option name="BLOCK_BRACE_PLACEMENT" value="2" />
+      <option name="FUNCTION_NON_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+      <option name="FUNCTION_TOP_AFTER_RETURN_TYPE_WRAP" value="0" />
+      <option name="FUNCTION_PARAMETERS_WRAP" value="5" />
+      <option name="FUNCTION_CALL_ARGUMENTS_WRAP" value="5" />
+      <option name="TEMPLATE_CALL_ARGUMENTS_WRAP" value="5" />
+      <option name="TEMPLATE_CALL_ARGUMENTS_ALIGN_MULTILINE" value="true" />
+      <option name="CLASS_CONSTRUCTOR_INIT_LIST_WRAP" value="5" />
+      <option name="CLASS_CONSTRUCTOR_INIT_LIST_NEW_LINE_BEFORE_COLON" value="1" />
+      <option name="ALIGN_INIT_LIST_IN_COLUMNS" value="false" />
+      <option name="SPACE_BEFORE_SUPERCLASS_COLON" value="false" />
+      <option name="HEADER_GUARD_STYLE_PATTERN" value="${FILE_NAME}_${EXT}" />
+      <option name="NAMESPACES_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="CLASSES_AND_STRUCTS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="ENUMS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="TYPEDEFS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+      <option name="UNIONS_NAMING_CONVENTION">
+        <value prefix="" style="PASCAL_CASE" suffix="" />
+      </option>
+    </Objective-C>
+    <codeStyleSettings language="ObjectiveC">
+      <option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
+      <option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
+      <option name="BLANK_LINES_BEFORE_IMPORTS" value="0" />
+      <option name="BLANK_LINES_AFTER_IMPORTS" value="0" />
+      <option name="BLANK_LINES_AROUND_CLASS" value="0" />
+      <option name="BLANK_LINES_AROUND_FIELD" value="1" />
+      <option name="BLANK_LINES_AROUND_METHOD" value="0" />
+      <option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
+      <option name="CLASS_BRACE_STYLE" value="2" />
+      <option name="ELSE_ON_NEW_LINE" value="true" />
+      <option name="WHILE_ON_NEW_LINE" value="true" />
+      <option name="CATCH_ON_NEW_LINE" value="true" />
+      <option name="ALIGN_MULTILINE_BINARY_OPERATION" value="false" />
+      <option name="METHOD_CALL_CHAIN_WRAP" value="1" />
+      <option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
+      <option name="FOR_STATEMENT_WRAP" value="1" />
+      <option name="ASSIGNMENT_WRAP" value="1" />
+      <indentOptions>
+        <option name="CONTINUATION_INDENT_SIZE" value="4" />
+      </indentOptions>
+    </codeStyleSettings>
+  </code_scheme>
+</component>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/codeStyleConfig.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+  </state>
+</component>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/misc.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/misc.xml
new file mode 100644
index 0000000..28a804d
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="JavaScriptSettings">
+    <option name="languageLevel" value="ES6" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/modules.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/modules.xml
new file mode 100644
index 0000000..24eddf4
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/sufst-openlogger_controller.iml" filepath="$PROJECT_DIR$/.idea/sufst-openlogger_controller.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/sufst-openlogger_controller.iml b/Legacy-firmware/sufst-openlogger_controller/.idea/sufst-openlogger_controller.iml
new file mode 100644
index 0000000..bc2cd87
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/sufst-openlogger_controller.iml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="CPP_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/vcs.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/.idea/workspace.xml b/Legacy-firmware/sufst-openlogger_controller/.idea/workspace.xml
new file mode 100644
index 0000000..09347fb
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/.idea/workspace.xml
@@ -0,0 +1,410 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CMakeRunConfigurationManager" shouldGenerate="true" shouldDeleteObsolete="true">
+    <generated />
+  </component>
+  <component name="CMakeSettings">
+    <configurations>
+      <configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
+    </configurations>
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="e173ebdc-c119-4235-9653-364cc21b27a5" name="Default Changelist" comment="">
+      <change afterPath="$PROJECT_DIR$/dashController.cpp" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/dashController.h" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/../sufst-openlogger/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../sufst-openlogger/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/can.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/can.cpp" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/ecuCan.cpp" beforeDir="false" afterPath="$PROJECT_DIR$/ecuCan.cpp" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/sufst-openlogger_controller.ino" beforeDir="false" afterPath="$PROJECT_DIR$/sufst-openlogger_controller.ino" afterDir="false" />
+    </list>
+    <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="ClangdSettings">
+    <option name="formatViaClangd" value="false" />
+  </component>
+  <component name="DatabaseView">
+    <option name="SHOW_INTERMEDIATE" value="true" />
+    <option name="GROUP_DATA_SOURCES" value="true" />
+    <option name="GROUP_SCHEMA" value="true" />
+    <option name="GROUP_CONTENTS" value="false" />
+    <option name="SORT_POSITIONED" value="false" />
+    <option name="SHOW_EMPTY_GROUPS" value="false" />
+    <option name="AUTO_SCROLL_FROM_SOURCE" value="false" />
+    <option name="HIDDEN_KINDS">
+      <set />
+    </option>
+    <expand />
+    <select />
+  </component>
+  <component name="FavoritesManager">
+    <favorites_list name="sufst-openlogger_controller" />
+  </component>
+  <component name="FileEditorManager">
+    <leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/sufst-openlogger_controller.ino">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="391">
+              <caret line="29" lean-forward="true" selection-start-line="29" selection-end-line="29" />
+              <folding>
+                <element signature="e#57#90#0" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/openLoggerController.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="576">
+              <caret line="175" column="87" selection-start-line="175" selection-start-column="87" selection-end-line="175" selection-end-column="87" />
+              <folding>
+                <element signature="e#40#73#0" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/openLoggerController.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="187">
+              <caret line="11" column="37" selection-start-line="11" selection-start-column="37" selection-end-line="11" selection-end-column="37" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/can.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="844">
+              <caret line="52" column="8" selection-start-line="52" selection-start-column="8" selection-end-line="52" selection-end-column="8" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/can.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="170">
+              <caret line="73" column="11" lean-forward="true" selection-start-line="73" selection-start-column="11" selection-end-line="73" selection-end-column="11" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/ecuCan.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="102">
+              <caret line="6" column="30" selection-start-line="6" selection-start-column="30" selection-end-line="6" selection-end-column="30" />
+              <folding>
+                <element signature="e#39#58#0" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/dashController.cpp">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="476">
+              <caret line="28" selection-start-line="28" selection-end-line="28" selection-end-column="28" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/dashController.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="153">
+              <caret line="9" column="18" selection-start-line="9" selection-start-column="5" selection-end-line="9" selection-end-column="18" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+      <file pinned="false" current-in-tab="false">
+        <entry file="file://$PROJECT_DIR$/ecuOpenloggerTags.h">
+          <provider selected="true" editor-type-id="text-editor">
+            <state relative-caret-position="34">
+              <caret line="2" column="2" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="2" />
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
+  </component>
+  <component name="FindInProjectRecents">
+    <findStrings>
+      <find>cir</find>
+      <find>open</find>
+      <find>openloggerStopped</find>
+      <find>CHECKING_FOR_START</find>
+      <find>OPENLOGGER_TYPE_INFO</find>
+      <find>OPENLOGGER_UART_TX_BUFFER_LEN</find>
+      <find>OPEN</find>
+      <find>uartStopbyte</find>
+      <find>openloggerRxCheckingForInfo</find>
+      <find>head</find>
+      <find>uartCurrentlyTransmitting</find>
+      <find>Serial1</find>
+      <find>*(</find>
+      <find>buffer</find>
+      <find>peek</find>
+      <find>openloggerTxDataCirBuffer</find>
+      <find>writes</find>
+      <find>uartTxDataAmount</find>
+      <find>cirBufferAvailable</find>
+      <find>availableForWrite</find>
+      <find>available</find>
+      <find>tail</find>
+      <find>Serial</find>
+      <find>OPENLOGGER_TX_BUFFER_LEN</find>
+      <find>startTag</find>
+      <find>&amp;</find>
+      <find>tx</find>
+      <find>&amp;=</find>
+      <find>openloggerProcess</find>
+      <find>cirBuffer</find>
+    </findStrings>
+    <replaceStrings>
+      <replace>Serial1</replace>
+      <replace>uartTypeInfo</replace>
+      <replace>uartStopByte</replace>
+      <replace>Serial</replace>
+    </replaceStrings>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
+  </component>
+  <component name="IdeDocumentHistory">
+    <option name="CHANGED_PATHS">
+      <list>
+        <option value="$PROJECT_DIR$/circularBuffer.cpp" />
+        <option value="$PROJECT_DIR$/circularBuffer.h" />
+        <option value="$PROJECT_DIR$/buffer.h" />
+        <option value="$PROJECT_DIR$/ecuCan.h" />
+        <option value="$PROJECT_DIR$/can.h" />
+        <option value="$PROJECT_DIR$/ecuOpenloggerTags.h" />
+        <option value="$PROJECT_DIR$/buffer.cpp" />
+        <option value="$PROJECT_DIR$/openLoggerController.h" />
+        <option value="$PROJECT_DIR$/openLoggerController.cpp" />
+        <option value="$PROJECT_DIR$/sufst-openlogger_controller.ino" />
+        <option value="$PROJECT_DIR$/can.cpp" />
+        <option value="$PROJECT_DIR$/dashController.cpp" />
+        <option value="$PROJECT_DIR$/dashController.h" />
+        <option value="$PROJECT_DIR$/ecuCan.cpp" />
+      </list>
+    </option>
+  </component>
+  <component name="OCFindUsagesOptions" text="true" ivars="false" properties="true" derivedClasses="false" />
+  <component name="ProjectFrameBounds" extendedState="6">
+    <option name="x" value="501" />
+    <option name="width" value="1428" />
+    <option name="height" value="1038" />
+  </component>
+  <component name="ProjectLevelVcsManager" settingsEditedManually="true">
+    <ConfirmationsSetting value="2" id="Add" />
+  </component>
+  <component name="ProjectView">
+    <navigator proportions="" version="1">
+      <foldersAlwaysOnTop value="true" />
+    </navigator>
+    <panes>
+      <pane id="ProjectPane">
+        <subPane>
+          <expand>
+            <path>
+              <item name="sufst-openlogger_controller" type="b2602c69:ProjectViewProjectNode" />
+              <item name="sufst-openlogger_controller" type="462c0819:PsiDirectoryNode" />
+            </path>
+          </expand>
+          <select />
+        </subPane>
+      </pane>
+      <pane id="Scope" />
+    </panes>
+  </component>
+  <component name="PropertiesComponent">
+    <property name="ASKED_SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
+    <property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
+    <property name="WebServerToolWindowFactoryState" value="false" />
+    <property name="last_opened_file_path" value="$PROJECT_DIR$" />
+    <property name="node.js.detected.package.eslint" value="true" />
+    <property name="node.js.detected.package.tslint" value="true" />
+    <property name="node.js.path.for.package.eslint" value="project" />
+    <property name="node.js.path.for.package.tslint" value="project" />
+    <property name="node.js.selected.package.eslint" value="(autodetect)" />
+    <property name="node.js.selected.package.tslint" value="(autodetect)" />
+    <property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
+    <property name="nodejs_npm_path_reset_for_default_project" value="true" />
+    <property name="settings.editor.selected.configurable" value="preferences.sourceCode.C/C++" />
+  </component>
+  <component name="RunDashboard">
+    <option name="ruleStates">
+      <list>
+        <RuleState>
+          <option name="name" value="ConfigurationTypeDashboardGroupingRule" />
+        </RuleState>
+        <RuleState>
+          <option name="name" value="StatusDashboardGroupingRule" />
+        </RuleState>
+      </list>
+    </option>
+  </component>
+  <component name="SvnConfiguration">
+    <configuration />
+  </component>
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="e173ebdc-c119-4235-9653-364cc21b27a5" name="Default Changelist" comment="" />
+      <created>1563403781995</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1563403781995</updated>
+      <workItem from="1563403785876" duration="5878000" />
+      <workItem from="1563472777392" duration="25184000" />
+      <workItem from="1563556486428" duration="2811000" />
+      <workItem from="1563582896736" duration="1316000" />
+      <workItem from="1563820826788" duration="5069000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TimeTrackingManager">
+    <option name="totallyTimeSpent" value="106065000" />
+  </component>
+  <component name="ToolWindowManager">
+    <frame x="-7" y="-7" width="1550" height="838" extended-state="6" />
+    <editor active="true" />
+    <layout>
+      <window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.49291784" visible="true" weight="0.16375838" />
+      <window_info id="Structure" order="1" sideWeight="0.50708216" side_tool="true" visible="true" weight="0.16375838" />
+      <window_info id="Favorites" order="2" side_tool="true" weight="0.3298872" />
+      <window_info anchor="bottom" id="Message" order="0" />
+      <window_info anchor="bottom" id="Find" order="1" />
+      <window_info anchor="bottom" id="Run" order="2" />
+      <window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
+      <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
+      <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
+      <window_info anchor="bottom" id="TODO" order="6" />
+      <window_info anchor="bottom" id="Version Control" order="7" weight="0.3295129" />
+      <window_info anchor="bottom" id="Database Changes" order="8" />
+      <window_info anchor="bottom" id="Terminal" order="9" />
+      <window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
+      <window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
+      <window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
+      <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
+      <window_info anchor="right" id="Database" order="3" weight="0.3295129" />
+    </layout>
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="1" />
+  </component>
+  <component name="editorHistoryManager">
+    <entry file="file://$PROJECT_DIR$/../sufst-openlogger/openLogger.cpp">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/../sufst-openlogger/openLogger.h">
+      <provider selected="true" editor-type-id="text-editor" />
+    </entry>
+    <entry file="file://$PROJECT_DIR$/circularBuffer.cpp" />
+    <entry file="file://$PROJECT_DIR$/circularBuffer.h" />
+    <entry file="file://$PROJECT_DIR$/ecuCan.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="357">
+          <caret line="21" selection-start-line="21" selection-end-line="21" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/openLoggerController.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="187">
+          <caret line="11" column="37" selection-start-line="11" selection-start-column="37" selection-end-line="11" selection-end-column="37" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/buffer.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="255">
+          <caret line="15" column="22" selection-start-line="15" selection-start-column="22" selection-end-line="15" selection-end-column="22" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/buffer.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="799">
+          <caret line="47" column="1" selection-start-line="47" selection-start-column="1" selection-end-line="47" selection-end-column="1" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/can.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="844">
+          <caret line="52" column="8" selection-start-line="52" selection-start-column="8" selection-end-line="52" selection-end-column="8" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/openLoggerController.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="576">
+          <caret line="175" column="87" selection-start-line="175" selection-start-column="87" selection-end-line="175" selection-end-column="87" />
+          <folding>
+            <element signature="e#40#73#0" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/ecuOpenloggerTags.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="34">
+          <caret line="2" column="2" lean-forward="true" selection-start-line="2" selection-start-column="2" selection-end-line="2" selection-end-column="2" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/can.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="170">
+          <caret line="73" column="11" lean-forward="true" selection-start-line="73" selection-start-column="11" selection-end-line="73" selection-end-column="11" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/sufst-openlogger_controller.ino">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="391">
+          <caret line="29" lean-forward="true" selection-start-line="29" selection-end-line="29" />
+          <folding>
+            <element signature="e#57#90#0" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/dashController.h">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="153">
+          <caret line="9" column="18" selection-start-line="9" selection-start-column="5" selection-end-line="9" selection-end-column="18" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/dashController.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="476">
+          <caret line="28" selection-start-line="28" selection-end-line="28" selection-end-column="28" />
+        </state>
+      </provider>
+    </entry>
+    <entry file="file://$PROJECT_DIR$/ecuCan.cpp">
+      <provider selected="true" editor-type-id="text-editor">
+        <state relative-caret-position="102">
+          <caret line="6" column="30" selection-start-line="6" selection-start-column="30" selection-end-line="6" selection-end-column="30" />
+          <folding>
+            <element signature="e#39#58#0" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
+  </component>
+</project>
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/buffer.cpp b/Legacy-firmware/sufst-openlogger_controller/buffer.cpp
new file mode 100644
index 0000000..b9f3742
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/buffer.cpp
@@ -0,0 +1,142 @@
+//
+// Created by Sil on 7/19/2019.
+//
+
+#include "buffer.h"
+
+uint8_t cirBufferBegin(cirBuffer_handle cirBuff, void *data, uint16_t len, uint8_t unitSize)
+{
+
+    if (cirBuff == NULL) {
+        return 0;
+    }
+
+    if (data == NULL) {
+        return 0;
+    }
+
+    cirBuff->head = 0;
+    cirBuff->tail = 0;
+    cirBuff->capacity = len;
+    cirBuff->full = 0;
+    cirBuff->data = (uint8_t *) data;
+    cirBuff->unitSize = unitSize;
+
+    return 1;
+}
+
+uint16_t cirBufferAvailable(cirBuffer_handle cirBuff)
+{
+    uint16_t availableForWrite = 0;
+
+    if (!cirBuff->full) {
+        if (cirBuff->head >= cirBuff->tail) {
+            availableForWrite = cirBuff->head - cirBuff->tail;
+        }
+        else {
+            availableForWrite = cirBuff->capacity - cirBuff->tail + cirBuff->head;
+        }
+    }
+    else {
+        availableForWrite = cirBuff->capacity;
+    }
+
+    return availableForWrite;
+}
+
+uint16_t cirBufferAvailableForWrite(cirBuffer_handle cirBuff)
+{
+    return cirBuff->capacity - cirBufferAvailable(cirBuff);
+}
+
+void cirBufferWrite(cirBuffer_handle cirBuff, void *unit)
+{
+    memcpy(&(cirBuff->data[cirBuff->head * cirBuff->unitSize]), unit, cirBuff->unitSize);
+
+    ++cirBuff->head &= (cirBuff->capacity - 1);
+
+    if (cirBuff->head == cirBuff->tail) {
+        cirBuff->full = 1;
+
+        ++cirBuff->tail &= (cirBuff->capacity - 1);
+    }
+}
+
+void cirBufferWriteBytes(cirBuffer_handle cirBuff, void *src, uint16_t len)
+{
+
+    uint16_t usedBytes = cirBufferAvailable(cirBuff);
+
+    if ((usedBytes + len) > cirBuff->capacity) {
+        cirBuff->full = 1;
+    }
+
+    for (uint16_t i = 0; i < len; i++) {
+        cirBuff->data[cirBuff->head] = ((uint8_t *) src)[i];
+
+        ++cirBuff->head &= cirBuff->capacity - 1;
+    }
+
+    if (cirBuff->full) {
+        cirBuff->tail = (cirBuff->tail + (len - (cirBuff->capacity - usedBytes))) & (cirBuff->capacity - 1);
+    }
+}
+
+void *cirBufferExternalWrite(cirBuffer_handle cirBuff)
+{
+    uint8_t *head = &(cirBuff->data[cirBuff->head]);
+
+    ++cirBuff->head &= cirBuff->capacity - 1;
+
+    if (cirBuff->head == cirBuff->tail) {
+        cirBuff->full = 1;
+
+        ++cirBuff->tail &= (cirBuff->capacity - 1);
+    }
+
+    return head;
+}
+
+void *cirBufferExternalRead(cirBuffer_handle cirBuff)
+{
+    uint8_t *tail = &(cirBuff->data[cirBuff->tail]);
+
+    ++cirBuff->tail &= (cirBuff->capacity - 1);
+
+    return (void *) tail;
+}
+
+void cirBufferRead(cirBuffer_handle cirBuff, void *loc)
+{
+
+    memcpy(loc, &(cirBuff->data[cirBuff->tail * cirBuff->unitSize]), cirBuff->unitSize);
+
+    ++cirBuff->tail &= (cirBuff->capacity - 1);
+
+    cirBuff->full = 0;
+
+}
+
+void *cirBufferPeek(cirBuffer_handle cirBuff)
+{
+    return (void *) (cirBuff->data[cirBuff->tail]);
+}
+
+void cirBufferReadBytes(cirBuffer_handle cirBuff, void *loc, uint16_t len)
+{
+    cirBuff->full = 0;
+
+    for (uint16_t i = 0; i < len; i++) {
+        ((uint8_t *) loc)[i] = cirBuff->data[cirBuff->tail];
+
+        ++cirBuff->tail &= cirBuff->capacity - 1;
+    }
+
+}
+
+void cirBufferReset(cirBuffer_handle cirBuff)
+{
+    cirBuff->head = 0;
+    cirBuff->tail = 0;
+    cirBuff->full = 0;
+}
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/buffer.h b/Legacy-firmware/sufst-openlogger_controller/buffer.h
new file mode 100644
index 0000000..d8f886d
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/buffer.h
@@ -0,0 +1,48 @@
+//
+// Created by Sil on 7/19/2019.
+//
+
+#ifndef BUFFER_H
+#define BUFFER_H
+
+#include "Arduino.h"
+
+typedef struct CirBuffer
+{
+    uint16_t head;
+    uint16_t tail;
+    uint8_t full;
+    uint8_t *data;
+    uint16_t capacity;
+    uint8_t unitSize;
+};
+
+typedef CirBuffer *cirBuffer_handle;
+
+/*
+ * THE LEN OF THE BUFFER MUST BE A POWER OF 2
+ */
+
+uint8_t cirBufferBegin(cirBuffer_handle cirBuff, void *data, uint16_t len, uint8_t unitSize);
+
+uint16_t cirBufferAvailable(cirBuffer_handle cirBuff);
+
+uint16_t cirBufferAvailableForWrite(cirBuffer_handle cirBuff);
+
+void cirBufferWrite(cirBuffer_handle cirBuff, void *unit);
+
+void cirBufferWriteBytes(cirBuffer_handle cirBuff, void *src, uint16_t len);
+
+void *cirBufferExternalWrite(cirBuffer_handle cirBuff);
+
+void cirBufferRead(cirBuffer_handle cirBuff, void *loc);
+
+void cirBufferReadBytes(cirBuffer_handle cirBuff, void *loc, uint16_t len);
+
+void *cirBufferExternalRead(cirBuffer_handle cirBuff);
+
+void *cirBufferPeek(cirBuffer_handle cirBuff);
+
+void cirBufferReset(cirBuffer_handle cirBuff);
+
+#endif //BUFFER_H
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/can.cpp b/Legacy-firmware/sufst-openlogger_controller/can.cpp
new file mode 100644
index 0000000..4cc3e65
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/can.cpp
@@ -0,0 +1,321 @@
+//
+// Created by Sil on 15/07/2019.
+//
+
+#include "can.h"
+// Watchdog
+#include <avr/wdt.h>
+#include "buffer.h"
+#include <mcp_can.h>
+#include <mcp_can_dfs.h>
+
+#include "ecuCan.h"
+
+// Can instance
+MCP_CAN can;
+
+volatile unsigned long lastCanMsgRecTimeMs = 0;
+
+static CanMsgTemplate canRxBuffer[CAN_RX_BUFFER_LEN];
+
+volatile CirBuffer canRxCirBuffer;
+
+static CanMsgTemplate canTxBuffer[CAN_TX_BUFFER_LEN];
+
+volatile CirBuffer canTxCirBuffer;
+
+extern void ecuCanMsg0x2000(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2001(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2002(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2003(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2004(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2005(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2006(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2007(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2008(CanMsgTemplate *canMsg);
+
+extern void ecuCanMsg0x2009(CanMsgTemplate *canMsg);
+
+// ECU can messages function pointers for calling the corresponding function when that msg is seen.
+// Used in function canParseRxMsg.
+void
+(*ecuCanFuncPtrs[10])(CanMsgTemplate *) = {ecuCanMsg0x2000, ecuCanMsg0x2001,
+                                           ecuCanMsg0x2002,
+                                           ecuCanMsg0x2003,
+                                           ecuCanMsg0x2004, ecuCanMsg0x2005,
+                                           ecuCanMsg0x2006,
+                                           ecuCanMsg0x2007, ecuCanMsg0x2008,
+                                           ecuCanMsg0x2009};
+
+uint8_t canBegin()
+{
+    if (!cirBufferBegin(&canRxCirBuffer, canRxBuffer, CAN_RX_BUFFER_LEN, sizeof(CanMsgTemplate))) {
+        return 0;
+    }
+
+    if (!cirBufferBegin(&canTxCirBuffer, canTxBuffer, CAN_TX_BUFFER_LEN, sizeof(CanMsgTemplate))) {
+        return 0;
+    }
+
+    pinMode(CAN_INT_PIN, INPUT_PULLUP);
+
+    // Initialize the Arduino CAN class with slave select pin.
+    can.init_CS(CAN_CS_PIN);
+
+    // Initialize the CAN bus with speed 1000kbps
+    if (can.begin(CAN_1000KBPS) == CAN_FAILINIT) {
+        return 0;
+    }
+
+
+    return 1;
+}
+
+uint8_t canSaveMsg()
+{
+    if (digitalRead(CAN_INT_PIN)) {
+        return 0;
+    }
+
+    union
+    {
+        uint8_t id[4];
+        uint32_t id32;
+    } uid;
+
+    if (can.checkReceive() != CAN_MSGAVAIL) {
+        return 0;
+    }
+
+    CanMsgTemplate canReceivedMsg;
+
+    if (can.readMsgBuf(&(canReceivedMsg.len), canReceivedMsg.data) != CAN_OK) {
+        return 0;
+    }
+
+    uid.id32 = can.getCanId();
+
+    canReceivedMsg.timestamp = millis();
+
+    canReceivedMsg.id = (uid.id[1] << 8) | uid.id[0];
+
+    cirBufferWrite(&canRxCirBuffer, &canReceivedMsg);
+
+#if DEBUG_CAN_RX
+    Serial.print("CAN SV RX: ");
+
+    Serial.print(canReceivedMsg.id, HEX);
+    Serial.print(" : ");
+    for(uint8_t i = 0; i < 7; i++) {
+        Serial.print(canReceivedMsg.data[i]);
+        Serial.print(", ");
+    }
+    Serial.println(canReceivedMsg.data[7]);
+#endif // DEBUG_CAN_RX;
+
+    return 1;
+}
+
+void canAddTxRequest(CanMsgTemplate *canMsg)
+{
+    if (NULL == canMsg) {
+        return;
+    }
+
+#if DEBUG_CAN_TX_REQS
+    Serial.print("CAN TX ADD: ");
+    Serial.print(canMsg.id, HEX);
+    Serial.print(" : ");
+    for(uint8_t i = 0; i < 7; i++) {
+      Serial.print(canMsg.data[i], HEX);
+      Serial.print(", ");
+    }
+    Serial.println(canMsg.data[7], HEX);
+#endif // DEBUG_CAN_TX_REQS
+
+    cirBufferWrite(&canTxCirBuffer, canMsg);
+}
+
+// External interrupt currently only designed to work with atmega 2560
+#if !defined(__AVR_ATmega2560__)
+#error "PLATFORM NOT SUPPORTED CURRENTLY"
+#endif // !defined(atmega2560)
+
+#if CAN_INT_PIN != 2
+#error "CAN_INT_PIN CHANGED FROM 2"
+#endif //CAN_INT_PIN != 2
+
+void canBeginExtInterrupt()
+{
+    noInterrupts();
+
+    // On the mega 2560 pin 2 is external interrupt 4
+    EIMSK &= ~(1 << INT4);
+
+    EICRB &= ~(1 << ISC41);
+    //EICRB &= ~(1 << ISC40);
+
+    EIMSK |= (1 << INT4);
+
+    interrupts();
+}
+
+ISR(INT4_vect) {
+
+    noInterrupts();
+
+    lastCanMsgRecTimeMs = millis();
+
+    canSaveMsg();
+
+    interrupts();
+}
+
+void canParseRxMsg(CanMsgTemplate *canMsg)
+{
+    if ((canMsg->id >= 0x2000) && (canMsg->id <= 0x200A)) {
+        // canMsg->idByte[0] holds the 0x01 in 0x2001 received can msg
+        // We use the sub byte of the can ecu msg to determine the corresonding function
+        // This removes the need for a long if statement giving significant performance boosts
+        (*ecuCanFuncPtrs[canMsg->idByte[0]])(canMsg);
+    }
+}
+
+void canProcessRx()
+{
+    uint8_t retVal = 0;
+
+    noInterrupts();
+    canSaveMsg();
+    interrupts();
+
+    noInterrupts();
+    while (cirBufferAvailable(&canRxCirBuffer) > 0) {
+
+        CanMsgTemplate canMsg;
+
+        cirBufferRead(&canRxCirBuffer, &canMsg);
+
+#if DEBUG_CAN_RX
+        Serial.print("CAN RX: ");
+
+        Serial.print(canMsg.id, HEX);
+        Serial.print(" : ");
+        for(uint8_t i = 0; i < 7; i++) {
+          Serial.print(canMsg.data[i]);
+          Serial.print(", ");
+        }
+        Serial.println(canMsg.data[7]);
+#endif // DEBUG_CAN_RX
+
+#if DEBUG_CAN_RX_MINIMAL
+        Serial.print("CAN RX : ");
+        Serial.println(canMsg.id, HEX);
+#endif // DEBUG_CAN_RX_MINIMAL
+
+        canParseRxMsg(&canMsg);
+
+        // This may seem dumb but this allows any pending interrupts to be serviced safely
+        // just before we start another loop. Otherwise if we stay in this loop too long without
+        // servicing any interrupts we might miss one.
+        interrupts();
+        noInterrupts();
+    }
+    interrupts();
+}
+
+uint8_t canProcessTx()
+{
+
+    uint8_t retVal = 1;
+
+    noInterrupts();
+    while (cirBufferAvailable(&canTxCirBuffer) > 0) {
+
+        CanMsgTemplate canMsg;
+
+        cirBufferRead(&canTxCirBuffer, &canMsg);
+
+#if DEBUG_CAN_TX
+        Serial.print("CAN TX: ");
+        Serial.print(canMsg.id, HEX);
+        Serial.print(" : ");
+        for(uint8_t i = 0; i < (canMsg.len - 1); i++) {
+          Serial.print(canMsg.data[i]);
+          Serial.print(", ");
+        }
+        Serial.println(canMsg.data[canMsg.len - 1]);
+#endif // DEBUG_CAN_TX
+
+#if DEBUG_CAN_TX_MINIMAL
+        Serial.print("CAN TX : ");
+        Serial.println(canMsg.id, HEX);
+#endif // DEBUG_CAN_TX_MINIMAL
+
+        uint8_t canTxWasSuccessful = 0;
+
+        for (uint8_t i = 0; i < CAN_TX_RETRY_LIMIT; i++) {
+            if (can.sendMsgBuf(canMsg.id, 1, canMsg.len,
+                               canMsg.data, true) == CAN_OK) {
+
+                canTxWasSuccessful = 1;
+
+                retVal = 1;
+
+                break;
+            }
+            else {
+                retVal = 0;
+            }
+
+        }
+
+        if (!canTxWasSuccessful) {
+
+#if DEBUG_CAN_TX || DEBUG_CAN_TX_MINIMAL
+            Serial.println("CAN TX: TX FAILED");
+#endif // DEBUG_CAN_TX || DEBUG_CAN_TX_MINIMAL
+
+        }
+
+        // This may seem dumb but this allows any pending interrupts to be serviced safely
+        // just before we start another loop. Otherwise if we stay in this loop too long without
+        // servicing any interrupts we might miss one.
+        interrupts();
+        noInterrupts();
+    }
+
+    interrupts();
+
+    return retVal;
+}
+
+void canNoActivityResetDevice()
+{
+    Serial.println("CAN ERROR : RESETTING DEVICE");
+    Serial.flush();
+
+#if SD_ENABLED
+
+    uint8_t payload[10] = {0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00};
+
+    sdAddToWriteBlocks(payload, 10);
+
+    sdWriteBufferBlocks();
+
+#endif //SD_ENABLED
+
+    // Enabled watchdog timer to reset device as we will not pat it
+    wdt_enable(WDTO_15MS);
+
+    while (true);
+
+}
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/can.h b/Legacy-firmware/sufst-openlogger_controller/can.h
new file mode 100644
index 0000000..4fc862a
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/can.h
@@ -0,0 +1,69 @@
+//
+// Created by Sil on 15/07/2019.
+//
+
+#ifndef SUFST_OPENLOGGER_CONTROLLER_CAN_H
+#define SUFST_OPENLOGGER_CONTROLLER_CAN_H
+
+#include "Arduino.h"
+
+// CAN_INT_PIN MUST BE 2
+#define CAN_INT_PIN 2
+#define CAN_CS_PIN 10
+
+#define CAN_RX_BUFFER_LEN 32
+#define CAN_TX_BUFFER_LEN 32
+
+#define CAN_RESET_DEVICE_ON_TIMEOUT 0
+#define CAN_NO_MSG_TIMEOUT_RESET_MS 10000
+
+#define CAN_TX_RETRY_LIMIT 5
+
+#define DEBUG_CAN_RX 0
+#define DEBUG_CAN_RX_MINIMAL 0
+
+#define DEBUG_CAN_TX 0
+#define DEBUG_CAN_TX_MINIMAL 0
+#define DEBUG_CAN_TX_REQS 0
+
+typedef struct CanMsgTemplate
+{
+    uint32_t timestamp;
+
+    union
+    {
+        uint16_t id;
+        // if id is 0x2001 then idByte[0] is 0x01 and idByte[1] is 0x20
+        // due to the endianness of the system
+        uint8_t idByte[2];
+    };
+
+    uint8_t len;
+
+    union
+    {
+        uint8_t data[8];
+        uint16_t data16[4];
+        uint32_t data32[2];
+        float dataFl[2];
+    };
+
+};
+
+uint8_t canBegin();
+
+uint8_t canSaveMsg();
+
+uint8_t canAddTxRequest(uint16_t id, void *data, uint8_t lenBytes);
+
+void canBeginExtInterrupt();
+
+void canParseRxMsg(CanMsgTemplate *canMsg);
+
+void canProcessRx();
+
+uint8_t canProcessTx();
+
+void canNoActivityResetDevice();
+
+#endif //SUFST_OPENLOGGER_CONTROLLER_CAN_H
diff --git a/Legacy-firmware/sufst-openlogger_controller/ecuCan.cpp b/Legacy-firmware/sufst-openlogger_controller/ecuCan.cpp
new file mode 100644
index 0000000..e7f5d9f
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/ecuCan.cpp
@@ -0,0 +1,280 @@
+//
+// Created by Sil on 7/21/2019.
+//
+
+#include "ecuCan.h"
+#include "openLoggerController.h"
+#include "ecuOpenloggerTags.h"
+
+struct EcuDataOpenlogger
+{
+    uint8_t startTag;
+    uint32_t timestamp;
+    uint16_t data;
+    uint8_t endTag;
+};
+
+void ecuOpenloggerWrite(EcuDataOpenlogger *ecuDataOpenlogger);
+
+void ecuOpenloggerSave(CanMsgTemplate *canMsgTemplate, uint8_t index);
+
+void ecuOpenloggerWrite(EcuDataOpenlogger &ecuDataOpenlogger)
+{
+    static uint8_t openloggerPayload[8];
+
+    memcpy(openloggerPayload, &(ecuDataOpenlogger.startTag), 1);
+
+    memcpy(&(openloggerPayload[1]), &(ecuDataOpenlogger.timestamp), 4);
+
+    memcpy(&(openloggerPayload[5]), &(ecuDataOpenlogger.data), 2);
+
+    memcpy(&(openloggerPayload[7]), &(ecuDataOpenlogger.endTag), 1);
+
+    openloggerWrite(openloggerPayload, 8);
+}
+
+void ecuOpenloggerSave(CanMsgTemplate *canMsg, uint8_t index)
+{
+    static EcuDataOpenlogger ecuDataOpenlogger;
+
+    uint8_t ecuId = canMsg->idByte[0];
+
+    uint8_t ecuParamterTag = ecuMsgParameterToOpenloggerTag[ecuId][index];
+
+    ecuDataOpenlogger.startTag = ecuParamterTag;
+
+    ecuDataOpenlogger.timestamp = canMsg->timestamp;
+
+    ecuDataOpenlogger.data = canMsg->data16[index];
+
+    ecuDataOpenlogger.endTag = ecuParamterTag;
+
+    ecuOpenloggerWrite(ecuDataOpenlogger);
+}
+
+void ecuCanMsg0x2000(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2000 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2000");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t rpm = canMsg->data16[0];
+    uint16_t tpsPerc = canMsg->data16[1];
+    uint16_t waterTempC = canMsg->data16[2];
+    uint16_t airTempC = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 0);
+    ecuOpenloggerSave(canMsg, 1);
+    ecuOpenloggerSave(canMsg, 2);
+}
+
+void ecuCanMsg0x2001(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2001 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2001");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t mainifoldPresKpa = canMsg->data16[0];
+    uint16_t lambdax1000 = canMsg->data16[1];
+    uint16_t speedKphx10 = canMsg->data16[2];
+    uint16_t oilPressKpa = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 1);
+}
+
+void ecuCanMsg0x2002(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2002 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2002");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t fuelPressKpa = canMsg->data16[0];
+    uint16_t oilTempC = canMsg->data16[1];
+    uint16_t batteryVx10 = canMsg->data16[2];
+    uint16_t fuelComsumLpHrx10 = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 2);
+
+    // Serial.println((float)(batteryVx10 / 10.0));
+}
+
+void ecuCanMsg0x2003(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2003 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2003");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t currentGear = canMsg->data16[0];
+    uint16_t advanceDegx10 = canMsg->data16[1];
+    uint16_t injectionTimeMsx100 = canMsg->data16[2];
+    uint16_t fuelComsumLp100kMx10 = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 1);
+}
+
+void ecuCanMsg0x2004(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2004 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2004");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t ana1mV = canMsg->data16[0];
+    uint16_t ana2mV = canMsg->data16[1];
+    uint16_t ana3mV = canMsg->data16[2];
+    uint16_t camAdvanceDegx10 = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 3);
+}
+
+void ecuCanMsg0x2005(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2005 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2005");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t camTargDegx10 = canMsg->data16[0];
+    uint16_t camPwmPercx10 = canMsg->data16[1];
+    uint16_t crankErrorsNr = canMsg->data16[2];
+    uint16_t camErrorsNr = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 0);
+}
+
+void ecuCanMsg0x2006(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2006 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2006");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t cam2AdvDegx10 = canMsg->data16[0];
+    uint16_t cam2TargDegx10 = canMsg->data16[1];
+    uint16_t cam2PwmPercx10 = canMsg->data16[2];
+    uint16_t external5VmV = canMsg->data16[3];
+}
+
+void ecuCanMsg0x2007(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2007 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2007");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t injDutyCyclePerc = canMsg->data16[0];
+    uint16_t lambdaPidTargPercx10 = canMsg->data16[1];
+    uint16_t lambdaPidAdjPercx10 = canMsg->data16[2];
+    uint16_t ecuSwitchesBitField = canMsg->data16[3];
+
+    ecuOpenloggerSave(canMsg, 0);
+    ecuOpenloggerSave(canMsg, 1);
+    ecuOpenloggerSave(canMsg, 2);
+}
+
+void ecuCanMsg0x2008(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2008 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2008");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    uint16_t rdSpeedKphx10 = canMsg->data16[0];
+    uint16_t rUdSpeedKphx10 = canMsg->data16[1];
+    uint16_t ldSpeedKphx10 = canMsg->data16[2];
+    uint16_t lUdSpeedKphx10 = canMsg->data16[3];
+}
+
+void ecuCanMsg0x2009(CanMsgTemplate *canMsg)
+{
+#if DEBUG_ECU_CAN
+    Serial.print("ECU : 0x2009 : ");
+    for (uint8_t i = 0; i < 3; i++) {
+        Serial.print(canMsg->data16[i], HEX);
+        Serial.print(" , ");
+    }
+    Serial.println(canMsg->data16[3], HEX);
+#endif //DEBUG_ECU_CAN
+
+#if DEBUG_ECU_CAN_MINIMAL
+    Serial.println("ECU : 0x2008");
+#endif //DEBUG_ECU_CAN_MINIMAL
+
+    // uint16_t rightLambdax1000 = canMsg->data16[0];
+}
\ No newline at end of file
diff --git a/Legacy-firmware/sufst-openlogger_controller/ecuCan.h b/Legacy-firmware/sufst-openlogger_controller/ecuCan.h
new file mode 100644
index 0000000..3e0f985
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/ecuCan.h
@@ -0,0 +1,38 @@
+//
+// Created by Sil on 7/21/2019.
+//
+
+#ifndef ECUCAN_H
+#define ECUCAN_H
+
+#include "Arduino.h"
+#include "can.h"
+
+/*
+ * These are called from can.cpp when their corresponding can msg id is seen.
+ * So functions name *must* ecuCanMsg0x200N.
+ *
+ */
+
+void ecuCanMsg0x2000(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2001(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2002(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2003(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2004(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2005(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2006(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2007(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2008(CanMsgTemplate *canMsg);
+
+void ecuCanMsg0x2009(CanMsgTemplate *canMsg);
+
+
+#endif //ECUCAN_H
diff --git a/Legacy-firmware/sufst-openlogger_controller/ecuOpenloggerTags.h b/Legacy-firmware/sufst-openlogger_controller/ecuOpenloggerTags.h
new file mode 100644
index 0000000..c0bc6d3
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/ecuOpenloggerTags.h
@@ -0,0 +1,19 @@
+//
+// Created by Sil on 7/21/2019.
+//
+
+#ifndef ECUOPENLOGGERTAGS_H
+#define ECUOPENLOGGERTAGS_H
+
+uint8_t ecuMsgParameterToOpenloggerTag[8][4] = {
+    {1, 2, 3, 4},
+    {5, 6, 7, 8},
+    {9, 10, 11, 12},
+    {13, 14, 15, 16},
+    {17, 18, 19, 20},
+    {21, 22, 23, 24},
+    {25, 26, 27, 28},
+    {29, 30, 31, 32}
+};
+
+#endif //ECUOPENLOGGERTAGS_H
diff --git a/Legacy-firmware/sufst-openlogger_controller/openLoggerController.cpp b/Legacy-firmware/sufst-openlogger_controller/openLoggerController.cpp
new file mode 100644
index 0000000..d530acb
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/openLoggerController.cpp
@@ -0,0 +1,296 @@
+//
+// Created by Sil on 14/07/2019.
+//
+
+#include "openLoggerController.h"
+#include "buffer.h"
+
+enum
+{
+    uartStartByte = 's',
+    uartStopByte = 'f'
+};
+
+enum
+{
+    uartTypeData = 0,
+    uartTypeCommand,
+    uartTypeInfo
+};
+
+enum
+{
+    uartCommandStartWrites = 0,
+    uartCommandStopWrites
+};
+
+enum
+{
+    uartInfoAlreadyRunning = 0,
+    uartInfoAlreadyIdle,
+    uartInfoWritesStarted,
+    uartInfoWritesStartError,
+    uartInfoStopped,
+    uartInfoStopError,
+    uartInfoWriteError,
+    uartInfoWritesNotStarted
+};
+
+typedef enum
+{
+    idle = 0,
+    running,
+    failedToStart,
+    failedToStop,
+    failToWrite
+} OpenloggerState;
+
+typedef enum
+{
+    checkingForStart = 0,
+    checkingForType,
+    checkingForInfo
+} OpenloggerUartRxState;
+
+static uint8_t openloggerTxDataBuffer[OPENLOGGER_TX_BUFFER_LEN];
+
+static CirBuffer openloggerTxDataCirBuffer;
+
+static uint8_t openloggerTxCommandBuffer[OPENLOGGER_TX_COMMAND_BUFFER_LEN];
+
+static CirBuffer openloggerTxCommandCirBuffer;
+
+OpenloggerState openloggerState = idle;
+
+OpenloggerUartRxState openloggerUartRxState = checkingForStart;
+
+static bool uartCurrentlyTransmitting = false;
+
+void openloggerIdle();
+
+void openloggerRunning();
+
+void openloggerFailedToStart();
+
+void openloggerFailedToStop();
+
+void openloggerFailedToWrite();
+
+void openloggerRxCheckingForStart();
+
+void openloggerRxCheckingForType();
+
+void openloggerRxCheckingForInfo();
+
+/*
+ * openloggerState_ptrs correspond to INFO packets, so e.g if OPENLOGGER_INFO_WRITES_STARTED (0x02) is seen then
+ * [2] is called which is openloggerRunning.
+ */
+
+OpenloggerState rxInfoTypeToStateLookup[8] = {running, idle, running, failedToStart, idle, failedToStop,
+                                              failToWrite, idle};
+
+void (*openloggerState_ptrs[8])(void) = {openloggerIdle, openloggerRunning,
+                                         openloggerFailedToStart, openloggerFailedToStop,
+                                         openloggerFailedToWrite};
+
+void (*openloggerUartRxState_ptrs[3])(void) = {openloggerRxCheckingForStart, openloggerRxCheckingForType,
+                                               openloggerRxCheckingForInfo};
+
+void serialEvent1()
+{
+    openloggerUartRxState_ptrs[openloggerUartRxState]();
+}
+
+void openloggerRxCheckingForStart()
+{
+
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING START ");
+    Serial.println(Serial1.peek());
+#endif // DEBUG_OPENLOGGER
+
+    if (Serial1.read() == uartStartByte) {
+        openloggerUartRxState = checkingForType;
+    }
+}
+
+void openloggerRxCheckingForType()
+{
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING FOR TYPE ");
+    Serial.println(Serial1.peek());
+#endif // DEBUG_OPENLOGGER
+
+    if (Serial1.read() == uartTypeInfo) {
+        openloggerUartRxState = checkingForInfo;
+    }
+    else {
+        openloggerUartRxState = checkingForStart;
+    }
+}
+
+void openloggerRxCheckingForInfo()
+{
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: CHECKING FOR INFO ");
+    Serial.println(Serial1.peek());
+#endif // DEBUG_OPENLOGGER
+    /*
+     * The value received from the openlogger dictates what state we are in.
+     */
+    openloggerState = rxInfoTypeToStateLookup[Serial1.read()];
+
+    openloggerUartRxState = checkingForStart;
+
+}
+
+void openloggerIdle()
+{
+
+}
+
+void openloggerRunning()
+{
+    /*
+     * The uart Tx buffer has a capacity of 64 bytes, if we try to write more than this then Serial.write becomes
+     * blocking, so we want to avoid this at all costs.
+     *
+     */
+
+    static uint8_t uartTxPayload[64];
+
+    static uint16_t uartAmountToTransmit = 0;
+
+    static uint32_t uartLastTransmissionMs = millis();
+
+    uint32_t uartCurrentMs = millis();
+
+    uint16_t uartTxDataAmount = cirBufferAvailable(&openloggerTxDataCirBuffer);
+
+    if (uartTxDataAmount > 0) {
+
+        if ((uartCurrentMs - uartLastTransmissionMs) >= 5) {
+            if (Serial1.availableForWrite() >= 35) {
+
+                uint8_t uartTxBytes = (uartTxDataAmount >= 32) ? 32 : uartTxDataAmount;
+
+                Serial1.write(uartStartByte);
+                Serial1.write(uartTypeData);
+                Serial1.write(uartTxBytes);
+
+                cirBufferReadBytes(&openloggerTxDataCirBuffer, uartTxPayload, uartTxBytes);
+
+                Serial1.write(uartTxPayload, uartTxBytes);
+
+                uartLastTransmissionMs = millis();
+            }
+        }
+    }
+}
+
+void openloggerFailedToStart()
+{
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: FAILED TO START");
+#endif // DEBUG_OPENLOGGER
+
+    openloggerState = idle;
+}
+
+void openloggerFailedToStop()
+{
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: FAILED TO STOP");
+#endif // DEBUG_OPENLOGGER
+
+    openloggerState = idle;
+}
+
+void openloggerFailedToWrite()
+{
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: FAILED TO WRITE");
+#endif // DEBUG_OPENLOGGER
+
+    openloggerState = idle;
+}
+
+void openloggerBegin(uint32_t serialBaud)
+{
+
+    Serial1.begin(serialBaud);
+
+    cirBufferBegin(&openloggerTxDataCirBuffer,
+                   openloggerTxDataBuffer,
+                   OPENLOGGER_TX_BUFFER_LEN,
+                   sizeof(uint8_t));
+
+    cirBufferBegin(&openloggerTxCommandCirBuffer,
+                   openloggerTxCommandBuffer,
+                   OPENLOGGER_TX_COMMAND_BUFFER_LEN,
+                   sizeof(uint8_t));
+
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: BEGIN FINISHED");
+#endif // DEBUG_OPENLOGGER
+}
+
+void openloggerBeginWrites()
+{
+    openloggerWriteCommand(uartCommandStartWrites);
+
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: OPLOG STARTING WRITES");
+#endif // DEBUG_OPENLOGGER
+}
+
+void openloggerStopWrites()
+{
+    openloggerWriteCommand(uartCommandStopWrites);
+
+#if DEBUG_OPENLOGGER
+    Serial.println("OPLOG: OPLOG STOPPING WRITES");
+#endif // DEBUG_OPENLOGGER
+}
+
+void openloggerProcess()
+{
+    if (!uartCurrentlyTransmitting) {
+        if (cirBufferAvailable(&openloggerTxCommandCirBuffer) > 0) {
+
+#if DEBUG_OPENLOGGER
+            Serial.print("OPLOG: COMMAND ");
+            Serial.println(*((uint8_t *)cirBufferPeek(&openloggerTxCommandCirBuffer)), HEX);
+#endif // DEBUG_OPENLOGGER
+
+            Serial1.write(uartStartByte);
+            Serial1.write(uartTypeCommand);
+            Serial1.write(*((uint8_t *) cirBufferExternalRead(&openloggerTxCommandCirBuffer)));
+            Serial1.flush();
+        }
+    }
+
+    openloggerState_ptrs[openloggerState]();
+}
+
+void openloggerWrite(void *pPayload, uint8_t payloadLen)
+{
+
+    if (openloggerState == running) {
+        cirBufferWriteBytes(&openloggerTxDataCirBuffer, pPayload, payloadLen);
+    }
+}
+
+void openloggerWriteCommand(uint8_t command)
+{
+
+#if DEBUG_OPENLOGGER
+    Serial.print("OPLOG: APPENDING COMMAND ");
+    Serial.println(command, HEX);
+    Serial.flush();
+#endif // DEBUG_OPENLOGGER
+
+    cirBufferWrite(&openloggerTxCommandCirBuffer, &command);
+
+}
diff --git a/Legacy-firmware/sufst-openlogger_controller/openLoggerController.h b/Legacy-firmware/sufst-openlogger_controller/openLoggerController.h
new file mode 100644
index 0000000..fd48ca6
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/openLoggerController.h
@@ -0,0 +1,49 @@
+//
+// Created by Sil on 14/07/2019.
+//
+
+#ifndef SUFST_OPENLOGGER_INO_SDCARDMASTER_H
+#define SUFST_OPENLOGGER_INO_SDCARDMASTER_H
+
+#include "Arduino.h"
+
+#define DEBUG_OPENLOGGER 0
+
+#define OPENLOGGER_TX_BUFFER_LEN 1024
+#define OPENLOGGER_TX_COMMAND_BUFFER_LEN 8
+
+/*
+ * The serial port is hard coded to serial1 so ensure openlogger is connected to serial1.
+ *
+ * There are three types of transactions: save this data, do this command or heres some info.
+ *
+ * STRUCTURE OF A VALID SD CARD UART SAVE THIS DATA TRANSACTION
+ *
+ * START BYTE | DATA TYPE | LENGTH BYTE | DATA BYTES | STOP BYTE
+ *
+ * STRUCTURE OF A VALID COMMAND TRANSACTION
+ *
+ * START BYTE | COMMAND TYPE | COMMAND BYTE | STOP BYTE
+ *
+ * STUCTURE OF VALID INFO TRANSACTION
+ *
+ * START BYTE | INFO TYPE | INFO BYTE | STOP BYTE
+ *
+ * If no rx has been received for more than 500ms the rx state is reset to checking for start byte
+ * This ensures the open logger does not get stuck in the middle of a transaction if the master stops sending data
+ *
+ */
+void openloggerBegin(uint32_t serialBaud);
+
+void openloggerBeginWrites();
+
+void openloggerStopWrites();
+
+void openloggerProcess();
+
+void openloggerWrite(void *pPayload, uint8_t payloadLen);
+
+void openloggerWriteCommand(uint8_t command);
+
+
+#endif //SUFST_OPENLOGGER_INO_SDCARDMASTER_H
diff --git a/Legacy-firmware/sufst-openlogger_controller/sufst-openlogger_controller.ino b/Legacy-firmware/sufst-openlogger_controller/sufst-openlogger_controller.ino
new file mode 100644
index 0000000..4a2d09a
--- /dev/null
+++ b/Legacy-firmware/sufst-openlogger_controller/sufst-openlogger_controller.ino
@@ -0,0 +1,64 @@
+#define DEBUG_ECU_CAN 0
+#define DEBUG_ECU_CAN_MINIMAL 0
+
+#include "openLoggerController.h"
+#include "ecuCan.h"
+#include "can.h"
+
+// Watchdog
+#include <avr/wdt.h>
+
+#define OPENLOGGER_SERIAL_BUAD_RATE 115200
+
+uint8_t arduinoProcessSerial();
+
+void setup()
+{
+    // put your setup code here, to run once:
+
+
+    // Serial port for host pc communications
+    Serial.begin(115200);
+
+    Serial.println("BEGIN");
+
+    // Openlogger runs on uart port TX1 RX1 (Serial1)
+    openloggerBegin(OPENLOGGER_SERIAL_BUAD_RATE);
+
+    canBegin();
+}
+
+void loop()
+{
+    // put your main code here, to run repeatedly:
+
+    /*
+   * ALL PROCESSES *MUST* BE NON BLOCKING
+   */
+    wdt_reset();
+
+    openloggerProcess();
+    arduinoProcessSerial();
+    canProcessRx();
+    canProcessTx();
+}
+
+uint8_t arduinoProcessSerial()
+{
+    if (Serial.available()) {
+
+        uint8_t serialByte = Serial.read();
+
+        switch (serialByte) {
+            case 'g':openloggerBeginWrites();
+
+                break;
+
+            case 's':openloggerStopWrites();
+
+                break;
+        }
+    }
+
+    return 1;
+}
-- 
GitLab