//
// GLOVEPIE INTERACTIVE WHITEBOARD SOFTWARE
// FOR DUAL IR LED ROCKER SWITCH MOUSE PEN (or equivalent) with WII REMOTE SENSOR
// Version 2.0 - Released for Publication
// Friday 9 September 2011
// By M.A.V. Brisbane, Australia
// DUAL IR LED ROCKER SWITCH MOUSE PEN details originally published at:
//
http://www.wiimoteproject.com/ir-pens/dual-ir-led-iwb-wii-mouse-pen/// PROGRAMMED IN GLOVEPIE VERSION 0.43 WITH 32-bit WINDOWS XP3 ON X86 INTEL PC
// Particular thanks to Carl Kenner (GlovePIE) and Nintendo (Wii Remote)
// and thanks to the Many Others for your technical contributions and inspirations
// MATHEMATICS OF PERSPECTIVE PROJECTION based on:
// SOURCE 1:
//
http://www1.cs.columbia.edu/~belhumeur/courses/compPhoto/heckbert-proj.pdf// Citation:
// "Fundamentals of Texture Mapping and Image Warping"
// Paul Heckbert
// pp 17-21, Master’s thesis, UCB/CSD 89/516, CS Division, U.C. Berkeley, June 1989.
// SOURCE 2:
//
http://www.decew.net/OSS/References/Quadrilateral%20mapping.pdf// Citation:
// "A Planar Perspective Image Matching using Point Correspondences and Rectangle-to-Quadrilateral Mapping,"
// Dong-Keun Kim, Byung-Tae Jang, Chi-Jung Hwang,
// ssiai, pp.0087, Fifth IEEE Southwest Symposium on Image Analysis and Interpretation, 2002
//NOTE: For consistency with convention, the co-ordinate origin for the Wii IR CAMERA Image and CURSOR Screen, is the TOP LEFT CORNER.
//The X-axis points rightward and the Y-axis is inverted and points downward
//This requires a corrective Y-axis transformation for the wiimote IR Image points: wiimote.dot1y -> 768 - wiimote.dot1y
// DONE LIST
// DONE - TEST CALIBRATION TARGETS
// DONE - TEST VIEW OF SCREEN CORNERS BY WII REMOTE CAMERA
// DONE - TEST TRACKING AREA UTILISATION
// DONE - TEST BATTERY LEVEL
// DONE - TEST REAL DUAL LED TWO BUTTON MOUSE PEN
// DONE - TEST INTEGRATION OF RIGHT BUTTON and LEFT BUTTON MOUSE COMMANDS USING SINGLE AND DUAL LED INDICATION
// DONE - TEST DRAG & DROP + CUT & PASTE
// DONE - TEST MINIMISING THE GLOVEPIE SET-UP SCREEN TO THE TRAY WITH PEN DOUBLE CLICK
// DONE - MAP OUT THE CONFIGURATION OF THE PEN MOUSE BUTTONS AND ROCKER SWITCH POSITIONS CORRESPONDING TO THE ACTUAL MOUSE OUTPUT COMMANDS
// DONE - TEST DYNAMIC MOUSE CLICK SPEED ADJUSTMENT FROM WINDOWS CONTROL PANEL
// FUTURE LIST
// Future - TEST LEFT HANDED OR RIGHT HANDED PEN SELECTION OPTION USING THE INITIAL CALIBRATION AND SET UP SCREEN
// **** LIMITATIONS ****
// Is is essential that both PEN IR LEDS can be detected by the WII REMOTE CAMERA when in use with the WHITEBOARD or other SCREEN
// The software is set up for RIGHT HANDED PEN USE and for the Wii Remote Camera to be seeing the left side of the pen
// The screen must have sufficient diffuse reflectivity so the TIP LED IR LIGHT is readily reflected and can be detected by the Wii Remote Camera
// - otherwise use a piece of matte single sided tape loosely stuck to the pen tip to act as a tip led reflection surface - it works well
// Be mindful of the pen button mapping with respect to the mouse button actions - including the timeout delay for the pressed button modes
// The software assumes the Wii Remote Camera and Screen are aligned with no significant horizontal roll angle difference
// The pen mouse click speed (Double Click speed) can be manually adjusted by the slider control in the Mouse section of Windows Control Panel
if starting
// LEFT MOUSE BUTTON COMMANDS
var.pointermode = false
// RIGHT MOUSE BUTTON COMMANDS
var.rightpressmode = false
// RIGHT HANDED OR LEFT HANDED PEN OPTION
// for left side view of pen - using pen with right hand and pen pointing left on screen
var.righthandpen = true
// ALTERNATIVELY - for right side view of pen - using pen with left hand - pointing right on screen
// CHANGE: var.righthandpen from '=true' to '=false'
var.lastmousecommand = ' none '
// FRAME BUFFERING VARIABLES FOR LED SWITCHING INDICATION
var.newvis1 = false
var.newvis2 = false
var.vis1 = false
var.vis2 = false
var.buffercount = 0
// inside screen margin fraction for point calibration
var.screenXmarginratio = 0.1
var.screenYmarginratio = 0.1
var.macrocount = 0
Cam.BgColour = 0xFFFFFF
// Screen calibration points
Cursor10.Visible = false
Cursor11.Visible = false
Cursor12.Visible = false
Cursor13.Visible = false
Cursor14.Visible = false
//Wiimote corner point extents
Cursor30.Visible = false
Cursor31.Visible = false
Cursor32.Visible = false
Cursor33.Visible = false
Cursor34.Visible = false
// Corner direction pointers
Cursor40.Visible = false
Cursor41.Visible = false
Cursor42.Visible = false
Cursor43.Visible = false
Cursor44.Visible = false
Cursor10.Caption = "Click on Centre"
Cursor11.Caption = "Click on Centre"
Cursor12.Caption = "Click on Centre"
Cursor13.Caption = "Click on Centre"
Cursor10.PermanentCursor = 2
Cursor11.PermanentCursor = 2
Cursor12.PermanentCursor = 2
Cursor13.PermanentCursor = 2
Cursor30.PermanentCursor = 2
Cursor31.PermanentCursor = 2
Cursor32.PermanentCursor = 2
Cursor33.PermanentCursor = 2
Cursor34.PermanentCursor = 2
Cursor41.PermanentCursor = -2
Cursor42.PermanentCursor = -2
Cursor43.PermanentCursor = -2
Cursor44.PermanentCursor = -2
var.visibleflag = 1
// Set WII IR CAMERA FOR MAXIMUM SENSITIVITY
// Start of Wiimote IR CAMERA Sensistivy Programming block
// step 1
// Enable IR Camera (Send 0x04 to Output Report 0x13)
WiimoteSend(1, 0x13, 0x04)
wait 100ms
// step 2
//Enable IR Camera 2 (Send 0x04 to Output Report 0x1a)
WiimoteSend(1, 0x1a, 0x04)
wait 100ms
// step 3
//Write 0x08 to register 0x4b00030
WiimotePoke(1,0x04b00030, 0x08)
wait 100ms
// step 4
//Write Sensitivity Block 1 to registers at 0x4b00000
WiimotePoke(1,0x04b00000, 0x02)
wait 100ms
WiimotePoke(1,0x04b00001, 0x00)
wait 100ms
WiimotePoke(1,0x04b00002, 0x00)
wait 100ms
WiimotePoke(1,0x04b00003, 0x00)
wait 100ms
WiimotePoke(1,0x04b00004, 0x00)
wait 100ms
WiimotePoke(1,0x04b00005, 0x00)
wait 100ms
WiimotePoke(1,0x04b00006, 0xFF)
wait 100ms
WiimotePoke(1,0x04b00007, 0x00)
wait 100ms
// maximimu sensitivity setting - 0xc0
WiimotePoke(1,0x04b00008, 0xc0)
wait 100ms
//step 5
//Write Sensitivity Block 2
WiimotePoke(1,0x04b0001a, 0x40)
wait 100ms
WiimotePoke(1,0x04b0001b, 0x00)
wait 100ms
//step 6
// Write Mode Number to register 0xb00033
WiimotePoke(1,0x04b00033, 0x01)
wait 100ms
//step 7
// Write 0x08 to register 0x4b00030 (again)
WiimotePoke(1,0x04b00030, 0x08)
wait 100ms
// END of Wiimote IR CAMERA Sensistivy Programming block
end if // starting
// DYNAMICALLY ADJUSTIBLE MOUSE CLICK SPEED TIMING
// CHANGE THE MOUSE CLICK SPEED IN THE WINDOWS CONTROL PANEL WHILST THIS PROGRAM IS RUNNING
// Open the VARIABLES Menu in GlovePIE or view the debug box status display to view the current mouse speed setting
// Pen mouse clicking time is set relative to the system mouse clicking time
// so as to lock-in the synchronisation of switching commands in the case structure
// POINTER BUTTON PRESSING NEEDS A NEGATIVE TIME DELAY TO BLOCK INCIDENTAL SINGLE CLICK FIRING IN THE CASE STRUCTURE - DO NOT MAKE POSITIVE
var.pointerinitiatetime = Mouse.DoubleClickTime - 20ms
var.pointerextendtime = Mouse.DoubleClickTime + 750ms
// CONTEXT BUTTON PRESSING NEEDS A NEGATIVE TIME DELAY TO BLOCK INCIDENTAL SINGLE CLICK FIRING IN THE CASE STRUCTURE - DO NOT MAKE POSITIVE
var.rightpressinitiatetime = Mouse.DoubleClickTime - 20ms
var.rightpressextendtime = Mouse.DoubleClickTime + 750ms
// WIIMOTE CAMERA CALIBRATION POINTS Module
// CALIBRATION - FOUR CORNER POINTS - LESS MARGIN
// TOP LEFT SCREEN POINT
if var.macrocount == 0
Cursor10.Visible = true
var.px0 = Screen.Width * var.screenXmarginratio
var.py0 = Screen.Height * var.screenYmarginratio
Cursor10.PosX = var.px0
Cursor10.PosY = var.py0
if wiimote.dot1vis == true
//WIIMOTE POINT 1 CAPTURE
var.x0 = wiimote.dot1x + 0.5
var.y0 = 767.5 - wiimote.dot1y
Cursor10.PermanentCursor = 12
Cursor10.Caption = "DONE"
wait 1s
var.macrocount = 1
//debug = var.x0 + ' ' + var.y0
//wait 10s
wait 0.5s
end if
end if // point 1 calibrationr
// TOP RIGHT SCREEN POINT
if var.macrocount == 1
Cursor11.Visible = true
var.px1 = Screen.Width * (1 - var.screenXmarginratio )
var.py1 = Screen.Height * var.screenYmarginratio
Cursor11.PosX = var.px1
Cursor11.PosY = var.py1
if wiimote.dot1vis == true
//WIIMOTE POINT 2 CAPTURE
var.x1 = wiimote.dot1x + 0.5
var.y1 = 767.5 - wiimote.dot1y
Cursor11.PermanentCursor = 12
Cursor11.Caption = "DONE"
wait 1s
var.macrocount = 2
//debug = var.x1 + ' ' + var.y1
//wait 10s
wait 0.5s
end if
end if // point 2 calibration
// BOTTOM RIGHT SCREEN POINT
if var.macrocount == 2
Cursor12.Visible = true
var.px2 = Screen.Width * (1 - var.screenXmarginratio )
var.py2 = Screen.Height * (1 - var.screenYmarginratio )
Cursor12.PosX = var.px2
Cursor12.PosY = var.py2
if wiimote.dot1vis == true
//WIIMOTE POINT 3 CAPTURE
var.x2 = wiimote.dot1x + 0.5
var.y2 = 767.5 - wiimote.dot1y
Cursor12.PermanentCursor = 12
Cursor12.Caption = "DONE"
wait 1s
var.macrocount = 3
//debug = var.x2 + ' ' + var.y2
//wait 10s
wait 0.5s
end if
end if // point 3 calibration
// BOTTOM LEFT SCREEN POINT
if var.macrocount == 3
Cursor13.Visible = true
var.px3 = Screen.Width * var.screenXmarginratio
var.py3 = Screen.Height * (1 - var.screenYmarginratio )
Cursor13.PosX = var.px3
Cursor13.PosY = var.py3
if wiimote.dot1vis == true
//WIIMOTE POINT 4 CAPTURE
var.x3 = wiimote.dot1x + 0.5
var.y3 = 767.5 - wiimote.dot1y
Cursor13.PermanentCursor = 12
Cursor13.Caption = "DONE"
wait 1s
var.macrocount = 4
//debug = var.x3 + ' ' + var.y3
//wait 10s
wait 0.5s
end if
end if // point 4 calibration
// Terminate Calibration Screen
if var.macrocount == 4
var.px4 = Screen.Width/2 - 350
var.py4 = Screen.height/2 - 200
Cursor14.PosX = var.px4
Cursor14.PosY = var.py4
wait 1s
var.macrocount = 5
// Screen calibration points
Cursor10.Visible = false
Cursor11.Visible = false
Cursor12.Visible = false
Cursor13.Visible = false
Cursor14.Visible = false
wait 1s
end if // end macrocount 4 : four point calibration complete
//END OF WIIMOTE CAMERA CALIBRATION POINTS Module