A port of KSP SerialIO and KSP Ethernet IO designed for a Nucleo F746ZG. This version doesn't read from or write to any external controls or displays but the user can press the USER_BUTTON to change the status of SAS and RCS. A final version of this project with full documentation and external hardware support is coming. This is an Alpha release.

Dependencies:   F7_Ethernet mbed mbed-rtos

Files at this revision

API Documentation at this revision

Comitter:
wakestrap
Date:
Sun Mar 15 04:35:51 2020 +0000
Parent:
15:03ed24574806
Child:
17:00d66e5edf58
Commit message:
Working V0.1. All Comms Works. No external controls except button press.

Changed in this revision

PacketHandler.cpp Show diff for this revision Revisions of this file
PacketHandler.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Sat Mar 14 01:33:34 2020 +0000
+++ b/main.cpp	Sun Mar 15 04:35:51 2020 +0000
@@ -2,187 +2,242 @@
 #include "EthernetInterface.h"
 #include <mbed.h>
 #include "Thread.h"
+
 /* ---------------------------------------------------------------------------------------- */
  
 #define PORT 2342
-#define DEBUG 1
+#define DEBUG 0
 
+#define OUTPUTENABLE 0
 
 #if DEBUG
 
 #endif
-/*
-void makePacket(char *Payload,char *Packet)
-{
-    char Header1 = 0xBE;
-    char Header2 = 0xEF;
-    int checksum = sizeof(*Payload);
-    
-    *Packet[0] = Header1;
-    *Packet[1] = Header2;
-    *Packet[2] = sizeof(*Payload);
-    
-    for (int i = 0; i < *Packet[2]; i++)
-    {
-        checksum ^= *Payload[i];
-        *Packet[i+3] = *Payload[i];
-    }
-    *Packet[sizeof(*Packet)-1] = checksum;
- }
-*/
+
+//pins for LEDs
+#define GLED 5
+#define YLED 6
+#define RLED 7
+#define SASLED 11
+#define RCSLED 12
+#define CG1LED 13
+
+//pins for input
+#define SASPIN 8
+#define RCSPIN 9
+#define CG1PIN 10
+#define THROTTLEPIN 0
+
+#define THROTTLEDB 4 //Throttle axis deadband
+
+//Input enums
+#define SAS 7
+#define RCS 6
+#define LIGHTS 5
+#define GEAR 4
+#define BRAKES 3
+#define PRECISION 2
+#define ABORT 1
+#define STAGE 0
 
-DigitalIn press(USER_BUTTON);
+//Action group statuses
+#define AGSAS      0
+#define AGRCS      1
+#define AGLight    2
+#define AGGear     3
+#define AGBrakes   4
+#define AGAbort    5
+#define AGCustom01 6
+#define AGCustom02 7
+#define AGCustom03 8
+#define AGCustom04 9
+#define AGCustom05 10
+#define AGCustom06 11
+#define AGCustom07 12
+#define AGCustom08 13
+#define AGCustom09 14
+#define AGCustom10 15
+
+//SAS Modes
+#define SMOFF           0
+#define SMSAS           1
+#define SMPrograde      2
+#define SMRetroGrade    3
+#define SMNormal        4
+#define SMAntinormal    5
+#define SMRadialIn      6
+#define SMRadialOut     7
+#define SMTarget        8
+#define SMAntiTarget    9
+#define SMManeuverNode  10
+
+//Navball Target Modes
+#define NAVBallIGNORE   0
+#define NAVBallORBIT    1
+#define NAVBallSURFACE  2
+#define NAVBallTARGET   3
+
+//macro
+#define details(name) (uint8_t*)&name,sizeof(name)
+
+//if no message received from KSP for more than 2s, go idle
+#define IDLETIMER 8000
+#define CONTROLREFRESH 25
+
+//warnings
+#define GWARN 9                  //9G Warning
+#define GCAUTION 5               //5G Caution
+#define FUELCAUTION 10.0         //10% Fuel Caution
+#define FUELWARN 5.0             //5% Fuel warning
 
