NETMF_Autopilot/Hardware/SkyTraqVenus6_GPS.cs

188 lines
6.0 KiB
C#

using System;
using System.IO;
using System.IO.Ports;
using Microsoft.SPOT;
using System.Threading;
using GHIElectronics.NETMF.System;
namespace PlaneOnBoardSoftware
{
public class SkyTraqVenus6_GPS
{
private byte MESSAGE_TYPE = 0x09;
private byte POSITION_RATE = 0x0E;
private DateTime GpsStartDate = new DateTime(1980, 1, 6);
SerialPort Uart;
byte[] rxBuffer = new byte[256];
int bufferPos = 0;
int packOffSet = 0;
private int gpsTimeOfWeek;
private int gpsWeekNumber;
//private Vector3D ECEFCoordinate = new Vector3D();
private Vector3D ECEFSpeed = new Vector3D();
public bool Has3DFix = false;
public double Latitude = 0;
public double Longitude = 0;
public float Altitude = 0;
public float EllipsoidAltitude = 0;
public float HorizontalDilution = 0;
public float VerticalDilution = 0;
public Vector3D Speed = new Vector3D();
public DateTime GpsTime = new DateTime();
public float Heading = 0;
public float GroundSpeed = 0;
public SkyTraqVenus6_GPS(SerialPort SerialPort)
{
Uart = SerialPort;
Uart.BaudRate = 9600;
Uart.Parity = Parity.None;
Uart.DataBits = 8;
Uart.StopBits = StopBits.One;
Uart.Open();
if (SerialPort.PortName.ToUpper() == "COM4")
{
FEZ_Low_Level.RemapCOM4to_TXAn2_RXAn3(Uart);
}
SendCommand(MESSAGE_TYPE, 2, 0); //Switch to Binary Output
//SendCommand(POSITION_RATE, 3, 0); //Switch to 1 Hz update rate
}
private void SendCommand(byte Command, byte Value1, byte Value2)
{
//<0xA0,0xA1>< PL><09>< message body><CS><0x0D,0x0A>
byte[] newCom = new byte[] { 0xA0, 0xA1, 0, 3, Command, Value1, Value2, 0xFF, 0x0D, 0x0A };
SetChecksum(newCom, 3);
Uart.Write(newCom, 0, 10);
Uart.Flush();
}
private byte GetChecksum(byte[] data, int PayloadLen)
{
int cs = 0;
for (int i = 0; i < PayloadLen; i++)
{
cs = cs ^ data[i + 4];
}
return (byte)cs;
}
private void SetChecksum(byte[] data, int PayloadLen)
{
data[PayloadLen + 4] = GetChecksum(data, PayloadLen);
}
public void ReadGPSData()
{
int read_count = 1;
int readLenght = 1;
int portBuffCount = Uart.BytesToRead;
while (portBuffCount > 0)
{
readLenght = portBuffCount;
if (readLenght > 128) readLenght = 128;
if (bufferPos > 128) bufferPos = 0;
read_count = Uart.Read(rxBuffer, bufferPos, readLenght);
portBuffCount -= read_count;
bufferPos += read_count;
}
for (int i = 0; i < 66; i++)
{
packOffSet = bufferPos - i - 66;
if (packOffSet < 0) break;
if (rxBuffer[packOffSet + 65] == 10 && rxBuffer[packOffSet + 64] == 13 &&
rxBuffer[packOffSet + 1] == 0xA1 && rxBuffer[packOffSet] == 0xA0)
break;
}
if (packOffSet > -1)
{
Has3DFix = (GetByte(2)==2);
Latitude = GetSignedInteger(10) * 10e-8;
Longitude = GetSignedInteger(14) * 10e-8;
/*ECEFCoordinate.X = GetSignedInteger(36) * 0.01f;
ECEFCoordinate.Y = GetSignedInteger(40) * 0.01f;
ECEFCoordinate.Z = GetSignedInteger(44) * 0.01f;*/
ECEFSpeed.X = GetSignedInteger(48) * 0.01f;
ECEFSpeed.Y = GetSignedInteger(52) * 0.01f;
ECEFSpeed.Z = GetSignedInteger(56) * 0.01f;
EllipsoidAltitude = GetSignedInteger(18) * 0.01f; //ellipsoid altitude
Altitude = GetSignedInteger(22) * 0.01f; //mean sea level altitude
HorizontalDilution = GetUSignInt16(30) * 0.01f;
VerticalDilution = GetUSignInt16(32) * 0.01f;
gpsWeekNumber = GetUSignInt16(4);
gpsTimeOfWeek = GetSignedInteger(6);
GpsTime = GpsStartDate.AddDays(gpsWeekNumber * 7).AddMilliseconds(gpsTimeOfWeek * 10);
Speed = ECEFtoLTPspeed(ECEFSpeed, Latitude, Longitude);
}
}
private Vector3D ECEFtoLTPspeed(Vector3D ECEFSpeed, double Latitude, double Longitude)
{
Vector3D GetLTPSpeed = new Vector3D();
double SinLat = MathEx.Sin(Latitude);
double SinLon = MathEx.Sin(Longitude);
double CosLat = MathEx.Cos(Latitude);
double CosLon = MathEx.Cos(Longitude);
GetLTPSpeed.X = (float)(-ECEFSpeed.X * SinLat * SinLon - ECEFSpeed.Y * SinLat * SinLon + ECEFSpeed.Z * CosLat); //Vnorth
GetLTPSpeed.Y = (float)(-ECEFSpeed.X * SinLon + ECEFSpeed.Y * CosLon); //Veast
GetLTPSpeed.Z = (float)(-ECEFSpeed.X * CosLat * CosLon - ECEFSpeed.Y * CosLat * SinLon + ECEFSpeed.Z * SinLat); //Vdown
return GetLTPSpeed;
}
private byte GetByte(int Field)
{
return rxBuffer[packOffSet + 3 + Field];
}
private int GetUSignInt16(int StartField)
{
int bufPos = packOffSet + 3 + StartField;
return (rxBuffer[bufPos] << 8) + rxBuffer[bufPos + 1];
}
private int GetSignedInteger(int StartField)
{
int buffer = 0;
for (int i = 0; i < 4; i++)
{
int bufPos = packOffSet + 3 + StartField + i;
buffer = (buffer << 8) + rxBuffer[bufPos];
}
return buffer;
}
}
}