Appendix 1:  Keyboard Code

 

//Gustavo Bitdinger - gbb7

//Rangarajan Rajagopalan - rr234

//ECE 476 Final Project - Weatherdog

//Mon. May 2, 2005

 

#include <Mega32.h>  

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <delay.h> 

#include <string.h>                                         

 

#define begin {

#define end   }

 

#define WAIT                        0              

#define CODE_DONE             1

 

flash unsigned char ascii_number[10] = {0x45, 0x16, 0x1E, 0x26, 0x25, 0x2E, 0x36, 0x3D, 0x3E, 0x46};

flash unsigned char ascii_alpha[26] = {0x1C, 0x32, 0x21, 0x23, 0x24, 0x2B, 0x34, 0x33, 0x43, 0x3B, 0x42, 0x4B, 0x3A, 0x31, 0x44, 0x4D, 0x15, 0x2D, 0x1B, 0x2C, 0x3C, 0x2A, 0x1D, 0x22, 0x35, 0x1A};

 

unsigned char received_word[32];  //the word received from the user keyboard

unsigned char received_word_index;  //the corresponding index

unsigned char keyboard;  //a variable to hold bits sent from the keyboard

unsigned char rx_kbd_data;   //a variable to hold the characters sent from the keyboard

unsigned char rx_kbd_data_index;  //the corresponding index

unsigned char butnum;  //used to find what character was sent from the keyboard                       

unsigned char found; //a variable to show if found in alpha or number table

unsigned char flag, break_flag, prev_break_flag;  //indicats if we have found keycode in the tables

unsigned char r_index, r_buffer[32], r_ready, r_char, t_index, t_buffer[32], t_ready, t_char, num_chars, tmp_string[32];  //standard UART variables

unsigned char char_received;  //0 if have not received character yet, 1 if checking if character is a break, 2 if processing a break.       

unsigned char index, spi_str_len;  //SPI variables

unsigned char rx_req_sent;  //indicates if we have asked for data back from pc

unsigned char count_time;  //allows us to only send character to TV every 100 ms

unsigned char search_done;  //1 if user pushed return on keyboard 

unsigned char counter;  //makes sure user can only start inputting again once PC has responded to previous request

 

//UART character-ready ISR

interrupt [USART_RXC] void uart_rcv(void)

begin

      r_char=UDR;    //get a char

      //build the input string

      if (r_index == 0) begin

            r_buffer[0] = ';';

            r_index++;

      end

      if (r_char != '\r') r_buffer[r_index++]=r_char;

      else

      begin

            putchar('\n');                //use putchar to avoid overwrite

            r_buffer[r_index]=0x00;       //zero terminate

            r_ready=1;                          //signal cmd processor

            UCSRB.7=0;                          //stop rec ISR

      end

end

 

 

//UART xmit-empty ISR

interrupt [USART_DRE] void uart_send(void)

begin

      t_char = t_buffer[++t_index];

      if (t_char == 0) begin

            UCSRB.5=0; //kill isr

            t_ready=1; //transmit done

      end

      else  UDR = t_char ;     //send the char

end

 

 

//nonblocking print: initializes ISR-driven transmit. This routine merely sets up the ISR, then

//sends one character.  The ISR does all the work.  

void send_string(void) begin

      t_ready=0;

      t_index=0;

      if (t_buffer[0]>0) begin

            putchar(t_buffer[0]);

            UCSRB.5=1; 

      end

 

end

 

//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 receive_string(void) begin

      r_ready=0;

      r_index=0;

      UCSRB.7=1;

end

 

//SPI interrupt

interrupt [SPI_STC] void spi_isr(void) begin

      PORTB.4 = 1;

end

 

              

interrupt [EXT_INT0] void ext0(void) begin    

      //only allow user to input a value if the user is not waiting for PC to return previous values

      if ((!search_done) && (counter == 0)) begin

      keyboard = (PIND & 0x08)>>3;  //get keyboard bit

            //append the bit onto rx_kbd_data if it is a data bit

            if ((rx_kbd_data_index > 0) && (rx_kbd_data_index < 9)) begin

            rx_kbd_data = rx_kbd_data | (keyboard << (rx_kbd_data_index-1));

      end

            //detect the end of a keyboard code

        if (rx_kbd_data_index == 10) begin

                  //set break flag if we have also received the break code

            if (rx_kbd_data == 0xF0) begin

                  flag = CODE_DONE;

                  break_flag = 1;

            end

            else begin

                  flag = CODE_DONE;

                  break_flag = 0;

            end

      end

        else begin

            flag = WAIT;

      end

      rx_kbd_data_index++;                     

     

            switch (flag) begin

           case CODE_DONE:

                  if (!break_flag && !prev_break_flag) begin  //indicates have received a complete keyboard code

                        //can't backspace at beginning, and we can't receive more than 4 characters except \n or backspace can be the 5th.

                  if ((!((rx_kbd_data == 0x66) && (num_chars == 0))) && ((num_chars<4) || (rx_kbd_data == 0x5A) || (rx_kbd_data == 0x66))) begin

                        //check for hardcoded characters

                        switch (rx_kbd_data) begin

                              case 0x29:  sprintf(t_buffer, "%c", 32);  found = 3;  break;  //<space>

                              case 0x5A:  sprintf(t_buffer, "%c%c", 10, 13);  found = 4;  break;  //\n\r

                              case 0x66:  sprintf(t_buffer, "%c%c%c", 8, 32, 8);  found = 5;  break;  //issue a back, space, back on a backspace 

                              default: break;

                        end

                        if (!prev_break_flag) begin  //can check for characters, i.e. code is not a break code

                              for (butnum=0; butnum<26; butnum++) begin  //alphabet codes

                                          if (ascii_alpha[butnum] == rx_kbd_data)  begin

                                                found = 1;

                                                break;

                                          end

                                    end                

                                    if (found == 0) begin

                                          for (butnum = 0; butnum<10; butnum++) begin  //number codes

                                                if (ascii_number[butnum] == rx_kbd_data) begin

                                                      found = 2;

                                                      break;

                                                end

                                          end         

                                    end

                                    if (found == 1) begin  //alphabet code    

                                          num_chars++;

                                          sprintf(t_buffer,"%c",97+butnum);

                                          PORTB.4 = 0;

                                          SPDR = 65+butnum;

                                //SEND CHARACTER TO TV

                                    end

                                    else if (found == 2) begin  //number code

                                          num_chars++;

                                          sprintf(t_buffer,"%c",48+butnum);

                                          PORTB.4 = 0;

                                          SPDR = 48+butnum;

                                          //SEND NUMBER TO TV

                                    end 

                                    else if (found == 3) begin  //space

                                          num_chars++;

                                          PORTB.4 = 0;

                                          SPDR = 32;

                                          //SEND SPACE TO TV

                                    end

                                    else if (found == 4) begin  //enter

                                        num_chars = 0;

                                        search_done = 1;

                                        PORTB.4 = 0;

                                        SPDR = 0;

                                        //SEND NULL TO TV

                                    end           

                                    else if (found == 5) begin  //backspace

                                          num_chars--;

                                          PORTB.4 = 0;

                                          SPDR = 8;

                                          //SEND BACKSPACE TO TV  

                                    end

                              end        

                              //updated received_word for regular characters, space, and enter.

                              if ((found >= 1) && (found <= 4)) begin

                                    //*****only want to send this in the while loop below*****  

                                    //add the character onto received_word

                                    strcat(received_word, t_buffer);

                                    if (found == 4) begin  //for an <enter>, actually append \n\r

                                          received_word_index = received_word_index + 2;

                                    end

                                    if (found != 4) begin  //increment index for every code except for the <enter>

                                          received_word_index++;

                                    end

                              end   

                              else if (found == 5) begin  //backspace        

                                    if (received_word_index > 0) begin

                                          received_word[received_word_index-1] = '\0';

                                          received_word_index--;

                                    end

                              end

                        end  

                  end

                        //reset variables

                  t_buffer[0] = '\0';                

                  found = 0;

                  rx_kbd_data = 0x00;

                  rx_kbd_data_index = 0;

                  prev_break_flag = break_flag;

            break;                               

            case WAIT:

                  break;

      end

      end

end

   

//timer 0 compare ISR, executes every 1ms

interrupt [TIM0_COMP] void timer0(void) begin     

      count_time++;

      //send a character to the TV every 100 ms.

      if (count_time == 50) begin

            if ((spi_str_len > 0) && (index <= spi_str_len)) begin

                  PORTB.4 = 0;

                  SPDR = r_buffer[index++]; 

            end

            else begin

                  TIMSK=0;    //turn off timer 0 cmp match ISR 

                  rx_req_sent = 0;

            end

            count_time = 0;

      end

end 

 

//=================================// Initializations

void initialize(void) begin

 

      GICR = 0b01000000;  //Bit6 of GICR is INT0 - pg. 45, so set up that interrupt.

 

      //connect KBD_DATA to bit 3 of PORTD.  Connect the video resistors to bit 5 and 6.

      keyboard = 0x00;  //configure keyboard input to 0.  

      rx_kbd_data = 0x00;

      rx_kbd_data_index = 0;

      butnum = 0;

      flag = 0;

      char_received = 0;

         

      //MCUCR Interrupt Sense Control 0 bits 1/0 (ISC01 and ISC00):

      //set bottom 2 bits of MCUCR to 10 - pg. 64 meaning sample INT0 on the falling edge of KBD_CLK.

      //don't forget to connect KBD_CLK to the INT0 pin.

      MCUCR = 0b00000010;

      DDRD = 0x00;

     

      //serial communication

      UCSRB = 0x18;  //turns on serial communication

      UBRRL = 103;  //sets baud rate.

      r_ready = 0;

      t_ready = 1;

      t_buffer[0] = '\0';

      num_chars = 0; 

     

      flag = WAIT;

      break_flag = 0;

      prev_break_flag = 0;     

      found = 0;     

     

      received_word[0] = '<';

      received_word_index = 1;  //this index refers to the position of the '<' 

     

      rx_req_sent = 1;

      count_time = 0;

     

      search_done = 0;

 

      //bit 7: interrupt enable

      //bit 6: SPI enable

      //bit 5: data bit order, 0:MSB first

      //bit 4: master/slave select, 1:master

      //bit 3: SCK polarity

      //bit 2: SCK phase

      //bits 1 and 0: SCK speed; 00=CLK/4

      SPCR = 0b11010000;

  

      //bit 7: SCK

      //bit 6: MISO (master in, slave out)

      //bit 5: MOSI (master out, slave in)

      //bit 4: !SS (slave select)

      DDRB = 0b10110000;

 

      //pull up slave selected

      PORTB.4 = 1;

     

      //set up timer 0 

      TIMSK=0;    //turn off timer 0 cmp match ISR

      OCR0 = 250;       //set the compare register to 250 time ticks

      TCCR0=0b00001011; //prescalar to CLK/64 and turn on clear-on-match

 

      counter = 0;

 

      #asm ("sei");

 

end

 

void main(void) begin

      initialize();

      

      //start t_buffer with a clear screen and send it over UART

      sprintf(t_buffer, "\f");

      send_string();

      t_buffer[0] = '\0';

     

      while(1) begin

     

            if (rx_req_sent == 0) begin  //have not asked to receive something from PC and need to

                  //set up the UART receive ISR to receive something from PC

                  if (counter != 5) begin  //if we still have something to receive, receive it

                        receive_string();

                        counter++;

                  end

                  else begin

                        counter = 0;

                  end

                  rx_req_sent = 1;  //rx_req_sent gets cleared in timer0 ISR, so set it now to indicate that we sent a request       

            end

 

            if (received_word[received_word_index-1] == 13) begin  //received a carriage return, i.e. user pushed enter.

                  t_buffer[0] = '\0';

                  strcpy(t_buffer, received_word);

                  strcat(t_buffer,tmp_string);

                  t_buffer[strlen(t_buffer)] = '\n';

                  t_buffer[strlen(t_buffer)] = '\0';

                  send_string();  //send t_buffer

                  received_word[0] = '<';  //nullify received_word

                  received_word[1] = '\0';

                  received_word_index = 1;  //reset the received_word index

                  //set up the UART receive ISR to receive back the temperature

                  receive_string();

                  counter++;

            end  

                    

            //if PC has sent a string, set up transmission of string over SPI to the video MCU.

            if (r_ready) begin

                  spi_str_len = strlen(r_buffer);

              index = 0;

                  r_ready = 0;

                  TIMSK=2;    //turn on timer 0 cmp match ISR

                  search_done = 0;  //allow user to enter new search now.

            end

       

      end  //while

 

end  //main

 

Back to Main Page