-    char id;              //1
-    float AP;             //2
-    float PE;             //3
-    float SemiMajorAxis;  //4
-    float SemiMinorAxis;  //5
-    float VVI;            //6
-    float e;              //7
-    float inc;            //8
-    float G;              //9
-    int TAp;              //10
-    int TPe;              //11
-    float TrueAnomaly;    //12
-    float Density;        //13
-    int period;           //14
-    float RAlt;           //15
-    float Alt;            //16
-    float Vsurf;          //17
-    float Lat;            //18
-    float Lon;            //19
-    float LiquidFuelTot;  //20
-    float LiquidFuel;     //21
-    float OxidizerTot;    //22
-    float Oxidizer;       //23
-    float EChargeTot;     //24
-    float ECharge;        //25
-    float MonoPropTot;    //26
-    float MonoProp;       //27
-    float IntakeAirTot;   //28
-    float IntakeAir;      //29
-    float SolidFuelTot;   //30
-    float SolidFuel;      //31
-    float XenonGasTot;    //32
-    float XenonGas;       //33
-    float LiquidFuelTotS; //34
-    float LiquidFuelS;    //35
-    float OxidizerTotS;   //36
-    float OxidizerS;      //37
-    uint32_t MissionTime;   //38
-    float deltaTime;      //39
-    float VOrbit;         //40
-    uint32_t MNTime;        //41
-    float MNDeltaV;       //42
-    uint16_t Pitch;          //43
-    uint16_t Roll;           //44
-    uint16_t Heading;        //45
-    uint16_t ActionGroups;  //46  status bit order:SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10 
-    char SOINumber;       //47  SOI Number (decimal format: sun-planet-moon e.g. 130 = kerbin, 131 = mun)
-    char MaxOverHeat;     //48  Max part overheat (% percent)
-    float MachNumber;     //49
-    float IAS;            //50  Indicated Air Speed
-    char CurrentStage;    //51  Current stage number
-    char TotalStage;      //52  TotalNumber of stages
-    float TargetDist;     //53  Distance to targeted vessel (m)
-    float TargetV;        //54  Target vessel relative velocity (m/s)
-    char NavballSASMode;  //55  Combined byte for navball target mode and SAS mode
-                             // First four bits indicate AutoPilot mode:
-                             // 0 SAS is off  //1 = Regular Stability Assist //2 = Prograde
-                             // 3 = RetroGrade //4 = Normal //5 = Antinormal //6 = Radial In
-                             // 7 = Radial Out //8 = Target //9 = Anti-Target //10 = Maneuver node
-                             // Last 4 bits set navball mode. (0=ignore,1=ORBIT,2=SURFACE,3=TARGET)
-    uint16_t ProgradePitch;  //56 Pitch   Of the Prograde Vector;  int_16 ranging from (-0x8000(-360 degrees) to 0x7FFF(359.99ish degrees)); 
-    uint16_t ProgradeHeading;//57 Heading Of the Prograde Vector;  see above for range   (Prograde vector depends on navball mode, eg Surface/Orbit/Target)
-    uint16_t ManeuverPitch;  //58 Pitch   Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
-    uint16_t ManeuverHeading;//59 Heading Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
-    uint16_t TargetPitch;    //60 Pitch   Of the Target   Vector;  see above for range;  (0 if no Target)
-    uint16_t TargetHeading;  //61 Heading Of the Target   Vector;  see above for range;  (0 if no Target)
-    uint16_t NormalHeading;  //62 Heading Of the Prograde Vector;  see above for range;  (Pitch of the Heading Vector is always 0)
-    char vesselSync;       //63 Starting with 1, increased on every VesselChange
+void Indicators();
+void initLEDS();
+void LEDSAllOff();
+void InitTxPackets();
+int input();
+char ControlStatus(char n);
+void output();
+void controls();
+void controlsInit();
+char getSASMode();
+char getNavballMode();
+void setSASMode(char m);
+void setNavballMode(char m);
+void MainControls(char n, bool s);
+void ControlGroups(char n, bool s);
+bool KSPBoardReceiveData();
+void KSPBoardSendData(uint8_t * data, uint8_t len);
+void Handshake();
+
+DigitalIn ControlButton(USER_BUTTON);
+
+int deadtime, deadtimeOld, controlTime, controlTimeOld;
+int now;
+Timer t;
+bool Connected = false;
+char VesselID = 0;
+char caution = 0, warning = 0, id;
+
+uint8_t rx_len;
+uint16_t * address;
+char buffer[256]; //address for temporary storage and parsing buffer
+uint8_t structSize;
+uint8_t rx_array_inx;  //index for RX parsing buffer
+uint8_t calc_CS;       //calculated Chacksum
+char payloadBuffer[255];
 
