Subversion Repositories HomeAutomation

Rev

Rev 270 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  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. }