// -*- Mode:C++ -*- /* * ad-box driver * works with Fraunhofer IMK AD-Box and Fakespace Cubic Mouse * * for additional information see: * http://www.imk.fraunhofer.de * http://www.fakespace.com * * written by Sascha Scholz <sascha.scholz@imk.fraunhofer.de> */ #include <stdio.h> // for fprintf, stderr #include "vrpn_ADBox.h" #include "vrpn_Serial.h" // for vrpn_write_characters, etc #include "vrpn_Types.h" // for vrpn_float64, vrpn_int32 class VRPN_API vrpn_Connection; vrpn_ADBox::vrpn_ADBox(char* name, vrpn_Connection *c, const char *port, long baud) : vrpn_Analog(name, c), vrpn_Button_Filter(name, c), ready(1), serial_fd(0), iNumBytes(0), iNumDigBytes(0), iFilterPos(0) { // Open the serial port if ( (serial_fd=vrpn_open_commport(port, baud)) == -1) { fprintf(stderr,"vrpn_ADBox: Cannot Open serial port\n"); ready = 0; } // find out what time it is - needed? vrpn_gettimeofday(×tamp, 0); vrpn_Analog::timestamp = timestamp; vrpn_Button::timestamp = timestamp; } vrpn_ADBox::~vrpn_ADBox() { vrpn_close_commport(serial_fd); } void vrpn_ADBox::mainloop() { // Call the generic server mainloop, since we are a server server_mainloop(); struct timeval timeout = {0,200000}; float fAnalog(0.0f); if(!ready) return; if (iNumBytes == 0) { vrpn_flush_output_buffer(serial_fd); vrpn_flush_input_buffer(serial_fd); buffer[0] = 'U'; vrpn_write_characters(serial_fd, buffer, 1); while (iNumBytes < 100 && vrpn_read_available_characters(serial_fd, buffer, 1,&timeout) == 1) iNumBytes++; switch (iNumBytes) { case 14: case 18: iNumDigBytes = 2; break; case 19: iNumDigBytes = 3; break; default: iNumBytes = 0; iNumDigBytes = 0; break; } if (iNumBytes != 0) { num_buttons = iNumDigBytes * 8; num_channel = (iNumBytes - iNumDigBytes) / 2; fprintf(stderr, "vrpn_ADBox: ad-box with %d digital and %d analog ports detected\n", num_buttons, num_channel); buffer[0] = 'U'; vrpn_write_characters(serial_fd, buffer, 1); ready = 1; // initialize the buttons and channels for (vrpn_int32 i=0; i<num_buttons; i++) buttons[i] = lastbuttons[i] = VRPN_BUTTON_OFF; for (vrpn_int32 j=0; j<num_channel; j++) { channel[j] = last[j] = 0; } } else { fprintf(stderr,"vrpn_ADBox: trying to detect ad-box\n"); vrpn_SleepMsecs(1000.0*1); } } else { buffer[0] = 'U'; vrpn_write_characters(serial_fd, buffer, 1); for (int c = 0; c < iNumBytes; c++) { if (vrpn_read_available_characters(serial_fd, &buffer[c], 1,&timeout) != 1) { fprintf(stderr,"vrpn_ADBox: could only read %d chars, %d expected\n",c,iNumBytes+1); iNumBytes = 0; iNumDigBytes = 0; break; } } vrpn_gettimeofday(×tamp, 0); vrpn_Analog::timestamp = timestamp; vrpn_Button::timestamp = timestamp; if (iNumBytes != 0) { int i(0); for (i = 0; i < iNumDigBytes; i++) for (int b = 0; b < 8; b++) buttons[8 * i + b] = (unsigned char) ((buffer[i] & (1 << b)) != 0 ? VRPN_BUTTON_OFF : VRPN_BUTTON_ON); for (i = 0; i < (iNumBytes - iNumDigBytes) / 2; i++) { int iOrg = iFilter[i][iFilterPos] = (int(buffer[iNumDigBytes + i * 2]) << 8) | int(buffer[iNumDigBytes + 1 + i * 2]); fAnalog = float(iOrg) / 1023.0f; int p(iFilterPos); do p = (p + 29) % 30; while (p != iFilterPos && iFilter[i][p] == iOrg); if (p != iFilterPos) { int iLast(iFilter[i][p]); if (iOrg - iLast == 1 || iLast - iOrg == 1) { do p = (p + 29) % 30; while (p != iFilterPos && iFilter[i][p] == iLast); if (p != iFilterPos && iFilter[i][p] == iOrg) fAnalog = float(iOrg + iLast) / 2046.0f; } } channel[i] = fAnalog; } iFilterPos = (iFilterPos + 1) % 30; vrpn_Button::report_changes(); vrpn_Analog::report_changes(); } } }