/// <summary> /// Sends the specified frame /// </summary> /// <param name="frame">The frame to send</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created private void SendFrame(ASHFrame frame) { if (m_SerialComm.IsOpen) { byte[] StuffedFrame = ASHFrame.StuffFrame(frame.RawFrame); byte[] DataToSend = new byte[StuffedFrame.Length + 1]; frame.TimeStamp = DateTime.Now; Array.Copy(StuffedFrame, DataToSend, StuffedFrame.Length); DataToSend[DataToSend.Length - 1] = FLAG_BYTE; if (m_Logger != null) { m_Logger.WriteASHFrameInfo(EZSPLogDirection.Send, frame); } // Send the Frame lock (m_SerialComm) { m_SerialComm.SendData(DataToSend); } switch (frame.ASHFrameType) { case ASHFrame.FrameType.Data: { if (m_SentFrames.Contains(frame) == false) { m_SentFrames.Add(frame); } break; } } } }
/// <summary> /// Retransmits the specified frame /// </summary> /// <param name="frame">The frame to retransmit</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created private void RetransmitFrame(ASHFrame frame) { frame.AckNumber = m_NCPFrameNumber; frame.IsRetransmitted = true; frame.RetransmitCount++; SendFrame(frame); }
/// <summary> /// Writes basic information for the ASH Layer of the protocol /// </summary> /// <param name="direction">The direction of the frame</param> /// <param name="frame">The frame to write</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created public void WriteASHFrameInfo(EZSPLogDirection direction, ASHFrame frame) { string Output = ""; if (direction == EZSPLogDirection.Send) { Output += "S: "; } else { Output += "R: "; } Output += "- ASH Frame: " + frame.ASHFrameType.ToString() + " - "; switch (frame.ASHFrameType) { case ASHFrame.FrameType.Data: { Output += "Frame Number: " + frame.FrameNumber.ToString() + " Ack Number: " + frame.AckNumber.ToString() + " Retransmit: " + frame.IsRetransmitted.ToString() + " Data: "; for (int Index = 0; Index < frame.Data.Length; Index++) { Output += frame.Data[Index].ToString("X2") + " "; } break; } case ASHFrame.FrameType.Ack: case ASHFrame.FrameType.Nak: { Output += "Ack Number: " + frame.AckNumber.ToString() + " Not Ready: " + frame.NotReady.ToString(); break; } case ASHFrame.FrameType.Error: { Output += "Error Code: "; for (int Index = 0; Index < frame.Data.Length; Index++) { Output += frame.Data[Index].ToString("X2") + " "; } break; } } Output += " CRC Valid: " + frame.IsCRCValid.ToString(); WriteLine(EZSPLogLevels.ASHProtocol, Output); }
/// <summary> /// Sends the specified data /// </summary> /// <param name="data">The data to send</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created public void SendData(byte[] data) { if (m_Connected) { ASHFrame NewDataFrame = new ASHFrame(); NewDataFrame.ASHFrameType = ASHFrame.FrameType.Data; NewDataFrame.FrameNumber = m_HostFrameNumber; NewDataFrame.AckNumber = m_NCPFrameNumber; NewDataFrame.Data = data; m_HostFrameNumber = (byte)((m_HostFrameNumber + 1) % 8); SendFrame(NewDataFrame); } else { throw new InvalidOperationException("ASH needs to be connected before data can be sent"); } }
/// <summary> /// Handles the Data Received event /// </summary> /// <param name="sender">The object that sent the event.</param> /// <param name="e">The event arguments</param> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created private void m_SerialComm_DataReceived(object sender, EventArgs e) { // We received data so we should attempt to read the next frame if (m_SerialComm.IsOpen) { byte[] NewFrameData = null; do { lock (m_SerialComm) { NewFrameData = m_SerialComm.ReadNextFrame(); } if (NewFrameData != null) { ASHFrame NewFrame = new ASHFrame(ASHFrame.UnstuffFrame(NewFrameData)); NewFrame.TimeStamp = DateTime.Now; if (m_Logger != null) { m_Logger.WriteASHFrameInfo(EZSPLogDirection.Receive, NewFrame); } if (m_Resetting) { // Ignore everything but the reset Ack if (NewFrame.ASHFrameType == ASHFrame.FrameType.ResetAck) { // The Reset method should be looking for this response so add it to the list of received frames m_ReceivedFrames.Add(NewFrame); } } else { switch (NewFrame.ASHFrameType) { case ASHFrame.FrameType.Data: { // Check to make sure that the CRC is valid and that the frame number is correct if (NewFrame.IsCRCValid && NewFrame.FrameNumber == m_NCPFrameNumber) { ASHFrame AckFrame = new ASHFrame(); AckFrame.ASHFrameType = ASHFrame.FrameType.Ack; AckFrame.AckNumber = (byte)((NewFrame.FrameNumber + 1) % 8); // Send the ack SendFrame(AckFrame); m_NCPFrameNumber = (byte)((m_NCPFrameNumber + 1) % 8); // Add the data frame and notify m_ReceivedFrames.Add(NewFrame); RemoveAcknowledgedFrames(NewFrame.AckNumber); OnFrameReceived(); } else if (NewFrame.IsCRCValid && NewFrame.IsRetransmitted) { ASHFrame AckFrame = new ASHFrame(); AckFrame.ASHFrameType = ASHFrame.FrameType.Ack; AckFrame.AckNumber = NewFrame.FrameNumber; // Send the ack SendFrame(AckFrame); // If the frame currently exists remove it m_ReceivedFrames.RemoveAll(f => f.FrameNumber == NewFrame.FrameNumber); // Add the data frame and notify m_ReceivedFrames.Add(NewFrame); RemoveAcknowledgedFrames(NewFrame.AckNumber); OnFrameReceived(); } else { if (m_RejectCondition == false) { m_RejectCondition = true; ASHFrame NakFrame = new ASHFrame(); NakFrame.ASHFrameType = ASHFrame.FrameType.Nak; NakFrame.AckNumber = NewFrame.AckNumber; SendFrame(NakFrame); } } break; } case ASHFrame.FrameType.Ack: { // A frame was acknowledged so it should be cleared from the list of pending items RemoveAcknowledgedFrames(NewFrame.AckNumber); break; } case ASHFrame.FrameType.Nak: { // We received a Nak for something sent so we need to retransmit byte CurrentAckNumber = NewFrame.AckNumber; while (CurrentAckNumber != m_HostFrameNumber) { if (m_SentFrames.Where(f => f.FrameNumber == CurrentAckNumber).Count() > 0) { // Update and retransmit the frame ASHFrame RetransmittedFrame = m_SentFrames.First(f => f.FrameNumber == CurrentAckNumber); RetransmittedFrame.IsRetransmitted = true; SendFrame(RetransmittedFrame); } CurrentAckNumber = (byte)((CurrentAckNumber + 1) % 8); } break; } case ASHFrame.FrameType.Error: { // Errors are fatal meaning this sessions is now over m_LastError = NewFrame.Data[1]; Disconnect(); break; } default: { // We should not be receiving Resets or Reset Acks now this should be considered an error Disconnect(); break; } } } } } while (NewFrameData != null); } }
/// <summary> /// Resets the NCP. /// </summary> /// <returns>True if the reset was successful. False otherwise.</returns> // Revision History // MM/DD/YY Who Version Issue# Description // -------- --- ------- ------ ------------------------------------------- // 08/09/11 RCG 2.52.00 Created private bool Reset() { bool HasReset = false; int RetryAttempt = 0; DisableSlip(); while (HasReset == false && RetryAttempt < RESET_RETRIES) { SendCancel(); Thread.Sleep(10); SendCancel(); Thread.Sleep(10); SendCancel(); Thread.Sleep(10); // Clear any data we may have received m_SerialComm.ClearBuffer(); // Send the Reset Frame ASHFrame ResetFrame = new ASHFrame(); ResetFrame.ASHFrameType = ASHFrame.FrameType.Reset; m_Resetting = true; SendFrame(ResetFrame); // Wait for the Reset Ack while ((DateTime.Now - ResetFrame.TimeStamp).TotalMilliseconds < T_RSTACK_MAX) { if (m_ReceivedFrames.Where(f => f.ASHFrameType == ASHFrame.FrameType.ResetAck).Count() > 0) { // We received the Reset Ack HasReset = true; m_Resetting = false; // Clear the received items m_ReceivedFrames.Clear(); break; } else { // We are still waiting for the ack Thread.Sleep(25); } } if (HasReset == false) { // Haven't found it so we will need to retry RetryAttempt++; } } if (HasReset) { // Send an Ack to indicate we are good to go ASHFrame AckFrame = new ASHFrame(); AckFrame.ASHFrameType = ASHFrame.FrameType.Ack; SendFrame(AckFrame); } return(HasReset); }