//***********************************************************
// Author: Mike Konicki
// Date: 2-26-2006
// Project Name: CMU.DLL
//
// Description: Full dll for Com and CMU functions using Karl Reihl's 2005
//                                Senior Capstone as starter for the comport code
//
//
//**********************************************************
#include <windows.h>
#include <stdio.h>

//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

//TYPEDEF STRUCTURES
//        -These structures exist to facilitate the
//                easy sending of data to and from the
//                dll to the main program

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//\/\/\/\/\/\/\/\/\
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/

typedef struct
{
        //M-Packet consists of the following values: Mx,My,X1,Y1,X2,Y2,pixels,confidence
        int MX;                        //x coordinate of the centroid
        int MY;                        //y coordinate of the centroid
        int X1;                        //upper left x coordinate
        int Y1;                        //upper left y coordinate
        int X2;                        //lower right x coordinate
        int Y2;                        //lower right y coordinate
        int Num_Pix;        //number of matching pixels in the box
        int Confid;                //confidence that it is the object according to the CMUcam
}M_PACKET;

typedef struct
{
        //C-Packet consists of the following values: X1,Y1,X2,Y2,pixels,confidence
        int X1;                        //upper left x coordinate
        int Y1;                        //upper left y coordinate
        int X2;                        //lower right x coordinate
        int Y2;                        //lower right y coordinate
        int Num_Pix;        //number of matching pixels in the box
        int Confid;                //confidence that it is the object according to the CMUcam
}C_PACKET;

typedef struct
{
        //S-Packet consists of the following values: Rmean,Gmean,Bmean,Rdev,Gdev,Bdev;
        int Rmean;                //Red Mean Color Value in the Image
        int Gmean;                //Green Mean Color Value in the Image
        int Bmean;                //Blue Mean Color Value in the Image
        int Rdev;                //Red Deviation Color Value in the Image
        int Gdev;                //Green Mean Color Value in the Image
        int Bdev;                //Blue Mean Color Value in the Image
}S_PACKET;

typedef struct
{
        //M-Packet consists of the following values: Spos,Mx,My,X1,Y1,X2,Y2,pixels,confidence
        int Spos;                //Servo Position
        int MX;                        //x coordinate of the centroid
        int MY;                        //y coordinate of the centroid
        int X1;                        //upper left x coordinate
        int Y1;                        //upper left y coordinate
        int X2;                        //lower right x coordinate
        int Y2;                        //lower right y coordinate
        int Num_Pix;        //number of matching pixels in the box
        int Confid;                //confidence that it is the object according to the CMUcam
}N_PACKET;

typedef struct
{
        //COL_PACKET consists of upper and lower bound RGB values for color tracking purposes
        //Used with the TC (trackcustomcolor) command
        int Rmax;                //Upper red bound
        int Rmin;                //Lower red bound
        int Gmax;                //Upper green bound
        int Gmin;                //Lower green bound
        int Bmax;                //Upper blue bound
        int Bmin;                //Lower blue bound
}COL_PACKET;



//GLOBAL VARIABLES
static HANDLE ComPort;                //Handle to our comport
static OVERLAPPED  o;                //Overlapped type whcih is used for the com_events
static int IN_PACKET;                //bool to keep track of whether or not we are in a packet stream




//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

//KARL RIEHL'S COMPORT CODE (Modified by Mike Konicki)
//        -Modified versions of karl's comport api which
//                was modified to allow for ease of use
//                and stealth (user doesnt have to touch)

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//\/\/\/\/\/\/\/\/\
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/


int _stdcall CMU_SetComSettings(int BaudRate, int ByteSize, DWORD Parity, DWORD StopBits)
//***********************************************************
//        Purpose: Sets the commport settings so that communication can occur between the program and the CMUcam
//
//        Input:  ComPort handle, BaudRate, ByteSize, Parity, StopBits are all communication settings for the comport
//
//        Output: 0 on failure, 1 on success
//**********************************************************
{
        DCB dcb;        //Struct that holds communication settings


        //Check Comstate to ensure we can change the settings
        if(!GetCommState(ComPort, &dcb))
                return 0;

        //Fill in the struct with the new communication protocal
        dcb.Parity =  Parity;
        dcb.BaudRate = BaudRate;
        dcb.ByteSize = ByteSize;
        dcb.StopBits = StopBits;

        //Set the protocal on the comport, check for a failure
        if(!SetCommState(ComPort, &dcb))
                return 0;

        return 1;        //return 1 on success
}


int _stdcall CMU_SetTimeouts(DWORD ReadInterval, int ReadMultiplier, int ReadConstant, int WriteMultiplier, int WriteConstant)
//**********************************************************
//        Purpose:  The function sets the length in milliseconds that a function will
//                                wait before it continues on with the following code.
//
//        Input: Timeout Settings and ComPort handle
//**********************************************************
{
        COMMTIMEOUTS timeouts;

        // Fills the COMMTIMEOUTS structure
        if (!GetCommTimeouts(ComPort, &timeouts))
                return 0;

        // Sets the fields in the structure
        timeouts.ReadIntervalTimeout = ReadInterval;
        timeouts.ReadTotalTimeoutConstant = ReadConstant;
        timeouts.ReadTotalTimeoutMultiplier = ReadMultiplier;
        timeouts.WriteTotalTimeoutConstant = WriteConstant;
        timeouts.WriteTotalTimeoutMultiplier = WriteMultiplier;

        // Sets the new timeouts
        if (!SetCommTimeouts(ComPort, &timeouts))
                return 0;

        return 1;
}


int _stdcall CMU_ClearOutputBuffer()
//**********************************************************
//        Purpose:  Clears the output buffer of the comport
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if (!PurgeComm(ComPort, PURGE_TXCLEAR))
                return 0;

        return 1;
}


int _stdcall CMU_ClearInputBuffer()
//**********************************************************
//        Purpose:  Clears the input buffer of the comport
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if (!PurgeComm(ComPort, PURGE_RXCLEAR))
                return 0;

        return 1;
}


int _stdcall CMU_ClearBuffers()
//**********************************************************
//        Purpose:  Clears the input & output buffers of the comport (calls the in and out clears)
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        // Clears the output buffer
        if (!CMU_ClearOutputBuffer())
                return 0;

        // Clears the input buffer
        if (!CMU_ClearInputBuffer())
                return 0;

        return 1;
}


int _stdcall CMU_SetBuffer(int Incoming, int Outgoing)
//***********************************************************
//        Purpose: Sets the read and write buffers for the com port
//
//        Input:  Handle to ComPort, incoming, outgoing rates
//
//        Output: 0 of fail, 1 on success
//**********************************************************
{
        // Sets the new buffer size
        if (!SetupComm(ComPort, Incoming, Outgoing))
                return 0;

        return 1;
}

