Go to most recent revision | Details | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 270 | johboh | 1 | #define STRICT |
| 2 | #include "SerialConnection.h" |
||
| 3 | |||
| 4 | |||
| 5 | |||
| 6 | void arrayCopy(unsigned char *src,unsigned int srcIndex,unsigned char *dst,unsigned int dstIndex,unsigned int length); |
||
| 7 | |||
| 8 | bool queueEnqueue(CanProtoMessage cpm); |
||
| 9 | bool queueDequeue(CanProtoMessage *cpm); |
||
| 10 | |||
| 11 | CanProtoMessage *cpmQueue; |
||
| 12 | int queueReadPointer=0; |
||
| 13 | int queueWritePointer=0; |
||
| 14 | int queueLength=0; |
||
| 15 | |||
| 16 | |||
| 17 | static HANDLE hCom; |
||
| 18 | static HANDLE hRunMutex; // "Keep Running" mutex |
||
| 19 | |||
| 20 | static void SerRead(void *pMyID); |
||
| 21 | |||
| 22 | SerialConnection::SerialConnection(LPCTSTR portName,EBaudrate baudRate,EDataBits byteSize,EParity parity, EStopBits stopBits) |
||
| 23 | { |
||
| 24 | SerialConnection::uportName=portName; |
||
| 25 | SerialConnection::ubaudRate=baudRate; |
||
| 26 | SerialConnection::ubyteSize=byteSize; |
||
| 27 | SerialConnection::uparity = parity; |
||
| 28 | SerialConnection::ustopBits=stopBits; |
||
| 29 | |||
| 30 | hCom = NULL; |
||
| 31 | } |
||
| 32 | |||
| 33 | SerialConnection::~SerialConnection() { } |
||
| 34 | |||
| 35 | bool SerialConnection::open() |
||
| 36 | { |
||
| 37 | DCB dcb; |
||
| 38 | |||
| 39 | // Check if the port isn't already opened |
||
| 40 | if (hCom) |
||
| 41 | { |
||
| 42 | printf ("Open - Port already opened\n"); |
||
| 43 | return false; |
||
| 44 | } |
||
| 45 | |||
| 46 | hCom = CreateFile( uportName, |
||
| 47 | GENERIC_READ | GENERIC_WRITE, |
||
| 48 | 0, // must be opened with exclusive-access |
||
| 49 | NULL, // no security attributes |
||
| 50 | OPEN_EXISTING, // must use OPEN_EXISTING |
||
| 51 | FILE_FLAG_OVERLAPPED, // not overlapped I/O |
||
| 52 | NULL // hTemplate must be NULL for comm devices |
||
| 53 | ); |
||
| 54 | |||
| 55 | if (hCom == INVALID_HANDLE_VALUE) |
||
| 56 | { |
||
| 57 | // Handle the error. |
||
| 58 | printf ("CreateFile failed with error %d.\n", GetLastError()); |
||
| 59 | return false; |
||
| 60 | } |
||
| 61 | |||
| 62 | // Build on the current configuration, and skip setting the size |
||
| 63 | // of the input and output buffers with SetupComm. |
||
| 64 | |||
| 65 | |||
| 66 | if (!GetCommState(hCom, &dcb)) |
||
| 67 | { |
||
| 68 | // Handle the error. |
||
| 69 | printf ("GetCommState failed with error %d.\n", GetLastError()); |
||
| 70 | return false; |
||
| 71 | } |
||
| 72 | |||
| 73 | // Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit. |
||
| 74 | |||
| 75 | dcb.BaudRate = SerialConnection::ubaudRate; // set the baud rate |
||
| 76 | dcb.ByteSize = SerialConnection::ubyteSize; // data size, xmit, and rcv |
||
| 77 | dcb.Parity = SerialConnection::uparity; // no parity bit |
||
| 78 | dcb.StopBits = SerialConnection::ustopBits; // one stop bit |
||
| 79 | |||
| 80 | if (!SetCommState(hCom, &dcb)) |
||
| 81 | { |
||
| 82 | // Handle the error. |
||
| 83 | printf ("SetCommState failed with error %d.\n", GetLastError()); |
||
| 84 | return false; |
||
| 85 | } |
||
| 86 | |||
| 87 | if (!SetCommMask(hCom, EV_RXCHAR)) |
||
| 88 | { |
||
| 89 | // Handle the error. |
||
| 90 | printf("SetCommMask failed with error %d.\n", GetLastError()); |
||
| 91 | return false; |
||
| 92 | } |
||
| 93 | |||
| 94 | hRunMutex = CreateMutex( NULL, TRUE, NULL ); // Set |
||
| 95 | _beginthread( SerRead, 0, 0 ); |
||
| 96 | |||
| 97 | printf ("Serial port successfully reconfigured.\n"); |
||
| 98 | return true; |
||
| 99 | } |
||
| 100 | |||
| 101 | HANDLE SerialConnection::getHandle() |
||
| 102 | { |
||
| 103 | |||
| 104 | return hCom; |
||
| 105 | } |
||
| 106 | |||
| 107 | |||
| 108 | bool SerialConnection::close() |
||
| 109 | { |
||
| 110 | ReleaseMutex( hRunMutex ); |
||
| 111 | CloseHandle( hRunMutex ); |
||
| 112 | |||
| 113 | if (hCom==0) |
||
| 114 | { |
||
| 115 | printf("Close - Method called when device is not open\n"); |
||
| 116 | return false; |
||
| 117 | } |
||
| 118 | |||
| 119 | CloseHandle(hCom); |
||
| 120 | |||
| 121 | return true; |
||
| 122 | } |
||
| 123 | |||
| 124 | bool SerialConnection::isOpen() |
||
| 125 | { |
||
| 126 | return (hCom != 0); |
||
| 127 | } |
||
| 128 | |||
| 129 | bool SerialConnection::write(LPCVOID lpBuffer, unsigned int nNumberOfBytesToWrite) |
||
| 130 | { |
||
| 131 | if (hCom==0) |
||
| 132 | { |
||
| 133 | printf("Close - Method called when device is not open\n"); |
||
| 134 | return false; |
||
| 135 | } |
||
| 136 | |||
| 137 | /* |
||
| 138 | OVERLAPPED ol; |
||
| 139 | memset(&ol,0,sizeof(ol)); |
||
| 140 | |||
| 141 | if (!WriteFileEx(hCom,lpBuffer,nNumberOfBytesToWrite,&ol,NULL)) |
||
| 142 | { |
||
| 143 | printf("Write - Unable to write the data\n"); |
||
| 144 | } |
||
| 145 | */ |
||
| 146 | |||
| 147 | OVERLAPPED osWrite = {0}; |
||
| 148 | DWORD dwWritten; |
||
| 149 | DWORD dwRes; |
||
| 150 | BOOL fRes; |
||
| 151 | |||
| 152 | |||
| 153 | // Create this write operation's OVERLAPPED structure's hEvent. |
||
| 154 | osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
||
| 155 | if (osWrite.hEvent == NULL) |
||
| 156 | { |
||
| 157 | printf("error creating overlapped event handle\n"); |
||
| 158 | return FALSE; |
||
| 159 | } |
||
| 160 | |||
| 161 | |||
| 162 | // Issue write. |
||
| 163 | if (!WriteFile(hCom, lpBuffer, nNumberOfBytesToWrite, &dwWritten, &osWrite)) |
||
| 164 | { |
||
| 165 | if (GetLastError() != ERROR_IO_PENDING) |
||
| 166 | { |
||
| 167 | printf("WriteFile failed, but isn't delayed. Report error and abort.\n"); |
||
| 168 | fRes = FALSE; |
||
| 169 | } |
||
| 170 | else |
||
| 171 | { |
||
| 172 | // Write is pending. |
||
| 173 | dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE); |
||
| 174 | switch(dwRes) |
||
| 175 | { |
||
| 176 | // OVERLAPPED structure's event has been signaled. |
||
| 177 | case WAIT_OBJECT_0: |
||
| 178 | if (!GetOverlappedResult(hCom, &osWrite, &dwWritten, FALSE)) |
||
| 179 | fRes = FALSE; |
||
| 180 | else |
||
| 181 | // Write operation completed successfully. |
||
| 182 | fRes = TRUE; |
||
| 183 | break; |
||
| 184 | |||
| 185 | default: |
||
| 186 | // An error has occurred in WaitForSingleObject. |
||
| 187 | // This usually indicates a problem with the |
||
| 188 | // OVERLAPPED structure's event handle. |
||
| 189 | fRes = FALSE; |
||
| 190 | break; |
||
| 191 | } |
||
| 192 | } |
||
| 193 | } |
||
| 194 | else fRes = TRUE; |
||
| 195 | // WriteFile completed immediately. |
||
| 196 | |||
| 197 | |||
| 198 | CloseHandle(osWrite.hEvent); |
||
| 199 | return fRes; |
||
| 200 | |||
| 201 | |||
| 202 | |||
| 203 | |||
| 204 | return false; |
||
| 205 | } |
||
| 206 | |||
| 207 | |||
| 208 | void SerRead(void *pMyID) |
||
| 209 | { |
||
| 210 | unsigned char iBuff[SERIAL_READ_BUFFER_SIZE]; |
||
| 211 | unsigned int iBuffPointer = 0; |
||
| 212 | |||
| 213 | cpmQueue = (CanProtoMessage *)malloc(QUEUE_PLACES*sizeof(CanProtoMessage)); |
||
| 214 | |||
| 215 | DWORD dwCommEvent; |
||
| 216 | DWORD dwRead; |
||
| 217 | unsigned char chRead[128]; |
||
| 218 | |||
| 219 | if (hCom ==0) |
||
| 220 | { |
||
| 221 | printf("Serial port closed."); |
||
| 222 | return; |
||
| 223 | } |
||
| 224 | |||
| 225 | OVERLAPPED osReader = {0}; |
||
| 226 | |||
| 227 | // Create the overlapped event. Must be closed before exiting |
||
| 228 | // to avoid a handle leak. |
||
| 229 | osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); |
||
| 230 | |||
| 231 | |||
| 232 | |||
| 233 | while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT ) |
||
| 234 | { |
||
| 235 | |||
| 236 | if (WaitCommEvent(hCom, &dwCommEvent, NULL)) |
||
| 237 | { |
||
| 238 | if (ReadFile(hCom, &chRead, 128, &dwRead, &osReader)) |
||
| 239 | { |
||
| 240 | |||
| 241 | // Read data, until there is nothing left |
||
| 242 | DWORD dwBytesRead = 0; |
||
| 243 | unsigned char szBuffer[SERIAL_INPUT_BUFFER_SIZE]; |
||
| 244 | do |
||
| 245 | { |
||
| 246 | |||
| 247 | if (dwRead > 0) |
||
| 248 | { |
||
| 249 | |||
| 250 | // Spara i array, sist. |
||
| 251 | arrayCopy(chRead, 0, iBuff, iBuffPointer, dwRead); |
||
| 252 | iBuffPointer += dwRead; |
||
| 253 | |||
| 254 | // Följ parserutin. |
||
| 255 | // Köa. |
||
| 256 | // flytta. |
||
| 257 | |||
| 258 | // När array större eller lika med PACKET_LENGTH... |
||
| 259 | while (iBuffPointer >= PACKET_LENGTH) |
||
| 260 | { |
||
| 261 | int startIndex = 0; |
||
| 262 | |||
| 263 | // Sök igenom efter start byte från början. |
||
| 264 | for (unsigned int i = 0; i < iBuffPointer; i++) |
||
| 265 | { |
||
| 266 | // Poppa alla bytes som inte är startbyte. |
||
| 267 | if (iBuff[i] != UART_START_BYTE) startIndex++; |
||
| 268 | else |
||
| 269 | { |
||
| 270 | // När startbyte hittas, kolla om återstående längd är större eller lika med PACKET_LENGTH (inkl startbyte) |
||
| 271 | if ((iBuffPointer - startIndex) >= PACKET_LENGTH) |
||
| 272 | { |
||
| 273 | //om så, kolla PACKET_LENGTH-1 byte fram. |
||
| 274 | if (iBuff[startIndex + PACKET_LENGTH - 1] == UART_END_BYTE) |
||
| 275 | { |
||
| 276 | // Om byte PACKET_LENGTH-1 är slutbyte så extraktas startIndex till slutbyteindex. |
||
| 277 | CanProtoMessage cmp(iBuff,startIndex + 1); |
||
| 278 | queueEnqueue(cmp); |
||
| 279 | |||
| 280 | |||
| 281 | // Sätt ny startindex och avsluta loop. |
||
| 282 | startIndex += PACKET_LENGTH; |
||
| 283 | break; |
||
| 284 | } |
||
| 285 | } |
||
| 286 | } |
||
| 287 | } |
||
| 288 | // och i slutet göra en array copy. |
||
| 289 | // Flytta ner allt efter slutbyte till index 0 i array. |
||
| 290 | arrayCopy(iBuff, startIndex, iBuff, 0, iBuffPointer - PACKET_LENGTH); |
||
| 291 | iBuffPointer -= startIndex; |
||
| 292 | } |
||
| 293 | } |
||
| 294 | |||
| 295 | |||
| 296 | }while (dwBytesRead == sizeof(szBuffer)-1); |
||
| 297 | |||
| 298 | //printf("byte receiced\n"); |
||
| 299 | |||
| 300 | |||
| 301 | } else { printf("Error (1): %d\n",GetLastError()); break;} |
||
| 302 | } else { printf("Error (2): %d\n",GetLastError()); break;} |
||
| 303 | } |
||
| 304 | |||
| 305 | |||
| 306 | } |
||
| 307 | |||
| 308 | bool SerialConnection::getMessage(CanProtoMessage *cpm) |
||
| 309 | { |
||
| 310 | return queueDequeue(cpm); |
||
| 311 | } |
||
| 312 | |||
| 313 | void arrayCopy(unsigned char *src,unsigned int srcIndex,unsigned char *dst,unsigned int dstIndex,unsigned int length) |
||
| 314 | { |
||
| 315 | // Copy an aray to another array (of unsigned chars == bytes) |
||
| 316 | for(unsigned int i=0;i<length;i++) dst[dstIndex+i]=src[srcIndex+i]; |
||
| 317 | } |
||
| 318 | |||
| 319 | |||
| 320 | bool queueEnqueue(CanProtoMessage cpm) |
||
| 321 | { |
||
| 322 | // Enqueue reveiced message to queue |
||
| 323 | if (queueLength>=QUEUE_PLACES) return false; |
||
| 324 | |||
| 325 | cpmQueue[queueWritePointer]=cpm; |
||
| 326 | |||
| 327 | queueLength++; |
||
| 328 | queueWritePointer++; |
||
| 329 | if (queueWritePointer>=QUEUE_PLACES) queueWritePointer=0; |
||
| 330 | |||
| 331 | printf("[%ld] Queue message, length: %d\n",GetTickCount(),queueLength); |
||
| 332 | |||
| 333 | return true; |
||
| 334 | } |
||
| 335 | bool queueDequeue(CanProtoMessage *cpm) |
||
| 336 | { |
||
| 337 | // Dequeue can message. |
||
| 338 | if (queueLength==0) return false; |
||
| 339 | |||
| 340 | cpm = &cpmQueue[queueReadPointer]; |
||
| 341 | |||
| 342 | queueLength--; |
||
| 343 | queueReadPointer++; |
||
| 344 | if (queueReadPointer>=QUEUE_PLACES) queueReadPointer=0; |
||
| 345 | |||
| 346 | return true; |
||
| 347 | } |