You are on page 1of 11

Armstrong 1

Tanner Armstrong
ECE 431
Final Lab Project Report
5/6/2015
Skywriter Final Lab Report
For my final lab project, I decided to choose the skywriter. My goal was to get the
skywriter to display a message that seemingly appeared written in midair by lighting a line of
eight LEDs at certain times.
First for of all, for the design of the skywriter, the hardware is taken care of by using a
suspended animation clock. The chip, on the other hand, is set in a pre-existing board which
contains a battery pack for two AAA batteries, a switch for which to switch between powering
the chip with the batteries or powering it with the debugger, a sixteen-pin holder for the chip, a
fourteen-pin holder for the wires coming from the suspended animation clock, a four-pin
placement for the debugger, and a red LED to determine which way the switch is thrown. The
software side of the project was much more of a challenge. In order for the skywriter to display
correctly, I had to use the Input Capture and Output Compare TPM functions of the HCS08.
There is a photocell in the suspended animation clock that detects when the oscillating wand of
the clock is halfway between the leftmost position and the center. Using the Input Capture TPM
function to detect when this photocell is active, it is possible to tell where the wand is and in
what direction it is traveling. I use this to determine when to start writing the message I want to
display. Using a pre-calculated table of delays to adjust the output compare value of the timer

Armstrong 2

channel, I am able to determine when to turn on the LEDs for a certain location in the path of the
wand. From there, it is just a simple issue of using a display array to display the correct line of
LEDs for the current position.
Secondly, the circuit of the skywriter was already pre-constructed on the circuit board I
plugged my chip into. All I had to determine is which port controlled what aspect of the
skywriter. PTAD0 is used for the input capture of the photocell and is wired to it as would be
expected. Port B, in its entirety, is used to control the LEDs on the wand. A green wire is used
to connect the four-pin debugger placement and the clock to the pin four of the chip which is
ground. Also, a black wire is used from the negative terminal of the battery pack to pin four of
the chip. A red wire is used from both the positive terminal of the battery pack and the voltage
pin of the four-pin debugger placement to provide power to pin three of the chip. Finally, the last
two brown wires connected to the four-pin debugger placement are connected to pin one and pin
two of the chip as they normally would be. The only other elements present in the circuit are a
switch for the battery pack, a red LED and a resistor for that LED. All of this is evident in the
picture provided.

Armstrong 3

Armstrong 4

Finally, the programming was definitely the most difficult part of this project. I had to
make use of several different functions in order for the skywriter to display correctly. Like all
labs we have done this year, I have a never-ending main loop.

I also have two different

interrupts that I use. One of them is the input capture of the photocell. This interrupt occurs
when a rising edge occurs on PTAD0. My second interrupt subroutine occurs when the TPM
reaches the value stored in the timer channel value register. When this interrupt occurs, the
program checks the output capture state and flows to the corresponding function. The sync
function is the initial state the output capture state starts in. This function waits until the wand
reaches the position at which the photocell is active and the wand is traveling to the left. This is
found by comparing the current time the photocell is active to the previous time the photocell
was active. The larger difference in these times shows that the wand is moving to the left. After
the sync function has determined that the wand is in the right place and moving the right
direction, it sets the two pointers to the front of the display array and delay array respectively.
The sync function then sets the next output compare value to the current time the photocell is
active plus the first value in the delay array. Then it sets the output compare state to turn the
LEDs on. After delaying for the first value in the delay array, which is 23 ms, the ledon function
turns on the LEDs according to the first value in the display array. The ledon state goes on to
advance the display array pointer, set the delay equal to how long the LEDs should be left on,
and sets the output capture state as ledoff. After delaying for as long as the LEDs are left on, the
ledoff function turns the LEDs off, advances the delay array pointer, checks to see if the delay
array pointer is at the end of the array, and then sets the delay and output capture state
accordingly. If the pointer is at the end of the array, the delay is set as 40 ms and the next output
capture state is set as sync. If the pointer is not at the end of the array, the delay is set as value in

Armstrong 5