int _stdcall CMU_ClearWrite()
//**********************************************************
//        Purpose:  Clears any waiting write commands from the buffer
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if (!PurgeComm(ComPort, PURGE_TXABORT))
                return 0;

        return 1;
}

int _stdcall CMU_ClearRead()
//**********************************************************
//        Purpose:  Clears any waiting reads from the buffer
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if (!PurgeComm(ComPort, PURGE_RXABORT))
                return 0;

        return 1;
}


int _stdcall CMU_ClearReadWrite()
//**********************************************************
//        Purpose:  Clears any waiting reads and/or writes from the buffer
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        // Clears the reads yet to be made
        if(!CMU_ClearRead())
                return 0;

        // Clears the writes yet to be made
        if(!CMU_ClearWrite())
                return 0;

        return 1;
}


int _stdcall CMU_ClearSignal()
//**********************************************************
//        Purpose:   Lets the port know it is ok to send/recieve data
//
//        Input: ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if(!EscapeCommFunction(ComPort, CLRDTR))
                return 0;

        if(!EscapeCommFunction(ComPort, CLRRTS))
                return 0;

        return 1;
}


int _stdcall CMU_SetSignal()
//**********************************************************
//        Purpose:   Lets the port know it is ok to send/recieve data
//
//        Input:        ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        if(!EscapeCommFunction(ComPort, SETDTR))
                return 0;
        if(!EscapeCommFunction(ComPort, SETRTS))
                return 0;

        return 1;
}


int _stdcall CMU_PortOpen(char *Port)
//***********************************************************
//        Purpose: Opens the port and initializes it to work with the default CMUcam settings
//
//        Input:  ComPort
//
//        Output: 0 on failure, HANDLE(int) on Success
//**********************************************************
{
        //Opens the port and sets the handle
        ComPort = CreateFile(Port, GENERIC_WRITE | GENERIC_READ, 00, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

        //Check to make sure handle is good
        if(ComPort == INVALID_HANDLE_VALUE)
                return 0;

        //Clear any possible signals on the comport
        if(!CMU_ClearSignal())
                return 0;

        //Sets the signal DTR and RTS signals on the comport
        if(!CMU_SetSignal())
                return 0;

        //Clear out the read write buffers
        if(!CMU_ClearReadWrite())
                return 0;

        //Possibly need a sleep(2) here

        //Set CMUcam Default communication Rates
        if(!CMU_SetComSettings(1152008, NOPARITY, ONESTOPBIT))
                return 0;

        //Set the read and write timeouts
        if(!CMU_SetTimeouts( MAXWORD, 0 ,0 ,0 ,0 ))
                return 0;

        //Set the buffer sizes to max for CMUcam
        if(!CMU_SetBuffer( 10281028))
                return 0;

        //Port Successfully Opened Return the com HANDLE
        return 1;
}



void _stdcall CMU_ClosePort()
//***********************************************************
//        Purpose: Closes the HANDLE to the comport
//
//        Input:  Handle to ComPort
//
//        Output: None
//**********************************************************
{

        CloseHandle(ComPort);

        return;
}


int _stdcall CMU_Read(unsigned char* ch, int NumBytesToRead)
//**********************************************************
//        Purpose: The function reads in from the input buffer and places the first
//                          byte at the address that is pointed to by the unsigned char pointer.
//
//        Input:        ComPort Handle, and read data (blank)
//
//  Output: 0 on fail, pointer on success
//**********************************************************
{
        DWORD NumBytesRead;
        if (!ReadFile(ComPort, ch, NumBytesToRead, &NumBytesRead, 0))
                return 0;

        return (int)NumBytesRead;
}

int _stdcall CMU_Write(unsigned char* ch, int NumBytesToWrite)
//**********************************************************
//        Purpose: The function writes the number of bytes starting at the memory
//                    location specified by the unsigned char pointer to the port.
//
//        Input:        ComPort Handle, and data
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        DWORD write;

        if (!WriteFile(ComPort, ch, NumBytesToWrite, &write, 0))
                return 0;

        return 1;
}

int _stdcall CMU_InputBufferSize()
//**********************************************************
//        Purpose: The function returns the number of bytes that are currently in the
//           input buffer.
//
//        Input:        ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        COMSTAT cs;
        DWORD err;

        ClearCommError(ComPort, &err, &cs);

        //return the size of the buffer
        return cs.cbInQue;
}

int _stdcall CMU_OutputBufferSize()
//**********************************************************
//        Purpose: The function returns the number of bytes that are
//                         currently in the output buffer.
//
//        Input:        ComPort Handle
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        COMSTAT cs;
        DWORD err;

        ClearCommError(ComPort, &err, &cs);

        //return the size of the buffer
        return cs.cbOutQue;
}





//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

//INTERNAL CODE MODULES
//        -These two modules handle almost all of the reading
//                of the comport one is for streams the other for
//                non-stream functions

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//\/\/\/\/\/\/\/\/\
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/





int _stdcall INTERNAL_ACKNCK(unsigned char * str, int buffer)
//***************************************************************************
//        Purpose: Simple reads in data after a transmission and determines  if
//                         the cmucam got it (ack) or didnt get it (nck)
//
//        Input:        str --> pointer to string, some functions need to draw info out of it
//
//  Output: 0 on nck, 1 on ack
//***************************************************************************
{

        DWORD Mask;                                                //Mask for COMEvent
        unsigned char test[750];                //buffer to hold data beign read in
        int i;                                                        //loop counter
        int start = 0;                                        //used as a flag when processing acks
        int cnt = 0;                                        //used with start when processing


        // Needed to set mask for WaitCommEvent
        SetCommMask(ComPort, EV_RXCHAR);

        //Wait a bit for the camera to process the command
        WaitCommEvent(ComPort, &Mask, &o);

        //Read from the buffer, for the entire buffer size
        if(!CMU_Read(&test[0],buffer)){
                return 0;
        }

        //in case of a framedump we dont want to remove
        //the chr 13's since that will hurt our data
        if(buffer > 500)
        {
                str = test;
                str[buffer +1] = '\0';
                return 1;
        }

        //Compare the imcoming data to see if we have an ACK or NCKm
        //only need to compare the first letter to save time
        if((int)'A' == (int)test[0])
        {
                //need to go through and remove the chr(13) or carraige return
                //if it isnt removed passed data comes out funky.  We are just
                //going to replace it with a Chr(32) or space
                for(i=0;i<buffer - 1;i++)
                {
                        if((int)test[i] != 13)        //if not enter copy it into our return string
                        {
                                //We dont want to save the ACK_
                                if(start == 1)
                                {
                                        sprintf(&str[cnt],"%c\0",test[i]);
                                        cnt = cnt + 1;
                                }//end if
                        }//end if
                        else                //got a CR need to replace it
                        {
                                //we dont want to save until after the ACK which will be marked
                                //with a Chr(13) we are replacing
                                if(start == 1)
                                {
                                        sprintf(&str[cnt],"%c\0",32);
                                        cnt = cnt + 1;
                                }//end if
                                else
                                        start = 1;
                        }//end else
                }//end for

                return 1;
        }

        //NCK recieved from CMUcamera something went wrong somewhere
        else
        {
                str = NULL;
                return 0;
        }
}




