#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "io.h"
#define NIL 0x00
//Absolute Zero
#define QUEUE_SIZE (32)
//Max Queue Size
//These are macros used to set, clear, or get a single bit from
an 8-bit variable.
//For example SET_BIT(temp,3); sets temp = 0x08.
#define SET_BIT(p,i) ((p) |= (1 << (i)))
#define CLR_BIT(p,i) ((p) &= ~(1 << (i)))
#define GET_BIT(p,i) ((p) & (1 << (i)))
//Interrupt service routine Settings
volatile
unsigned
int
timerFlag
=
0;//Timer
flag
//Interrupt service routine
//We enter this function ~4 times per millisecond,
//We can set a flag that signals a period has passed every period*4
times the function is entered.
//If our period is 1000 ms, then we would enter the function
1000*4 = 4000 times before transitioning to next state.
ISR(TIMER0_OVF_vect)
{
//Timer0 overflow interrupt service routine
//Set flag, use "timerFlag"
timerFlag
=
1;
}
//Configure ATMega32 Timer control registers. Correct values
can be found in ATMega32 datasheet.
void
InitTimer()
{
//Set prescaler.
TCCR0
|=
(1<<CS01);
//Enable Overflow Interrupt Enable on Timer.
TIMSK
|=
(1<<TOIE0);
//Initialize starting value of timer
TCNT0
=
0
;
}
//Conversion table from keypad input to corresponding character.
unsigned
char
conv_table[]
=
{
'1',
'2',
'3',
'A',
'4',
'5',
'6',
'B',
'7',
'8',
'9',
'C',
'*',
'0',
'#',
'D'
};
//Variables to implement our circular queue.
const
unsigned
int
MAX_QUEUE_SIZE
=
32;
unsigned
char
queue[QUEUE_SIZE]
=
{0};
//Queue of characters to output.
unsigned
int
queue_front
=
0;
//Queue front index.
unsigned
int
queue_back
=
0;
//Queue back index.
unsigned
int
num_objects
=
0;
//Number of objects in queue.
//Functionality - Push a character onto back of queue
//Parameter: takes in a single unsigned char.
//Returns: One if full else zero.
unsigned
int
push_queue(unsigned
char
c)
{
//If queue is not full.
//Increment back counter, modulate according to the max queue
size, and increase number of objects.
//Put data into correct location.
//Return not full.
//Else Return queue is full.
return
1;
}
//Functionality - Pop first character from top of queue.
//Parameter: None
//Returns: unsigned char from queue else null character.
unsigned
char
pop_queue()
{
//If queue is not empty.
//Retrieve data in correct location.
//Clear location with null character.
//Increment front counter and modulate according to the max
queue size.
//Return data.
//Else return null character to indicate empty.
return
'\0';
}
//Struct for Tasks represent a running process in our simple
real-time operating system.
typedef
struct
_task
{
//Tasks should have members that include: state, period, a measurement
of elapsed time, and a function pointer.
int
state;
//Task's current state
unsigned
long
int
period;
//Task period
unsigned
long
int
elapsedTime;
//Time elapsed since last task tick
int
(*TickFct)(int);
//Task tick function
}
task;
//Declare an array of tasks and an integer containing the number
of tasks in our system
task task1,
task2;
//Add more tasks if necessary
task
*tasks[]
=
{
&task1,
&task2
};
const
int
numTasks
=
sizeof(tasks)/sizeof(task*);
//Enumeration of states.
enum
Producer_States
{
Producer_S0
/*... Add More ...*/
};
//State machine functions take in their current state as an
argument and return the next state.
int
Producer_SMTick(int
state)
{
//State machine 1 transitions
switch
(state)
{
case
-1:
state
=
Producer_S0;
break;
case
Producer_S0:
state
=
Producer_S0;
break;
//...Add More
default:
state
=
-1;
break;
}
//State machine 1 actions
switch(state)
{
case
-1:
break;
case
Producer_S0:
break;
//...Add More
default:
break;
}
return
state;
}
//Enumeration of states.
enum
Consumer_States
{
Consumer_S0/*...*/
};
//State machine functions take in their current state as an
argument and return the next state.
int
Consumer_SMTick(int
state)
{
//State machine 2 code
return
state;
}
//Add more state machines if necessary.
//Constants used for key scaning.
const
unsigned
int
FOUR
=
4;
const
unsigned
int
EIGHT
=
8;
//Scan the keypad to see if a button is pressed.
unsigned
char
key_scan()
{
unsigned
int
i,j;
for(
i
=
FOUR;
i
<
EIGHT;
i++
)
{
// Set one column at a time to Zero Voltage.
PORTC
=
(~NIL
&
~(1<<i))
&
0xF0;
//Keep only four most significant bits.
for
(
j
=
0;
j
<
FOUR;
j++
)
{
//Scan each row checking if a button was pressed.
/* Use i and j to index into conversion table */
if(
GET_BIT(PINC,j)
==
0
){return
conv_table[(i-FOUR)+(j*FOUR)];}
}
}
return
'\0';
}
//Implement scheduler code from PES Chapter 7.
int
main()
{
//Set Data Direction Registers
DDRA
=
0xFF;//LCD
Data Signals(PORTA[0-7])
DDRB
=
0xC0;//LCD
Control Signals(PORTB[0-1]) and AVR Programmer(PINB[5-7] and
RESET)
DDRC
=
0xF0;//Keypad(PIN[0-3]
and PORTC[4-7])
DDRD
=
0xFC;//Optional
Buttons(PIND[0-1]) and LEDs(PORTD[2-3])
SREG
|=
(1<<7);//Enable
Global Interrupts
InitTimer();//Start
timer
LCD_init();//Setup
LCD
LCD_ClearScreen();//Clear
the LCD
//Timer based: 4 interrupts per ms * 50 = 50 ms
const
unsigned
long
int
P_period
=
4*50;
//Period for Producer task 1. (50 ms)
//Timer based: 4 interrupts per ms * 1000 = 1000 ms
const
unsigned
long
int
C_period
=
4*1000;
//Period for Consumer task 2.(1000 ms)
const
unsigned
long
int
GCD
=
1;//Greatest
common divisor for all tasks or smallest time unit for tasks.
task1.state
=
-1;//Task
1 initial state.
task1.period
=
P_period;//Task
1 Period.
task1.elapsedTime
=
P_period;//Task
1 current elasped time.
task1.TickFct
=
&Producer_SMTick;//Function
pointer for the tick 1.
task2.state
=
-1;//Task
2 initial state.
task2.period
=
C_period;//Task
2 Period.
task2.elapsedTime
=
C_period;//Task
2 current elasped time.
task2.TickFct
=
&Consumer_SMTick;//Function
pointer for the tick 2.
unsigned
int
i;
//Scheduler for-loop iterator
while(1)
{
//Scheduler code
for
(
i
=
0;
i
<
numTasks;
i++
)
{
if
(
tasks[i]->elapsedTime
==
tasks[i]->period
)
{
//Task is ready to tick
tasks[i]->state
=
tasks[i]->TickFct(tasks[i]->state);//Setting
next state for task
tasks[i]->elapsedTime
=
0;//Reset
the elapsed time for next tick.
}
tasks[i]->elapsedTime
+=
GCD;
}
while(!timerFlag);
timerFlag
=
0;
}
printf("%s
\n",
"Error: Program should not exit!");
return
0;
}
|