-void float2Bytes(char bytes_temp[4],float float_variable){ 
-  union {
-    float a;
-    unsigned char bytes[4];
-  } thing;
-  thing.a = float_variable;
-  memcpy(bytes_temp, thing.bytes, 4);
-}
-
-void unpackVesselData(char *PayloadBuffer, int payloadLength)
+struct VesselData
 {
-    char varBuffer[8];
-    id = PayloadBuffer[0];              //1
-    if(id == 0x01)
-    {   
-        //float AP - 1    
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+1];
-        }
-        /**
-        varBuffer[1]=PayloadBuffer[2];
-        varBuffer[2]=PayloadBuffer[3];
-        varBuffer[3]=PayloadBuffer[4];
-        **/ 
-        AP = *(float *)&varBuffer;
-        
-        // float PE - 5
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+5];
-        }    
-        PE = *(float *)&varBuffer;
-        
-        //float SemiMajorAxis - 9
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+9];
-        }  
-        SemiMajorAxis = *(float *)&varBuffer;
-        
-        //float SemiMinorAxis - 13
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+13];
-        }  
-        SemiMinorAxis = *(float *)&varBuffer;  //5
-        
-        //float VVI 17
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+17];
-        }  
-        VVI = *(float *)&varBuffer;            //6
-        
-        //float e - 21
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+21];
-        }  
-        e = *(float *)&varBuffer;              //7
-        
-        //float inc - 25
-        for(int i=0; i < 4; i++)
-        {
-            varBuffer[i]=PayloadBuffer[i+25];
-        }  
-        inc = *(float *)&varBuffer;            //8
-    }
-    else
-    {
-        printf("Bad Packet Id: %d", id);
-    }
-}
+     char id;              //1
+     float AP;             //2
+     float PE;             //3
+     float SemiMajorAxis;  //4
+     float SemiMinorAxis;  //5
+     float VVI;            //6
+     float e;              //7
+     float inc;            //8
+     float G;              //9
+     int TAp;              //10
+     int TPe;              //11 41
+     float TrueAnomaly;    //12
+     float Density;        //13
+     int period;           //14
+     float RAlt;           //15
+     float Alt;            //16 61
+     float Vsurf;          //17
+     float Lat;            //18
+     float Lon;            //19
+     float LiquidFuelTot;  //20
+     float LiquidFuel;     //21
+     float OxidizerTot;    //22
+     float Oxidizer;       //23
+     float EChargeTot;     //24
+     float ECharge;        //25
+     float MonoPropTot;    //26
+     float MonoProp;       //27
+     float IntakeAirTot;   //28
+     float IntakeAir;      //29
+     float SolidFuelTot;   //30
+     float SolidFuel;      //31
+     float XenonGasTot;    //32
+     float XenonGas;       //33
+     float LiquidFuelTotS; //34
+     float LiquidFuelS;    //35
+     float OxidizerTotS;   //36
+     float OxidizerS;      //37
+     uint32_t MissionTime;   //38
+     float deltaTime;      //39
+     float VOrbit;         //40
+     uint32_t MNTime;        //41
+     float MNDeltaV;       //42 165
+     uint16_t Pitch;          //43
+     uint16_t Roll;           //44
+     uint16_t Heading;        //45
+     uint16_t ActionGroups;  //46   173 status bit order:SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10 
+     char SOINumber;       //47  SOI Number (decimal format: sun-planet-moon e.g. 130 = kerbin, 131 = mun)
+     char MaxOverHeat;     //48 175 Max part overheat (% percent)
+     float MachNumber;     //49
+     float IAS;            //50  Indicated Air Speed
+     char CurrentStage;    //51  Current stage number
+     char TotalStage;      //52  185 TotalNumber of stages
+     float TargetDist;     //53  Distance to targeted vessel (m)
+     float TargetV;        //54  193 Target vessel relative velocity (m/s)
+     char NavballSASMode;  //55 194 Combined char for navball target mode and SAS mode
+                                 // First four bits indicate AutoPilot mode:
+                                 // 0 SAS is off  //1 = Regular Stability Assist //2 = Prograde
+                                 // 3 = RetroGrade //4 = Normal //5 = Antinormal //6 = Radial In
+                                 // 7 = Radial Out //8 = Target //9 = Anti-Target //10 = Maneuver node
+                                 // Last 4 bits set navball mode. (0=ignore,1=ORBIT,2=SURFACE,3=TARGET)
+     uint16_t ProgradePitch;  //56 Pitch   Of the Prograde Vector;  int_16 ranging from (-0x8000(-360 degrees) to 0x7FFF(359.99ish degrees)); 
+     uint16_t ProgradeHeading;//57 Heading Of the Prograde Vector;  see above for range   (Prograde vector depends on navball mode, eg Surface/Orbit/Target)
+     uint16_t ManeuverPitch;  //58 Pitch   Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
+     uint16_t ManeuverHeading;//59 Heading Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
+     uint16_t TargetPitch;    //60 Pitch   Of the Target   Vector;  see above for range;  (0 if no Target)
+     uint16_t TargetHeading;  //61 Heading Of the Target   Vector;  see above for range;  (0 if no Target)
+     uint16_t NormalHeading;  //62 Heading Of the Prograde Vector;  see above for range;  (Pitch of the Heading Vector is always 0)
+     char vesselSync;       //63 208 Starting with 1, increased on every VesselChange
+};
 
 
+struct HandShakePacket
+{
+  char id;
+  char M1;
+  char M2;
+  char M3;
+};
 
+struct ControlPacket {
+  char id;
+  char MainControls;                  //SAS RCS Lights Gear Brakes Precision Abort Stage
+  char Mode;                          //0 = stage, 1 = docking, 2 = map
+  short ControlGroup;          //control groups 1-10 in 2 chars
+  char NavballSASMode;                //AutoPilot mode
+  char AdditionalControlByte1; //9
+  int32_t Pitch;                          //-1000 -> 1000
+  int32_t Roll;                           //-1000 -> 1000
+  int32_t Yaw;                            //-1000 -> 1000
+  int32_t TX;                             //-1000 -> 1000
+  int32_t TY;                             //-1000 -> 1000
+  int32_t TZ;                             //-1000 -> 1000
+  int32_t WheelSteer;                     //-1000 -> 1000
+  int32_t Throttle;                       //    0 -> 1000
+  int32_t WheelThrottle;                  //    0 -> 1000
+  char vesselSync;                    //Starting with 1, increased on every VesselChange
+};
+
+HandShakePacket HPacket;
+VesselData VData;
+ControlPacket CPacket;
+EthernetInterface eth;
+TCPSocketConnection sock;
+ 
 
 int main() {
-   
-    EthernetInterface eth;
+    //SETUP
+    
+    t.start();
+    printf("\n\r KSP mbedIO V0.1 \n\r");
     eth.init(); //Use DHCP
     eth.connect();
     printf("\nServer IP Address is %s\n\r", eth.getIPAddress());
@@ -193,228 +248,710 @@
     Endpoint KSPServer;
     char buffer[256];
     
-        printf("Waiting for UDP packet...\n\r");
-        int n = server.receiveFrom(KSPServer, buffer, sizeof(buffer));
-        buffer[n] = '\0';
-        #if DEBUG
-        printf("Received packet from: %s\n\r", KSPServer.get_address());
-        //printf("Packet contents : '%s'\n\r",buffer);
-        #endif
-       // server.sendTo(client, buffer, n)
-   
-      
-    /**
-    
-    HSPacket.id=0;
-    HSPacket.M1=3;
-    HSPacket.M2=1;
-    HSPacket.status=4;
-    **/
-    char HSPayload[4]={0x00, 0x03, 0x01, 0x04};
-    char HSPacket[sizeof(HSPayload)+4];
-    char Header1 = 0xBE;
-    char Header2 = 0xEF;
-    int checksum = sizeof(HSPayload);
-    
-    HSPacket[0] = Header1;
-    HSPacket[1] = Header2;
-    HSPacket[2] = sizeof(HSPayload);
-    
-    int CurrentPacketLength=0;
-    int CurrentBytesRead=0;
-    char PayloadBuffer[300];
-    char NewPacketBuffer[300];
+    printf("Waiting for UDP packet...\n\r");
+    int n = server.receiveFrom(KSPServer, buffer, sizeof(buffer));
+    buffer[n] = '\0';
+    #if DEBUG
+    printf("Received packet from: %s\n\r", KSPServer.get_address());
+    #endif
 
-    for (int i = 0; i < sizeof(HSPayload); i++)
-    {
-        checksum ^= HSPayload[i];
-        HSPacket[i+3] = HSPayload[i];
-    }
-    HSPacket[sizeof(HSPacket)-1] = checksum;
-    
-    
-    for(int i=0;i<sizeof(HSPacket);i++)
-    {
-        printf("%c", HSPacket[i]);
-    }
-    
-    //makePacket(HSPayload, HSPacket);
-    
-    TCPSocketConnection sock;
+    sock.set_blocking(false, 500); // Set socket to non-blocking and set the timeout for 500ms
     
     while (sock.connect(KSPServer.get_address(), PORT) < 0) {
         printf("Unable to connect to KSPServer on Port %d \r\n", PORT);
         wait(1);
     }
+    printf("Connected to KSPServer on Port %d \r\n", PORT);
+    Handshake();
+    printf("Handshake sent \r\n");
     
-    printf("Connected to KSP Server \n\r");
-    sock.send(HSPacket, sizeof(HSPacket));
+    
+    initLEDS();
+    InitTxPackets();
+   // controlsInit();
+
+    LEDSAllOff();
+    while(true)
+    {
+        input();
+        output();
+    }
+}
+
+
+
+//////////////////////////////////////////////////
+/////////////////// CONTROLS /////////////////////
+//////////////////////////////////////////////////
+
+void Indicators() {
+    caution = 0;
+    warning = 0;
+    
+    caution += VData.G > GCAUTION;
+    warning += VData.G > GWARN;
+    caution += VData.LiquidFuelS/VData.LiquidFuelTotS*100 < FUELCAUTION;
+    warning += VData.LiquidFuelS/VData.LiquidFuelTotS*100 < FUELWARN;
+    
+    if (caution != 0)
+    {
+        printf("Yellow! \n\r");
+    }
+    else
+    {
+        //yel off
+    }
     
-    while (sock.is_connected()) {
-        char buffer[300];
-        int ret;
+    if (warning != 0)
+    {
+        printf("RED! \n\r");
+    }
+    else
+    {
+        //red off
+    }
+    #if OUTPUTENABLE
+    printf("AP : %f \n\r", VData.AP);
+    printf("Sync : %d \n\r", VData.vesselSync);
+    printf("Alt : %f \n\r", VData.Alt);
+    printf("Vsurf : %f \n\r", VData.Vsurf);
+    if(ControlStatus(AGSAS)) printf("AGSAS ON \n\r");
+    if(ControlStatus(AGRCS)) printf("AGRCS ON \n\r");
+    if(ControlStatus(AGCustom01)) printf("AGCustom1 ON \n\r");
+    #endif
+}
+
+void initLEDS() {
+
+}
+
+void LEDSAllOff() {
+
+}
+
+void InitTxPackets() {
+  HPacket.id = 0;  
+  CPacket.id = 101;
+}
+
+
+//////////////////////////////////////////////////
+//////////////////// INPUT   /////////////////////
+//////////////////////////////////////////////////
+
+int input() {
+  int returnValue = -1;
+  now = t.read_ms();
+
+  if (KSPBoardReceiveData())
+  {
+    deadtimeOld = now;
+    returnValue = id;
+    switch(id) 
+    {
+        case 0: //Handshake packet
+            Handshake();
+            #if DEBUG
+            printf("HS Packet recieved\n\r");
+            #endif
+            break;
+        case 1:
+            VesselID = VData.vesselSync;
+            Indicators();
+            #if DEBUG
+            printf("VD Packet recieved\n\r");
+            #endif
+            break;
+    }
+    Connected = true;
+  }
+  
+  else
+  { //if no message received for a while, go idle
+    deadtime = now - deadtimeOld; 
+    if (deadtime > IDLETIMER)
+    {
+      deadtimeOld = now;
+      Connected = false;
+      LEDSAllOff();
+      printf("No packets for a while... going Idle \n\r");
+    }    
+  }
+
+  return returnValue;
+}
+
+char ControlStatus(char n)
+{
+  return ((VData.ActionGroups >> n) & 1) == 1;
+}
+
+//////////////////////////////////////////////////
+///////////////////// OUTPUT /////////////////////
+//////////////////////////////////////////////////
+
+void output() {
+  now = t.read_ms();
+  controlTime = now - controlTimeOld;
+  if (controlTime > CONTROLREFRESH) {
+    controlTimeOld = now;
+    controls();
+  }
+}
+
+void controls() {
+  if (Connected) {
+
+    if (!ControlButton) { //--------- This is how you do main controls
+        MainControls(SAS, 1);
+        setSASMode(SMSAS); //setting SAS mode
+        #if DEBUG
+        printf("SAS PRESS \n\r");
+        #endif
+      //setNavballMode(NAVBallSURFACE); //setting navball mode
+    }
+    else {
+      //setNavballMode(NAVBallTARGET);
+      MainControls(SAS, 0);
+    }
+
+    if (ControlButton)
+      MainControls(RCS, 1);
+    else
+      MainControls(RCS, 0);
+
+    /**
+    if (digitalRead(CG1PIN))   //--------- This is how you do control groups
+      ControlGroups(1, 1);
+    else
+      ControlGroups(1, 0);
+      **/
+    /*
+       if (getSASMode() == SMPrograde) { //--------- This is how you read SAS modes
+         //Blink LED, do stuff, etc.
+       }
+
+       if (getNavballMode() == NAVBallTARGET) { //--------- This is how you read navball modes
+         //Blink LED, do stuff, etc.
+       }
+    */
+
+    //This is an example of reading analog inputs to an axis, with deadband and limits
+    //CPacket.Throttle = constrain(map(analogRead(THROTTLEPIN), THROTTLEDB, 1024 - THROTTLEDB, 0, 1000), 0, 1000);
+
+    //This is an example of reading analog inputs to an axis, with deadband and limits
+    //CPacket.Pitch = constrain(map(analogRead(THROTTLEPIN),0,1024,-1000,1000),-1000, 1000);
+    CPacket.vesselSync = VData.vesselSync;
+    KSPBoardSendData(details(CPacket));
+  }
+}
+
+void controlsInit() {
+  /**
+  pinMode(SASPIN, INPUT_PULLUP);
+  pinMode(RCSPIN, INPUT_PULLUP);
+  pinMode(CG1PIN, INPUT_PULLUP);
+  **/
+}
+
+char getSASMode() {
+  return VData.NavballSASMode & 0b00001111; // leaves alone the lower 4 bits of; all higher bits set to 0.
+}
+
+char getNavballMode() {
+  return VData.NavballSASMode >> 4; // leaves alone the higher 4 bits of; all lower bits set to 0.
+}
+
+void setSASMode(char m) {
+  CPacket.NavballSASMode &= 0b11110000;
+  CPacket.NavballSASMode += m;
+}
+
+void setNavballMode(char m) {
+  CPacket.NavballSASMode &= 0b00001111;
+  CPacket.NavballSASMode += m << 4;
+}
+
+void MainControls(char n, bool s) {
+  if (s)
+    CPacket.MainControls |= (1 << n);       // forces nth bit of x to be 1.  all other bits left alone.
+  else
+    CPacket.MainControls &= ~(1 << n);      // forces nth bit of x to be 0.  all other bits left alone.
+}
+
+void ControlGroups(char n, bool s) {
+  if (s)
+    CPacket.ControlGroup |= (1 << n);       // forces nth bit of x to be 1.  all other bits left alone.
+  else
+    CPacket.ControlGroup &= ~(1 << n);      // forces nth bit of x to be 0.  all other bits left alone.
+}
+
+
+
+
+//////////////////////////////////////////////////
+//////////////// COMMUNICATIONS///////////////////
+//////////////////////////////////////////////////
+
+
+
+bool KSPBoardReceiveData() {
+    int ret;
         
-        ret = sock.receive(buffer, sizeof(buffer)-1);
-        buffer[ret] = '\0';
-        if(ret > 0)
+    ret = sock.receive(buffer, sizeof(buffer)-1);
+    
+    if(ret > 0)
+    {
+      int packetCheckState = 0;
+        #if DEBUG
+        printf("Packet Rx'd \n\r");
+        #endif
+        for(int x = 0; x < 4; x++)
         {
-            int CurrentState = 0;
-            
-            for (int x = 0; x < sizeof(buffer)-1; x++)
-            {
-                switch (CurrentState)
+          switch(packetCheckState){
+            case 0: // CHECK HEADER 1
+                if(buffer[packetCheckState] == 0xBE)
                 {
-                    case 0: //HEADER 1
-                        if (buffer[x] == 0xBE) CurrentState = 1;
-                        break;
-                    case 1:
-                        if (buffer[x] == 0xEF) CurrentState = 2;
-                        else CurrentState = 0;
-                        break;
-                    case 2: //HEADER 2
-                        CurrentPacketLength = (int)buffer[x];
-                        checksum = CurrentPacketLength;
-                        CurrentBytesRead = 0;
-                        CurrentState = 3;
-                        break;
-                    case 3: //PAYLOAD SIZE
-                        PayloadBuffer[CurrentBytesRead] = buffer[x];
-                        CurrentBytesRead++;
-                        if (CurrentBytesRead == CurrentPacketLength)
-                        {
-                            CurrentState = 4;
-                        }
-                        break;
-                    case 4://CHECKSUM
-                        for (int i = 0; i < CurrentPacketLength; i++)
-                        {
-                            checksum ^= PayloadBuffer[i];
-                        }
-                        if(buffer[x] == checksum)
-                        {
-                            #if DEBUG
-                            printf("Checksum Success. Payload recieved. \r\n");
-                            #endif
-                        }
-                        else printf("Checksum Failed! Sorry. \r\n");
-                        CurrentState = 0;
-                        break;
+                    packetCheckState++;
+                }
+                break;
+            case 1: // CHECK HEADER 2
+                if(buffer[packetCheckState] == 0xEF)
+                {
+                    packetCheckState++;
                 }
-            }
-            #if DEBUG
-            printf("Payload ID: %d \r\n", PayloadBuffer[0]);
-            #endif
-            if(PayloadBuffer[0] == 0)
-            {
-                
+                break;
+            case 2: // GET PAYLOAD SIZE
+                rx_len = buffer[packetCheckState];
+                packetCheckState++;
+                #if DEBUG
+                printf("PL Size at Rx: %d \n\r", rx_len);
+                #endif
+                break;
+            case 3:
+                id = buffer[packetCheckState];
+                #if DEBUG
+                printf("Packet ID: %d \n\r", id);
+                #endif
+                if(id == 0)
+                {
+                    structSize = sizeof(HPacket);   
+                    address = (uint16_t*)&HPacket;
+                }
+                else if(id == 1)
+                {
+                    structSize = sizeof(VData);   
+                    address = (uint16_t*)&VData;     
+                }
+                else
+                {
+                    printf("Bad Packet ID: %d", buffer[packetCheckState]);
+                    packetCheckState = 0;
+                }
+                break;
+            default :
+                printf("Something went wrong in Packet Rx Loop \r\n");
+                break;
             }
-            if(PayloadBuffer[0] == 1)
+        }
+        
+        if(packetCheckState == 3) //We had a valid packet
+        {
+            calc_CS = rx_len;
+            for(int i = 0; i < rx_len; i++)
             {
-                unpackVesselData(PayloadBuffer, CurrentPacketLength);
-                #if OUTPUTENABLE
-                printf("AP %f \n\r", AP);
-                #endif
-                printf("00000%s",PayloadBuffer);
-                printf("CCCCC%c",checksum);
-                //sock.send(HSPacket, sizeof(HSPacket));
+                payloadBuffer[i] = buffer[i+3];
+                calc_CS^=buffer[i+3];
             }
             
-            else
+            if(calc_CS == buffer[rx_len+3])   //CS Check
             {
+                char varBuffer[4];
+                #if DEBUG
+                printf("Checksum Passed! \n\r");
+                #endif
+                
+                // A note to the reader, I hate this as much as you do. I really do. 
+                // But I'm a shitty programmer and this compiler pads structs for alignment and it fucks up the memcpy approach. 
+                // I fought this, I really did. But it's 2AM, and I just want my fucking code to work. So forgive me this sin.
+                
+                //memcpy(address,payloadBuffer,structSize);
                 
-            }
-            
-                                         //55  Combined byte for navball target mode and SAS mode
+                VData.id = payloadBuffer[0];              //1
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+1];
+                }    
+                VData.AP = *(float *)&varBuffer;
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+5];
+                }
+                VData.PE = *(float *)&varBuffer;             //3
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+9];
+                }
+                VData.SemiMajorAxis = *(float *)&varBuffer;  //4
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+13];
+                }
+                VData.SemiMinorAxis = *(float *)&varBuffer;  //5
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+17];
+                }
+                VData.VVI = *(float *)&varBuffer;            //6
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+21];
+                }
+                VData.e = *(float *)&varBuffer;              //7
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+25];
+                }
+                VData.inc = *(float *)&varBuffer;            //8
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+29];
+                }
+                VData.G = *(float *)&varBuffer;              //9
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+33];
+                }
+                VData.TAp = *(int *)&varBuffer;              //10
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+37];
+                }
+                VData.TPe = *(int *)&varBuffer;              //11 41
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+41];
+                }
+                VData.TrueAnomaly = *(float *)&varBuffer;    //12
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+44];
+                }
+                VData.Density = *(float *)&varBuffer;        //13
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+49];
+                }
+                VData.period = *(int *)&varBuffer;           //14
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+53];
+                }
+                VData.RAlt = *(float *)&varBuffer;           //15
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+57];
+                }
+                VData.Alt = *(float *)&varBuffer;            //16 61
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+61];
+                }
+                VData.Vsurf = *(float *)&varBuffer;          //17
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+65];
+                }
+                VData.Lat = *(float *)&varBuffer;            //18
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+69];
+                }
+                VData.Lon = *(float *)&varBuffer;            //19
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+73];
+                }
+                VData.LiquidFuelTot = *(float *)&varBuffer;  //20
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+77];
+                }
+                VData.LiquidFuel = *(float *)&varBuffer;     //21
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+81];
+                }
+                VData.OxidizerTot = *(float *)&varBuffer;    //22
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+85];
+                }
+                VData.Oxidizer = *(float *)&varBuffer;       //23
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+89];
+                }
+                VData.EChargeTot = *(float *)&varBuffer;     //24
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+93];
+                }
+                VData.ECharge = *(float *)&varBuffer;        //25
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+97];
+                }
+                VData.MonoPropTot = *(float *)&varBuffer;    //26
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+101];
+                }
+                VData.MonoProp = *(float *)&varBuffer;       //27
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+104];
+                }
+                VData.IntakeAirTot = *(float *)&varBuffer;   //28
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+109];
+                }
+                VData.IntakeAir = *(float *)&varBuffer;      //29
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+113];
+                }
+                VData.SolidFuelTot = *(float *)&varBuffer;   //30
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+117];
+                }
+                VData.SolidFuel = *(float *)&varBuffer;      //31
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+121];
+                }
+                VData.XenonGasTot = *(float *)&varBuffer;    //32
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+125];
+                }
+                VData.XenonGas = *(float *)&varBuffer;       //33
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+129];
+                }
+                VData.LiquidFuelTotS = *(float *)&varBuffer; //34
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+133];
+                }
+                VData.LiquidFuelS = *(float *)&varBuffer;    //35
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+137];
+                }
+                VData.OxidizerTotS = *(float *)&varBuffer;   //36
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+141];
+                }
+                VData.OxidizerS = *(float *)&varBuffer;      //37
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+145];
+                }
+                VData.MissionTime = *(uint32_t *)&varBuffer;   //38
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+149];
+                }
+                VData.deltaTime = *(float *)&varBuffer;      //39
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+153];
+                }
+                VData.VOrbit = *(float *)&varBuffer;         //40
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+157];
+                }
+                VData.MNTime = *(uint32_t *)&varBuffer;        //41
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+161];
+                }
+                VData.MNDeltaV = *(float *)&varBuffer;       //42 165
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+165];
+                }
+                VData.Pitch = *(float *)&varBuffer;          //43//////////////////////////
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+167];
+                }
+                VData.Roll = *(float *)&varBuffer;           //44
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+169];
+                }
+                VData.Heading = *(float *)&varBuffer;        //45
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+173];
+                }
+                VData.ActionGroups = *(float *)&varBuffer;  //46   173 status bit order:SAS, RCS, Light, Gear, Brakes, Abort, Custom01 - 10 
+                VData.SOINumber = payloadBuffer[177];       //47  SOI Number (decimal format: sun-planet-moon e.g. 130 = kerbin, 131 = mun)
+                VData.MaxOverHeat = payloadBuffer[178];    //48 175 Max part overheat (% percent)
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+179];
+                }
+                VData.MachNumber = *(float *)&varBuffer;     //49
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+183];
+                }
+                VData.IAS = *(float *)&varBuffer;            //50  Indicated Air Speed
+                
+                VData.CurrentStage = payloadBuffer[187];    //51  Current stage number
+                VData.TotalStage = payloadBuffer[188];      //52  185 TotalNumber of stages
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+189];
+                }
+                VData.TargetDist = *(float *)&varBuffer;     //53  Distance to targeted vessel (m)
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+193];
+                }
+                VData.TargetV = *(float *)&varBuffer;        //54  193 Target vessel relative velocity (m/s)
+                VData.NavballSASMode = payloadBuffer[197];  //55 194 Combined char for navball target mode and SAS mode
                                          // First four bits indicate AutoPilot mode:
                                          // 0 SAS is off  //1 = Regular Stability Assist //2 = Prograde
                                          // 3 = RetroGrade //4 = Normal //5 = Antinormal //6 = Radial In
                                          // 7 = Radial Out //8 = Target //9 = Anti-Target //10 = Maneuver node
                                          // Last 4 bits set navball mode. (0=ignore,1=ORBIT,2=SURFACE,3=TARGET)
-            char MainControls = 0b11111111;                  //SAS RCS Lights Gear Brakes Precision Abort Stage 
-            char Mode = 0b00000000;                          //0 = stage, 1 = docking, 2 = map (Bit 0-3) 
-                                                       //0 = Auto, 1 = Free, 2 = Orbital, 3 = Chase, 4 = Locked (Bit 4-7)
-            uint16_t ControlGroup = 0b00000000;                //control groups 1-10 in 2 bytes
-             char NavballSASMode = press;                //AutoPilot mode (See above for AutoPilot modes)(Ignored if the equal to zero or out of bounds (>10)) //Navball mode
-             short Throttle = 500; 
-            if(press)
-            {
-                NavballSASMode = 0b01000000;
-                Throttle = 0;
-                printf("PRESS\n\r\n");
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+198];
+                }
+                VData.ProgradePitch = *(float *)&varBuffer;  //56 Pitch   Of the Prograde Vector;  int_16 ranging from (-0x8000(-360 degrees) to 0x7FFF(359.99ish degrees)); 
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+200];
+                }
+                VData.ProgradeHeading = *(float *)&varBuffer;//57 Heading Of the Prograde Vector;  see above for range   (Prograde vector depends on navball mode, eg Surface/Orbit/Target)
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+202];
+                }
+                VData.ManeuverPitch = *(float *)&varBuffer;  //58 Pitch   Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
+                for(int i=0; i < 4; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+204];
+                }
+                VData.ManeuverHeading = *(float *)&varBuffer;//59 Heading Of the Maneuver Vector;  see above for range;  (0 if no Maneuver node)
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+205];
+                }
+                VData.TargetPitch = *(float *)&varBuffer;    //60 Pitch   Of the Target   Vector;  see above for range;  (0 if no Target)
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+206];
+                }
+                VData.TargetHeading = *(float *)&varBuffer;  //61 Heading Of the Target   Vector;  see above for range;  (0 if no Target)
+                for(int i=0; i < 2; i++)
+                {
+                    varBuffer[i]=payloadBuffer[i+207];
+                }
+                VData.NormalHeading = *(float *)&varBuffer;  //62 Heading Of the Prograde Vector;  see above for range;  (Pitch of the Heading Vector is always 0)
+                VData.vesselSync = payloadBuffer[208];    
+
+                rx_len = 0;
+                return true;
             }
             else
             {
-                NavballSASMode = 0b00000000;
+                //failed checksum, need to clear this out anyway
+                printf("Failed Checksum! Sorry \n\r");
+                rx_len = 0;
+                rx_array_inx = 1;
+                return false;
             }
