Andrew Sawchuk - ajs94
Joseph Tanen - jst36
Cornell ECE476 - Airmouse Initiative - Code

#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){


  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;



    UDR= send_message[message_pos]; //otherwise keep sending message





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



              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


                       if(x1>128){  //this if-else reverses the two halves of the x-scale


                        /*x1= ~x1;  //this code flips the x-axis





                        /*x1= ~x1;  //this code flips the x-axis





              if(y1>128){  //this if-else inverts the y-scale


              /*  y1= ~y1;  //this code flips the y-axis




                y1= (y1 ^ 0x80);

              /*  y1= ~y1;  //this code flips the y-axis



              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






Back to Main Page