Subversion Repositories HomeAutomation

Rev

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

#define STRICT
#include "SerialConnection.h"



void arrayCopy(unsigned char *src,unsigned int srcIndex,unsigned char *dst,unsigned int dstIndex,unsigned int length);

bool queueEnqueue(CanProtoMessage cpm);
bool queueDequeue(CanProtoMessage *cpm);

CanProtoMessage *cpmQueue;
int queueReadPointer=0;
int queueWritePointer=0;
int queueLength=0;


static HANDLE hCom;
static HANDLE  hRunMutex;  // "Keep Running" mutex 

static void SerRead(void *pMyID);

SerialConnection::SerialConnection(LPCTSTR portName,EBaudrate baudRate,EDataBits byteSize,EParity parity, EStopBits stopBits)
{
    SerialConnection::uportName=portName;
    SerialConnection::ubaudRate=baudRate;
    SerialConnection::ubyteSize=byteSize;
    SerialConnection::uparity = parity;
    SerialConnection::ustopBits=stopBits;

    hCom = NULL;
}

SerialConnection::~SerialConnection() {  }

bool SerialConnection::open()
{
    DCB dcb;

    // Check if the port isn't already opened
    if (hCom)
    {
        printf ("Open - Port already opened\n");
        return false;
    }

    hCom = CreateFile( uportName,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    NULL, // no security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    FILE_FLAG_OVERLAPPED,    // not overlapped I/O
                    NULL  // hTemplate must be NULL for comm devices
                    );

    if (hCom == INVALID_HANDLE_VALUE) 
    {
       // Handle the error.
       printf ("CreateFile failed with error %d.\n", GetLastError());
       return false;
    }

    // Build on the current configuration, and skip setting the size
    // of the input and output buffers with SetupComm.


    if (!GetCommState(hCom, &dcb)) 
    {
      // Handle the error.
      printf ("GetCommState failed with error %d.\n", GetLastError());
      return false;
    }

    // Fill in DCB: 57,600 bps, 8 data bits, no parity, and 1 stop bit.

    dcb.BaudRate = SerialConnection::ubaudRate;     // set the baud rate
    dcb.ByteSize = SerialConnection::ubyteSize;             // data size, xmit, and rcv
    dcb.Parity = SerialConnection::uparity;        // no parity bit
    dcb.StopBits = SerialConnection::ustopBits;    // one stop bit

    if (!SetCommState(hCom, &dcb)) 
    {
      // Handle the error.
      printf ("SetCommState failed with error %d.\n", GetLastError());
      return false;
    }

    if (!SetCommMask(hCom, EV_RXCHAR))
    {
        // Handle the error. 
        printf("SetCommMask failed with error %d.\n", GetLastError());
        return false;
    }

    hRunMutex = CreateMutex( NULL, TRUE, NULL );      // Set 
    _beginthread( SerRead, 0, 0 );

    printf ("Serial port successfully reconfigured.\n");
    return true;
}

HANDLE SerialConnection::getHandle()
{

    return hCom;
}


bool SerialConnection::close()
{
    ReleaseMutex( hRunMutex );
    CloseHandle( hRunMutex );

    if (hCom==0)
    {
        printf("Close - Method called when device is not open\n");
        return false;
    }

    CloseHandle(hCom);

    return true;
}

bool SerialConnection::isOpen()
{
    return (hCom != 0);
}

bool SerialConnection::write(LPCVOID lpBuffer, unsigned int nNumberOfBytesToWrite)
{
    if (hCom==0)
    {
        printf("Close - Method called when device is not open\n");
        return false;
    }

    /*
    OVERLAPPED ol;
    memset(&ol,0,sizeof(ol));

    if (!WriteFileEx(hCom,lpBuffer,nNumberOfBytesToWrite,&ol,NULL))
    {
        printf("Write - Unable to write the data\n");
    }
*/

    OVERLAPPED osWrite = {0};
   DWORD dwWritten;
   DWORD dwRes;
   BOOL fRes;


    // Create this write operation's OVERLAPPED structure's hEvent.
   osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
   if (osWrite.hEvent == NULL)
   {
      printf("error creating overlapped event handle\n");
      return FALSE;
   }


    // Issue write.
   if (!WriteFile(hCom, lpBuffer, nNumberOfBytesToWrite, &dwWritten, &osWrite)) 
   {
      if (GetLastError() != ERROR_IO_PENDING) 
      { 
         printf("WriteFile failed, but isn't delayed. Report error and abort.\n");
         fRes = FALSE;
      }
      else
      {
         // Write is pending.
         dwRes = WaitForSingleObject(osWrite.hEvent, INFINITE);
         switch(dwRes)
         {
            // OVERLAPPED structure's event has been signaled. 
            case WAIT_OBJECT_0:
                 if (!GetOverlappedResult(hCom, &osWrite, &dwWritten, FALSE))
                       fRes = FALSE;
                 else
                  // Write operation completed successfully.
                  fRes = TRUE;
                 break;
            
            default:
                 // An error has occurred in WaitForSingleObject.
                 // This usually indicates a problem with the
                // OVERLAPPED structure's event handle.
                 fRes = FALSE;
                 break;
         }
      }
   }
   else fRes = TRUE;
      // WriteFile completed immediately.
      

   CloseHandle(osWrite.hEvent);
   return fRes;




    return false;
}


