CLEON CONNECTOR  1.0
Parameter updating SW for cloud-offloaded GPS receiver (CLEON)
Communication.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.IO.Ports;
10 using System.Threading;
11 using System.Globalization;
12 using System.Diagnostics;
13 
14 namespace CLEON_Connector
15 {
16  public partial class Form1
17  {
18  long currentTimeTick;
19 
20  // Called if a byte is received
21  private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
22  {
23  SerialPort sp = (SerialPort)sender;
24 
25  byte receivedByte = 0;
26 
27  // If there's some bytes to read
28  while (sp.BytesToRead > 0)
29  {
30  // Read single byte
31  receivedByte = (byte)sp.ReadByte();
32 
33  // Call received byte processing function
34  ProcessReceivedByte(receivedByte);
35  }
36  }
37 
38  // Send a command via USB
39  // - There should be an ACK per every command sent
40  private void SendUSBCommand(byte command)
41  {
42  // First two bytes are header (0x55)
43  USBSsndFrame[0] = Constants.serialFrameHeader;
44  USBSsndFrame[1] = Constants.serialFrameHeader;
45 
46  // Byte type array
47  byte[] bytes = new byte[4];
48 
49  // Insert command to sending frame
50  switch (command)
51  {
52  // Command 'connect (0x01)', 'Update sample count (0x04)', 'Update sample gap (0x05)', 'Update chunk count (0x06)', and 'Update chunk gap (0x07)'
53  case Constants.commandConnect:
54  USBSsndFrame[2] = 1;
55  USBSsndFrame[3] = command;
56  break;
57  // Command 'Update RTC time' (0x02)
58  // - Update year, month, day, hour, minute, and second
59  case Constants.commandUpdateRTCTime:
60  DateTime now;
61  int year, month, day, hour, minute, second;
62  // Wait until milisecond becomes zero
63  while (DateTime.Now.Millisecond != 0) ;
64  now = DateTime.Now;
65  year = now.Year;
66  month = now.Month;
67  day = now.Day;
68  hour = now.Hour;
69  minute = now.Minute;
70  second = now.Second;
71  USBSsndFrame[2] = 8;
72  USBSsndFrame[3] = command;
73  USBSsndFrame[4] = (byte)(year >> 8);
74  USBSsndFrame[5] = (byte)(year & 0xff);
75  USBSsndFrame[6] = (byte)month;
76  USBSsndFrame[7] = (byte)day;
77  USBSsndFrame[8] = (byte)hour;
78  USBSsndFrame[9] = (byte)minute;
79  USBSsndFrame[10] = (byte)second;
80  break;
81  // Command 'Update time tick' (0x03)
82  // - Update UTC time tick
83  case Constants.commandUpdateTimeTick:
84  // Wait until millisecond becomes zero
85  while (DateTime.Now.Millisecond != 0) ;
86  currentTimeTick = DateTime.UtcNow.Ticks;
87  // Drop millisecond part because CLEON runs its own clock to calculate millisecond part
88  currentTimeTick = (long)(currentTimeTick / 10000000);
89  currentTimeTick *= 10000000;
90 
91  USBSsndFrame[2] = 9;
92  USBSsndFrame[3] = command;
93  USBSsndFrame[4] = (byte)(currentTimeTick & 0xff);
94  USBSsndFrame[5] = (byte)(currentTimeTick >> 8);
95  USBSsndFrame[6] = (byte)(currentTimeTick >> 16);
96  USBSsndFrame[7] = (byte)(currentTimeTick >> 24);
97  USBSsndFrame[8] = (byte)(currentTimeTick >> 32);
98  USBSsndFrame[9] = (byte)(currentTimeTick >> 40);
99  USBSsndFrame[10] = (byte)(currentTimeTick >> 48);
100  USBSsndFrame[11] = (byte)(currentTimeTick >> 56);
101  break;
102  case Constants.commandUpdateSampleCount:
103  bytes = BitConverter.GetBytes(iSampleCount);
104  USBSsndFrame[2] = 5;
105  USBSsndFrame[3] = command;
106  USBSsndFrame[4] = bytes[0];
107  USBSsndFrame[5] = bytes[1];
108  USBSsndFrame[6] = bytes[2];
109  USBSsndFrame[7] = bytes[3];
110  break;
111  case Constants.commandUpdateSampleGap:
112  bytes = BitConverter.GetBytes(iSampleGap);
113  USBSsndFrame[2] = 5;
114  USBSsndFrame[3] = command;
115  USBSsndFrame[4] = bytes[0];
116  USBSsndFrame[5] = bytes[1];
117  USBSsndFrame[6] = bytes[2];
118  USBSsndFrame[7] = bytes[3];
119  break;
120  case Constants.commandUpdateChunkCount:
121  bytes = BitConverter.GetBytes(iChunkCount);
122  USBSsndFrame[2] = 5;
123  USBSsndFrame[3] = command;
124  USBSsndFrame[4] = bytes[0];
125  USBSsndFrame[5] = bytes[1];
126  USBSsndFrame[6] = bytes[2];
127  USBSsndFrame[7] = bytes[3];
128  break;
129  case Constants.commnadUpdateChunkGap:
130  bytes = BitConverter.GetBytes(iChunkGap);
131  USBSsndFrame[2] = 5;
132  USBSsndFrame[3] = command;
133  USBSsndFrame[4] = bytes[0];
134  USBSsndFrame[5] = bytes[1];
135  USBSsndFrame[6] = bytes[2];
136  USBSsndFrame[7] = bytes[3];
137  break;
138  default:
139  break;
140  }
141 
142  // Build CRC
143  USBSsndFrame[33] = BuildCRC(USBSsndFrame);
144 
145  // Last two bytes are footer (0xAA)
146  USBSsndFrame[34] = Constants.serialFrameFooter;
147  USBSsndFrame[35] = Constants.serialFrameFooter;
148 
149  // Write prepared USBsendFrame
150  serialPort1.Write(USBSsndFrame, 0, Constants.serialFrameLength);
151  }
152 
153  // Build CRC
154  private byte BuildCRC(byte[] targetArray)
155  {
156  byte ucCheckOctet = 0;
157 
158  for (int i = 3; i < (Constants.serialFrameLength - 3); i++)
159  {
160  if (i == 0)
161  {
162  ucCheckOctet = targetArray[i];
163  }
164  if (i >= 1)
165  {
166  ucCheckOctet ^= targetArray[i];
167  }
168  }
169 
170  ucCheckOctet = (byte)~ucCheckOctet;
171 
172  return ucCheckOctet;
173  }
174 
175  // State machine for USB frame reception
176  private void ProcessReceivedByte(byte receivedByte)
177  {
178  switch (USBRecvFrameByteCount)
179  {
180  case 0:
181  case 1:
182  if (receivedByte == Constants.serialFrameHeader)
183  {
184  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
185  USBRecvFrameByteCount++;
186  }
187  else
188  {
189  USBRecvFrameByteCount = 0;
190  // request retransmission
191  }
192  break;
193  case 2:
194  if ((USBRecvFrame[0] == Constants.serialFrameHeader) && (USBRecvFrame[1] == Constants.serialFrameHeader) &&
195  (receivedByte > 0) && (receivedByte < Constants.serialFrameDataAndCommandLength))
196  {
197  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
198  USBRecvFrameByteCount++;
199  }
200  else
201  {
202  USBRecvFrameByteCount = 0;
203  // request retransmission
204  }
205  break;
206  case 3:
207  case 4:
208  case 5:
209  case 6:
210  case 7:
211  case 8:
212  case 9:
213  case 10:
214  case 11:
215  case 12:
216  case 13:
217  case 14:
218  case 15:
219  case 16:
220  case 17:
221  case 18:
222  case 19:
223  case 20:
224  case 21:
225  case 22:
226  case 23:
227  case 24:
228  case 25:
229  case 26:
230  case 27:
231  case 28:
232  case 29:
233  case 30:
234  case 31:
235  case 32:
236  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
237  USBRecvFrameByteCount++;
238  break;
239  case 33:
240  if (receivedByte == BuildCRC(USBRecvFrame))
241  {
242  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
243  USBRecvFrameByteCount++;
244  }
245  else
246  {
247  USBRecvFrameByteCount = 0;
248  // request retransmission
249  }
250  break;
251  case 34:
252  if (receivedByte == Constants.serialFrameFooter)
253  {
254  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
255  USBRecvFrameByteCount++;
256  }
257  else
258  {
259  USBRecvFrameByteCount = 0;
260  // request retransmission
261  }
262  break;
263  case 35:
264  if (receivedByte == Constants.serialFrameFooter)
265  {
266  USBRecvFrame[USBRecvFrameByteCount] = receivedByte;
267  USBRecvFrameByteCount = 0;
268  bFLAG_USBFrameReceived = true;
269  }
270  else
271  {
272  USBRecvFrameByteCount = 0;
273  // request retransmission
274  }
275  break;
276  default:
277  // request retransmission
278  break;
279  }
280  }
281  }
282 }