LED Display Driver Module Code
In order to make the scoreboard operation as transparent and readable as possible in the main game module code, a driver module was written to drive the LED display. This module is documented in the header file and provides functions to the main module to do the following:
- Initialize the Scoreboard
- Set the timer value anywhere from 00 to 99
- Decrement the timer
- Increment the player and computer scores
- Update the display either periodically, or immediately.
The actual files for the code are linked below:
Header File
/* Make sure this is imported only once */
#ifndef SCOREBOARDH
#define SCOREBOARDH
/* NOTE: This module controls the use of ports T3-T7 on the C32.
Before using any of the functions provided by the module,
InitializeScoreboard() must be called. This module initializes
the ME218 timer modules to a 1ms clock tick when used.
*/
/* #define TESTMODE */ /* Comment this line out to use it as a module with no main function */
#define INITIAL_TIME 60 /* The initial time to display on the scoreboard */
/* Public Functions */
void InitializeScoreboard(void); /* Initializes the input and output pins on the scoreboard */
/* and resets the scores to 0 and timer to a default time, defined above*/
int DecrementScoreboardTime(void); /* Subtracts 1 from the Timer. Returns a 1 if Time is expired, 0 otherwise */
int IncrementPlayerScore(void); /* Adds 1 to the Player score. Returns a 1 if maxed out, 0 otherwise */
int IncrementComputerScore(void); /* Adds 1 to the COmputer score. Returns a 1 if maxed out, 0 otherwise */
void SetScoreboardTime(char time[]); /* Input a new time as a 2 character string of digits e.g. "60" */
void updatedisplay(void); /* Force refreshes the 7 segment displays */
void updatedisplayfractionally(void); /* Refreshes the 7 segment display every 10 times it's called */
#endif
.C File
/* #includes */
#include <stdio.h>
#include <ME218_C32.h>
#include <timers12.h> /* used for TMRS12_X functions */
#include "scoreboard.h"
/* #defines to make the code more readable */
#define CLOCKBITHI BIT3HI
#define CLOCKBITLO BIT3LO
#define COMPSCOREBITHI BIT4HI
#define COMPSCOREBITLO BIT4LO
#define TIMER1BITHI BIT5HI
#define TIMER1BITLO BIT5LO
#define TIMER10BITHI BIT6HI
#define TIMER10BITLO BIT6LO
#define USERSCOREBITHI BIT7HI
#define USERSCOREBITLO BIT7LO
/* #define string indices such that '1572' indicates time of 57 and scores: user: 1, comp: 2 */
#define COMP 3 /* Computer Score */
#define TIMER1 2 /* 1s digit of timer */
#define TIMER10 1 /* 10s digit of timer */
#define USER 0 /* User score */
/* #defines for what test function to run when running the scoreboard independently */
#define NONE 0
#define CYCLE 1
#define TESTSIG 2
#define SCORETEST 3
/* Local Function Prototypes */
static void initialize(void);
static void pulse_clock(void);
static void wait_milliseconds(int milliseconds);
static void load_shift_register(char *stringAtoH[]);
static void display(char *input);
static void cycle_test(void);
static void SetUserScore(char input);
static void SetComputerScore(char input);
/* Local Variables */
static char scoreboard[] = " \0"; /* initialize the module variable 'scoreboard' to track its current contents */
/*********************************/
/******** PUBLIC FUNCTIONS *******/
/*********************************/
/***** Main() *******/
/* This function is for use only in testing purposes, and can be omitted by #define in the header file */
#ifdef TESTMODE
void main( void) {
int foolwhile = 5;
int n;
int mode = SCORETEST;
int expired = FALSE;
initialize();
if(mode == TESTSIG) {
while(foolwhile) {
display("2222");
for (n=0; n<50; n++);
}
}
if(mode == SCORETEST) {
while(foolwhile) {
/* test the initialization and decrementing functions */
printf("Initializing Scoreboard...\r\n");
InitializeScoreboard();
wait_milliseconds(2000);
printf("Now decrement the timer until it expires\r\n");
printf("Initial Timer value is %c%c\r\n",scoreboard[TIMER10],scoreboard[TIMER1]);
/* make sure the timer expired flag works */
while (expired == FALSE) {
wait_milliseconds(300);
expired = DecrementScoreboardTime();
printf("Timer value is %c%c\r\n",scoreboard[TIMER10],scoreboard[TIMER1]);
}
printf("Timer Expired!!\r\n");
/* Test the score incrementing function */
expired = FALSE;
printf("Time to increment the player's score\r\n");
while (expired == FALSE) {
expired = IncrementPlayerScore();
printf("Player Score is %c\r\n",scoreboard[USER]);
wait_milliseconds(1000);
}
}
}
if(mode == CYCLE) cycle_test();
return;
}
#endif
/***** InitializeScoreboard() *******/
/* Sets the output pins for the C32, sets player and computer scores to 0 */
/* and sets the timer to the value given in the header file. */
void InitializeScoreboard(void) {
initialize();
SetUserScore('0');
SetComputerScore('0');
SetScoreboardTime("INITIAL_TIME");
updatedisplay();
return;
}
/***** SetScoreboardTime() *******/
/* Set the scoreboard timer to the time given as an input string of two */
/* digits. E.G. "60" or "99" or "00" */
void SetScoreboardTime(char time[]) {
scoreboard[TIMER1] = time[1]; /* Set 1s digit of timer */
scoreboard[TIMER10] = time[0]; /* Set 10s digit of timer */
updatedisplay(); /* Write to the display */
return;
}
/***** IncrementPlayerScore() *******/
/* Adds one to the player score and returns a 1 if it is maxed out. */
/* If the score is still in an ok range (i.e. is below 9) it returns 0 */
int IncrementPlayerScore(void) {
int maxedout = FALSE;
/* Use a switch case to handle 'incrementing' a character value */
switch (scoreboard[USER]) {
case '0' : SetUserScore('1'); break;
case '1' : SetUserScore('2'); break;
case '2' : SetUserScore('3'); break;
case '3' : SetUserScore('4'); break;
case '4' : SetUserScore('5'); break;
case '5' : SetUserScore('6'); break;
case '6' : SetUserScore('7'); break;
case '7' : SetUserScore('8'); break;
case '8' : SetUserScore('9'); maxedout=TRUE; printf("Player Score maxed out\r\n"); break;
default : printf("Invalid Player Score value\r\n"); break;
}
updatedisplay();
return maxedout;
}
/***** IncrementComputerScore() *******/
/* Adds one to the computer score and returns a 1 if it is maxed out. */
/* If the score is still in an ok range (i.e. is below 9) it returns 0 */
int IncrementComputerScore(void) {
int maxedout = FALSE;
/* Use a switch case to handle 'incrementing' a character value */
switch (scoreboard[COMP]) {
case '0' : SetComputerScore('1'); break;
case '1' : SetComputerScore('2'); break;
case '2' : SetComputerScore('3'); break;
case '3' : SetComputerScore('4'); break;
case '4' : SetComputerScore('5'); break;
case '5' : SetComputerScore('6'); break;
case '6' : SetComputerScore('7'); break;
case '7' : SetComputerScore('8'); break;
case '8' : SetComputerScore('9'); maxedout=TRUE; printf("Comp Score maxed out\r\n"); break;
default : printf("Invalid Comp Score value\r\n"); break;
}
updatedisplay();
return maxedout;
}
/***** DecrementScoreboardTime() *******/
/* Subtracts one from the current timer and returns TRUE if the timer is expired */int DecrementScoreboardTime(void) {
int timerexpired = FALSE;
/* Use switch cases to decrement the timer value stored as a character */
switch (scoreboard[TIMER1]) {
case '0' :
scoreboard[TIMER1] = '9';
switch (scoreboard[TIMER10]) {
/* handle rollover into the 10s digit */
case '0' : scoreboard[TIMER1] = '0'; SetComputerScore('1'); timerexpired=TRUE; ; break;
case '1' : scoreboard[TIMER10] = '0'; break;
case '2' : scoreboard[TIMER10] = '1'; break;
case '3' : scoreboard[TIMER10] = '2'; break;
case '4' : scoreboard[TIMER10] = '3'; break;
case '5' : scoreboard[TIMER10] = '4'; break;
case '6' : scoreboard[TIMER10] = '5'; break;
case '7' : scoreboard[TIMER10] = '6'; break;
case '8' : scoreboard[TIMER10] = '7'; break;
case '9' : scoreboard[TIMER10] = '8'; break;
default : printf("Invalid Value Exists in Timer 10 spot\r\n"); break;
}
break;
case '1' : scoreboard[TIMER1] = '0'; break;
case '2' : scoreboard[TIMER1] = '1'; break;
case '3' : scoreboard[TIMER1] = '2'; break;
case '4' : scoreboard[TIMER1] = '3'; break;
case '5' : scoreboard[TIMER1] = '4'; break;
case '6' : scoreboard[TIMER1] = '5'; break;
case '7' : scoreboard[TIMER1] = '6'; break;
case '8' : scoreboard[TIMER1] = '7'; break;
case '9' : scoreboard[TIMER1] = '8'; break;
default : printf("Invalid Value Exists in Timer 1 spot\r\n"); break;
}
updatedisplay();
return timerexpired;
}
/***** UpdateDisplay() *******/
/* Force the display to update to the contents in memory */
void updatedisplay(void) {
display(scoreboard);
return;
}
/***** UpdateDisplayFractionally() *******/
/* To prevent updating the display from slowing the E&S framework */
/* call this function to only occasionally update it (10% of the time) */
/* when including this function in a display loop. This is recommended */
/* as otherwise the display may drift due to shift register problems */
void updatedisplayfractionally(void) {
static int n = 0;
n++;
if (n % 10 == 0) {
display(scoreboard);
}
return;
}
/**********************************/
/******** PRIVATE FUNCTIONS *******/
/**********************************/
/***** Initialize() *******/
/* Initializes the outputs on the C32 */
static void initialize(void)
{
// Set Ports T0-1 to outputs
DDRT = DDRT | (CLOCKBITHI | COMPSCOREBITHI | TIMER1BITHI | TIMER10BITHI | USERSCOREBITHI);
return;
}
/***** pulse_clock() *******/
/* briefly pulse the clock high */
static void pulse_clock(void)
{
int n = 0;
for (n=0; n<50; n++);
PTT = PTT | CLOCKBITHI; /* Rising edge on the clock */
for (n=0; n<50; n++); /* Waste some time to let the pulse go through */
PTT = PTT & CLOCKBITLO; /* Falling edge on the clock */
for (n=0; n<10; n++);
return;
}
/***** wait_milliseconds() *******/
/* Convenient, blocking function to wait during initialization or testing sequences */
static void wait_milliseconds(int milliseconds)
{
int time_started;
TMRS12_Init(TMRS12_RATE_1MS); /* ensure timer module is started and the tick is right */
time_started = TMRS12_GetTime();
while (TMRS12_GetTime()-time_started<=milliseconds)
{ /* wait for the count to reach the critical value */
}
return;
}
/***** display() *******/
/* Uses a switch case to parse an string of 4 input characters into patterns */
/* for display on a 7-segment LED display. It then calls the function */
/* load_shift_register to write the sequences to the scoreboard. */
static void display(char *input)
{
char *output[4];
int i;
/* Repeat the matching for each input character */
for (i=0; i<4; i++) {
switch (input[i]) {
/* Map characters to appropriate patterns of segments. 1s are on, 0s are off */
/* Sequences correspond to the standard A,B,C,D,E,F,G,DP labelling of 7-segment */
/* displays. */
case '0' : output[i] = "11111100"; break;
case '1' : output[i] = "01100000"; break;
case '2' : output[i] = "11011010"; break;
case '3' : output[i] = "11110010"; break;
case '4' : output[i] = "01100110"; break;
case '5' : output[i] = "10110110"; break;
case '6' : output[i] = "10111110"; break;
case '7' : output[i] = "11100000"; break;
case '8' : output[i] = "11111110"; break;
case '9' : output[i] = "11110110"; break;
case 'A' : output[i] = "11101110"; break;
case 'B' : output[i] = "00111110"; break;
case 'C' : output[i] = "10011100"; break;
case 'D' : output[i] = "01111010"; break;
case 'E' : output[i] = "10011110"; break;
case 'F' : output[i] = "10001110"; break;
case 'H' : output[i] = "01101110"; break;
case 'I' : output[i] = "01100000"; break;
case 'O' : output[i] = "11111100"; break;
case 'S' : output[i] = "10110110"; break;
case 'L' : output[i] = "00011100"; break;
case 'P' : output[i] = "11001110"; break;
case 'Y' : output[i] = "01110110"; break;
case ' ' : output[i] = "00000000"; break;
/* Debugging cases */
case 'a' : output[i] = "10000000"; printf("a\r\n"); break;
case 'b' : output[i] = "01000000"; printf("b\r\n"); break;
case 'c' : output[i] = "00100000"; printf("c\r\n"); break;
case 'd' : output[i] = "00010000"; printf("d\r\n"); break;
case 'e' : output[i] = "00001000"; printf("e\r\n"); break;
case 'f' : output[i] = "00000100"; printf("f\r\n"); break;
case 'g' : output[i] = "00000010"; printf("g\r\n"); break;
case 'p' : output[i] = "00000001"; printf("dp\r\n"); break;
/* Default Case */
default : output[i] = "00000000"; break;
}
}
load_shift_register(output); /* load the sequences to the shift register */
return;
}
/***** load_shift_register() *******/
/* Loads the output of the display function to the shift registers */
static void load_shift_register(char *displayinfo[])
{
int i;
/* clear out what's in the register by writing a bunch of HIs to turn it all off*/
for(i=1; i<=8; i++) {
PTT = PTT & (COMPSCOREBITLO & TIMER1BITLO & TIMER10BITLO & USERSCOREBITLO);
pulse_clock();
}
/* Load the new display, changing a single segment across all */
/* four displays, then pulsing the shared clock to set it */
/* and move on to the next segment */
for(i=7; i>=0; i--) {
if (displayinfo[USER][i] == '1') PTT = PTT | (USERSCOREBITHI);
if (displayinfo[USER][i] == '0') PTT = PTT & (USERSCOREBITLO);
if (displayinfo[COMP][i] == '1') PTT = PTT | (COMPSCOREBITHI);
if (displayinfo[COMP][i] == '0') PTT = PTT & (COMPSCOREBITLO);
if (displayinfo[TIMER1][i] == '1') PTT = PTT | (TIMER1BITHI);
if (displayinfo[TIMER1][i] == '0') PTT = PTT & (TIMER1BITLO);
if (displayinfo[TIMER10][i] == '1') PTT = PTT | (TIMER10BITHI);
if (displayinfo[TIMER10][i] == '0') PTT = PTT & (TIMER10BITLO);
pulse_clock();
}
return;
}
/***** Cycle_test() *******/
/* Displays a looping message on the scoreboard */
static void cycle_test(void) {
/* Display a never ending loop of "HI 218 PEOPLE" */
int foolwhile = 5;
while(foolwhile) {
display(" H"); wait_milliseconds(600);
display(" HI"); wait_milliseconds(600);
display(" HI "); wait_milliseconds(600);
display("HI 2"); wait_milliseconds(600);
display("I 21"); wait_milliseconds(600);
display(" 218"); wait_milliseconds(600);
display("218 "); wait_milliseconds(600);
display("18 P"); wait_milliseconds(600);
display("8 PE"); wait_milliseconds(600);
display(" PEO"); wait_milliseconds(600);
display("PEOP"); wait_milliseconds(600);
display("EOPL"); wait_milliseconds(600);
display("OPLE"); wait_milliseconds(600);
display("PLE "); wait_milliseconds(600);
display("LE "); wait_milliseconds(600);
display("E "); wait_milliseconds(600);
display(" "); wait_milliseconds(600);
}
}
/***** SetUserScore() *******/
/* Allows the User Score to be set to any value. Used for initalization */
static void SetUserScore(char input) {
scoreboard[USER] = input;
return;
}
/***** SetComputerScore() *******/
/* Allows the Computer Score to be set to any value. Used for initalization */
static void SetComputerScore(char input) {
scoreboard[COMP] = input;
return;
}