int _stdcall INTERNAL_PACKET_PROCESS(int* slot1, int* slot2, int* slot3, int* slot4, int* slot5, int* slot6, int* slot7, int* slot8, int* slot9, int buffer)
//***************************************************************************
//        Purpose: Reads data from the packet streams (M,N,C,S) and splits it up
//                         into (upto) 9 different int* which will get sent back to the
//                         function that called it. That function knows what numbers are
//                         what and actually fills in teh data structs for the main program
//
//        Input:        int* slot(1-9) --> holds the various numbers returned from the packet stream
//                        buffer --> how much to read out of the packet stream before processing
//
//  Output: 0 on nck, 1 on ack
//***************************************************************************
{
        DWORD Mask;                                        //Mask for COMEvent
        unsigned char test[150];        //input of packet
        int startofpacket;                        //mark start of a packet string
        int i;                                                //Int for loop counter
        char* tok1;                                        //Used for token ripping
        char* tok2;                                        //Used for token ripping
        char* tok3;                                        //Used for token ripping
        char* tok4;                                        //Used for token ripping
        char* tok5;                                        //Used for token ripping
        char* tok6;                                        //Used for token ripping
        char* tok7;                                        //Used for token ripping
        char* tok8;                                        //Used for token ripping
        char* tok9;                                        //Used for token ripping


        // Needed to set mask for WaitCommEvent
        SetCommMask(ComPort, EV_RXCHAR);

        //Wait a bit for the camera to process the command
        WaitCommEvent(ComPort, &Mask, &o);

        //Read from the buffer, for the entire buffer size
        if(!CMU_Read(&test[0],buffer)){
                return 0;
        }

        //Removes all Chr(13)'s from the string
        //if strtok hits a Chr(13) it will generate
        //a nasty exception error
        for(i=0;i<buffer;i++)
        {
                if((int)test[i] == 13)
                {
                        sprintf(&test[i],"%c\0",32);
                }
        }

        //Go through the loop and find start of the packet
        for(i=0;i<buffer;i++)
        {
                if((int)test[i] == 0)
                {
                        //Check to see if it is a start of a packet in which
                        //case we need to add 1 to the start for strtok
                        if((int)test[i+1] == (int)'S' || (int)test[i+1] == (int)'C' || (int)test[i+1] == (int)'M' || (int)test[i+1] == (int)'N'){
                                startofpacket = i + 3;
                                break;
                        }
                        //if it is not the start of a packet then we
                        //dont have to worry about the extra char in the packet
                        else{
                                startofpacket = i + 2;
                                break;
                        }
                }//end big if
        }//end for

        //Signal that we are inside a packet already
        //so ping knows this in order to clear buffers
        //after a call or not
        IN_PACKET = 1;

//******************************************
//use strtok to rip apart the packets
//******************************************

        //See if the first token is ok, if it fails error
        tok1 = strtok(&test[startofpacket]," ");
        if(tok1 == NULL)
                return 0;
        else
                *slot1 = atoi(tok1);

        //See if 2nd token is ok, if it fails error
        tok2 = strtok(NULL," ");
        if(tok2 == NULL)
                return 0;
        else
                *slot2 = atoi(tok2);

        //See if 3rd token is ok, if it fails error
        tok3 = strtok(NULL," ");
        if(tok3 == NULL)
                return 0;
        else
                *slot3 = atoi(tok3);

        //See if 4th token is ok, if it fails error
        tok4 = strtok(NULL," ");
        if(tok4 == NULL)
                return 0;
        else
                *slot4 = atoi(tok4);

        //See if 5th token is ok, if it fails error out
        tok5 = strtok(NULL," ");
        if(tok5 == NULL)
                return 0;
        else
                *slot5 = atoi(tok5);

        //See if 6th token is ok, if it fails error out
        tok6 = strtok(NULL," ");
        if(tok6 == NULL)
                return 0;
        else
                *slot6 = atoi(tok6);

        //See if 7th token is ok, if it fails its ok since packet size
        //can be 6 for 'S' or 'C' packets
        tok7 = strtok(NULL," ");
        if(tok7 == NULL)
                return 1;
        else
                *slot7 = atoi(tok7);

        //See if token 8 is ok, if it fails error out no token size of 7
        tok8 = strtok(NULL," ");
        if(tok8 == NULL)
                return 0;
        else
                *slot8 = atoi(tok8);

        //check token 9 if it fails return success 'M' packet is
        //size 8
        tok9 = strtok(NULL," ");
        if(tok9 == NULL)
                return 1;
        else
                *slot9 = atoi(tok9);

        return 1;
}


//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

//CAMERA FUNCTIONS (CMU_Cam routines)
//        -These fucntions prepare and send messages to
//                the CMUcam. The internal functions do the
//                actual reading though

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
//\/\/\/\/\/\/\/\/\
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/


int _stdcall CAM_Ping()
//**********************************************************
//        Purpose: Pings the Camera to check for activity
//
//        Input:        None
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[1];
        unsigned char * ret;
        unsigned char store[20];

        //Clear the buffers since a ping also serves as the stream killer for packets
        if(!CMU_ClearBuffers())
                return 0;

        //Give our pointer something to point to
        ret = store;
        //Send the Command to ping CMUcam
        msg[0] = '\r';


//****************************
//This is if we are currently in a packet stream.
//EndPacket calls ping which is the safest way to
//to destroy a packet stream since it will not
//reset any of the registers currently set by the user
//****************************
        if(IN_PACKET == 1)
        {
                //Send it once, to stop packets from coming in
                if(!CMU_Write(&msg[0],1))
                        return 0;                                //Failed return 0

                //Delay so the packet stream can be terminated
                Sleep(100);

                //Clear the buffers since a ping also serves as the stream killer for packets
                //and clean out the packet data in the buffer. YES the ack/nck on the ping is lost
                //but all we are concerned with here is stopping the packet stream
                if(!CMU_ClearBuffers())
                        return 0;

                Sleep(100);

                IN_PACKET = 0;
        }

        //Send it
        if(!CMU_Write(&msg[0],1))
                return 0;                                //Failed return 0

        //Make sure the packet went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        //Return Success
        return 1;

}//End CAM_Ping


