Code





//EE476 - Spring 20019

//FINAL PROJECT - Wireless email pager

//

//Ajay Deonarine (add4) and Johnny Tseng (jjt9)

//-------------------------------------------

 

#include <90s8515.h>

#include <stdio.h> // sprintf

#include <delay.h> // delay_ms

#include <lcd.h> // LCD driver routines    

#include <stdlib.h>

 

//**********************************************************

//Global Declarations

//**********************************************************

 

//timer 1 constants

#define prescale1 1

#define clear_on_match 8

 

//task timers

unsigned int keypad_timer;            //task scheduleing timeout counters

unsigned int receiver_timer;         

unsigned int transmitter_timer;

unsigned int checkmail; 

 

                    

#define keypad_ovfl 30  

#define receiver_ovfl 2

#define transmitter_ovfl 2

#define checkmail_ovfl 100     

 

 

//expire timers

int ACK_timer;             //Ack timeout

unsigned int timeout; //receiving msg timeout

unsigned int trysend_timer;  //try send timeout

 

#define ACK_ovfl 5000

#define timeout_ovfl 5000

#define trysend_ovfl 5000

 

/*------------------------------    

            SUBROUTINES          

-------------------------------*/

void initialize(void);   

 

//KeyPad detect state machine

void KeyCommand(void); 

void KeyPad(void);            //keypad scanning

void Release(void);

void Debounce(void);

void DetectTerm(void);

void StillPressed(void);

void DebounceRelease(void);   

                  

//Transmitter

void TrySend(void);

void SendAck(void);

void SendMsg(void);  //send msg

 

 

//Receiver       

void WaitForInit(void);

void WaitForAck(void);

void ReceiveMessage(void);                       

      

 

 

//RESET

void Reset(void); //clears lcd and message

 

 

 

/*------------------------------    

            KEYPAD STUFF        

-------------------------------*/  

#define maxkeys 27

 

//KEYPAD STATES

#define keycommand_state 0;

#define release_state 1;

#define debounce_state 2;

#define detectterm_state 3;

#define stillpressed_state 4;

#define debouncerelease_state 5;

 

 

unsigned char keypadEnable;

char keypadstate; 

unsigned char key, butnum, lastnum;  

unsigned char keycount; 

unsigned char maybe;

unsigned char termSend, termReset, termSpace;

 

//key pad scan table

flash unsigned char keytbl[26]={0xee, 0xed, 0xeb, 0xde, 0xdd, 0xdb, 0xbe, 0xbd, 0xbb, 0x7e, 0x6c, 0x6d, 0x69, 0x5c, 0x5d, 0x59, 0x3c, 0x3d, 0x39, 0x7c, 0x6a, 0x6b, 0x5a, 0x7a, 0x5b, 0x3b};      

flash unsigned char keymap[24]={ 'a', 'b' , 'c' , 'd' , 'e' , 'f' , 'g' , 'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' , 'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' , 'x'}; //missing xyz

 

/*------------------------------    

       SEND MESSAGE STUFF          

-------------------------------*/

#define max_msg_size 81                    //maximum num of char the message can have

                                                                                    //80 + 1, 1 is terminating char

unsigned char compose;                     //0=not composing, 1=compose mode         

unsigned char reading;

 

unsigned char sendmessage[max_msg_size];

 

//unsigned char max_msg_size;   //this is the maximum # of characters per message

unsigned char sendmsg_index;            //current index of the message

unsigned char readytosend;            //0=no data to send, 1=data present                                        

 

/*------------------------------    

       READ MESSAGE STUFF          

-------------------------------*/

unsigned char receivedmessage[max_msg_size];

unsigned char receivedmsg_index;            //current index of the message

unsigned char readytoread;            //0=no data to read, 1=data present

unsigned char readatleastonce=0;

 

                                        

/*------------------------------    

            RECEIVER STUFF          

-------------------------------*/  

#define r_wait_for_init 0;

#define r_wait_for_ack 1;         

#define r_receive_message 2;  

#define r_nop 99;

 

unsigned char receivedByte;            //the byte read from the receiver                     

unsigned char r_status;             //receiver status                 

unsigned char receivingmsg;            //1 = receiver receiving MESSAGE

//unsigned char ACKreceived;                     

                   

/*------------------------------    

            TRANSMITTER STUFF          

-------------------------------*/  

#define t_try_send 0;

#define t_send_message 1;

#define t_send_ack 2;   

#define  t_nop 99;

 

unsigned char t_status;                        //transmitter status

