Back to main page

#include <util/delay.h>
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>

// for easier reading
#define begin {
#define end }

// time for task1, every 50 ms
#define t1 50

// State machine state names
// Taken from debounceGCC644.c test file from lab 2 of ECE 4760
#define NoPush 1
#define MaybePush 2
#define Pushed 3
#define MaybeNoPush 4

// the key read in from the key and the key read in last time
char key, lastkey;

// the button number of the keypad, based on key
char butnum;

// Flag whether a button is pushed, and current state of the
// button debounce state machine
char PushFlag, PushState;

// table of keys corresponding to the 12 buttons of the keypad
char keytbl[12] = {0xaf,
0xdd, 0xbd, 0x7d,
0xdb, 0xbb, 0x7b,
0xd7, 0xb7, 0x77,
0xcf, 0x6f};

// stores the letters selected by user to be displayed
char lettbl[30];

// position in the array lettbl for displaying purposes
volatile char letcount;

// counter for adding letters to lettbl
char letTotal;

// 0 means currently displaying message
// 1 means currently reading keypad from user
char state;

// 2 means butnum is multiplied by 10
// 1 means do not multiply butnum by 10
// this is for 2 digit inputs, reading one digit at a time
char dec;

// keeps track of whether the button number is used when pushed
// so that we do not reuse the same button number unless it is pushed
// again
char taskDone;

// which color to display in
// 1, 2, and 3 mean a single color of blue, green, or red
// 4, 5, and 6 means each letter is a different color than
// its adjacent letters
volatile char colormode;

// colormodeEnable if one means the input from the keypad is the color
// mode choice, when 0 input from the keypad is for letter choice
char colormodeEnable;

// for displaying purposes, each letter is represented by 6 bytes
// letPos keeps track of which byte is displayed next
volatile char letPos;

// timer for task 1, every 50 ms
volatile char time1;

void initialize(void);
void task1(void);

// a two dimensional array containing all 26 letters of the alphabet
// in capitalized form and a space. This array is based on the one
// provided in video_codeGCC644.c for lab 4 of ECE 4760. It has been
// inverted and rotated to make displaying easier in this case.
char letters[27][6] = {
//Space
{0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111,
0b11111111},
//A
{0b11111111,
0b10000001,
0b01110111,
0b01110111,
0b01110111,
0b10000001},
//B
{0b11111111,
0b10010011,
0b01101101,
0b01101101,
0b01101101,
0b00000001},
//C
{0b11111111,
0b10111011,
0b01111101,
0b01111101,
0b01111101,
0b10000011},
//D
{0b11111111,
0b10000011,
0b01111101,
0b01111101,
0b01111101,
0b00000001},
//E
{0b11111111,
0b01101101,
0b01101101,
0b01101101,
0b01101101,
0b00000001},
//F
{0b11111111,
0b01101111,
0b01101111,
0b01101111,
0b01101111,
0b00000001},
//G
{0b11111111,
0b10100011,
0b01101101,
0b01111101,
0b01111101,
0b10000011},
//H
{0b11111111,
0b00000001,
0b11101111,
0b11101111,
0b11101111,
0b00000001},
//I
{0b11111111,
0b11111111,
0b01111101,
0b00000001,
0b01111101,
0b11111111},
//J
{0b11111111,
0b01111111,
0b00000011,
0b01111101,
0b11111101,
0b11111011},
//K
{0b11111111,
0b01111101,
0b10111011,
0b11010111,
0b11101111,
0b00000001},
//L
{0b11111111,
0b11111101,
0b11111101,
0b11111101,
0b11111101,
0b00000001},
//M
{0b11111111,
0b00000001,
0b10111111,
0b11001111,
0b10111111,
0b00000001},
//N
{0b11111111,
0b00000001,
0b11110111,
0b11101111,
0b11011111,
0b00000001},
//O
{0b11111111,
0b10000011,
0b01111101,
0b01111101,
0b01111101,
0b10000011},
//P
{0b11111111,
0b10011111,
0b01101111,
0b01101111,
0b01101111,
0b00000001},
//Q
{0b11111111,
0b10000101,
0b01111011,
0b01110101,
0b01111101,
0b10000011},
//R
{0b11111111,
0b10011101,
0b01101011,
0b01100111,
0b01101111,
0b00000001},
//S
{0b11111111,
0b01110011,
0b01101101,
0b01101101,
0b01101101,
0b10011101},
//T
{0b11111111,
0b01111111,
0b01111111,
0b00000001,
0b01111111,
0b01111111},
//U
{0b11111111,
0b00000011,
0b11111101,
0b11111101,
0b11111101,
0b00000011},
//V
{0b11111111,
0b00000111,
0b11111011,
0b11111101,
0b11111011,
0b00000111},
//W
{0b11111111,
0b00000011,
0b11111101,
0b11100011,
0b11111101,
0b00000011},
//X
{0b11111111,
0b00111001,
0b11010111,
0b11101111,
0b11010111,
0b00111001},
//Y
{0b11111111,
0b00011111,
0b11101111,
0b11110001,
0b11101111,
0b00011111},
//Z
{0b11111111,
0b00111101,
0b01011101,
0b01101101,
0b01110101,
0b01111001}
};