int _stdcall CAM_Init(char * port)
//**********************************************************
//        Purpose: Calls the routine to setup up the port for the CMUcam,
//
//        Input:        Port Address
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{

        //Open the port to the CMUcam
        if(!CMU_PortOpen(port))
                return 0;

        // Creates an event for the OVERLAPPED structure
        o.hEvent = CreateEvent(
        NULL,   // default security attributes
        FALSE,  // auto reset event
        FALSE,  // not signaled
        NULL    // no name
                );

    //Intialize the rest of the OVERLAPPED structure to zero. which
        //is used for the com_event functions
    o.Internal = 0;
    o.InternalHigh = 0;
    o.Offset = 0;
    o.OffsetHigh = 0;

        //Delay to let the camera finish connecting
        Sleep(100);

        //Return we got a good port
        return 1;

}//End CAM_Init


int _stdcall CAM_TrackLight(unsigned char* mode)
//**********************************************************
//        Purpose: Sets the tracking light to on, off, or auto mode
//
//        Input:        mode (0,1,2)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to else we get warnings when compiling
        ret = store;

        //Check to make sure our input is valid (0,1,2 only)
        if (mode != '0' && mode != '1' && mode != '2')
                return 0;

        //Build the command string for the CMUcam (Tracking Light)
        msg[0] = 'L';
        msg[1] = '1';
        msg[2] = ' ';
        msg[3] = mode;
        msg[4] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;

}//End CAM_TrackLight


int _stdcall CAM_ClockSpeed(unsigned char speed)
//**********************************************************
//        Purpose: Sets the clockspeed to the user selected amout
//
//        Input:        speed(2,3,4,5,6,7,8)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;

        //Check to make sure the input is valid
        if(speed != '2' && speed != '3' && speed != '4' && speed != '5' && speed !=  '6' && speed != '7' && speed != '8' )
        {
                return 0;
        }


        //Build the command string for the CMUcam (Clock Speed)
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '7';
        msg[5] = ' ';
        msg[6] = speed;
        msg[7] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],8))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        //Return Success
        return 1;

}//End CAM_ClockSpeed


int _stdcall CAM_Brightness(int bri)
//**********************************************************
//        Purpose: Sets the Brightness to the user selected amout
//
//        Input:        Brightness (0-255)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char bright[3];
        unsigned char msg[20];
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;

        //Checl for valid input
        if(bri <= 0 || bri >= 255)
                return 0;

        //Convert the number for the brightness into a string
        //and store it in bright array
        itoa(bri, bright,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(bri < 10)
        {
                bright[1] = ' ';
                bright[2] = ' ';
        }
        else if(bri < 100)
        {
                bright[2] = ' ';
        }

        //Build the header for the command
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '6';
        msg[4] = ' ';
        msg[5] = bright[0];
        msg[6] = bright[1];
        msg[7] = bright[2];
        msg[8] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],9))
                return 0;

        printf("Writting\n");

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        //Return Success
        return 1;
}//End CAM_Brightness




int _stdcall CAM_Contrast(int con)
//**********************************************************
//        Purpose: Sets the Brightness to the user selected amout
//
//        Input:        Brightness (0-255)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char contrast[3];
        unsigned char msg[20];
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;

        //Checl for valid input
        if(con <=0 || con >=255)
                return 0;

        //Convert the number for the brightness into a string
        //and store it in bright array
        itoa(con, contrast,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(con < 10)
        {
                contrast[1] = ' ';
                contrast[2] = ' ';
        }
        else if(con < 100)
        {
                contrast[2] = ' ';
        }


        //Build the header for the command
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '6';
        msg[4] = ' ';
        msg[5] = contrast[0];
        msg[6] = contrast[1];
        msg[7] = contrast[2];
        msg[8] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],9))
                return 0;

        printf("Writting\n");

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        //Return Success
        return 1;
}//End CAM_Brightness


int _stdcall CAM_GetVersion(unsigned char * version)
//**********************************************************
//        Purpose: Gets The Current FirmwareVersion
//
//        Input:        ptr which can point to the version info
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam

        //Build the command string for the CMUcam (Tracking Light)
        msg[0] = 'G';
        msg[1] = 'V';
        msg[2] = ' ';
        msg[3] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],4))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(version, 18))
                return 0;

        //Return Success, pointer doesnt need to be returned since it is
        //only using an address
        return 1;

}//End CAM_GetVersion



int _stdcall CAM_HalfHorizontalMode(unsigned char mode)
//**********************************************************
//        Purpose: Sets the camera to Half-horizontal mode
//                         when on everyother odd colum is skipped to save time
//
//        Input:        mode (1=on, 0=off)
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Check to make sure our input is valid (0,1  only)
        if (mode != '0' && mode != '1')
                return 0;

        //Build the command string for the CMUcam (Half-horizontal)
        msg[0] = 'H';
        msg[1] = 'M';
        msg[2] = ' ';
        msg[3] = mode;
        msg[4] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;

}//End CAM_TrackLight



int _stdcall CAM_NoiseFilter(unsigned char filter)
//**********************************************************
//        Purpose: Enables or disables the Noise Filter on the
//                         cmucam
//
//        Input:        mode (1=on, 0=off)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Check to make sure our input is valid (0,1 only)
        if (filter != '0' && filter != '1' )
                return 0;

        //Build the command string for the CMUcam (Noise Filter)
        msg[0] = 'N';
        msg[1] = 'F';
        msg[2] = ' ';
        msg[3] = filter;
        msg[4] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;

}//End CAM_NoiseFilter


int _stdcall CAM_MiddleMassMode(int mode)
//**********************************************************
//        Purpose: Either disables or enables middle mass mode or
//                         enables middle mass mode with servo support. This
//                         function should never be used except when called
//                         by other functions.
//
//        Input:        mode (1=on, 0=off, 10 on with servo)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;

        //Check to make sure our input is valid (0,1, 10 only)
        if(mode != 1 && mode != 0 && mode != 10)
                return 0;

        //Build teh command string if it is mode = 10
        if(mode == 10)
        {
                msg[0] = 'M';
                msg[1] = 'M';
                msg[2] = ' ';
                msg[3] = '1';
                msg[4] = '0';
                msg[5] = '\r';

                //send the command
                if(!CMU_Write(&msg[0],6))
                        return 0;
        }
        else        //if it is 1 or 0 just use itoa to make the string
        {
                msg[0] = 'M';
                msg[1] = 'M';
                msg[2] = ' ';
                itoa(mode,&msg[3],10);                //convert int to char for the CMUcam
                msg[4] = '\r';

                //send the command
                if(!CMU_Write(&msg[0],5))
                        return 0;
        }


        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;

}//End CAM_MiddleMassMode



