/********************************************************************/
/*                                                                  */
/*  Modemctr.cpp: Sample Modem Control Signals Testing Program      */
/*                                                                  */
/*  This program allows the user to toggle the Modem Control        */
/*  on a UART based serial communications card.                     */
/*  Please view the file abstract.txt for more information.         */
/*                                                                  */
/*  (c)Copyright Sealevel Systems, Inc., 1999                       */
/*                                                                  */
/*  SEALEVEL SYSTEMS INCORPORATED.                                  */
/*  155 Technology Place                                            */
/*  P.O. Box 830                                                    */
/*  Liberty, SC 29657  USA                                          */
/*  (864) 843-4343                                                  */
/*  (864) 843-3067 FAX                                              */
/*                                                                  */
/********************************************************************/

#include <stdio.h>
#include <conio.h>
#include <windows.h>

#define ESC 27


int main(int argc, char *argv[])
{
    char    rts                = 0;
    char    dtr                = 0;
    char    oldrts             = 0;
    char    olddtr             = 0;
    int     key_pressed        = 0;
    DWORD   old_modem_ctr_regs = 1;      
    DWORD   modem_ctr_regs     = 0;    // Modem control-registers
    HANDLE  comport            = NULL; // Handle for COM port
    HANDLE  winStdOut;                 // Console Handle
    CONSOLE_SCREEN_BUFFER_INFO consoleInfo; // Used for retrieving/setting 
                                            // cursor position.

    printf("Sample UART Modem Control Signals Testing Program v1.00.\n");
    printf("(c)Copyright Sealevel Systems, Inc., 1999.\n\n");
    
    // Open COM port
    if ((comport = 
         CreateFile("COM1", 
                    GENERIC_READ | GENERIC_WRITE, // for reading and writing
                    0,                            // exclusive access
                    NULL,                         // no security attributes
                    OPEN_EXISTING,              
                    FILE_ATTRIBUTE_NORMAL,
                    NULL)) == INVALID_HANDLE_VALUE)
    {
        printf("Unable to open COM1.\n\n");
        printf("Press any key to exit.");
        getch();
        return(1);
    }
    printf("COM1 opened.\n\n");

    printf("Press: - R to toggle RTS (Request-to-send) signal.\n");
    printf("       - D to toggle DTR (Data-terminal-ready) signal.\n");
    printf("       - ESC to exit.\n\n");
    
    // Get Console Handle
    winStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
    // Clear the Data-Terminal-Ready (DTR) and Request-To-Send (RTS)
    // signals
    EscapeCommFunction(comport,CLRDTR);
    EscapeCommFunction(comport,CLRRTS);
    
    while (key_pressed != ESC)
    {
        // Acquire modem control-register values
        GetCommModemStatus(comport, &modem_ctr_regs);

        if ((modem_ctr_regs != old_modem_ctr_regs) ||
            (oldrts != rts) || (olddtr != dtr))
        {
            printf("Modem Control Status:\n");
            printf("RTS: ");
            if (rts)                         // Request-to-send on?
                printf("ON ");
            else
                printf("OFF");

            printf("\tDTR: ");
            if (dtr)                         // Data-terminal-ready on?
                printf("ON ");
            else
                printf("OFF");

            printf("\n\nModem Signal Status:\n");
            
            printf("\rCTS: ");
            if (modem_ctr_regs & MS_CTS_ON)  // clear-to-send on?
                printf("ON ");
            else
                printf("OFF");

            printf("\tDSR: ");
            if (modem_ctr_regs & MS_DSR_ON)  // data-set-ready on?
                printf("ON ");
            else
                printf("OFF");

            printf("\tRING: ");
            if (modem_ctr_regs & MS_RING_ON) // ring indicator on?
                printf("ON ");
            else
                printf("OFF");
        
            printf("\tRLSD: ");
            if (modem_ctr_regs & MS_RLSD_ON) // receive-line-signal-detect on?
                printf("ON ");
            else
                printf("OFF");

            // Determine current cursor position, then set new one.
            GetConsoleScreenBufferInfo(winStdOut, &consoleInfo);
            consoleInfo.dwCursorPosition.X  = 0;
            consoleInfo.dwCursorPosition.Y -= 4;

            SetConsoleCursorPosition(winStdOut, consoleInfo.dwCursorPosition);       
        }
        
        old_modem_ctr_regs = modem_ctr_regs;
        oldrts             = rts;
        olddtr             = dtr;

        if (kbhit())
        {
            key_pressed = getch();

            switch(key_pressed)
            {
                case 'r':
                case 'R':
                    rts ^= TRUE; // Toggle RTS between 0 and 1
                    break;
                case 'd':
                case 'D':
                    dtr ^= TRUE; // Toggle RTS between 0 and 1
                    break;
                default:
                    break;
            }
            
            if (rts)
                EscapeCommFunction(comport,SETRTS); // Set RTS On
            else 
                EscapeCommFunction(comport,CLRRTS); // Set RTS Off
            
            if (dtr)
                EscapeCommFunction(comport,SETDTR); // Set DTR On 
            else 
                EscapeCommFunction(comport,CLRDTR); // Set DTR Off
        }
    }

    CloseHandle(comport);
    printf("\n\n\n\n\n");
    
    return(0);
}