#include <Mega32.h>
#include
<stdio.h>
#include <delay.h>
#include
<stdlib.h>
#define LCDwidth 16
#define t1 1
#define t2
40
#define t3 120
#define
MAX_STEP 10
#define
X_SCALE 0
#define Y_SCALE 0
#define HIGH_TIME 7
#define STORAGE
500
void initialize(void);
void get_cmd_init(void);
void mouse_lookup(void);
void step_motors(void);
void draw(void);
void
debounce(void);
void res_pos(void);
void teach(void);
void
playback(void);
//array for storing the movement by the mouse during
recording
char rec_x[STORAGE];
char rec_y[STORAGE];
char mouse_in[3];
//input from the mouse
char mouse_in_byte;
//individual byte from the mouse
int time1, time2, time3;
//timer variables
char debug_ctr;
char cmd_rdy;
char byte_ctr;
char lb,rb;
//for left and right mouse buttons
signed int xin, yin;
char x_dir, x_amt, y_dir, y_amt;
char step_state = 0;
char step_ctr = 0;
int dx, dy;
signed char frac;
//line drawing algorithm variable
char done_step;
char
step_ready;
char yscale, xscale;
signed char xdif, ydif;
char xdir,
ydir;
char d_state = 0;
//debouncer state variable
char res_flag = 0;
//reset mode flag
char teach_flag = 0;
//record/teach mode flag
char res_state = 0;
//reset state variable
char
res_ctr=0;
char
step_size=0;
//step size variable
char let_ctr=0;
int rec_ctr;
char play=0;
int play_ctr =
0;
char
nobut;
//timer0 ISR
interrupt[TIM0_COMP]
void cool(void)
{
if (time1) time1--;
if (time2) time2--;
if (time3)
time3--;
}
void main(void)
{
initialize();
while(1) {
//received 1 byte from
the mouse
if (cmd_rdy == 1)
{
cmd_rdy = 0;
mouse_lookup();
}
if (done_step)
{
draw();
done_step = 0;
}
if
(time1 == 0){
step_motors();
time1 = t1;
}
if(time3 ==0){
//interrupt at 30ms
time3 = t3;
debounce(); //call debounce state machine
if (res_flag)
res_pos();
if (play)
playback();
}
PORTC = ~teach_flag;
}
}
void get_cmd_init(void) {
cmd_rdy=0;
UCSRB.7=1;
}
interrupt[USART_RXC]void
interface(void) {
mouse_in[byte_ctr] = UDR; //read in value
if ((mouse_in[0] &
0x40) >> 6) //check for first byte in packet
byte_ctr++;
else byte_ctr = 0;
if (byte_ctr == 3){ //packet
complete
cmd_rdy = 1;
byte_ctr = 0;
}
}
void
initialize(void)
{
byte_ctr = 0;
DDRB = 0xff;
DDRA = 0;
DDRC = 0xff;
TCCR0 = 0b00001011;
OCR0 = 62;
//set PIT to .25ms
UCSRB = 0x10;
UBRRL = 0x40; //set baud rate
to 1200
UBRRH = UBRRH | 0x03;
led = UBRRH;
UCSRC = 0b10000110;
TIMSK = 0b00000010;
done_step = 1;
step_ready = 0;
PORTB = 0xff;
xscale = X_SCALE;
yscale = Y_SCALE;
get_cmd_init();
led = 0;
time1 = 0;
debug_ctr = 0;
cmd_rdy = 0;
byte_ctr = 0;
xdif = 0;
ydif = 0;
rec_ctr = 0;
byte_trash = 0;
time1 = t1;
//enable interrupts
#asm
sei
#endasm
}
void
mouse_lookup(void)
{
lb = (mouse_in[0] >> 5) & 1; //check
button position
rb = (mouse_in[0] >> 4) &
1;
yin = ((mouse_in[0] << 4) & 0xc0) | ((mouse_in[2] &
0x3f)); //decode packet
xin = ((mouse_in[0] << 6) & 0xc0) | ((mouse_in[1] &
0x3f));
if (rb ==1) xin = 0; //disable movement if button
is depressed
if (lb ==1) yin = 0;
xdif =xin;
ydif =yin;
done_step = 1;
if (teach_flag){ //save data if recording
rec_x[rec_ctr] = xdif;
rec_y[rec_ctr] = ydif;
rec_ctr++;
if (rec_ctr == STORAGE) //check for end of array
teach_flag = 0;
//stop recording
}
}
//step each motor 1 step in
either direction
//dir = 1 step up or
right
//dir = 0
step left or down
// clk is the step clock (1 for step and 0 for no
step)
void step_motors(void)
{
//PORTB output is
setup as such:
// bit 7 6 5 4 3 2 1 0
//
size x_clk y_clk x_dir y_dir
switch(step_state){
case 0:
PORTB = 0;
if (step_ready == 1) {
step_state = 1;
step_ready = 0;
//setup variables for Line algorithm
dx = x_amt << 1;
dy = y_amt << 1;
}
break;
case 1:
if (dx > dy) //if slope is
less than 1
{
frac = dy - (dx>>1);
step_state = 2;
}
else
{
step_state = 6;
frac = dx - (dy>>1);
}
break;
case 2:
if (x_amt >
0)
{
//setup direction bits
PORTB = (step_size<<4) | (ydir) | (xdir << 1);
step_state = 3;
}
else
{
step_state = 0;
}
break;
case 3:
step_ctr
= 0;
if (frac >= 0)
{
step_state = 5;
}
else step_state = 4;
frac = frac + dy;
x_amt--;
break;
case 4:
step_ctr++;
PORTB = (step_size<<4)
| ydir | (xdir << 1) | (0x08); //only step the x
motor
if (step_ctr == HIGH_TIME)
//do this case 7 times to obey clock reqr
step_state = 2;
break;
case 5:
step_ctr++;
PORTB = (step_size<<4)
| ydir | (xdir << 1) | (0x0c);
//step both the
x and y motor
if (step_ctr ==
HIGH_TIME)
//do this case 7 times to obey clock reqr
step_state = 2;
break;
case 6:
PORTB = 0;
if (y_amt > 0)
{
//setup direction bits
PORTB = (step_size<<4) | ydir | (xdir << 1);
step_state = 7;
}
else
{
step_state = 0;
}
break;
case 7:
step_ctr
= 0;
if (frac >= 0)
{
step_state = 9;
}
else step_state = 8;
frac = frac + dx;
y_amt--;
break;
case 8:
step_ctr++;
PORTB = (step_size<<4)
| ydir | (xdir << 1) | (0x04); //only step the y
motor
if (step_ctr == HIGH_TIME)
//do this case 7 times to obey clock reqr
step_state = 6;
break;
case 9:
step_ctr++;
PORTB = (step_size<<4)
| ydir | (xdir << 1) | (0x0c);
//step both the
x and y motor
if (step_ctr ==
HIGH_TIME)
//do this case 7 times to obey clock reqr
step_state = 6;
break;
}
}
void draw(void)
{
//do calculation
for x and y amount and direction
//set cmd_ready =
1 to start the motors stepping
//checks two's
complement and calculates magnitude
if (xdif <
0)
{
xdif = ~xdif;
xdif++;
xdir = 0;
}
else
{
xdir = 1;
}
if (ydif <
0)
{
ydir = 0;
ydif = ~ydif;
ydif++;
}
else ydir = 1;
x_amt = xdif
>> 1;
y_amt = ydif >> 1;
if ((x_amt + y_amt) > (25) )
step_size = 0;
else step_size = 1;
//set max steps
at anytime to be 10
//since stepping
at 444 Hz, each step takes ~2.25ms
//10 steps take
22ms which would be the lowest resolution of the mouse updating
if (x_amt >
MAX_STEP){
x_amt = MAX_STEP;
}
if (y_amt > MAX_STEP)
{
y_amt = MAX_STEP;
}
step_ready =
1;
}
void debounce(void) //state machine for 3
button debouncing
{
switch(d_state){
case 0:
if (~PINA == 1)
d_state = 1;
if (~PINA == 2)
d_state = 4;
if (~PINA == 4)
d_state = 7;
break;
case 1:
if (~PINA == 1)
d_state = 2;
else d_state = 0;
break;
case 2:
if (~PINA == 1){
res_flag = 1;
d_state = 2;
}
else d_state = 3;
break;
case 3:
if (~PINA == 1)
d_state = 2;
else {
d_state = 0;
}
break;
case 4:
if (~PINA == 2)
d_state = 5;
else d_state = 0;
break;
case 5:
if (~PINA == 2){
d_state = 5;
}
else d_state = 6;
break;
case 6:
if (~PINA == 2)
d_state = 5;
else
{
d_state = 0;
teach_flag = teach_flag ^
1;
if (teach_flag == 1)
rec_ctr = 0;
}
break;
case 7:
if (~PINA == 4)
d_state = 8;
else d_state = 0;
break;
case 8:
if (~PINA == 4){
d_state = 8;
play = 1;
}
else d_state = 9;
break;
case 9:
if (~PINA == 4)
d_state = 8;
else
{
d_state = 0;
}
break;
}
}
void
res_pos(void)
//state machine to center stylus
{
UCSRB.7 = 0; //disable
interrupts
switch(res_state)
{
case 0:
//move stylus to bottom
xdif = 0;
ydif = 60;
done_step = 1;
res_ctr++;
if (res_ctr>=80)
{
res_ctr = 0;
res_state = 1;
}
break;
case 1:
xdif = 0; //move stylus
up a bit from bottom
ydif = -60;
done_step = 1;
res_ctr++;
if (res_ctr>=2)
{
res_ctr = 0;
res_state = 2;
}
break;
case 2:
xdif = 60; //move to far
left
ydif = 0;
done_step = 1;
res_ctr++;
if (res_ctr>=160)
{
res_ctr = 0;
res_state = 3;
}
break;
case 3:
xdif = -60; //move to be centered horizontally
ydif = 0;
done_step = 1;
res_ctr++;
if (res_ctr>=50)
{
res_ctr = 0;
res_state = 4;
}
break;
case 4:
xdif = 0;
ydif = -60; //move to be centered
vertically
done_step = 1;
res_ctr++;
if (res_ctr>=40)
{
res_ctr = 0;
res_state = 0;
res_flag = 0;
get_cmd_init();
}
break;
}
}
void playback(void)
{
UCSRB.7 = 0;
//disable mouse
xdif = rec_x[play_ctr]; //load
value from array
ydif = rec_y[play_ctr];
done_step = 1;
play_ctr++;
if(play_ctr == rec_ctr)
{ //check for end
of record
play = 0;
//end playback
play_ctr = 0;
get_cmd_init();
//reset variables
}
}