void SerRead(void *pMyID)
{
    unsigned char iBuff[SERIAL_READ_BUFFER_SIZE];
    unsigned int iBuffPointer = 0;

    cpmQueue = (CanProtoMessage *)malloc(QUEUE_PLACES*sizeof(CanProtoMessage));

    DWORD dwCommEvent;
    DWORD dwRead;
    unsigned char chRead[128];

    if (hCom ==0)
    {
        printf("Serial port closed.");
        return;
    }

    OVERLAPPED osReader = {0};

    // Create the overlapped event. Must be closed before exiting
    // to avoid a handle leak.
    osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);



    while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT )
    {

        if (WaitCommEvent(hCom, &dwCommEvent, NULL)) 
        {
            if (ReadFile(hCom, &chRead, 128, &dwRead, &osReader))
            {

                // Read data, until there is nothing left
                DWORD dwBytesRead = 0;
                unsigned char szBuffer[SERIAL_INPUT_BUFFER_SIZE];
                do
                {

                    if (dwRead > 0)
                    {
                    
                        // Spara i array, sist.
                        arrayCopy(chRead, 0, iBuff, iBuffPointer, dwRead);
                        iBuffPointer += dwRead;

                        // Följ parserutin.
                        // Köa.
                        // flytta.

                         // När array större eller lika med PACKET_LENGTH...
                        while (iBuffPointer >= PACKET_LENGTH)
                        {
                            int startIndex = 0;

                            // Sök igenom efter start byte från början.
                            for (unsigned int i = 0; i < iBuffPointer; i++)
                            {
                                // Poppa alla bytes som inte är startbyte.
                                if (iBuff[i] != UART_START_BYTE) startIndex++;
                                else
                                {
                                    // När startbyte hittas, kolla om återstående längd är större eller lika med PACKET_LENGTH (inkl startbyte)
                                    if ((iBuffPointer - startIndex) >= PACKET_LENGTH)
                                    {
                                        //om så, kolla PACKET_LENGTH-1 byte fram.
                                        if (iBuff[startIndex + PACKET_LENGTH - 1] == UART_END_BYTE)
                                        {
                                            // Om byte PACKET_LENGTH-1 är slutbyte så extraktas startIndex till slutbyteindex.
                                            CanProtoMessage cmp(iBuff,startIndex + 1);
                                            queueEnqueue(cmp);
                                            

                                            // Sätt ny startindex och avsluta loop.
                                            startIndex += PACKET_LENGTH;
                                            break;
                                        }
                                    }
                                }
                            }
                            // och i slutet göra en array copy.
                            // Flytta ner allt efter slutbyte till index 0 i array.
                            arrayCopy(iBuff, startIndex, iBuff, 0, iBuffPointer - PACKET_LENGTH);
                            iBuffPointer -= startIndex;
                        }
                    }


                }while (dwBytesRead == sizeof(szBuffer)-1);
        
                //printf("byte receiced\n");


            } else { printf("Error (1): %d\n",GetLastError()); break;}
        } else { printf("Error (2): %d\n",GetLastError()); break;}
    }


}

bool SerialConnection::getMessage(CanProtoMessage *cpm)
{
    return queueDequeue(cpm);
}

void arrayCopy(unsigned char *src,unsigned int srcIndex,unsigned char *dst,unsigned int dstIndex,unsigned int length)
{
    // Copy an aray to another array (of unsigned chars == bytes)
    for(unsigned int i=0;i<length;i++) dst[dstIndex+i]=src[srcIndex+i];
}


bool queueEnqueue(CanProtoMessage cpm)
{
    // Enqueue reveiced message to queue
    if (queueLength>=QUEUE_PLACES) return false;

    cpmQueue[queueWritePointer]=cpm;

    queueLength++;
    queueWritePointer++;
    if (queueWritePointer>=QUEUE_PLACES) queueWritePointer=0;

    printf("[%ld] Queue message, length: %d\n",GetTickCount(),queueLength);

    return true;
}
bool queueDequeue(CanProtoMessage *cpm)
{
    // Dequeue can message.
    if (queueLength==0) return false;

    cpm = &cpmQueue[queueReadPointer];

    queueLength--;
    queueReadPointer++;
    if (queueReadPointer>=QUEUE_PLACES) queueReadPointer=0;

    return true;
}