/* Copyright (C) 2008 Giovanni Di Mingo This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Author: Giovanni Di Mingo Email: giovanni@dimingo.com */ /* * See&Touch Mouse firmware */ #include // Statuses for mouse leds // note: the numeric sequence defines the visual sequence #define LED_UP 0x01 #define LED_RIGHT 0x02 #define LED_DOWN 0x03 #define LED_LEFT 0x04 #define LED_LEFT_CLICK 0x05 #define LED_RIGHT_CLICK 0x06 // Last status for mouse scanning #define LAST_STATUS 6 // Commands for mouse led #define UP 0x01 #define DOWN 0x02 #define LEFT 0x03 #define RIGHT 0x04 #define LEFT_CLICK 0x05 #define RIGHT_CLICK 0x06 // Commands for device #define ALL_OFF 0x00 #define ALL_ON 0x07 #define ALL_BLINK 0x08 // Mouse button status #define RELEASED 0x00 #define PRESSED 0x01 // Resolution definitions #define HIGH_RESOLUTION 1 // pixel #define LOW_RESOLUTION 2 // pixel #define REPETITIONS_THRESHOLD 30 // number of repetitions needed for changing resolution // define output pins for click int leftClickPin = 7; int rightClickPin = 6; // define output pins for arrows int leftPin = 5; int upPin = 4; int rightPin = 3; int downPin = 2; // define input pin for switch (button) int buttonPin = 12; // define test pin (pin 13 with led) int testPin = 13; // define time variables for debouncing the button press long time = 0; // the last time the button was pressed long debounce = 200; // the debounce time (in milliseconds), increase if the output flickers // define the button variables int currentButton; // the current reading from the button pin int previousButton = HIGH; // the previous reading from the button pin // define the pixel resolution for mouse movements byte resolution = LOW_RESOLUTION; // define the delay for changing status unsigned long scanTime = 2000; // define the status of the FSM byte status = 0; // callback function for MsTimer2 // change the status of the FSM void changeStatus() { if (status == LAST_STATUS) { status = 1; } else { status++; } } // end changeStatus // check if button is pressed using debouncing boolean isButtonPressed() { currentButton = digitalRead(buttonPin); boolean isPressed = false; // if we just pressed the button (i.e. the input went from HIGH to LOW), // and we've waited long enough since the last press to ignore any noise... if (currentButton == LOW && previousButton == HIGH && millis() - time > debounce) { isPressed = true; // remember when the last button was pressed time = millis(); } // remember the last button value previousButton = currentButton; return isPressed; } // end isButtonPressed // -------------------------------------------------------------------------- // sendByte // // Send a byte to the serial port // void sendByte(byte data) { Serial.print(data); } // end sendByte // Send a mouse command to the serial port void sendCommand(byte command) { byte byteToSend = 0; switch (command) { case UP: byteToSend = 0x40 | ((((-resolution) & 0xc0) >> 4) & 0x0c); sendByte(byteToSend); sendByte(0); byteToSend = (-resolution) & 0x3f; sendByte(byteToSend); break; case DOWN: byteToSend = 0x40 | ((((resolution) & 0xc0) >> 4) & 0x0c); sendByte(byteToSend); sendByte(0); byteToSend = (resolution) & 0x3f; sendByte(byteToSend); break; case LEFT: sendByte(0x40 | ((((-resolution) & 0xc0) >> 6)) & 0x03); sendByte((-resolution) & 0x3f); sendByte(0); break; case RIGHT: sendByte(0x40 | ((((resolution) & 0xc0) >> 6)) & 0x03); sendByte((resolution) & 0x3f); sendByte(0); break; case LEFT_CLICK: // left button pressed sendByte(0x60); sendByte(0); sendByte(0); // left button released sendByte(0x40); sendByte(0); sendByte(0); break; case RIGHT_CLICK: // right button pressed sendByte(0x50); sendByte(0); sendByte(0); // right button released sendByte(0x40); sendByte(0); sendByte(0); break; } // end switch } // end send command // setup function void setup() { // set mouse led pins as output pinMode(leftClickPin, OUTPUT); pinMode(rightClickPin, OUTPUT); pinMode(leftPin, OUTPUT); pinMode(upPin, OUTPUT); pinMode(rightPin, OUTPUT); pinMode(downPin, OUTPUT); // set button pin as input pinMode(buttonPin, INPUT); // activate the pullup resistor on button pin digitalWrite(buttonPin, HIGH); // set test pin as output pinMode(testPin, OUTPUT); /* digitalWrite(leftClickPin, HIGH); digitalWrite(rightClickPin, HIGH); digitalWrite(leftPin, HIGH); digitalWrite(upPin, HIGH); digitalWrite(rightPin, HIGH); digitalWrite(downPin, HIGH); */ // begin the serial communication Serial.begin(1200); // speed 1200 baud // set the correct data parameters UCSR0C=0x04; // data 7 bit, stop 1 bit // initialize the led scanning MsTimer2::set(scanTime, changeStatus); MsTimer2::start(); } // end setup // loop function void loop() { /* digitalWrite(leftClickPin, HIGH); digitalWrite(rightClickPin, HIGH); digitalWrite(leftPin, HIGH); digitalWrite(upPin, HIGH); digitalWrite(rightPin, HIGH); digitalWrite(downPin, HIGH); delay(1000); digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); delay(1000); */ // turn on/off the led according to the button status digitalWrite(testPin, digitalRead(buttonPin)); // finite state machine // the status is changed by the MsTimer2 callback function switch (status) { // all leds are off case ALL_OFF: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); break; // leftClick led is on case LED_LEFT_CLICK: digitalWrite(leftClickPin, HIGH); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); if (isButtonPressed()) { sendCommand(LEFT_CLICK); while (digitalRead(buttonPin) == LOW) { sendCommand(LEFT_CLICK); } // end while } // end if break; // rightClick led is on case LED_RIGHT_CLICK: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, HIGH); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); if (isButtonPressed()) { sendCommand(RIGHT_CLICK); while (digitalRead(buttonPin) == LOW) { sendCommand(RIGHT_CLICK); } // end while } // end if break; // left led is on case LED_LEFT: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, HIGH); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); if (isButtonPressed()) { sendCommand(LEFT); while (digitalRead(buttonPin) == LOW) { sendCommand(LEFT); } // end while } // end if break; // up led is on case LED_UP: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, HIGH); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); if (isButtonPressed()) { sendCommand(UP); while (digitalRead(buttonPin) == LOW) { sendCommand(UP); } // end while } // end if break; // right led is on case LED_RIGHT: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, HIGH); digitalWrite(downPin, LOW); if (isButtonPressed()) { sendCommand(RIGHT); while (digitalRead(buttonPin) == LOW) { sendCommand(RIGHT); } // end while } // end if break; // down led is on case LED_DOWN: digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, HIGH); if (isButtonPressed()) { sendCommand(DOWN); while (digitalRead(buttonPin) == LOW) { sendCommand(DOWN); } // end while } // end if break; // all leds are on case ALL_ON: digitalWrite(leftClickPin, HIGH); digitalWrite(rightClickPin, HIGH); digitalWrite(leftPin, HIGH); digitalWrite(upPin, HIGH); digitalWrite(rightPin, HIGH); digitalWrite(downPin, HIGH); break; // all leds are blinking case ALL_BLINK: digitalWrite(leftClickPin, HIGH); digitalWrite(rightClickPin, HIGH); digitalWrite(leftPin, HIGH); digitalWrite(upPin, HIGH); digitalWrite(rightPin, HIGH); digitalWrite(downPin, HIGH); delay(1000); digitalWrite(leftClickPin, LOW); digitalWrite(rightClickPin, LOW); digitalWrite(leftPin, LOW); digitalWrite(upPin, LOW); digitalWrite(rightPin, LOW); digitalWrite(downPin, LOW); delay(1000); break; } // end switch } // end loop