-             
-             
-             char AdditionalControlByte1 = 0;        //Bit 0: Open Menu, Bit 1: Open Map
-             short Pitch = 0;                        //-1000 -> 1000
-             short Roll = 0;                         //-1000 -> 1000
-             short Yaw = 0;                          //-1000 -> 1000
-             short TX = 0;                           //-1000 -> 1000
-             short TY = 0;                           //-1000 -> 1000
-             short TZ = 0;                           //-1000 -> 1000
-             short WheelSteer = 0;                   //-1000 -> 1000
-             //short Throttle = 500;                     // 0 -> 1000
-             short WheelThrottle = 0;                // 0 -> 1000
-             char vesselSync = PayloadBuffer[sizeof(PayloadBuffer)-1];
-             char vSync = vesselSync + 30;
-            printf("Vsync %c \n\r\n", vSync);
-            char CSPayload[26];
-            char CSPacket[sizeof(CSPayload)+4];
-            Header1 = 0xBE;
-            Header2 = 0xEF;
-            checksum = sizeof(CSPayload);
-            
-            CSPacket[0] = Header1;
-            CSPacket[1] = Header2;
-            CSPacket[2] = sizeof(CSPayload);
-            
-            CSPayload[0] = 101; //Csid 101
-            CSPayload[1] = MainControls;
-            CSPayload[2] = Mode;
-            CSPayload[3] = ControlGroup & 0xff;
-            CSPayload[4] = (ControlGroup >> 8);
-            CSPayload[5] = NavballSASMode;
-            CSPayload[6] = AdditionalControlByte1;
-            CSPayload[7] = Pitch & 0xff;
-            CSPayload[8] = (Pitch >> 8);
-            CSPayload[9] = Roll & 0xff;
-            CSPayload[10] = (Roll >> 8);
-            CSPayload[11] = Yaw & 0xff;
-            CSPayload[12] = (Yaw >> 8);
-            CSPayload[13] = TX & 0xff;
-            CSPayload[14] = (TX >> 8);
-            CSPayload[15] = TY & 0xff;
-            CSPayload[16] = (TY >> 8);
-            CSPayload[17] = TZ & 0xff;
-            CSPayload[18] = (TZ >> 8);
-            CSPayload[19] = WheelSteer & 0xff;
-            CSPayload[20] = (WheelSteer >> 8);
-            CSPayload[21] = Throttle & 0xff;
-            CSPayload[22] = (Throttle >> 8);
-            CSPayload[23] = WheelThrottle & 0xff;
-            CSPayload[24] = (WheelThrottle >> 8);
-            CSPayload[25] = vesselSync;
-            
-            for (int i = 0; i < sizeof(CSPayload); i++)
-            {
-                checksum ^= CSPayload[i];
-                CSPacket[i+3] = CSPayload[i];
-            }
-            CSPacket[sizeof(CSPacket)-1] = checksum;     
-            sock.send_all(CSPacket, sizeof(CSPacket));
-            
-            
+                
+
         }
