#include <Mega32.h>
#include <delay.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define CUTOFF 1 //define radius of cutoff region around 0
int extint; //keeps track of
number of external interrupts
char send_message[12]; //message to send
over serial
unsigned char
message_pos; //message cursor
int connected, enabled; //keeps track of the connected/disconnected
//and enabled/disabled states of the device
unsigned int ms_timebase; //milliseconds
unsigned int keypress_timebase; //time for keypresses and buttons
unsigned char
accel, x1, y1, scroll; //data read and
processed from ADC
unsigned char
admuxnum; //specifies which pin to read the ADC from
unsigned char
pushed[4], prevpush[4], button[4]; //button debouncing variables
unsigned char
i; //used for button reading loops
interrupt [EXT_INT0] void RTS(void){
extint++;
if(extint>1){ //wait until after first external interrupt
message_pos= 0;
send_message[0]= 'M'; //tell Windows we're a serial scroll mouse
send_message[1]= 'Z';
send_message[2]= 0;
UCSRB.5= 1;
PORTD.7= 1;
connected= 1; //we're connected
enabled= 1; //device is enabled
if(extint>5) {
GICR= 0; //after we've been recognized, stop telling Windows what we
are
}
}
interrupt [USART_DRE] void send(void){
if(send_message[message_pos]==0){ //if no more message, stop sending
UCSRB.5= 0;
}
else{
UDR= send_message[message_pos];
//otherwise keep sending message
message_pos++;
}
}
interrupt [ADC_INT] void readADC(void){
accel=
ADCH; //read
acceleration from ADC and store into accel
}
void initialize(){ //initialize all
the variables
UCSRB= 0x18; //enable
TX
UBRRH= 0b00000011; //1200
baud
UBRRL= 0b01000000; //setting
up serial
DDRD= 0xFA; //set
up port D
PORTD.7= 0; //turn on LED
DDRB= 0x00; //set up port B
PORTB= 0xFF;
extint=
0; //start at
first external interrupt
MCUCR= 0b10010010; //set mcu to interrupt on any
change in serial line
GICR= 0x40; //enable external interrupts
admuxnum=
0; //read
x-axis first
x1= 0; //0 x-coords
y1= 0; //0 y-coords
accel=
0; //0
acceleration
ADMUX= 0b01100000; //read x-axis first
ADCSR= 0b11101111; //adc status
connected= 0; //device is not
connected
enabled= 0; //device is
disabled
for(i=0; i<4; i++){ //reset all button
pushes
prevpush[i]= 1;
pushed[i]= 1;
button[i]= 0;
}
memset(send_message, 0, 12); //allocate memory
for serial comm
message_pos= 0; //set message cursor at beginning
#asm("sei"); //enable interrupts
}
void main(void){
initialize(); //initialize
variables used
while(1){ //never stop
running
if(connected==1){ //if device is
connected
for(i=0; i<4;i++){ //detect any buttons pressed
pushed[i]= (PINB>>i) & 0x01;
if(prevpush[i]==
pushed[i]){
button[i]= (~pushed[i]) & 0x01; //make sure they're
pressed
}
}
if(prevpush[0]==1
&& pushed[0]==0){ //if it was the enable button
enabled=
enabled ^ 0x01; //then
toggle enable/disable status of device
}
for(i=0; i<4;i++){ //otherwise store the button push
prevpush[i]= pushed[i];
}
if(admuxnum==0){ //if set to read
x-axis acceleration
ADMUX= 0b01100001; //setup the ADC pin
#asm("sleep"); //sleep processor to help sync up ADC reads
x1= accel; //read ADC
admuxnum++; //switch to read
y-axis
}
else{
ADMUX=0b01100000; //reading y-axis
#asm("sleep"); //sleep processor to help sync up ADC reads
y1= accel; //read ADC
admuxnum=
0; //switch
back to read x-axis again
if(x1==0) x1= 127; //re-scale x-axis to be inverted
else{
if(x1>128){ //this if-else
reverses the two halves of the x-scale
x1-=128;
/*x1= ~x1; //this code flips
the x-axis
x1+=1;*/
}
else{
x1+=128;
/*x1= ~x1; //this code flips
the x-axis
x1+=1;*/
}
}
if(y1>128){ //this if-else inverts the y-scale
y1-=128;
/* y1= ~y1; //this code flips the y-axis
y1+=1;*/
}
else{
y1= (y1 ^ 0x80);
/* y1= ~y1; //this code flips the y-axis
y1+=1;*/
}
memcpy(&scroll, &y1, 1);
//copy the value of y1 into scroll
scroll= (scroll
& 0x07) | ((y1>>4) & 0x08);
//scale down scroll speed
y1 = (signed
char)((signed char)y1>>2); //scale down mouse
speed in y-axis
x1 = (signed char)((signed char)x1>>2); //scale down mouse
speed in x-axis
//if x value is
in the cutoff range, make it zero
if(((signed char)x1) < CUTOFF && ((signed char)x1) >
-CUTOFF) x1=0;
//normalize
any other values to respect cutoff range
if(((signed char)x1) >= CUTOFF) x1= ((signed
char)((signed char)x1) - CUTOFF);
if(((signed char)x1) <= -CUTOFF) x1= ((signed char)((signed char)x1) +
CUTOFF);
//if y
value is in cutoff range, make it zero
if(((signed char)y1) < CUTOFF && ((signed char)y1) >
-CUTOFF) y1=0;
//normalize
any other values to respect cutoff range
if(((signed char)y1) >= CUTOFF) y1= ((signed
char)((signed char)y1) - CUTOFF);
if(((signed char)y1) <= -CUTOFF) y1= ((signed char)((signed char)y1) +
CUTOFF);
PORTD.7= button[3]
& 0x01; //set
LED to button 3
if(enabled==1){ //if the mouse status is enabled
if(button[3]==0){ //if not scrolling
//assemble
motion packets
send_message[0]= 0xC0 | ((button[1]<<5) & 0x20) |
((button[2]<<4) & 0x10)
|((y1>>4)&
0x0C) | ((x1>>6)& 0x03);
send_message[1]= 0x80 | (x1 &
0x3F);
send_message[2]= 0x80 | (y1 &
0x3F);
send_message[3]= 0x80;
}
if(button[3]==1){ //if scrolling
send_message[0]= 0xC0; //assemble
scrolling packets
send_message[1]= 0x80;
send_message[2]= 0x80;
send_message[3]= 0x80 | ((scroll)
& 0x0F);
}
send_message[4]= 0; //end transmission
message_pos= 0; //reset message cursor
UCSRB.5= 1; //send the message through the serial interface
while(UCSRB.5==1){} //until the message is done sending
}
}
}
}
}