/* Richard Irons February 5, 2003 */ /* Lab 2, Num 5 */ /* */ /* Purpose: Display scaling circles based */ /* on Cricket photocell sensor data read */ /* from serial port. */ /* */ /* NOTE: Code to open and read serial */ /* port was taken from Microsoft web site.*/ /* */ /* -------------------------------------- */ #include #include #include #include #include #include #include #define RMI_DEBUG 0 #define X 0 #define Y 1 #define INITIAL_WIN_WIDTH 400 #define INITIAL_WIN_HEIGHT 400 #define WIN_START_POS_X 0 #define WIN_START_POS_Y 0 #define RMI_PI 3.14159265358979323846 #define DEG_TO_RAD(deg) (deg * (RMI_PI / 180.0)) #define RAD_TO_DEG(rad) (rad * (180.0 / RMI_PI)) #define TRANSFORM_X_2D(x,y,r) ((x * cos(r)) - (y * sin(r))) #define TRANSFORM_Y_2D(x,y,r) ((x * sin(r)) + (y * cos(r))) /* Local Variables */ static GLsizei win_height = INITIAL_WIN_HEIGHT; static GLsizei win_width = INITIAL_WIN_WIDTH; static int dl_id = -1; static int cur_op_circle = -1; static GLfloat rotate_angle = 0.0; static GLfloat circle_scale = 1.0; static HANDLE hCom; static void _display_func(void); static void _reshape_func(GLsizei w, GLsizei h); static void _main_menu_func(int select_num); static void _construct_menus(void); static GLfloat _random_color(); /* ========================================================================== */ /* static void _init_serial_port - Initialize serial port. */ /* ========================================================================== */ static int _init_serial_port() { DCB PortDCB; hCom = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // default security attributes OPEN_EXISTING, 0, NULL ); if (hCom == INVALID_HANDLE_VALUE) { printf("ERROR - Unable to open serial port.\n"); // Handle the error. return(1); } // Initialize the DCBlength member. PortDCB.DCBlength = sizeof (DCB); // Get the default port setting information. GetCommState (hCom, &PortDCB); // Change the DCB structure settings. PortDCB.BaudRate = 9600; // Current baud PortDCB.fParity = TRUE; // Enable parity checking PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx PortDCB.fOutX = FALSE; // No XON/XOFF out flow control PortDCB.fInX = FALSE; // No XON/XOFF in flow control PortDCB.fErrorChar = FALSE; // Disable error replacement PortDCB.fNull = FALSE; // Disable null stripping PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on // error PortDCB.ByteSize = 8; // Number of bits/byte, 4-8 PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space PortDCB.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 // Configure the port according to the specifications of the DCB // structure. if (!SetCommState (hCom, &PortDCB)) { // Could not configure the serial port. printf("ERROR - Unable to configure port.\n"); return(1); } return(0); } /* ========================================================================== */ /* static void _reshape_func() - Handles resizing of window. */ /* ========================================================================== */ static void _reshape_func(GLsizei w, GLsizei h) { /* Reset matrices and set viewing volume to new window width and height */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (GLdouble)w, 0.0, (GLdouble)h, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Set viewport to new window width and height */ glViewport(0, 0, w, h); /* Save new window width and height */ win_width = w; win_height = h; glutPostRedisplay(); } /* ========================================================================== */ /* static void _display_func(void) - glut display function. */ /* ========================================================================== */ static void _display_func(void) { int i,j; GLfloat cur_pt[2]; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); /* Using one color for the background */ glClearColor(0.45, 0.45, 0.45, 0.0); glClear(GL_COLOR_BUFFER_BIT); if (dl_id == -1) { dl_id = glGenLists(1); glNewList(dl_id, GL_COMPILE); #if 0 glBegin(GL_LINE_STRIP); #else glBegin(GL_POLYGON); #endif for (i=0; i<360; i++) { cur_pt[X] = TRANSFORM_X_2D(20.0,0.0,DEG_TO_RAD((GLfloat)i)); cur_pt[Y] = TRANSFORM_Y_2D(20.0,0.0,DEG_TO_RAD((GLfloat)i)); glVertex2fv(cur_pt); } glEnd(); glEndList(); } for (i=0; i<((win_height/50)-1); i++) { for (j=0; j<((win_width/50)-1); j++) { GLfloat col[3] = { 1.0, 1.0, 0.0 }; glPushMatrix(); glTranslatef(win_width/2.0, win_height/2.0, 0.0); glRotatef(rotate_angle, 0.0, 0.0, 1.0); glTranslatef(-win_width/2.0, -win_height/2.0, 0.0); cur_pt[X] = 50.0 + (50.0 * ((GLfloat)j)); cur_pt[Y] = 50.0 + (50.0 * ((GLfloat)i)); glTranslatef(cur_pt[X], cur_pt[Y], 0.0); glScalef(circle_scale, circle_scale, circle_scale); glColor3f(col[0], col[1], col[2]); glCallList(dl_id); glPopMatrix(); } } glFlush(); glutSwapBuffers(); } /* ========================================================================== */ /* static void _idle_func(void) - glut idle function. */ /* ========================================================================== */ static void _idle_func(void) { BOOL bResult; DWORD nBytesRead; DWORD photo_sensor_value = 0; /* Rotation angle for all circles */ rotate_angle += 1.0; if (rotate_angle >=360.0) rotate_angle = 0.0; /* Circle Scale */ // Attempt a synchronous read operation. bResult = ReadFile(hCom, &photo_sensor_value, 1, &nBytesRead, NULL) ; if (bResult && nBytesRead ) { #if RMI_DEBUG printf("*** SOMETHING READ %d %d %d %x ***\n",bResult,nBytesRead, photo_sensor_value, photo_sensor_value); #endif /* Scale will be somethin from about 0.0 to about 1.5 */ /* Invert sensor data: Dark - Low, Light - High */ circle_scale = (255.0 - photo_sensor_value) / 192.0; } else { /* Leave circle scale alone if nothing read */ #if RMI_DEBUG printf("*** NOTHTHING READ ***\n"); #endif } glutPostRedisplay(); } /* ========================================================================== */ /* static void _main_menu_func() - Process main menu selections that are not */ /* sub menus. */ /* ========================================================================== */ static void _main_menu_func(int select_num) { switch (select_num) { /* Exit */ case 1: glDeleteLists(dl_id, 1); exit(0); break; default: printf("Invalid main menu selection\n"); break; } } /* ========================================================================== */ /* static void _construct_menus() - Construct all the menus that are */ /* available when the right mouse button is pressed. */ /* ========================================================================== */ static void _construct_menus(void) { /* Create Main Menu */ glutCreateMenu(_main_menu_func); glutAddMenuEntry("Exit", 1); /* Attach menus to right mouse button */ glutAttachMenu(GLUT_RIGHT_BUTTON); } /* ========================================================================== */ /* int main() - Program setup and control */ /* ========================================================================== */ int main(int argc, char** argv) { /* Open serial port receiving cricket sensor data */ if (_init_serial_port()) exit(1); /* Perform glut setup */ glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(win_width, win_height); glutInitWindowPosition(WIN_START_POS_X, WIN_START_POS_Y); glutCreateWindow("Cricket Sensor Circles"); /* Initialize matrices and viewing volume */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (GLdouble)win_width, 0.0, (GLdouble)win_height, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glFlush(); /* Setup up callbacks */ glutDisplayFunc(_display_func); glutReshapeFunc(_reshape_func); glutIdleFunc(_idle_func); /* Construct all menus */ _construct_menus(); glutMainLoop(); /* Main processing loop */ return(0); }