//*********************************************************
// The main function
int main(void)
begin
// initializes the program
initialize();

// infinite loop
while (1)
begin
// if 50 ms have passed call task 1
if (time1 == 0) task1();

// if we are in display state and the timer0 ISR
// is not enabled, enable it
if ((state == 0) && (TIMSK0 != 2))
begin
// enable timer0 ISR
TIMSK0 = (1<<OCIE0A);
end // end if state == 0
// else if we are in the input state and the timer0
// ISR is not yet disabled
else if ((state == 1) && (TIMSK0 != 0))
begin
// disable timer0
TIMSK0 = 0;
// reset counter for lettbl input
letTotal = 0;
// reset lettbl to being all spaces
for (int m = 0; m < 30; m++)
begin
lettbl[m] = 0;
end // end for
end // end else if
end // end while(1)
end // end main

//*********************************************************
// timer0 ISR for displaying message, blinking LEDs
ISR (TIMER0_COMPA_vect)
begin
// display a letter on the LEDs, each if corresponds to
// a different color, colormode 1-3 all letters same color,
// colormode 4-6 each letter is a different color
if ((colormode == 1) || (colormode == 4))
begin
PORTA = letters[lettbl[letcount]][letPos];
PORTB = 0xff;
PORTC = 0xff;
end // end if mode 1 or 4
else if ((colormode == 2) || (colormode == 5))
begin
PORTA = 0xff;
PORTB = letters[lettbl[letcount]][letPos];
PORTC = 0xff;
end // end if mode 2 or 5
else if ((colormode == 3) || (colormode == 6))
begin
PORTA = 0xff;
PORTB = 0xff;
PORTC = letters[lettbl[letcount]][letPos];
end // end if mode 3 or 6

// increment letPos, to display next byte on LEDs
letPos++;
// if letPos is the maximum position
if (letPos == 6)
begin
// reset letPos for next letter
letPos = 0;
// increment to next letter in lettbl
letcount--;
// if letcount is maximum value for lettbl index
if (letcount == 255)
begin
// reset letcount to display message again
letcount = 29;
end // end if letcount == 0
// if colormode is in the changing letter colors mode
if (colormode > 3)
begin
// change color for next letter
colormode++;
end // end if colormode is in changing color mode
// if colormode is beyond the max colormode value
if (colormode == 7)
begin
// reset to first color in changing color mode
colormode = 4;
end // end if colormode == 7
end // end if letPos == 6
end // end timer0 ISR

//*********************************************************
// timer2 ISR, times 1 ms
ISR (TIMER2_COMPA_vect)
begin
// if time is not 0 decrement it
if(time1 > 0) time1--;
end // end timer2 ISR