unsigned char sendingmsg;                  //1 = transmitter sending MESSAGE         

 

 

/*------------------------------    

            LCD STUFF          

-------------------------------*/

#asm

    .equ __lcd_port=0x15

#endasm

                                                   

//LCD location

//for sending

char lcd_x;

char lcd_y; 

 

 

/*------------end of declaration---------------*/

 

       

//**********************************************************

//timer 1 compare-match A ISR                  

//use timer 1 to handle date and time

interrupt [TIM1_COMPA] void cmpA_overflow(void) 

{

     

  //task timers

  if (keypad_timer>0)       --keypad_timer;            //to get 30ms        

  if (receiver_timer>0)       --receiver_timer;    

  if (transmitter_timer>0)    --transmitter_timer;    

  if (checkmail>0)            --checkmail;

 

}

 

 

//**********************************************************

//Set it all up

//**********************************************************

void initialize(void){

 

  //set up the ports

  DDRD=0x00;    // PORT D is an input for the receiver

  DDRA=0xff;            //PORT A is an output for the transmitter

  DDRB=0xFF;

  PORTB=0x00;

  delay_us(15);

  DDRB=0x00;

 

 

 //set up timer 1

  TIMSK=TIMSK | 0x40;            //turn on timer 1 compare match interrupt

  OCR1A = 4000;               //to get 1ms

  TCCR1B = prescale1 + clear_on_match;              //start timer1

 

  TCNT1 = 0;                             //and zero the timer

 

 

  //init the task timers

  keypad_timer = keypad_ovfl;

  receiver_timer = receiver_ovfl;  

  transmitter_timer = transmitter_ovfl;

 

  ACK_timer = -1;

  trysend_timer = trysend_ovfl;

  timeout = timeout_ovfl;

 

  //init the keypad vars      

  keypadEnable = 1;      //enable keypad

  keycount = 0;

  butnum = 99;   //99 is the defined release state key

  lastnum = 99;

  key = 0;  

  maybe = 0;        

  termSend = 23;   //set this to keytbl[29] = send message                        

  termReset = 24;

  termSpace = 25; //right space

 

 

  //Message initializations                            

  compose=0;

  reading=0;

 

  sendmsg_index = 0;

  readytosend=0;

 

  receivedmsg_index = 0;                          

  readytoread = 0;

   

  //transmitter initializations     

  t_status = t_nop;

  sendingmsg=0;    

   

  //receiver initializations

  r_status = r_wait_for_init;

  receivingmsg=0;

 

  //LCD initializations

    //LCD uses PORT C

    lcd_init(20); // initialize the LCD for 16 char wide

    lcd_x=0;

    lcd_y=0;

 

    lcd_clear();  //clear it

   

 

  //Initial LCD display

  lcd_gotoxy(0,0);

  lcd_putsf("Hello");        

  lcd_gotoxy(0,1);

  lcd_putsf("please press: ");

  lcd_gotoxy(0,2);

  lcd_putsf("'a'=read,");

  lcd_gotoxy(0,3);      

  lcd_putsf("'b'=compose");

  lcd_gotoxy(0,0);      

 

   

  ////////////////////////////

 

  //crank up the ISRs

  #asm

 

            clr r17

            sei

  #endasm         

            

   

}

 

 

//**********************************************************         

//MAIN

//**********************************************************         

void main(void)

{

             

  //start 

  initialize();

 

 

  // Start LOOP  - never ends

  while (1) {

                    

    /*------------------------------    

            Check to see if there is message

    -------------------------------*/ 

    if (checkmail == 0) {

      checkmail = checkmail_ovfl;

           

      if( (keypadEnable) && (readytoread) && (!compose) && (!reading)) {          

                                   

        //write a constant string from flash

            lcd_gotoxy(0,0);

            lcd_putsf("GOT MSG!");        

            lcd_gotoxy(0,1);

            lcd_putsf("please press: ");

            lcd_gotoxy(0,2);

            lcd_putsf("'a'=read,");

            lcd_gotoxy(0,3);      

            lcd_putsf("'b'=compose");

            lcd_gotoxy(0,0);   

     }

   }

           

    /*------------------------------    

            KeyPad Scanning Task

    -------------------------------*/ 

    if ( (keypad_timer==0) && (keypadEnable) ) {

                   keypad_timer = keypad_ovfl;  //reload timer

   

                if(keypadstate==0)    KeyCommand();       

                if(keypadstate==1)    Release();       

                if(keypadstate==2)    Debounce();       

                if(keypadstate==3)    DetectTerm();       

                if(keypadstate==4)    StillPressed();       

                if(keypadstate==5)    DebounceRelease();       

     

           

    }        

   

      /*------------------------------    

            Transmitter Task          

    ------------------------------*/        

    if (transmitter_timer==0){

       

        transmitter_timer = transmitter_ovfl;  //reload timer

       

                if(t_status==0)    TrySend(); 

               if(t_status==1)    SendMsg(); 

            if(t_status==2)    SendAck();

                           

   

    }         

             

    /*------------------------------    

            Receiver Task   

    -------------------------------*/ 

    if (receiver_timer==0){

    

                receiver_timer = receiver_ovfl;            //reload timer

           

               receivedByte=PIND;            //read byte at receiver

                       

        if(r_status==0)    WaitForInit();

                if(r_status==1)    WaitForAck();

                if(r_status==2)    ReceiveMessage(); 

   

           

    }

   

           

  }                   

           

}

                                                                     

 

 