int _stdcall CAM_Reset()
//**********************************************************
//        Purpose: Resets the camera to default settings
//
//        Input:        none
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'R';
        msg[1] = 'S';
        msg[2] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],3))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 19))
                return 0;

        return 1;

}//End CAM_Reset




int _stdcall CAM_SwitchMode(unsigned char mode)
//**********************************************************
//        Purpose: Sets the switch mode to on or off. Switch mode
//                         when activated means that everother packet will
//                         be a S-packet (statistical packet). off returns
//                         only the normall C or M-packets.
//
//        Input:        mode (1=on, 0=off)
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Check to make sure our input is valid (0,1  only)
        if (mode != '0' && mode != '1')
                return 0;

        //Build teh command string
        msg[0] = 'S';
        msg[1] = 'M';
        msg[2] = ' ';
        msg[3] = mode;
        msg[4] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;

}//End CAM_SwitchMode


int _stdcall CAM_STR_MC()
//**********************************************************
//        Purpose: Starts the mean color stream
//
//        Input:         None
//
//  Output:  None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        int temp1,temp2, temp3;
        int Rmean, Gmean, Bmean, Rdev, Gdev, Bdev;

        //Build the command string
        msg[0] = 'G';
        msg[1] = 'M';
        msg[2] = ' ';
        msg[3] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through and recieve the data back
        //need to through in a few empty chars since packet handler can handle
        //bigger packets then the "S" packet we are expecting even though we dont return it since
        //this function simple initializes the stream it is not for packet streaming
        if(!INTERNAL_PACKET_PROCESS(&Rmean,&Gmean,&Bmean,&Rdev,&Gdev,&Bdev,&temp1,&temp2,&temp3, 50))
                return 0;

        return 1;
}//End CAM_GetMeanColor



int _stdcall CAM_EndPacket()
//**********************************************************
//        Purpose: Ends the packet stream by sending a ping
//                         to the camera
//
//        Input:        none
//
//  Output: 1 on success 0 on error
//**********************************************************
{
        //Just call the ping function to sever the packet stream
        Sleep(200);

        if(!CAM_Ping())        //May not succeed on first try due to the massive amount of incoming data
        {
                Sleep(400);                //let the comport clean itself...
                if(!CAM_Ping())        //and try again
                        return 0;
                else
                        return 1;
        }
        else
        {
                return 1;
        }
}



int _stdcall CAM_Get_MC(S_PACKET* spack)
{
//**********************************************************
//        Purpose: Returns the mean color of the image it is currently
//                         seeing. If SW is used it will return only the screen
//                         selected in there.
//
//                         Same as CAM_GetMeanColor except it uses the packet
//                         stream initialized by that function (no sending only reading)
//
//        Input:         S_PACKET Struct Pointer
//
//  Output: S_PACKET Struct containing: R,G,B mean values & R,G,B deviation values
//                        1 on success 0 on error
//**********************************************************
        int temp1,temp2, temp3;
        int Rmean, Gmean, Bmean, Rdev, Gdev, Bdev;


        //Check to see the command went through and recieve the data back
        //need to through in a few empty chars since packet handler can handle
        //bigger packets then the "S" packet we are expecting
        if(!INTERNAL_PACKET_PROCESS(&Rmean,&Gmean,&Bmean,&Rdev,&Gdev,&Bdev,&temp1,&temp2,&temp3, 50))
                return 0;

        //Fill in the data for the struct
        spack->Rmean = Rmean;
        spack->Gmean = Gmean;
        spack->Bmean = Bmean;
        spack->Rdev = Rdev;
        spack->Gdev = Gdev;
        spack->Bdev = Bdev;

        return 1;
}


int _stdcall CAM_STR_TCO_Centroid()
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        int temp3;
        int Mx, My, X1, Y1, X2, Y2, pixels, confidence;

        //For some odd reason the camera has to be initialzed this way
        //so we start the MeanColor Stream off and then kill it off again
        //with endpacket
        if(!CAM_STR_MC())
                return 0;

        if(!CAM_EndPacket())
                return 0;

        //Set the MiddleMassMode to Centroid Data on
        if(!CAM_MiddleMassMode(1))
                return 0;

        //Build teh command string
        msg[0] = 'T';
        msg[1] = 'W';
        msg[2] = ' ';
        msg[3] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Looking for a "M" packet
        if(!INTERNAL_PACKET_PROCESS(&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp3, 50))
                return 0;

        return 1;

}//End CAM_GetMeanColor



int _stdcall CAM_Get_TCO_Centroid(M_PACKET* mpack)
{
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
        int temp3;
        int Mx, My, X1, Y1, X2, Y2, pixels, confidence;

        //Prepare to handle a type "M" string
        if(!INTERNAL_PACKET_PROCESS(&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp3, 50))
                return 0;

        //Fill in the struct data
        mpack->MX = Mx;
        mpack->MY = My;
        mpack->X1 = X1;
        mpack->Y1 = Y1;
        mpack->X2 = X2;
        mpack->Y2 = Y2;
        mpack->Num_Pix = pixels;
        mpack->Confid = confidence;

        return 1;
}


int _stdcall CAM_STR_TCO()
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:        None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        int temp1,temp2,temp3;
        int X1, Y1, X2, Y2, pixels, confidence;


        //For some odd reason the camera has to be initialzed this way
        //so we start the MeanColor Stream off and then kill it off again
        //with endpacket
        if(!CAM_STR_MC())
                return 0;

        if(!CAM_EndPacket())
                return 0;


        //Set the MiddleMassMode to Centroid Data off
        if(!CAM_MiddleMassMode(0))
                return 0;

        //Build the command string
        msg[0] = 'T';
        msg[1] = 'W';
        msg[2] = ' ';
        msg[3] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Looking for a "C" packet
        if(!INTERNAL_PACKET_PROCESS(&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp1,&temp2,&temp3, 75))
                return 0;

        return 1;

}//End CAM_GetMeanColor