//*********************************************************
// task for reading from keypad and setting up lettbl for
// displaying
void task1(void)
begin
// reset 50 ms timer for task1
time1 = t1;
// read upper half of key
_delay_us(5);
DDRD = 0x1f;
PORTD = 0xe0;
_delay_us(5);
key = PIND;
// read lower half of key
DDRD = 0xe0;
PORTD = 0x1f;
_delay_us(5);
key = key | PIND;

// debounce state machine, taken and modified from
// debounceGCC644.c test file from lab 2 of ECE 4760
switch (PushState)
begin
// if state is that there is no push
case NoPush:
// if key is a equal to the last key, maybe pushed state
if ((key & lastkey) && (key != 0xff)) PushState=MaybePush;
// else if key is not equal to last key, still no push state
else PushState=NoPush;
break;
// if state is that there may be a push
case MaybePush:
// if key is equal to last key
if ((key & lastkey) && (key != 0xff))
begin
// the key is pushed, pushed state
PushState=Pushed;
// flag saying key is pushed
PushFlag=1;
end // end if
// else the key is not pushed, no push state
else PushState=NoPush;
break;
// if the key is pushed
case Pushed:
// if the key is equal to lastkey, still pushed, pushed state
if ((key & lastkey) && (key != 0xff)) PushState=Pushed;
// else key may not be pushed, maybe no push state
else PushState=MaybeNoPush;
break;
// if the key may not be pushed
case MaybeNoPush:
// if key equals last key, key is pushed, pushed state
if ((key & lastkey) && (key != 0xff)) PushState=Pushed;
// else key is not pushed
else
begin
// key is not pushed, no push state
PushState=NoPush;
// flag saying key is not pushed
PushFlag=0;
end // end if
break;
end // end switch
// lastkey equals the current key to be compared with the next key
// in the state machine
lastkey = key;

if (PushFlag == 0)
begin
taskDone = 0;
end

// if the key is an actual key and it is pushed
if ((key != 0xff) && (PushFlag == 1) && (taskDone == 0))
begin
// for loop compares key to the keytbl to determine
// the button number
for (butnum=0; butnum<12; butnum++)
begin
// if key matches the current indexed value from
// keytbl, stop the for loop, saves butnum
if (keytbl[butnum]==key) break;
end // end for
end // end if PushFlag
// if the key does not match, then butnum is set to 12
// meaning no actual button is pushed
else butnum=12;

// if the state is 1, meaing we are currently in message input state
if ((state == 1) && (PushFlag == 1) && (taskDone == 0))
begin
taskDone = 1;
// if we are not currently reading input for the color mode
if (colormodeEnable == 0)
begin
// if we are currently reading the first digit of a 2 digit
// input and the input is within range and we have not filled
// the letter table
if ((dec == 2) && (butnum < 3) && (letTotal < 30))
begin
// put the tens digit into the current indexed position
// of lettbl
lettbl[letTotal] = 10 * butnum;
// decrement dec, corresponding to ones digit
dec--;
end // end if reading tens digit
// else if reading tens digit and the lettbl is not full,
// but the button chosen is outside the tens digit range
else if ((dec == 2) && (butnum < 10) && (letTotal <30))
begin
// decrment dec, corresponding to ones digit now
dec--;
end // end else if butnum is out of tens digit range
// else if we are reading the ones digit and the lettbl
// is not full
else if ((dec == 1) && (butnum < 10) && (letTotal < 30))
begin
// put the ones digit in the current index of lettbl
lettbl[letTotal] = lettbl[letTotal] + butnum;
// check if value is with in letters array range
if (lettbl[letTotal] > 26)
begin
lettbl[letTotal] = 0;
end
// we are reading input for the tens digit
// for the next letter
dec++;
// we are storing the next letter in the next
// position in lettbl
letTotal++;
end // end if inputting ones digit
// if the reset key is pushed, we go to display mode
else if (butnum == 10)
begin
// program state is now in display mode
state = 0;
end // end if butnum == 10
// if the talk key is pressed
else if (butnum == 11)
begin
// next input is now for the color mode
colormodeEnable = 1;
end // end if butnum == 11
end // end if colormodeEnable == 0
// else colormodeEnable == 1
else if (colormodeEnable == 1)
begin
// if one of the 6 modes is chosen
if ((butnum < 7) && (butnum > 0))
begin
// the color mode is set
colormode = butnum;
// color mode is read, so we go back
// to letter input state
colormodeEnable = 0;
end // end if mode is chosen
end // end else if colormodeEnable == 1
end // end state == 1
// else if we are in the display state
else if ((state == 0) && (PushFlag == 1) && (taskDone == 0))
begin
taskDone = 1;
// if the reset button is pushed
if (butnum == 10)
begin
// go into input state
state = 1;
end // end if butnum == 10
end // end else if state == 0
end // end task 1