-//        sock.send_all(HSPacket, sizeof(HSPacket));
     }
     
-      printf("We got shut down! Socket Closed!");
-    sock.close();
+    return false;
+}
+
+void KSPBoardSendData(uint8_t * data, uint8_t len){
+    uint8_t CS = len;
+    char fullPacket[len+4];
+    fullPacket[0] = 0xBE;
+    fullPacket[1] = 0xEF;
+    fullPacket[2] = len;
     
-    eth.disconnect();
+    if(*(data) == 101)
+    {
+        fullPacket[3] = 101; //Csid 101
+        fullPacket[4] = CPacket.MainControls;
+        fullPacket[5] = CPacket.Mode;
+        fullPacket[6] = CPacket.ControlGroup & 0xff;
+        fullPacket[7] = (CPacket.ControlGroup >> 8);
+        fullPacket[8] = CPacket.NavballSASMode;
+        fullPacket[9] = CPacket.AdditionalControlByte1;
+        fullPacket[10] = CPacket.Pitch & 0xff;
+        fullPacket[11] = (CPacket.Pitch >> 8);
+        fullPacket[12] = CPacket.Roll & 0xff;
+        fullPacket[13] = (CPacket.Roll >> 8);
+        fullPacket[14] = CPacket.Yaw & 0xff;
+        fullPacket[15] = (CPacket.Yaw >> 8);
+        fullPacket[16] = CPacket.TX & 0xff;
+        fullPacket[17] = (CPacket.TX >> 8);
+        fullPacket[18] = CPacket.TY & 0xff;
+        fullPacket[19] = (CPacket.TY >> 8);
+        fullPacket[20] = CPacket.TZ & 0xff;
+        fullPacket[21] = (CPacket.TZ >> 8);
+        fullPacket[22] = CPacket.WheelSteer & 0xff;
+        fullPacket[23] = (CPacket.WheelSteer >> 8);
+        fullPacket[24] = CPacket.Throttle & 0xff;
+        fullPacket[25] = (CPacket.Throttle >> 8);
+        fullPacket[26] = CPacket.WheelThrottle & 0xff;
+        fullPacket[27] = (CPacket.WheelThrottle >> 8);
+        fullPacket[28] = CPacket.vesselSync;
+        for(int i = 0; i<len; i++)
+        {
+            CS^= fullPacket[i+3];
+        }
+        fullPacket[sizeof(fullPacket)-1] = CS;
+    }
+    else
+    {
+        for(int i = 0; i<len; i++)
+        {
+            CS^=*(data+i);
+            fullPacket[i+3] = *(data+i);
+        }
+        fullPacket[sizeof(fullPacket)-1] = CS;
+    }
+    #if DEBUG
+    printf("Sending a Packet \n\r");
+    #endif
+    sock.send(fullPacket, sizeof(fullPacket)); // Send the packet 
+}
+
+void Handshake(){
+
+    HPacket.id = 0;
+    HPacket.M1 = 3;
+    HPacket.M2 = 1;
+    HPacket.M3 = 4;
     
-    while(1) {}
-}
\ No newline at end of file
+    KSPBoardSendData(details(HPacket));
+}