/*---------------------End Main()---------------------------*/

/*-------------------------------------------------------------*/

 

//**********************************************************         

//Transmitter TASK  --

//**********************************************************        

 

//Send Ackknowledgement back

void SendAck(void){

int i=0;             

 

            DDRB=0xFF;

              PORTB=0xFF; //TE =high

           

            PORTA='A'; //send A  

            delay_ms(300);

            PORTA='A'; //send A  

            delay_ms(300);

            PORTA='A'; //send A  

            delay_ms(500);

 

           

              PORTB=0x00;

              DDRB=0x00;

               

            t_status = t_nop;           

                receivedmsg_index=0;

            //reset message:

            for(i=0; i<max_msg_size; i++){

             receivedmessage[i]='\0';

            }

                                       

            r_status = r_receive_message;

 

            if(!compose){

              lcd_clear(); 

              lcd_putsf("Receiving...");

            }

           

}

 

//Try to initialize sending

void TrySend(void){                       

 

  //if not receiving message, send X

  if (!receivingmsg){                                

           

    lcd_clear();

                       

    DDRB=0xFF;

    PORTB=0xFF;

              

    PORTA='X';

    delay_ms(300);

    PORTA='X';

    delay_ms(300);

    PORTA='X';

    delay_ms(500);

 

 

    PORTB=0x00;

    DDRB=0x00;

           

    //initialize next state var   

    sendingmsg=1;                          

    receivingmsg=0;

    r_status = r_wait_for_ack;  //change receiver status to "wait for ack"

    ACK_timer = ACK_ovfl;            //start Ack expire timer

    t_status = t_nop;              //transmitter == do nothing

                       

  }

 

  //else don't do anything until receiving ended

  else { 

    t_status = t_try_send;   

    trysend_timer--;

           

                //trysend expire

            if (trysend_timer == 0){  

           

              lcd_clear();

              lcd_putsf("trysend timeout");

              delay_ms(2000);         

                          Reset();

            }

 

  }

 

}

      

 

void SendMsg(void){ 

 

               DDRB=0xFF;

             PORTB=0xFF; //TE =high

           

  //sending message here                   

  if( (sendmsg_index < max_msg_size-1) && (sendmessage[sendmsg_index] != 'T') ){

 

    PORTA = sendmessage[sendmsg_index];

    sendmsg_index++;                  

    delay_ms(300);       

    t_status=t_send_message;

  }

 

  //done sending                                                                     

  else {

    //send terminating char 'T'

    PORTA = sendmessage[sendmsg_index];

    sendmsg_index++;                  

    delay_ms(300);       

 

    //Done sending, reset

    PORTB=0x00;  //TE= off;

    DDRB=0x00;  

   

    //Initialize next state variables          

    sendmsg_index=0;

    sendingmsg = 0;

    lcd_clear();

    lcd_gotoxy(0,0);

    lcd_putsf("successful!");

    t_status=t_nop;

    delay_ms(2000);

    Reset();                

 

  }

 

 

}

         

 

/*-------------------------------------------------------------*/

 

//**********************************************************         

//Task Receiver   --

 

//Wait for X from the other end to initialize

void WaitForInit(void){                              

  //don't start unless not sending msg, and not reading, or msg read at least once

  if (!sendingmsg && !reading ) {

 

    if (receivedByte == 'X'){  

      delay_ms(300);                 

     

      //initialize nextstate var

      receivingmsg=1;

      sendingmsg=0;

      r_status = r_receive_message;

      t_status = t_send_ack;

           

      if(!compose){  

                 lcd_clear();

                lcd_putsf("GOTX");

      }

                           

              

 

    }               

  }

 

}  

 

 