int _stdcall CAM_Get_TCO(C_PACKET* cpack)
{
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
        int temp1,temp2,temp3;
        int X1, Y1, X2, Y2, pixels, confidence;


        //Prepare to handle a type "C" string
        if(!INTERNAL_PACKET_PROCESS(&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp1,&temp2,&temp3, 75))
                return 0;

        //Fill in the struct with data
        cpack->X1 = X1;
        cpack->Y1 = Y1;
        cpack->X2 = X2;
        cpack->Y2 = Y2;
        cpack->Num_Pix = pixels;
        cpack->Confid = confidence;

        return 1;
}

int _stdcall CAM_STR_TCO_Servo()
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        int Spos,Mx, My, X1, Y1, X2, Y2, pixels, confidence;


        //For some odd reason the camera has to be initialzed this way
        //so we start the MeanColor Stream off and then kill it off again
        //with endpacket
        if(!CAM_STR_MC())
                return 0;

        if(!CAM_EndPacket())
                return 0;

        //Set the MiddleMassMode to Centroid Data on
        if(!CAM_MiddleMassMode(10))
                return 0;

        //Build teh command string
        msg[0] = 'T';
        msg[1] = 'W';
        msg[2] = ' ';
        msg[3] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Looking for a "N" packet
        if(!INTERNAL_PACKET_PROCESS(&Spos,&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,50))
                return 0;

        return 1;
}//End CAM_GetMeanColor


int _stdcall CAM_Get_TCO_Servo(N_PACKET* npack)
{
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
        int Spos,Mx, My, X1, Y1, X2, Y2, pixels, confidence;


        //Prepare to handle a type "N" string
        if(!INTERNAL_PACKET_PROCESS(&Spos,&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,65))
                return 0;

        //Fill in the struct with data
        npack->Spos = Spos;
        npack->MX = Mx;
        npack->MY = My;
        npack->X1 = X1;
        npack->Y1 = Y1;
        npack->X2 = X2;
        npack->Y2 = Y2;
        npack->Num_Pix = pixels;
        npack->Confid = confidence;

        return 1;
}


int _stdcall CAM_ColMode_RGB_ON()
//**********************************************************
//        Purpose: Sets the CMUcam to RGB mode with auto whitebalance
//                         turned ON
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '8';
        msg[5] = ' ';
        msg[6] = '4';
        msg[7] = '4';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_ColMode_RGB_OFF()
//**********************************************************
//        Purpose: Sets the CMUcam to RGB mode with auto whitebalance
//                         turned OFF
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '8';
        msg[5] = ' ';
        msg[6] = '4';
        msg[7] = '0';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_ColMode_YCrCb_ON()
//**********************************************************
//        Purpose: Sets the CMUcam to YCrCb mode with auto whitebalance
//                         turned ON
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '8';
        msg[5] = ' ';
        msg[6] = '3';
        msg[7] = '6';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_ColMode_YCrCb_OFF()
//**********************************************************
//        Purpose: Sets the CMUcam to YCrCb mode with auto whitebalance
//                         turned OFF
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '8';
        msg[5] = ' ';
        msg[6] = '3';
        msg[7] = '2';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_AutoExposure_GainOFF()
//**********************************************************
//        Purpose: Sets the CMUcam's autoexposure to off
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '9';
        msg[5] = ' ';
        msg[6] = '3';
        msg[7] = '2';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_AutoExposure_GainON()
//**********************************************************
//        Purpose: Sets the CMUcam's autoexposure to on
//
//        Input:         None
//
//  Output: None
//**********************************************************
{
        unsigned char msg[20];                        //Message being sent to the CMUcam
        unsigned char * ret;
        unsigned char store[20];

        //Give our pointer something to point to
        ret = store;


        //Build teh command string
        msg[0] = 'C';
        msg[1] = 'R';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '9';
        msg[5] = ' ';
        msg[6] = '3';
        msg[7] = '3';
        msg[8] = ' ';
        msg[9] = '\r';


        //send the command
        if(!CMU_Write(&msg[0],10))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}


int _stdcall CAM_STR_TCC_Centroid(COL_PACKET* cpack)
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
{
        unsigned char Rmax[2], Gmax[2], Bmax[2];
        unsigned char Rmin[2], Gmin[2], Bmin[2];
        unsigned char msg[30];
        unsigned char * ret;
        unsigned char store[20];
        int temp3;
        int Mx, My, X1, Y1, X2, Y2, pixels, confidence;



        //Give our pointer something to point to
        ret = store;

        //Set the MiddleMassMode to Centroid Data on
        if(!CAM_MiddleMassMode(1))
                return 0;

        //Need to test each of the variables to make sure they are within the 0-255 range the user is allowed

//Start with Rmax, check it, convert it, and store it for later use
        if(cpack->Rmax < 0 || cpack->Rmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Rmax, Rmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Rmax < 10){
                Rmax[1] = ' ';
                Rmax[2] = ' ';
        }
        else if(cpack->Rmax  < 100){
                Rmax[2] = ' ';
        }


//Gmax, check it, convert it, and store it for later use
        if(cpack->Gmax < 0 || cpack->Gmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Gmax, Gmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Gmax < 10){
                Gmax[1] = ' ';
                Gmax[2] = ' ';
        }
        else if(cpack->Gmax  < 100){
                Gmax[2] = ' ';
        }


//Bmax, check it, convert it, and store it for later use
        if(cpack->Bmax < 0 || cpack->Bmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Bmax, Bmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Bmax < 10){
                Bmax[1] = ' ';
                Bmax[2] = ' ';
        }
        else if(cpack->Bmax  < 100){
                Bmax[2] = ' ';
        }


//Rmin, check it, convert it, and store it for later use
        if(cpack->Rmin < 0 || cpack->Rmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Rmin, Rmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Rmin < 10){
                Rmin[1] = ' ';
                Rmin[2] = ' ';
        }
        else if(cpack->Rmin  < 100){
                Rmin[2] = ' ';
        }


//Gmin, check it, convert it, and store it for later use
        if(cpack->Gmin < 0 || cpack->Gmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Gmin, Gmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Gmin < 10){
                Gmin[1] = ' ';
                Gmin[2] = ' ';
        }
        else if(cpack->Gmin  < 100){
                Gmin[2] = ' ';
        }


//Bmin, check it, convert it, and store it for later use
        if(cpack->Bmin < 0 || cpack->Bmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Bmin, Bmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Bmin < 10){
                Bmin[1] = ' ';
                Bmin[2] = ' ';
        }
        else if(cpack->Bmin  < 100){
                Bmin[2] = ' ';
        }

        //Build our message (its ugly but only way that works)
        msg[0] = 'T';
        msg[1] = 'C';
        msg[2] = ' ';
        msg[3] = Rmin[0];
        msg[4] = Rmin[1];
        msg[5] = Rmin[2];
        msg[6] = ' ';
        msg[7] = Rmax[0];
        msg[8] = Rmax[1];
        msg[9] = Rmax[2];
        msg[10] = ' ';
        msg[11] = Gmin[0];
        msg[12] = Gmin[1];
        msg[13] = Gmin[2];
        msg[14] = ' ';
        msg[15] = Gmax[0];
        msg[16] = Gmax[1];
        msg[17] = Gmax[2];
        msg[18] = ' ';
        msg[19] = Bmin[0];
        msg[20] = Bmin[1];
        msg[21] = Bmin[2];
        msg[22] = ' ';
        msg[23] = Bmax[0];
        msg[24] = Bmax[1];
        msg[25] = Bmax[2];
        msg[26] = ' ';
        msg[27] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],30))
                return 0;

        //Prepare to handle a type "M" string
        if(!INTERNAL_PACKET_PROCESS(&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp3, 50))
                return 0;

        return 1;
}