//*********************************************************
// initialize the program
void initialize(void)
begin
// set timer0 ISR to time the blinking of the LEDs
// to display the message
OCR0A = 157;
TIMSK0= (1<<OCIE0A);
TCCR0B= 3;
TCCR0A= (1<<WGM01);

// set timer2 ISR to time 1 ms
OCR2A = 249;
TIMSK2= (1<<OCIE0A);
TCCR2B= 3;
TCCR2A= (1<<WGM01);

// PORTs A, B, and C are outputs
DDRA = 0xff;
DDRB = 0xff;
DDRC = 0xff;

// set task 1 timer to time 50 ms
time1 = t1;

// initialize statemachine to no push
PushState = NoPush;
// initialize flag to no push
PushFlag = 0;
// initialize key to no push
key = 0xff;
// initialize last key to no push
lastkey = 0xff;
// initialize butnum to no push
butnum = 12;
// initialize dec to reading for tens digit
dec = 2;
// intialize taskDone to task not yet done
taskDone = 0;

// initialize lettbl to display the message "MESSAGE"
lettbl[0] = 13;
lettbl[1] = 5;
lettbl[2] = 19;
lettbl[3] = 19;
lettbl[4] = 1;
lettbl[5] = 7;
lettbl[6] = 5;

// initialize the rest of lettbl not displaying MESSAGE
// to be spaces
for (int i = 7; i < 30; i++)
begin
lettbl[i] = 0;
end

/* lettbl[0] = 1;
lettbl[1] = 2;
lettbl[2] = 3;
lettbl[3] = 4;
lettbl[4] = 5;
lettbl[5] = 6;
lettbl[6] = 7;
lettbl[7] = 8;
lettbl[8] = 9;
lettbl[9] = 10;
lettbl[10] = 11;
lettbl[11] = 12;
lettbl[12] = 13;
lettbl[13] = 14;
lettbl[14] = 15;
lettbl[15] = 16;
lettbl[16] = 17;
lettbl[17] = 18;
lettbl[18] = 19;
lettbl[19] = 20;
lettbl[20] = 21;
lettbl[21] = 22;
lettbl[22] = 23;
lettbl[23] = 24;
lettbl[24] = 25;
lettbl[25] = 26;
lettbl[26] = 1;
lettbl[27] = 2;
lettbl[28] = 3;
lettbl[29] = 4;*/

// initialize the counter for displaying lettbl to 0
letcount = 30;
// initialize letTotal to the number of letters in MESSAGE
letTotal = 7;

// initialize the program state to display MESSAGE
state = 0;

// intialize the color mode to be a single color
colormode = 4;
// initialize the color mode enable to be 0, meaning not
// reading the color mode as input yet
colormodeEnable = 0;

// initialize the letter postion to 0
letPos = 0;

// crank up the ISRs
sei();
end // end initialize

 

Back to main page