//Wait for Ack

void WaitForAck(void){

 

  ACK_timer--;

 

  //Check to see if Ack is received

  if (receivedByte == 'A'){     

    delay_ms(300);             

   

    r_status = r_nop;            //receiver == do nothing

    t_status = t_send_message;  //transmitter == send message

 

    lcd_clear();

    lcd_putsf("gotACK");

   

    //Initialize next state variables

    sendingmsg=1;    //sending msg next

    receivingmsg=0;  //turn receiving message off

    ACK_timer = -1;      //turn off Ack expire timer

    sendmsg_index=0;    //initialize variable

           

//lcd_puts(sendmessage);

 

  }           

 

  //If ACK not received, and ack timer expires

  else if (ACK_timer ==0){

   //OUTPUT ERR and ABORT         

            lcd_clear();

            lcd_putsf("TIMEOUT!"); 

    DDRB=0xFF;

    PORTB=0xFF;

              

    PORTA='Z';

    delay_ms(500);

 

    PORTB=0x00;

    DDRB=0x00;

 

    delay_ms(2000);

            Reset();

           

  }

 

 

}

 

 

//Receive message

void ReceiveMessage(void){ 

            PORTB=0x00;

            DDRB=0x00;

              timeout--;

                                           

//            lcd_putchar(receivedByte);

//            delay_ms(300);

           

  if (timeout == 0){

               

               lcd_clear();

               lcd_putsf("connect timeout\n");

               lcd_putsf("resetting...");

               delay_ms(2000);

               Reset();

               

  }          

 

  //preventing from receiving ACk of own transmitter       

  else if ( (receivedByte=='A') || (receivedByte=='X')) {                          

            //do nothing    

              delay_ms(100);

  }                                                                  

           

  //store message  

  else if( (receivedmsg_index < max_msg_size) && (receivedByte!='T') && (receivedByte!='A') && (receivedByte!='X') ){

 

  timeout = timeout_ovfl;  //reset timeout expire timer

 

  receivedmessage[receivedmsg_index] = receivedByte;

  receivedmsg_index++;                  

 

  delay_ms(300);             

  }

 

  //Done receiving

  else {          

 

  //Initialize nextstate var 

  readytoread=1;

  receivedmsg_index=0;

  receivingmsg = 0;

  r_status = r_wait_for_init;

 

  }

 

 

 

}

 

 

 

/*-------------------------------------------------------------*/

 

 

 

/*-------------------------------------------------------------*/

 

//**********************************************************         

//Task KeyCommand   -- keypad detection state machine

void KeyCommand(void){

 

  //reset                  

  sendmsg_index =0;

  receivedmsg_index =0;

 

  butnum=99;

 

  KeyPad();               

  keypadstate=release_state;

 

} 

 

//STATES STARTS HERE//           

 

//Release

void Release(){               

 

 

  if (butnum==99){

    KeyPad();

    //goto Release State

    keypadstate=release_state;

 

  }        

  else{

    maybe=butnum;

    KeyPad();

    keypadstate=debounce_state;

    //goto Debounce State

  }

}

 

 

//Debounce

void Debounce(){              

 

  if (butnum==maybe){ 

 

            /////////////echo keypad//

//            printf("%d\r\n",butnum);

                       

            keypadstate=detectterm_state;

            //goto DetectTerm State

           

  }

  else{

    KeyPad();

    keypadstate=release_state;

    //goto Release State

   

  }

 

 

} 

 

//DetectTerm

