public GarminProtoPhysicalLayer() { //base.auto = true; rxPacket = new RxPacket(); TransTimeout = transactTimeout; // (ms) #if DEBUG LibSys.StatusBar.Trace("GarminProtoPhysicalLayer() buffer=" + rxPacket.RxBuffer.Length + " timeout=" + transactTimeout); #endif Open(); }
private uint TransTimeout; // (ms) public GarminProtoPhysicalLayer() { //base.auto = true; rxPacket = new RxPacket(); TransTimeout = transactTimeout; // (ms) #if DEBUG LibSys.StatusBar.Trace("GarminProtoPhysicalLayer() buffer=" + rxPacket.RxBuffer.Length + " timeout=" + transactTimeout); #endif Open(); }
/// <summary> /// computes checksum on the Rx buffer /// </summary> /// <returns>checksum</returns> public byte RxChecksum(RxPacket rxPacket) { byte cs = (byte)(rxPacket.RxPacketId + rxPacket.RxDatalength); for (int i = 0; i < rxPacket.RxBufferP; i++) { cs += rxPacket.RxBuffer[i]; } cs = (byte)(256 - cs); return(cs); }
public void logIncoming(RxPacket rxPacket) { if (Project.gpsLogPackets) { string str = "in: <" + pidToString(rxPacket.RxPacketId) + "> cnt=" + rxPacket.RxDatalength + " :"; int i; for (i = 0; i < rxPacket.RxBufferP && i < 100; i++) { str += " " + rxPacket.RxBuffer[i]; } if (i < rxPacket.RxBufferP) { str += "..."; } LibSys.StatusBar.Trace(str); } }
// this function knows about the boundaries of the packets and receives complete packets, // sending ACK / NAK as needed. protected override void OnRxChar(byte ch) { bool prevDle = gotDle; gotDle = (ch == 0x10); uint uch = (uint)ch; /* if(gotDle || prevDle) { log("-- ch: " + ((byte)ch) + " gotDle=" + gotDle + " prevDle=" + prevDle + " p=" + rxPacket.RxBufferP + " state=" + packetState); } else { log("ch: " + ((byte)ch)); } */ switch(packetState) { case PacketState.resync: //logError("resync -- ch: " + ((byte)ch)); resyncLostCount++; if(prevDle && ch == 0x3) // wait for opening DLE { logError("resync --> outside, lost " + resyncLostCount + " chars"); packetState = PacketState.outside; resyncLostCount = 0; } else if(gotDle && prevCh == 0x3) { logError("resync --> pid, lost " + resyncLostCount + " chars"); packetState = PacketState.pid; resyncLostCount = 0; } break; case PacketState.outside: if(gotDle) // wait for opening DLE { packetState = PacketState.pid; } else { if(ch != 0x3) { //logError("-- inbetween: " + ((byte)ch)); } else { //log("-- inbetween: " + ((byte)ch)); } } break; case PacketState.pid: if(gotDle || ch == 0x3) { // two DLE's is a wrong place ro resync, go on syncing: packetState = PacketState.resync; logError("-- two DLE's or 0x3 in pid"); break; } arxPacket = new RxPacket(); arxPacket.RxPacketId = ch; //log("-- pid -- RxPacketId: " + arxPacket.RxPacketId); packetState = PacketState.datalength; break; case PacketState.datalength: // first DLE in sequence of two is ignored: if(gotDle && prevDle || !gotDle) // DLE stuffing { if(prevDle && !gotDle) // single DLE not allowed - resync { logError("-- datalength ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxDatalength = (int)uch; //log("-- datalength -- RxDatalength: " + arxPacket.RxDatalength); packetState = PacketState.data; arxPacket.RxBufferP = 0; gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.data: // first DLE in sequence of two is ignored: if(gotDle && prevDle || !gotDle) // DLE stuffing { if(prevDle && !gotDle) // single DLE not allowed - resync { logError("-- data ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxBuffer[arxPacket.RxBufferP++] = ch; if(arxPacket.RxBufferP >= arxPacket.RxDatalength) { packetState = PacketState.chksum; } gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.chksum: // first DLE in sequence of two is ignored: if(gotDle && prevDle || !gotDle) // DLE stuffing { if(prevDle && !gotDle) // single DLE not allowed - resync { logError("-- chksum ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxBuffer[arxPacket.RxBufferP] = ch; packetState = PacketState.trailer; gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.trailer: logIncoming(arxPacket); if(arxPacket.RxPacketId != (byte)BasicPids.Pid_Ack_Byte && arxPacket.RxPacketId != (byte)BasicPids.Pid_Nak_Byte) { // some devices respond with two-byte ACK/NAK and do not understand standard // one-byte ACK/NAK. Match our response with whatever they have sent us before: byte[] rspBody = useTwoByteAck ? new byte[] { 0x0, 0x2, 0x0, 0x0 } : new byte[] { 0x0, 0x1, 0x0 }; // incoming ACK/NAK are not responded to, others are: byte cs = RxChecksum(arxPacket); if(ch != 0x10 || cs != arxPacket.RxBuffer[arxPacket.RxBufferP]) { logError("bad packet received (sending NAK) - ch=" + ((byte)ch) + " RxPacketId=" + arxPacket.RxPacketId + " cs=" + cs + " rec_cs=" + arxPacket.RxBuffer[arxPacket.RxBufferP]); arxPacket.RxBufferP = 0; // buffer data no good // prepare to send NAK: rspBody[0] = (byte)BasicPids.Pid_Nak_Byte; arxPacket.RxBadPacket = true; // signal bad packet has been received and NAK'ed rspBody[2] = arxPacket.RxPacketId; Send(rspBody); // send NAK } else { //log("good packet received (sending ACK) - ch=" + ((byte)ch) + " RxPacketId=" + arxPacket.RxPacketId + " cs=" + cs); // prepare to send ACK: rspBody[0] = (byte)BasicPids.Pid_Ack_Byte; arxPacket.RxBadPacket = false; rspBody[2] = arxPacket.RxPacketId; Send(rspBody); // send ACK } } else { // incoming ACK / NAK are not responded to arxPacket.RxBadPacket = false; // ACK / NAK considered good no matter what. useTwoByteAck = (arxPacket.RxDatalength == 2); // make sure we match their ACK size } rxPacket = arxPacket; arxPacket = null; gotDle = false; // trailer is a real DLE and doesn't participate in DLE stuffing resyncLostCount = 0; /* if (TransFlag.WaitOne(0,false)) // Transact/Receive waiting for result? { // we are not in Transact, let async OnRxPacket() work: if(!RxBadPacket) { byte[] packetBody; lock(RxBuffer) { packetBody = new Byte[RxBufferP - 1]; Array.Copy(RxBuffer, packetBody, (int)RxBufferP - 1); RxBufferP = 0; } OnRxPacket(RxPacketId, packetBody); // good unsolicited packet - call the callback function // knowing that ACK or NAK has been already sent } else { RxBufferP = 0; OnRxPacket(RxPacketId, null); // bad unsolicited packet - call the callback function // knowing that ACK or NAK has been already sent } } else */ { TransFlag.Set(); // we are in Transact or Receive, let it pick the result, good or bad, // knowing that ACK or NAK has been already sent } packetState = PacketState.outside; // 0x3 will be ignored in search for 0x10 break; } prevCh = ch; }
/// <summary> /// computes checksum on the Rx buffer /// </summary> /// <returns>checksum</returns> public byte RxChecksum(RxPacket rxPacket) { byte cs = (byte)(rxPacket.RxPacketId + rxPacket.RxDatalength); for(int i=0; i < rxPacket.RxBufferP ;i++) { cs += rxPacket.RxBuffer[i]; } cs = (byte)(256 - cs); return cs; }
public void logIncoming(RxPacket rxPacket) { if(Project.gpsLogPackets) { string str = "in: <" + pidToString(rxPacket.RxPacketId) + "> cnt=" + rxPacket.RxDatalength + " :"; int i; for(i=0; i < rxPacket.RxBufferP && i < 100 ;i++) { str += " " + rxPacket.RxBuffer[i]; } if(i < rxPacket.RxBufferP) { str += "..."; } LibSys.StatusBar.Trace(str); } }
// this function knows about the boundaries of the packets and receives complete packets, // sending ACK / NAK as needed. protected override void OnRxChar(byte ch) { bool prevDle = gotDle; gotDle = (ch == 0x10); uint uch = (uint)ch; /* * if(gotDle || prevDle) * { * log("-- ch: " + ((byte)ch) + " gotDle=" + gotDle + " prevDle=" + prevDle + " p=" + rxPacket.RxBufferP + " state=" + packetState); * } * else * { * log("ch: " + ((byte)ch)); * } */ switch (packetState) { case PacketState.resync: //logError("resync -- ch: " + ((byte)ch)); resyncLostCount++; if (prevDle && ch == 0x3) // wait for opening DLE { logError("resync --> outside, lost " + resyncLostCount + " chars"); packetState = PacketState.outside; resyncLostCount = 0; } else if (gotDle && prevCh == 0x3) { logError("resync --> pid, lost " + resyncLostCount + " chars"); packetState = PacketState.pid; resyncLostCount = 0; } break; case PacketState.outside: if (gotDle) // wait for opening DLE { packetState = PacketState.pid; } else { if (ch != 0x3) { //logError("-- inbetween: " + ((byte)ch)); } else { //log("-- inbetween: " + ((byte)ch)); } } break; case PacketState.pid: if (gotDle || ch == 0x3) { // two DLE's is a wrong place ro resync, go on syncing: packetState = PacketState.resync; logError("-- two DLE's or 0x3 in pid"); break; } arxPacket = new RxPacket(); arxPacket.RxPacketId = ch; //log("-- pid -- RxPacketId: " + arxPacket.RxPacketId); packetState = PacketState.datalength; break; case PacketState.datalength: // first DLE in sequence of two is ignored: if (gotDle && prevDle || !gotDle) // DLE stuffing { if (prevDle && !gotDle) // single DLE not allowed - resync { logError("-- datalength ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxDatalength = (int)uch; //log("-- datalength -- RxDatalength: " + arxPacket.RxDatalength); packetState = PacketState.data; arxPacket.RxBufferP = 0; gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.data: // first DLE in sequence of two is ignored: if (gotDle && prevDle || !gotDle) // DLE stuffing { if (prevDle && !gotDle) // single DLE not allowed - resync { logError("-- data ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxBuffer[arxPacket.RxBufferP++] = ch; if (arxPacket.RxBufferP >= arxPacket.RxDatalength) { packetState = PacketState.chksum; } gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.chksum: // first DLE in sequence of two is ignored: if (gotDle && prevDle || !gotDle) // DLE stuffing { if (prevDle && !gotDle) // single DLE not allowed - resync { logError("-- chksum ch: " + ((byte)ch) + " after single DLE caused resync"); packetState = PacketState.resync; break; } arxPacket.RxBuffer[arxPacket.RxBufferP] = ch; packetState = PacketState.trailer; gotDle = false; // so that prevDle won't be influenced by two legit DLE's } break; case PacketState.trailer: logIncoming(arxPacket); if (arxPacket.RxPacketId != (byte)BasicPids.Pid_Ack_Byte && arxPacket.RxPacketId != (byte)BasicPids.Pid_Nak_Byte) { // some devices respond with two-byte ACK/NAK and do not understand standard // one-byte ACK/NAK. Match our response with whatever they have sent us before: byte[] rspBody = useTwoByteAck ? new byte[] { 0x0, 0x2, 0x0, 0x0 } : new byte[] { 0x0, 0x1, 0x0 }; // incoming ACK/NAK are not responded to, others are: byte cs = RxChecksum(arxPacket); if (ch != 0x10 || cs != arxPacket.RxBuffer[arxPacket.RxBufferP]) { logError("bad packet received (sending NAK) - ch=" + ((byte)ch) + " RxPacketId=" + arxPacket.RxPacketId + " cs=" + cs + " rec_cs=" + arxPacket.RxBuffer[arxPacket.RxBufferP]); arxPacket.RxBufferP = 0; // buffer data no good // prepare to send NAK: rspBody[0] = (byte)BasicPids.Pid_Nak_Byte; arxPacket.RxBadPacket = true; // signal bad packet has been received and NAK'ed rspBody[2] = arxPacket.RxPacketId; Send(rspBody); // send NAK } else { //log("good packet received (sending ACK) - ch=" + ((byte)ch) + " RxPacketId=" + arxPacket.RxPacketId + " cs=" + cs); // prepare to send ACK: rspBody[0] = (byte)BasicPids.Pid_Ack_Byte; arxPacket.RxBadPacket = false; rspBody[2] = arxPacket.RxPacketId; Send(rspBody); // send ACK } } else { // incoming ACK / NAK are not responded to arxPacket.RxBadPacket = false; // ACK / NAK considered good no matter what. useTwoByteAck = (arxPacket.RxDatalength == 2); // make sure we match their ACK size } rxPacket = arxPacket; arxPacket = null; gotDle = false; // trailer is a real DLE and doesn't participate in DLE stuffing resyncLostCount = 0; /* * if (TransFlag.WaitOne(0,false)) // Transact/Receive waiting for result? * { * // we are not in Transact, let async OnRxPacket() work: * if(!RxBadPacket) * { * byte[] packetBody; * lock(RxBuffer) * { * packetBody = new Byte[RxBufferP - 1]; * Array.Copy(RxBuffer, packetBody, (int)RxBufferP - 1); * RxBufferP = 0; * } * OnRxPacket(RxPacketId, packetBody); // good unsolicited packet - call the callback function * // knowing that ACK or NAK has been already sent * } * else * { * RxBufferP = 0; * OnRxPacket(RxPacketId, null); // bad unsolicited packet - call the callback function * // knowing that ACK or NAK has been already sent * } * } * else */ { TransFlag.Set(); // we are in Transact or Receive, let it pick the result, good or bad, // knowing that ACK or NAK has been already sent } packetState = PacketState.outside; // 0x3 will be ignored in search for 0x10 break; } prevCh = ch; }