int _stdcall CAM_Get_TCC_Centroid(M_PACKET* mpack)
{
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
        int temp3;
        int Mx, My, X1, Y1, X2, Y2, pixels, confidence;

        //Prepare to handle a type "M" string
        if(!INTERNAL_PACKET_PROCESS(&Mx,&My,&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp3, 50))
                return 0;

        //Fill in the struct data
        mpack->MX = Mx;
        mpack->MY = My;
        mpack->X1 = X1;
        mpack->Y1 = Y1;
        mpack->X2 = X2;
        mpack->Y2 = Y2;
        mpack->Num_Pix = pixels;
        mpack->Confid = confidence;

        return 1;
}


int _stdcall CAM_STR_TCC(COL_PACKET* cpack)
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
{
        unsigned char Rmax[2], Gmax[2], Bmax[2];
        unsigned char Rmin[2], Gmin[2], Bmin[2];
        unsigned char msg[30];
        unsigned char * ret;
        unsigned char store[20];
        int temp1,temp2,temp3;
        int X1, Y1, X2, Y2, pixels, confidence;

        //Give our pointer something to point to
        ret = store;

        //Set the MiddleMassMode to Centroid Data on
        if(!CAM_MiddleMassMode(0))
                return 0;

        //Need to test each of the variables to make sure they are within the 0-255 range the user is allowed

//Start with Rmax, check it, convert it, and store it for later use
        if(cpack->Rmax < 0 || cpack->Rmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Rmax, Rmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Rmax < 10){
                Rmax[1] = ' ';
                Rmax[2] = ' ';
        }
        else if(cpack->Rmax  < 100){
                Rmax[2] = ' ';
        }


//Gmax, check it, convert it, and store it for later use
        if(cpack->Gmax < 0 || cpack->Gmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Gmax, Gmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Gmax < 10){
                Gmax[1] = ' ';
                Gmax[2] = ' ';
        }
        else if(cpack->Gmax  < 100){
                Gmax[2] = ' ';
        }


//Bmax, check it, convert it, and store it for later use
        if(cpack->Bmax < 0 || cpack->Bmax > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Bmax, Bmax ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Bmax < 10){
                Bmax[1] = ' ';
                Bmax[2] = ' ';
        }
        else if(cpack->Bmax  < 100){
                Bmax[2] = ' ';
        }


//Rmin, check it, convert it, and store it for later use
        if(cpack->Rmin < 0 || cpack->Rmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Rmin, Rmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Rmin < 10){
                Rmin[1] = ' ';
                Rmin[2] = ' ';
        }
        else if(cpack->Rmin  < 100){
                Rmin[2] = ' ';
        }


//Gmin, check it, convert it, and store it for later use
        if(cpack->Gmin < 0 || cpack->Gmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Gmin, Gmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Gmin < 10){
                Gmin[1] = ' ';
                Gmin[2] = ' ';
        }
        else if(cpack->Gmin  < 100){
                Gmin[2] = ' ';
        }


//Bmin, check it, convert it, and store it for later use
        if(cpack->Bmin < 0 || cpack->Bmin > 255)
                return 0;

        //convert the int to a unsigned char
        itoa(cpack->Bmin, Bmin ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(cpack->Bmin < 10){
                Bmin[1] = ' ';
                Bmin[2] = ' ';
        }
        else if(cpack->Bmin  < 100){
                Bmin[2] = ' ';
        }


        //Build our message (its ugly but only way that works)
        msg[0] = 'T';
        msg[1] = 'C';
        msg[2] = ' ';
        msg[3] = Rmin[0];
        msg[4] = Rmin[1];
        msg[5] = Rmin[2];
        msg[6] = ' ';
        msg[7] = Rmax[0];
        msg[8] = Rmax[1];
        msg[9] = Rmax[2];
        msg[10] = ' ';
        msg[11] = Gmin[0];
        msg[12] = Gmin[1];
        msg[13] = Gmin[2];
        msg[14] = ' ';
        msg[15] = Gmax[0];
        msg[16] = Gmax[1];
        msg[17] = Gmax[2];
        msg[18] = ' ';
        msg[19] = Bmin[0];
        msg[20] = Bmin[1];
        msg[21] = Bmin[2];
        msg[22] = ' ';
        msg[23] = Bmax[0];
        msg[24] = Bmax[1];
        msg[25] = Bmax[2];
        msg[26] = ' ';
        msg[27] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],30))
                return 0;

        //Prepare to handle a type "M" string
        if(!INTERNAL_PACKET_PROCESS(&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp1,&temp2,&temp3, 50))
                return 0;

        return 1;
}


int _stdcall CAM_Get_TCC(C_PACKET* cpack)
{
//**********************************************************
//        Purpose: Returns the box that the shape is in, pixels are the
//                         number of matching pixels within the square. Confidence
//                         is the level of certainty the camera places on the square
//
//        Input:         Holding int pointers for the data
//
//  Output: (x1,y1),(x2,y2) square upper left lower right of the object
//                        pixels within the square and confidence of that square
//**********************************************************
        int temp1,temp2,temp3;
        int X1, Y1, X2, Y2, pixels, confidence;


        //Prepare to handle a type "C" string
        if(!INTERNAL_PACKET_PROCESS(&X1,&Y1,&X2,&Y2,&pixels,&confidence,&temp1,&temp2,&temp3, 50))
                return 0;

        //Fill in the struct with data
        cpack->X1 = X1;
        cpack->Y1 = Y1;
        cpack->X2 = X2;
        cpack->Y2 = Y2;
        cpack->Num_Pix = pixels;
        cpack->Confid = confidence;

        return 1;
}