void DetectTerm(){            

//check for term type

 

 

  //go into compose mode

  if ( (butnum == 1) && (!compose) ){ 

       //ready for compose             

      lcd_clear();

      lcd_x=0;

      lcd_y=0;

     

       compose=1; 

       reading=0;

  }  

 

      

  //read message

  else if ( (butnum==0) && (!compose) ) {

              lcd_clear();

              reading=1;

              compose=0;

              readatleastonce=1;

           

            if (readytoread){

              

              lcd_puts(receivedmessage);

           

               

            }

            else {

              lcd_clear();

              lcd_putsf("no msgs");

              lcd_gotoxy(0,1);

              lcd_putsf("press 'Clr' to exit");

           

            }

          

  }

 

  else if ( (butnum== termReset) ){

                        Reset();

            } 

 

 

  //send message

  else if ( (butnum == termSend) && (compose) ){

                   

             

           

             //REQUEST SEND

             lcd_clear();

             lcd_gotoxy(0,0);

             lcd_putsf("Message saved. ");

             lcd_gotoxy(0,1);

             lcd_putsf("Connecting.. ");

             lcd_gotoxy(0,2);

             lcd_putsf("Please wait... ");

 

             //                                         

             

             sendmessage[sendmsg_index] = 'T';    //end of msg

             sendmsg_index++;

             

             keypadEnable=0;  //turn off keypad              

             t_status = t_try_send;

 

 

  }                                 

 

  //otherwise

  else if (compose) {                         

           

 

    //checks to see if message exceeds max allowable size

  if (sendmsg_index < max_msg_size - 1 ){

    //echo to LCD

           

                if(lcd_x == 20){

                lcd_x==0;

                lcd_y++;

                }

                                               

                        if(butnum == termSpace){ 

                          lcd_putchar(' ');              

                          lcd_x++;

                          sendmessage[sendmsg_index]=' ';

                          sendmsg_index++;    

                        }

                       

                        else {   

                          lcd_putchar( keymap[butnum]); 

                          lcd_x++;               

                          //stores in message           

                          sendmessage[sendmsg_index]=keymap[butnum];                 

                          sendmsg_index++;  

                        }

               

             

    } else {

   

    //notify msg exceed max size

            //output to lcd       

             lcd_clear();     

             lcd_putsf("msg exceeds max, ...send?");           

             lcd_gotoxy(0,1);

             lcd_putsf("('Send'=send, 'Clr'=clr)");

   

   

    }

 

 

  }

 

    //for checking still pressed           

    lastnum = butnum;

   

    KeyPad();

    //goto StillPressed State

    keypadstate=stillpressed_state;

 

 

 

   

}

 

//StillPressed

void StillPressed(){          

 

  if (butnum == lastnum){

    KeyPad();

    keypadstate=stillpressed_state;

    //goto StillPressed State

 

  }

  else{

    KeyPad();

    keypadstate=debouncerelease_state;   

    //goto DebounceRelease State

           

  }

 

}

  

void DebounceRelease(void){   

 

  if (butnum == lastnum){

    KeyPad();

    keypadstate=stillpressed_state;

    //goto StillPressed State

   

  }               

  else{                           

    KeyPad();

    keypadstate=release_state;

    //goto to Release State

  }

}

                                        

       

 

//**********************************************************         

//KeyPad   -- KeyPad Scanning

void KeyPad(void){  

                          

             

            //get upper nibble

             DDRB= 0x0f;

             PORTB = 0xf0;

             delay_us(5);

             key = PINB;

              

             //get lower nibble

             DDRB = 0xf0;

             PORTB = 0x07;   //only want to read in the lower 3 bits

             delay_us(5);

             key = key | PINB;

             key = key | 0x08;

              

             //find matching keycode in keytbl

             if (key != 0xff){  

               

                for (butnum=0; butnum<maxkeys; butnum++){   

                    if (keytbl[butnum]==key)  break;  

                }

                

                if (butnum==maxkeys) butnum=99; //99 = not pressed or not matched

 

             } 

             

             else butnum=99;            //99 = not pressed or not matched       

             

                         

}

 

 

/////////////////////////////////////

//Reset

void Reset(void){               

 

  //reset lcd

  lcd_clear();  //clear it  

  lcd_x=0;

  lcd_y=0;             

 

 

  //Reinitialize Screen

  lcd_gotoxy(0,0);

  lcd_putsf("Hello");        

  lcd_gotoxy(0,1);

  lcd_putsf("please press: ");

  lcd_gotoxy(0,2);

  lcd_putsf("'a'=read,");

  lcd_gotoxy(0,3);      

  lcd_putsf("'b'=compose");

  lcd_gotoxy(0,0);   

 

  //reset send/receive message var

  sendmsg_index = 0;   

  sendingmsg = 0;

  receivingmsg = 0;

  receivedmsg_index = 0;

  compose = 0;

  reading = 0;

     

  //resets keypad

  keypadEnable=1;

  keypadstate=keycommand_state;   //detect keypad again         

  butnum = 99;       

 

  //reset expire timer

  ACK_timer = -1;

  trysend_timer = trysend_ovfl;

  timeout = timeout_ovfl;

 

  //reset t/r status var

  t_status = t_nop;

  r_status = r_wait_for_init;

 

 

}








Site developed by Johnny Tseng and Ajay Deonarine.