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
main.cpp
- Committer:
- wakestrap
- Date:
- 2020-03-15
- Revision:
- 16:0eda62f0d9e8
- Parent:
- 15:03ed24574806
- Child:
- 17:00d66e5edf58
File content as of revision 16:0eda62f0d9e8:
#include "mbed.h" #include "EthernetInterface.h" #include <mbed.h> #include "Thread.h" /* ---------------------------------------------------------------------------------------- */ #define PORT 2342 #define DEBUG 0 #define OUTPUTENABLE 0 #if DEBUG #endif //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 //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 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]; struct VesselData { 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() { //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()); UDPSocket server; server.bind(PORT); 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()); #endif 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"); 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 } 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); if(ret > 0) { int packetCheckState = 0; #if DEBUG printf("Packet Rx'd \n\r"); #endif for(int x = 0; x < 4; x++) { switch(packetCheckState){ case 0: // CHECK HEADER 1 if(buffer[packetCheckState] == 0xBE) { packetCheckState++; } break; case 1: // CHECK HEADER 2 if(buffer[packetCheckState] == 0xEF) { packetCheckState++; } 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(packetCheckState == 3) //We had a valid packet { calc_CS = rx_len; for(int i = 0; i < rx_len; i++) { payloadBuffer[i] = buffer[i+3]; calc_CS^=buffer[i+3]; } 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); 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) 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 { //failed checksum, need to clear this out anyway printf("Failed Checksum! Sorry \n\r"); rx_len = 0; rx_array_inx = 1; return false; } } } 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; 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; KSPBoardSendData(details(HPacket)); }