//LAB 7 CODE - Transmitter
//Michael Jardin
//Nick Liu
//Monday, 7:30-10:30 Lab
#include <Mega163.h>
//timeout values for each task
#define t1
20
#define t2
50
#define t3
30
#define left 1
//value to determine left engine
#define right 2
//value to determine right engine
#define voltSegments 17
//number of different voltages for motors
#define off
0x08
//transmission byte indicating hovercraft should be off
#define idle
0x88
//transmission byte indicating hovercraft is idle
//define pushbutton debounce states
#define nopush 0
#define maybepushed 1
#define pushed 2
#define maybenopush 3
//the subroutines
void task1(void);
//runs receive interrupt at t1 interval
void task2(void);
//reads in analog input and turns into transmission byte
void task3(void);
//power on/off button debounce state machine
void initialize(void);
//sets up the mcu
void gets_int(void);
//nonblocking transmit interrupt scheme
void map(char direction);
//maps values to format used for transmission byte
//define variables
unsigned char reload;
//timer 0 reload to set 1 mSec
unsigned char time1, time2, time3;
//keeps track of current
time of each task
unsigned char r_ready;
//flag for receive done interrupt
unsigned char r_char;
//current character
int Ain;
//raw A to D number
unsigned char first;
//flag used to read in right and left input
unsigned char i;
//counter
float voltage;
//analog voltage read in
unsigned char value;
//temporary value used to construct transmission byte
unsigned char state, pushflag;
//current state of debounce state machine
//Lookup table used to determine what value to set analog voltage
flash float voltsIn[voltSegments]=
{-0.02, 0.31, 0.62, 0.93, 1.25,
1.56, 1.86, 2.20, 2.50, 2.81, 3.11,
3.42, 3.73, 4.05, 4.36, 4.68, 5.05};
//lookup table to determine direction and magnitude of each engine
flash unsigned char packet[16]=
{15, 14, 13, 12, 11, 10, 9, 8, 8, 1, 2, 3, 4, 5, 6, 7};
//**********************************************************
//timer 0 overflow ISR
interrupt [TIM0_OVF] void timer0_overflow(void)
{
TCNT0=reload; //reload to force 1 mSec overflow
if (time1>0) --time1;
//Decrement the two times if they are not already zero
if (time2>0) --time2;
if (time3>0) --time3;
}
interrupt [UART_DRE] void udr_empty(void)
{
UDR = r_char;
//transmits a char
UCSRB.5=0;
//stop trans ISR
r_ready=1;
//ready to start the interrupt again
}
//**********************************************************
//Entry point and task scheduler loop
void main(void)
{
initialize();
while(1){
//main task scheduler loop -- never exits!
if (time1==0)
task1();
if (r_char!=off)
//if the hovercraft is on, only then read in engine voltages
if (time2==0)
task2();
if (time3==0)
task3();
}
}
//***********************************************************
void map(char direction)
{
i = 0;
while (!((voltage >= voltsIn[i]) && (voltage < voltsIn[i+1])
&& (i < voltSegments)))
i++;
if (i == voltSegments)
//if voltage is not inside the range
r_char=idle;
//stop the motor
else {
value = packet[i];
//set value to specific magnitude
if (direction == left) {
value <<= 4;
//shift bits 4 spaces to the left
value += 0x0f;
//make 1st 4 bits = 1111
r_char = r_char & 0x0f;
//clear out left four bits
r_char += 0xf0;
//make last 4 bits = 1111
r_char = r_char & value;
//replace left 4 bits with value
}
else {
value += 0xf0;
//make last 4 bits 1111
r_char = r_char & 0xf0;
//clear out right four bits
r_char += 0x0f;
//make 1st 4 bits = 1111
r_char = r_char & value;
//replace right 4 bits with value
}
}
}
//**********************************************************
void task1(void)
//used to keep 20 msec base for TX interrupt
{
time1 = t1;
if (r_ready)
gets_int();
//ready to transmit data
}
//**********************************************************
void task2(void)
//A/D converter
{
time2 = t2;
if(ADCSR.6 == 0 && first){
Ain = ADCH;
Ain >>= 2;
//obtain only 6 bit accuracy
voltage =(float)Ain;
voltage=(voltage/64) * 5.0;
map(left);
//set up the correct opcode
ADMUX = 0b00100001;
//need to adjust the first three values for Aref, READ channel 1
ADCSR.6 = 1;
//init A to D Conversion
first = 0;
}
if(ADCSR.6 == 0 && first == 0){
Ain = ADCH;
Ain >>= 2;
voltage =(float)Ain;
voltage=(voltage/64) * 5.0;
map(right);
//set up the correct opcode
ADMUX = 0b00100000;
//need to adjust the first three values for Aref, READ channel 0
ADCSR.6 = 1;
//init A to D Conversion
first = 1;
}
}
//**********************************************************
void task3(void)
//debounce for power on/off button
{
time3=t3;
switch(state) {
case nopush:
if (PINC ==
0x01)
//if
a button push is detected
state=maybepushed;
//move to the next
state
else
state=nopush;
break;
case maybepushed:
if (PINC ==
0x01)
//if
that same button is still pushed
state=pushed;
//move to the pushed state
else
state=nopush;
//else there is no button push
break;
case pushed:
if (PINC
== 0x01){
//if again that button is pushed
state = pushed;
pushflag=1;
}
else if
(pushflag){
if (r_char==off)
//turn on/off the hovercraft
r_char=idle;
else r_char=off;
pushflag=0;
}
else
state=maybenopush;
//else maybe the button wasn't pushed
break;
case maybenopush:
if (PINC == 0x01)
//if that
button is pushed
state=pushed;
//go back to the
pushed state
else
state=nopush;
//else there was
no button push
break;
}
}
//**********************************************************
// -- non-blocking keyboard check initializes ISR-driven
// receive. This routine merely sets up the ISR, which then
//does all the work of getting a command.
void gets_int(void)
{
r_ready=0;
UCSRB.5=1;
}
//**********************************************************
//Set it all up
void initialize(void)
{
//Set up UART communication
UCSRB =0x08;
UBRR = 255 ;
//set up the ports
DDRD=0xff;
// PORT D is an output
DDRC=0x00;
// PORT C is an input (left control)
DDRA=0x00;
// PORT A is an input (right control)
PORTC=0;
PORTA=0;
//set up timer 0
reload=256-62;
//value for 1 Msec
TCNT0=reload;
//preload timer 1 so that is interrupts after 1 mSec.
TCCR0=3;
//prescalar to 64
TIMSK=1;
//turn on timer 0 overflow ISR
//init the task timers
time1=t1;
time2=t2;
//set up A/D converter
ADMUX = 0b00100000;
//READ channel 0
ADCSR = 0b11000110;
//start conversion
r_ready=1;
//ready to start transmitting
r_char = off;
//hovercraft is powered off
state = nopush;
//crank up the ISRs
#asm
sei
#endasm
}