Code:
#include <windows.h>
#include <string.h>
#include <stdio.h>
#include "Clock3.h"
#define SamplingTime 20 //in milliseconds; ideally, it should be 20 ms
#define KP 1
#define KI 1
#define KD 1
#define DATAPORT 0x378
#define CONTROLPORT 0x37a
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); //Callback function prototype
//Main program:
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst,
LPSTR lpszArgs, int nWinMode)
{
char szWinName[] = "MyWin"; /* name of window class */
HWND hwnd;
MSG msg;
WNDCLASSEX wcl;
/* Define a window class. */
wcl.cbSize = sizeof(WNDCLASSEX);
wcl.hInstance = hThisInst; /* handle to this instance */
wcl.lpszClassName = szWinName; /* window class name */
wcl.lpfnWndProc = WindowFunc; /* window function */
wcl.style = 0; /* default style */
wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); /* standard icon */
wcl.hIconSm = LoadIcon(NULL, IDI_WINLOGO); /* small icon */
wcl.hCursor = LoadCursor(NULL, IDC_ARROW); /* cursor style */
wcl.lpszMenuName = NULL; /* no main menu */
wcl.cbClsExtra = 0; /* no extra */
wcl.cbWndExtra = 0; /* information needed */
/* Make the window white. */
wcl.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
/* Register the window class. */
if(!RegisterClassEx(&wcl)) return 0;
/* Now that a window class has been registered, a window
can be created. */
hwnd = CreateWindow(
szWinName, /* name of window class */
"Processing Mouse Messages", /* title */
WS_OVERLAPPEDWINDOW, /* window style - normal */
CW_USEDEFAULT, /* X coordinate - let Windows decide */
CW_USEDEFAULT, /* Y coordinate - let Windows decide */
CW_USEDEFAULT, /* width - let Windows decide */
CW_USEDEFAULT, /* height - let Windows decide */
HWND_DESKTOP, /* no parent window */
NULL, /* no menu */
hThisInst, /* handle of this instance of the program */
NULL /* no additional arguments */
);
/* Display the window. */
ShowWindow(hwnd, nWinMode);
UpdateWindow(hwnd);
/* Create the message loop. */
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg); /* translate keyboard messages */
DispatchMessage(&msg); /* return control to Windows 98 */
}
return msg.wParam;
}
/* This function is called by Windows 98 and is passed
messages from the message queue.
*/
LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
static char str[255] = "", key; /* holds output string */
static char *clr = " ";
static BOOL greenlight = 0; //static variables are initialized only once
static BOOL delta_t;
static LONG xref, i=1;
static LONG x[3];
static short move[4]={5,6,10,9}; // %0101 -> %0110 -> %1010 -> %1001, just like the website
static Clock timer, clock;
typedef UINT (CALLBACK* LPFNDLLFUNC1)(INT,INT);
typedef UINT (CALLBACK* LPFNDLLFUNC2)(INT);
HINSTANCE hDLL; // Handle to DLL
LPFNDLLFUNC1 Output; // Function pointer
LPFNDLLFUNC2 Input; // Function pointer
INT Addr;
INT AddrIn;
INT Value;
hDLL = LoadLibrary("Inpout32");
if (hDLL != NULL)
{
Output = (LPFNDLLFUNC1)GetProcAddress(hDLL,"Out32");
Input = (LPFNDLLFUNC2)GetProcAddress(hDLL,"Inp32");
if (!Output || !Input)
{
// handle the error FreeLibrary(hDLL);
}
}
Addr = 0x378;
AddrIn = 0x379;
Value = 0;
Output(Addr, Value);
INT somenum = Input(Addr);
/* end of motor stuff */
switch(message) {
case WM_CHAR:
hdc = GetDC(hwnd);
switch(wParam)
{
case 'r': case 'R': //Pressing 'r' or 'R' sets reference point, resets timer
greenlight = 1;
timer.reset();
xref=x[2];
x[1]=0;
TextOut(hdc, 10, 400, clr, strlen(clr));
sprintf(str, "xref = %d", xref);
TextOut(hdc, 10, 400, str, strlen(str));
Output(CONTROLPORT,0); //set the mode of LPT1 to write mode
break;
case 's': case 'S': //Pressing 's' or 'S' halts all operations
greenlight = 0;
Output(DATAPORT,0);
break;
case 'q': case 'Q':
PostQuitMessage(0);
ReleaseDC(hwnd, hdc);
default:
greenlight = greenlight;
}
ReleaseDC(hwnd, hdc);
break;
case WM_RBUTTONDOWN: // Clicking right mouse button clears some data
hdc = GetDC(hwnd);
TextOut(hdc, 10, 100, clr, strlen(clr));
TextOut(hdc, 10, 200, clr, strlen(clr));
TextOut(hdc, 10, 230, clr, strlen(clr));
TextOut(hdc, 100, 400, clr, strlen(clr));
ReleaseDC(hwnd, hdc);
break;
case WM_LBUTTONDOWN: // Clicking left mouse button closes the window (terminates operations)
hdc = GetDC(hwnd);
PostQuitMessage(0);
ReleaseDC(hwnd, hdc);
break;
case WM_MOUSEMOVE: // Processing pointer motion
hdc = GetDC(hwnd);
if (greenlight == 1)
{
/* Just Displaying */
TextOut(hdc, 10, 50, clr, strlen(clr));
sprintf(str, "Time passed is %f seconds", (float)timer.time()/1000);
TextOut(hdc, 10, 50, str, strlen(str));
/* Sampling begins here */
if (timer.sample(SamplingTime))
{
BOOL delta_t=(long)timer+SamplingTime;
x[0]=x[1];
x[1]=LOWORD(lParam)-xref;
//theta
TextOut(hdc, 10, 200, clr, strlen(clr));
sprintf(str, "x[0] = %d", x[0]);
TextOut(hdc, 100, 200, str, strlen(str));
TextOut(hdc, 10, 230, clr, strlen(clr));
sprintf(str, "x[1] = %d", x[1]);
TextOut(hdc, 100, 230, str, strlen(str));
TextOut(hdc, 100, 400, clr, strlen(clr));
sprintf(str, "%d", delta_t);
TextOut(hdc, 100, 400, str, strlen(str));
TextOut(hdc, 10, 100, clr, strlen(clr));
sprintf(str, "The angular velocity is %f pixels/sec", (float)(x[1]-x[0])/delta_t*1000);
TextOut(hdc, 10, 100, str, strlen(str));
//theta_dot
/* won't work here because it will only enter here if you move the mouse */
clock.reset();
if (LOWORD(lParam)-xref > 0)
{ /* move motor clockwise */ }
if (LOWORD(lParam)-xref < 0)
{/* move motor counter-clockwise */}
}
}
x[2]=LOWORD(lParam); //Set x-coordinate of reference point
TextOut(hdc, 10, 10, clr, strlen(clr));
sprintf(str, "Mouse coordinates are at (%d, %d)", LOWORD(lParam), HIWORD(lParam));
TextOut(hdc, 10, 10, str, strlen(str));
/* Calculating the desired force (PID) */
//float F_desired = KP*(0-theta) + KD*theta_dot + KI*
/* Motor commands corresponding to F_desired go here */
ReleaseDC(hwnd,hdc);
break;
case WM_DESTROY: // Terminate the program
PostQuitMessage(0);
break;
default:
/* Let Windows 98 process any messages not specified in
the preceding switch statement. */
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
Here is the code for Clock.h: