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