int _stdcall CAM_DumpFrame(unsigned char* FRAME)
//**********************************************************
//        Purpose: Calls the command to dump a frame and then puts that
//                         data in an char[] array since the data are ascii
//                         values 34407 of them total at defalt frame sizes.
//
//        Input:        pointer to the start of the frame string
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{
        unsigned char msg[7];                        //Message being sent to the CMUcam
        DWORD Mask;                                                //Mask for COMEvent
        char test[2500];
        long i = 0;
        int temp;

        //Build the command string for the CMUcam (Clock Speed)
        msg[0] = 'D';
        msg[1] = 'F';
        msg[2] = '\r';


        //Reset the buffer sizes so we are garantueed not to miss any
        //data due to it coming in to fast
        if(!CMU_SetBuffer(5000,5000))
                return 0;


        //send the command
        if(!CMU_Write(&msg[0],3))
                return 0;

        // Needed to set mask for WaitCommEvent
        SetCommMask(ComPort, EV_RXCHAR);

        //Wait a bit for the camera to process the command
        WaitCommEvent(ComPort, &Mask, &o);

        //Sleep nessecary else the buffer may be empty when we go in
        Sleep(45);

        //Loop until the buffer is empty since we can't read it in one sweep
        do
        {
                temp = CMU_InputBufferSize();

                //Read from the buffer, for the entire buffer size
                if(!CMU_Read(&test[0],temp)){
                        return 0;
                }

                //Need to add the string onto the FRAME string
                memcpy(&FRAME[i],&test[0],temp);
                i = i + temp;

                //Rest to let more stuff fill the buffer before the size check
                Sleep(25);
        }while(CMU_InputBufferSize() > 0); //end while loop

        //terminate our string with an end of sring marker
        FRAME[i+1] = '\0';

        //Need to find and remove the "ACK" for the user so
        //they wont have to worry about it
        for(i=0;i<33407;i++)
        {
                if((int)FRAME[i] == 13)
                {
                        *FRAME = FRAME[i+1];
                        break;
                }
        }

        //Reset the buffers back to their normal sizes
        if(!CMU_SetBuffer(1028,1028))
                return 0;

        //Final check that is possible from our side is to make sure
        //the first char in the FRAME array is a '1' which signifies
        //and good packet since it starts with 1
        if((int)FRAME[0] != 1)
                return 0;

        //Return Success
        return 1;
}



int _stdcall CAM_ClosePort()
//**********************************************************
//        Purpose: just calls the CMU_ClosePort function
//
//        Input:        none
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{


        CMU_ClosePort();
        return 1;
}



int _stdcall CAM_SetWindowSize(int xx, int yy, int xx2, int yy2)
//**********************************************************
//        Purpose: Readjusts the size of the CMUCams resolution
//
//        Input:        new screen coordiantes
//
//  Output: 0 on fail, 1 on success
//**********************************************************
{

        char x[3], y[3], x2[3], y2[3];
        unsigned char msg[21];
        unsigned char * ret;
        unsigned char store[5];

        //Give our pointer something to point to else we get warnings
        ret = store;


//Start with xx, make sure it aint bigger then xx2
        if(xx > xx2)
                return 0;

        //convert the int to a unsigned char
        itoa(xx, x ,10);


        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(xx < 10){
                x[1] = ' ';
                x[2] = ' ';
        }
        else if(xx  < 100){
                x[2] = ' ';
        }

//Start with xx2

        //convert the int to a unsigned char
        itoa(xx2, x2 ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(xx2 < 10){
                x2[1] = ' ';
                x2[2] = ' ';
        }
        else if(xx2  < 100){
                x2[2] = ' ';
        }


//Start with yy, make sure it aint bigger then yy2
        if(yy > yy2)
                return 0;

        //convert the int to a unsigned char
        itoa(yy, y ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(yy < 10){
                y[1] = ' ';
                y[2] = ' ';
        }
        else if(yy  < 100){
                y[2] = ' ';
        }


//Start with yy2

        //convert the int to a unsigned char
        itoa(yy2, y2 ,10);

        //Check the size of the ints so we dont get buffer errors with nothing in the data
        if(yy2 < 10){
                y2[1] = ' ';
                y2[2] = ' ';
        }
        else if(yy2  < 100){
                y2[2] = ' ';
        }

        //Build our message (its ugly but only way that works)
        msg[0] = 'S';
        msg[1] = 'W';
        msg[2] = ' ';
        msg[3] = x[0];
        msg[4] = x[1];
        msg[5] = x[2];
        msg[6] = ' ';
        msg[7] = y[0];
        msg[8] = y[1];
        msg[9] = y[2];
        msg[10] = ' ';
        msg[11] = x2[0];
        msg[12] = x2[1];
        msg[13] = x2[2];
        msg[14] = ' ';
        msg[15] = y2[0];
        msg[16] = y2[1];
        msg[17] = y2[2];
        msg[18] = ' ';
        msg[19] = '\r';

        //send the command
        if(!CMU_Write(&msg[0],20))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        return 1;
}



int _stdcall CAM_LineMode(unsigned char* IMAGE)
//**********************************************************
//        Purpose: returns the binary packed image of what the
//                         cmucam is looking at
//
//        Input:   pointer to the binary packed data
//
//        Output:  1 on success, 0 on failure
//**********************************************************
{
        unsigned char msg[7];                        //Message being sent to the CMUcam
        unsigned char* ret;
        unsigned char store[647];

        ret = store;

        //Build the command string for the CMUcam (Clock Speed)
        msg[0] = 'P';
        msg[1] = 'M';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '\r';


        //Set the command to enable linemode
        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;


        Sleep(25);

        //Build the command string for the CMUcam (Clock Speed)
        msg[0] = 'L';
        msg[1] = 'M';
        msg[2] = ' ';
        msg[3] = '1';
        msg[4] = '\r';


        //Set the command to enable linemode
        //send the command
        if(!CMU_Write(&msg[0],5))
                return 0;


        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 5))
                return 0;

        Sleep(25);

        //Build the command string for the CMUcam (Clock Speed)
        msg[0] = 'T';
        msg[1] = 'W';
        msg[2] = ' ';
        msg[3] = '\r';


        //Set the command to enable linemode
        //send the command
        if(!CMU_Write(&msg[0],4))
                return 0;

        //Check to see the command went through
        if(!INTERNAL_ACKNCK(ret, 647))
                return 0;

        return 1;
}//end Cam_lineMode