#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