the delay array and the next output capture state is set as ledon. The ledon and ledoff functions
alternate until you reach the end of the delay array therefore fully displaying the message. The
final function is a putmsg function that takes a message and changes it into a series of pairs of
hexadecimal values that control which LEDs to turn on and places them into the display array.
The rest of the code is a bunch of look-up tables used by the putmsg function to decode each
character in the message to be displayed.
In conclusion, the project went as planned. The only troubles I had were trying to figure
out how the output compare and input capture channels worked and how to set the delay by
adjusting the output compare value. If I were to start the project over, I would go back and
calculate my own delay values and timings so that I could get the message to scroll. I attempted
to do this already, but it turns out that the calculations of the number of columns you can write to
is off by a little bit as the wand tends to come back and write over the end of the message. If I
were to suggest an addition to the project, it would be to attempt to get it to scroll as I have run
out of time. As for the goal of the project, however, I have already accomplished it.

Armstrong 6

Armstrong 7

Appendix
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#define BUFSIZ 103
unsigned int ledstart,prevsync,currsync,deltatime,LEDduration;
unsigned const char *dispptr, *newdispptr;
unsigned const int *delayptr;
void (*ocstate)(void);
void sync(void), ledon(void), ledoff(void);
void putmsg(unsigned char *);
extern unsigned const char display[];
extern unsigned const int deltbl[];
extern unsigned const char font[];
static unsigned char dispbuf[BUFSIZ];
void main(void) {
unsigned int i;
SOPT1 = SOPT1_BKGDPE_MASK+SOPT1_RSTPE_MASK;
PTAPE = 0xfe;
PTBDD = 0xff;
ICSTRM = NV_ICSTRM;
for (i=0;i<400;i++); /* delay 2 ms, I hope */
ICSC2 = 0;

/* up speed to 8 MHz */

/* copy initial display to buffer */


for (i=0; i<BUFSIZ; i++)
dispbuf[i] = display[i];
/* init the TPM using bus clock divided by 8 */
TPMSC = 0x0b; //CPWMS = 0
TPMC0SC = 0x44; /* ch 0 is input capture rising */
TPMC0SC_CH0F = 0; /* clear any latent events */
EnableInterrupts; /* enable interrupts */
/* include your code here */
ocstate = sync; /* initial output capture state */
TPMC1V = TPMCNT; /* set first trigger to full rollover */
TPMC1SC = TPMC1SC_MS1A_MASK+TPMC1SC_CH1IE_MASK; /* oc interrupts */
putmsg("
Hello World!"); //sample putmsg call
newdispptr = dispbuf; //set front element display pointer to front of
display array

Armstrong 8
for(;;)
/* loop forever */
asm wait
}
interrupt VectorNumber_Vtpmch0 void icisr() {
TPMC0SC_CH0F = 0; //clear flag
EnableInterrupts;
prevsync = currsync;
currsync = TPMC0V; //currsync equals counter value of input capture
}
interrupt VectorNumber_Vtpmch1 void ocisr() {
ocstate(); //check output capture state
TPMC1SC_CH1F = 0; //clear flag
}
void sync() {
deltatime = currsync - prevsync;
if (deltatime > 17500)
TPMC1V += 5000;
else
{
dispptr = dispbuf; //set dispptr to pointer pointing to the new first
element to be displayed
delayptr = deltbl; //set delay pointer to front of delay array
TPMC1V = currsync + *delayptr; //output compare value equals the
current sync plus the delay
ocstate = ledon; //turn leds on
}
}
void ledon() {
PTBD = *dispptr; //turn on leds according to corresponding display array
++dispptr; //advance display pointer
if (dispptr > (dispbuf + BUFSIZ)) {
dispptr = dispbuf;
}
LEDduration = TPMC1V; //save value that started ledon state
TPMC1V += 200;
ocstate = ledoff; //set next state to ledoff
/*student code goes here, it took me 4 lines*/
}
void ledoff() {
PTBD = 0; //turn leds off
++delayptr;
if (*delayptr == 0){
TPMC1V += 40000;
//newdispptr++;
//if (newdispptr > (dispbuf + BUFSIZ)) {
//newdispptr = dispbuf;
//}
ocstate = sync;
} else{
TPMC1V += *delayptr;
ocstate = ledon;

Armstrong 9
}
/*student code goes here, it took me 11 lines*/
}
void putmsg(unsigned char *msg) {
unsigned int i,j;
for (i=0;i<BUFSIZ;i++)
dispbuf[i] = 0;
for (i=0;i<BUFSIZ && *msg;i+=2)
{
for (j=0;j<5 && i<BUFSIZ && font[(*msg-' ')*5+j];j++)
dispbuf[i++] = font[(*msg-' ')*5+j];
msg++;
}
}
unsigned const char display[BUFSIZ] =
{128,64,32,16,8,4,2,1,
/* left diag line */
0,0,0,0,0,0,0,0,0,0,0,
/* left gap */
0xfe,0x10,0x10,0x10,0xfe,0,0,
/* H */
0x1c,0x2a,0x2a,0x2a,0x18,0,0,
/* e */
0xfe,0,0,
/* l */
0xfe,0,0,
/* l */
0x1c,0x22,0x22,0x22,0x1c,0,0,
/* o */
0,0,0,0,
0xf0,0x0c,0x02,0x0c,0x10,0x0c, /* W */
0x02,0x0c,0xf0,0,0,
0x1c,0x22,0x22,0x22,0x1c,0,0,
/* o */
0x1e,0x20,0x20,0x20,0x10,0,0,
/* r */
0xfe,0,0,
/* l */
0x1c,0x22,0x22,0x22,0xfc,
/* d */
0,0,0,0,0,0,0,0,0,0,0,0,
/* right gap */
1,2,4,8,16,32,64,128};
/* right diag line */
unsigned const int deltbl[] =
{21500, /* delay from sync to leftmost column */
2014,1345,1089,942,844,773,718,675,
639,609,583,561,542,525,510,497,
485,474,464,455,446,439,432,425,
419,414,409,404,400,395,392,388,
385,382,379,377,374,372,370,369,
367,365,364,363,362,361,361,360,
360,359,359,
/* center position */
359,359,360,
360,361,361,362,363,364,365,367,
369,370,372,374,377,379,382,385,
388,392,395,400,404,409,414,419,
425,432,439,446,455,464,474,485,
497,510,525,542,561,583,609,639,
675,718,773,844,942,1089,1345,2014,
0}; /* mark end of table */
unsigned const char font[] =
{0,0,0,0,0,
0xf2,0,0,0,0,

/* space */
/* ! */

Armstrong 10
0,0,0,0,0,
0x28,0xfe,0x28,0xfe,0x28,
0x24,0x54,0xfe,0x54,0x48,
0xc4,0xc8,0x10,0x26,0x46,
0x6c,0x92,0xaa,0x44,0x0a,
0xa0,0xc0,0,0,0,
0x38,0x44,0x82,0,0,
0x82,0x44,0x38,0,0,
0x28,0x10,0x7c,0x10,0x28,
0x10,0x10,0x7c,0x10,0x10,
0x05,0x06,0,0,0,
0x10,0x10,0x10,0x10,0x10,
0x06,0x06,0,0,0,
0x04,0x08,0x10,0x20,0x40,

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

space for " */


# */
$ */
% */
& */
' */
( */
) */
* */
+ */
, */
- */
. */
/ */

0x7c,0x8a,0x92,0xa2,0x7c,
0x42,0xfe,0x02,0,0,
0x42,0x86,0x8a,0x92,0x62,
0x84,0x82,0xa2,0xd2,0x8c,
0x18,0x28,0x48,0xfe,0x08,
0xe4,0xa2,0xa2,0xa2,0x9c,
0x3c,0x52,0x92,0x92,0x0c,
0xc0,0x8e,0x90,0xa0,0xc0,
0x6c,0x92,0x92,0x92,0x6c,
0x60,0x92,0x92,0x94,0x78,
0x6c,0x6c,0,0,0,
0x65,0x66,0,0,0,
0x10,0x28,0x44,0x82,0,
0x28,0x28,0x28,0x28,0x28,
0x82,0x44,0x28,0x10,0,
0x40,0x80,0x8a,0x90,0x60,

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

0
1
2
3
4
5
6
7
8
9
:
;
<
=
>
?

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

0x4c,0x92,0x9e,0x82,0x7c,
0x7e,0x88,0x88,0x88,0x7e,
0xfe,0x92,0x92,0x92,0x6c,
0x7c,0x82,0x82,0x82,0x44,
0xfe,0x82,0x82,0x82,0x7c,
0xfe,0x92,0x92,0x92,0x82,
0xfe,0x90,0x90,0x90,0x80,
0x7c,0x82,0x82,0x92,0x5e,
0xfe,0x10,0x10,0x10,0xfe,
0x82,0xfe,0x82,0,0,
0x04,0x02,0x82,0xfc,0x80,
0xfe,0x10,0x28,0x44,0x82,
0xfe,0x02,0x02,0x02,0x02,
0xfe,0x40,0x30,0x40,0xfe,
0xfe,0x20,0x10,0x08,0xfe,
0x7c,0x82,0x82,0x82,0x7c,

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

@
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O

*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

0xfe,0x90,0x90,0x90,0x60,
0x7c,0x82,0x8a,0x84,0x7a,
0xfe,0x90,0x98,0x94,0x62,
0x62,0x92,0x92,0x92,0x8c,
0x80,0x80,0xfe,0x80,0x80,
0xfc,0x02,0x02,0x02,0xfc,
0xf8,0x04,0x02,0x04,0xf8,
0xfc,0x02,0x0c,0x02,0xfc,

/*
/*
/*
/*
/*
/*
/*
/*

P
Q
R
S
T
U
V
W

*/
*/
*/
*/
*/
*/
*/
*/

Armstrong 11
0xc6,0x28,0x10,0x28,0xc6,
0xe0,0x10,0x0e,0x10,0xe0,
0x86,0x8a,0x92,0xa2,0xc2,
0xfe,0x82,0x82,0,0,
0,0,0,0,0,
0x82,0x82,0xfe,0,0,
0x20,0x40,0x80,0x40,0x20,
0x01,0x01,0x01,0x01,0x01,

/*
/*
/*
/*

0x60,0xa0,0,0,0,
0x1c,0x22,0x22,0x14,0x3e,
0xfe,0x14,0x22,0x22,0x1c,
0x1c,0x22,0x22,0x22,0,
0x1c,0x22,0x22,0x14,0xfe,
0x1c,0x2a,0x2a,0x12,0,
0x10,0x7e,0x90,0x80,0x40,
0x10,0x2a,0x2a,0x2a,0x3c,
0xfe,0x10,0x20,0x20,0x1e,
0x22,0xbe,0x02,0,0,
0x02,0x01,0x21,0xbe,0,
0xfe,0x08,0x14,0x22,0,
0x82,0xfe,0x02,0,0,
0x3e,0x20,0x1e,0x20,0x1e,
0x3e,0x10,0x20,0x20,0x1e,
0x1c,0x22,0x22,0x22,0x1c,

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

`
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o

0x3f,0x24,0x24,0x24,0x18,
0x18,0x24,0x24,0x14,0x3f,
0x3e,0x10,0x20,0x20,0x10,
0x12,0x2a,0x2a,0x2a,0x04,
0x20,0xfc,0x22,0x02,0x04,
0x3c,0x02,0x02,0x04,0x3e,
0x38,0x04,0x02,0x04,0x38,
0x3c,0x02,0x0c,0x02,0x3c,
0x22,0x14,0x08,0x14,0x22,
0x38,0x05,0x05,0x05,0x3e,
0x22,0x26,0x2a,0x32,0x22,
0x10,0x6c,0x82,0,0,
0xfe,0,0,0,0,
0x82,0x6c,0x10,0,0,
0x10,0x10,0x54,0x38,0x10,
0x10,0x38,0x54,0x10,0x10
};

/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*
/*

p */
q */
r */
s */
t */
u */
v */
w */
x */
y */
z */
{ */
| */
} */
-> */
<- */

/* end of source file */

X
Y
Z
[

*/
*/
*/
*/

/* ] */
/* ^ */
/* _ */
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/
*/

You might also like