#include
<mega32.h>
#include
<delay.h>
#include
<stdio.h>
//timeout
values for each task
/* the I2C
bus is connected to PORTA */
/* the SDA
signal is bit 3 */
/* the SCL
signal is bit 4 */
#asm
.equ __i2c_port=0x1B
.equ __sda_bit=3
.equ __scl_bit=4
#endasm
#include
<i2c.h>
#define
BUS10 0b10100110 //chip1 block 0
#define
BUS11 0b10101110 //chip1 block 1
#define
BUS20 0b10100000 //chip2 block 0
#define
BUS21 0b10101000 //chip2 block 1
#define
begin {
#define end
}
//States for
Key Debounce
#define
Release 1
#define
Debounce 2
#define
Terminator 3
#define Done
4
#define
StillSame 5
#define
DebounceRelease 6
//own tasks
void
wordSearch(void);
void
compare(void);
void
speak(void);
void
keyBounce(void);
void
keyLog(void);
void
irSensor(void);
unsigned
char eeprom_read(unsigned char addressH, unsigned char addressL, unsigned char
EEPROM_BUS_ADDRESS);
unsigned char
intRead(unsigned int address, unsigned char EEPROM_BUS_ADDRESS);
void
initialize(void); //all the usual mcu stuff
unsigned int
starDex=0;
unsigned
char inWord[20];
unsigned
char compWord[20];
unsigned int
pos1, pos2, pos3, pos4;
unsigned
char stillMatch;
unsigned int
maxMatch;
unsigned int
speakIndex;
unsigned int
alloDex[20];
unsigned int
wordLength;
unsigned int
i,j,k,l;
char
debug1=0,debug2=0;
char time1,
time2;
char
inWordDex=0;
char
numBraille=0;
char
butNum='';
char
butNumL='';
char
PushState;
char
maxStar;
unsigned
char irTimer;
unsigned
char irReading;
//timer 0
compare ISR
interrupt
[TIM0_COMP] void timer0_compare(void)
begin
//Decrement the three times if they are not
already zero
if
(time1>0) --time1;
if
(time2>0) --time2;
if (irTimer>0) --irTimer;
end
//**********************************************************
//Entry
point and task scheduler loop
void
main(void)
begin
initialize();
while(1){
if(time1==0){
keyBounce(); //calls the debouncer function for the
buttons
}
if(irTimer==0){
irSensor(); //calls the IR Sensor task
}
}
end
//**********************************************************
//Task
subroutines
//the IR
Sensor
//checks if
the user is too close to an object
void
irSensor(void){
irTimer
= 300; //resets the task timer
TIMSK=0; //turns off timer cmp-match so other tasks
//do not
interfere when speaking
irReading
= ADCH; //takes reading from ADC
ADCSR.6=1; //prepares ADC for next reading
if(irReading
> 170){ //if user is within about
35cm
//will
say "DANGER" if user is too close
UDR
= 20;
delay_ms(1);
UDR = 127;
delay_ms(1);
UDR = 21;
delay_ms(1);
UDR = 114;
delay_ms(1);
UDR = 22;
delay_ms(1);
UDR = 88;
delay_ms(1);
UDR = 23;
delay_ms(1);
UDR = 5;
delay_ms(1);
UDR = 174;
delay_ms(1);
UDR = 154;
delay_ms(1);
UDR = 7;
delay_ms(1);
UDR = 165;
delay_ms(1);
UDR = 151;
delay_ms(1);
}
TIMSK=2; //turns cmp-match back on
}
//Converts
the braille to its alphanumeric character
void
keyLog(void){
butNum='*'; //default value of butNum which indeclares
not pushed
//switch statements for the non-numerical
braille
if(numBraille==0){
switch(~PINB){
case(0b10000000):
butNum='a';
break;
case(0b11000000):
butNum='b';
break;
case(0b10010000):
butNum='c';
break;
case(0b10011000):
butNum='d';
break;
case(0b10001000):
butNum='e';
break;
case(0b11010000):
butNum='f';
break;
case(0b11011000):
butNum='g';
break;
case(0b11001000):
butNum='h';
break;
case(0b01010000):
butNum='i';
break;
case(0b01011000):
butNum='j';
break;
case(0b10100000):
butNum='k';
break;
case(0b11100000):
butNum='l';
break;
case(0b10110000):
butNum='m';
break;
case(0b10111000):
butNum='n';
break;
case(0b10101000):
butNum='o';
break;
case(0b11110000):
butNum='p';
break;
case(0b11111000):
butNum='q';
break;
case(0b11101000):
butNum='r';
break;
case(0b01110000):
butNum='s';
break;
case(0b01111000):
butNum='t';
break;
case(0b10100100):
butNum='u';
break;
case(0b11100100):
butNum='v';
break;
case(0b01011100):
butNum='w';
break;
case(0b10110100):
butNum='x';
break;
case(0b10111100):
butNum='y';
break;
case(0b10101100):
butNum='z';
break;
case(0b00111100): //for
the braille character that indicates a number follows
butNum='#';
break;
case(0b00000001): //for when the speak button is pressed
butNum='+';
break;
} //end of switch
} //end of if-statement
//For numbers
0-9
else
if(numBraille==1){
//numBraille=0;
switch(~PINB){
case(0b10000000):
butNum='1';
break;
case(0b11000000):
butNum='2';
break;
case(0b10010000):
butNum='3';
break;
case(0b10011000):
butNum='4';
break;
case(0b10001000):
butNum='5';
break;
case(0b11010000):
butNum='6';
break;
case(0b11011000):
butNum='7';
break;
case(0b11001000):
butNum='8';
break;
case(0b01010000):
butNum='9';
break;
case(0b01011000):
butNum='0';
break;
case(0b00111100): //for the braille character that
indicates a number follows
butNum='#';
break;
case(0b00000001): //for when the speak button is
pressed
butNum='+';
break;
} //end of switch
} //end of else if
}
//Debounces
the buttons
void
keyBounce(void)
begin
time1=100; //resets the timer for keybounce
TIMSK=0; //turns of the cmp-match interrupt
//to avoid any other
tasks from interfering
switch(PushState)
begin
case(Release):
if(butNum == '*') //Checks to see if the button is valid
begin
PushState = Release;
keyLog();
end
else
begin
PushState = Debounce;
keyLog();
end
break;
case(Debounce):
if(butNum !='*')
begin
PushState = Terminator;
end
else
begin
PushState = Release;
keyLog();
end
break;
case(Terminator):
if(butNum=='+'){
PushState = Done;
wordSearch();
}
else if (butNum!='#'){
PushState =
StillSame;
inWord[wordLength++] = butNum;
if(numBraille==1){
numBraille=0;
}
}
else{
PushState = StillSame;
numBraille=1;
}
butNumL=butNum;
keyLog();
break;
case(Done):
PushState = Done;
break;
case(StillSame):
if(butNum != '*')
begin
PushState = StillSame;
keyLog();
end
else
begin
PushState = DebounceRelease;
keyLog();
end
break;
case(DebounceRelease):
if(butNum != '*')
begin
PushState = StillSame;
keyLog();
end
else
begin
PushState = Release;
keyLog();
end
end
TIMSK=2; //turns
the cmp-match interrupt back on
end
//******************************************************
//Reads in
the input from the keypad
//searches
for the word in the dictionary
//and stores
the indexes for the allophones
//in allodex
to be used later on in speak()
//will
tranverse through the dictionary looking for the
//for the
largest matching words
void
wordSearch(void){
starDex=0;
//Resets alloDex
for(j=0; j<20;j++){
alloDex[j] = '';
}
pos4=0;
while(wordLength > 0){
pos1=0;
maxMatch=0;
starDex=0;
//Extracts
the word from dictionary to be compared to compWord
while(starDex<maxStar){
if
(intRead(pos1,BUS10)=='*'){
pos2=0;
starDex++;
compare();
} //end of dic compare
else{
compWord[pos2]=intRead(pos1,BUS10);
pos2++;
} //end of else
pos1++;
} //end of while
for(i = 0; i<maxMatch; i++){
inWord[i] = '';
}
for(i=maxMatch; i<wordLength;
i++){
inWord[i-maxMatch] = inWord[i];
inWord[i] = '';
}
wordLength-=maxMatch;
alloDex[pos4] = speakIndex;
pos4++;
} // end of wordLength while loop
speak();
PushState = StillSame;
} //end of wordSearch
//compares
the inputted word with the compare word
//saving the
number of matching characters
void compare(void){
//sprintf(lcd_buffer,"%-i",debug1);
// display the count
//lcd_gotoxy(0,1);
//lcd_puts(lcd_buffer);
pos3=0;
stillMatch=1;
while(stillMatch){
//if the word extract from
dictionary ran out
if(compWord[pos3]=='' &&
pos3>maxMatch){
speakIndex=starDex;
//
sprintf(lcd_buffer,"%-i",speakIndex);
// display the count
//lcd_gotoxy(0,0);
//lcd_puts(lcd_buffer);
maxMatch = pos3;
} //end of if
stillMatch= ( inWord[pos3]==
compWord[pos3]);
if(inWord[pos3]=='' &&
compWord[pos3]==''){
stillMatch=0; //break out from the whileloop
since we found the word
} //end of if
pos3++;
} //end of while loop
//Resets compWord
for(j=0; j<20;j++){
compWord[j] = '';
}
} //end of
compare
//outputs
the allophones for the inputted word
void
speak(void){
i=0;
//current star number
j=0;
//alloDex index
k=0;
//dic list index
l=0;
while(alloDex[l]!=''){
k=0;
i=0;
while(i<alloDex[l]){
if(intRead(k,BUS20) == '*'){
i++;
}
// end of if
k++;
}
//end of while
//sets up the initial parameters for
speakjet
UDR = 20;
delay_ms(1);
UDR = 127; //sets
up the volume. Takes values from 0 to 127
delay_ms(1);
UDR = 21;
delay_ms(1);
UDR = 114; //sets up the speed. Takes values from 0 to 127
delay_ms(1);
UDR = 22;
delay_ms(1);
UDR = 88; //sets up the pitch. Takes values from 0 to 255
delay_ms(1);
UDR = 23;
delay_ms(1);
UDR = 5; //sets up bend. Takes values from 0 to 15
delay_ms(1);
//loops through the array of speak
indexes
//speaking each allophone until the
while(intRead(k,BUS20)!='*'){
UDR = intRead(k,BUS20);
delay_ms(1);
k++;
} //end of while with allodic[k]
l++;
} //end
of while for transversing alloDex
//Resets the inputted word
for(j=0; j<20;j++){
inWord[j] = '';
}
} //end of speak
//reads the
byte at location addressL to addressH
//and at
EEPROM_BUS_ADDRESS
//EEPROM has
two blocks so EEPROM_BUS_ADDRESS specifies which one
unsigned
char eeprom_read(unsigned char addressH, unsigned char addressL, unsigned char
EEPROM_BUS_ADDRESS) {
unsigned
char data;
i2c_start();
i2c_write(EEPROM_BUS_ADDRESS);
i2c_write(addressH);
i2c_write(addressL);
i2c_start();
i2c_write(EEPROM_BUS_ADDRESS
| 1);
data=i2c_read(0);
i2c_stop();
return data;
}
//Takes
"address" which is the addressH concatenated with addressL
//and
EEPROM_BUS_ADDRESS which selects 1 of the 2 blocks
unsigned char
intRead(unsigned int address, unsigned char EEPROM_BUS_ADDRESS){
unsigned char H=0;
unsigned char L=0;
H=address>>8; //isolates the high byte address
L=((address<<8)>>8); //isolates the low byte address
return
eeprom_read(H, L, EEPROM_BUS_ADDRESS);
//returns the value at that address
}
//**********************************************************
//Set it all
up
void
initialize(void)
begin
//Setup the ports
DDRB = 0x00; //turns
on portB to input
DDRA = 0xff;
//turns on portD to output
PORTA = 0x00; //turns
on portA to input
//set up timer 0
TIMSK=2; //turn
on timer 0 cmp match ISR
OCR0 = 250;
//set the compare re to 250
time ticks
//prescalar to 64 and turn on clear-on-match
TCCR0=0b00001011;
UCSRB = 0b00011000 ; //hex 0x18
UBRRL = 103 ; //using a 16 MHz crystal (9600
baud)
//Setup timer
time1=50;
time2=100;
irTimer = 300;
//initializes initial variables
wordLength=0;
PushState=Release;
DDRD.7=1;
PORTD.7=0;
//init the A to D converter
//channel zero/ left adj /EXTERNAL Aref
//!!!CONNECT Aref jumper!!!!
ADMUX = 0b00100000;
//enable ADC and set prescaler to
1/128*16MHz=125,000
//and clear interupt enable
//and start a conversion
ADCSR = 0b11000111;
//Produces a set of sounds to tell user
//that the device is on
UDR = 20;
delay_ms(1);
UDR = 96;
delay_ms(1);
UDR = 21;
delay_ms(1);
UDR = 114;
delay_ms(1);
UDR = 22;
delay_ms(1);
UDR = 88;
delay_ms(1);
UDR = 23;
delay_ms(1);
UDR = 5;
delay_ms(1);
UDR =199;
delay_ms(1);
UDR = 7;
delay_ms(1);
UDR = 137;
delay_ms(1);
UDR =4;
delay_ms(1);
UDR = 1;
delay_ms(1);
UDR = 178;
delay_ms(1);
UDR = 155;
delay_ms(1);
//crank up the ISRs
#asm
sei
#endasm
end