Chapter 13.3: Straits -- Status Display
"Okay, guys, I have to focus on Julia's computer, so let's all work on our keyboard controllers on our own for a while."
"Focus on your girlfriend, huh?" Tanya was apparently feeling a little catty.
"So you're finally owning up to it!", Suzanne pouted. "What did it take?"
"Oh, shutup, Suzanne," Mike grumbled. "I, for one, don't want to hear about it."
Wallace also complained. "Leading us on, and then jumping ship for your girlfriend?"
Winston admonished, "We can handle this. Bob and Jennifer almost have it worked out, anyway."
Jennifer shook her head. "It's time for us all to work on our own for a bit. That's what we're here for."
"Should you just abandon everyone for me?" Julia asked.
"I'm not abandoning anybody, and Jennifer's right."
Doctor Brown just watched in amusement.
There was more grumbling, and some of the members of the group parked themselves where they could watch as I used scratch paper to show Julia how the display translation tables would be put together. But I ignored them and proceeded to recreate a diagram from Saturday.
"Others have theirs wired up differently, but the way you ended up wiring yours is the same order as the diagram I drew. Bottom left is the high bit, and decimal is the low bit. Let's name those."
"Name them?"
"Give them names in the program."
"Okay."
"We'll call the bottom left segment BLS, and it will be binary 10000000."
"You and Dad both told me about converting to hexadecimal four bits at a time, so that's 1000 and 0000, which comes out as $80?"
I gave her a thumbs-up and scrawled
BLS EQU $80 ; 1000 0000"Instead of BLS, BLT would not be a good name?"
Julia and I chuckled at her joke, and so did the students who were listening.
"No?"
"Well, I was thinking S for segment, but why not? T for the last letter of 'bit'. How about the rest?"
"Like this?" Julia wrote out code, intuiting the permutations from the line I'd written:
BLT EQU $80 ; 1000 0000"Yep."
BT EQU $40 ; 0100 0000
BRT EQU $20 ; 0010 0000
MT EQU $10 ; 0001 0000
TLT EQU $08 ; 0000 1000
TT EQU $04 ; 0000 0100
TRT EQU $02 ; 0000 0010
DT EQU $01 ; 0000 0001
"Oh, maybe T is a little confusing."
"It's okay. We'll keep it. As long as we can read it and understand it."
"Then we'll need comment lines to help us remember?"
"Such as?"
She wrote,
* T FOR BIT:"Looks good, and it keeps it short for the screen we're working on."
* BOTTOM, TOP, MIDDLE
* LEFT, RIGHT, DECIMAL
"Do the last four EQU lines need the dollar sign and the zero?"
"No, they're the same in decimal and hex, with or without the leading zero. But simplifying them would make the form less obvious, so let's keep them this way. So, now let's use those to make a table of segments, like we figured out on Saturday. The zero will be the first entry. Which bits does it use?"
"All but the middle and the decimal?"
"Okay. We can use '.OR.' to put bits together, so it can look like this:"
TABLE"That's not going to fit in the 32 column screen."
FCB BLT.OR.BT.OR.BRT.OR.TRT.OR.TT.OR.TLT
"True, but that's okay. Wrapping won't hurt. Oh, but it's also ugly -- hard to read, and that is not okay. Maybe I can think of something to help."
After a little thought, I wrote
CUP EQU BLT.OR.BT.OR.BRT"It sort of helps."
CAP EQU TRT.OR.TT.OR.TLT
*
TABLE
FCB CUP.OR.CAP
"Heh. Okay, there's zero. One is easy."
She scribbled her guess, "BRT.OR.TRT". "Is that it?"
"Right."
With a bit of scribbling, erasing, and rescribbling, we had this:
BCUP EQU BLT.OR.BT.OR.BRT"I can sort of see what the table is, but how does that get into the LEDs?" Julia asked me.
TCAP EQU TRT.OR.TT.OR.TLT
ONET EQU BRT.OR.TRT
TRCUP EQU TT.OR.TRT.OR.MT
BLCUP EQU MT.OR.BLT.OR.BT
BRCUP EQU MT.OR.BRT.OR.BT
TCUP EQU TLT.OR.MT.OR.TRT
TLCUP EQU TT.OR.TLT.OR.MT
BCAP EQU BLT.OR.BT.OR.BRT
VBAR EQU TLT.OR.BLT
*
SEGTBL
FCB BCUP.OR.TCAP ; 0
FCB ONET ; 1
FCB TRCUP.OR.BLCUP ; 2
FCB TRCUP.OR.BRCUP ; 3
FCB TCUP.OR.BRT ; 4
FCB TLCUP.OR.BRCUP ; 5
FCB TLCUP.OR.BCUP ; 6
FCB TT.OR.ONET ; 7
FCB BCUP.OR.TCAP.OR.MT ; 8
FCB TCAP.OR.BRCUP ; 9
FCB TCAP.OR.BCAP ; A
FCB VBAR.OR.BRCUP ; b
FCB BLCUP ; c
FCB BLCUP.OR.ONET ; d
FCB TCAP.OR.BLCUP ; e
FCB VBAR.OR.TLCUP ; F
"I've been avoiding that question for a whole week. I want to use a parameter stack, but we're a little tight on both RAM and registers. I guess we're not going to be trying to run two displays at once, so global variables should work."
Julia looked at me with a blank expression.
I proceeded anyway. "We'll have a variable for the current number to display and a variable for the current column to display in, and --" I scribbled:
NUMDSP RMB 1"We can squeeze those into a single byte if we need to, but let's do it simple first."
CLMDSP RMB 1
PUTDIG"I'm lost."
LDX NUMDSP ; HIGH BITS ZERO!
LDA SEGTBL,X
LDX CLMDSP ; HIGH BITS ZERO!
The lab erupted in applause, and I looked around and realized that everyone was gathered around listening, and Mark, Jeff, Mike, and even Bob and Jennifer had been taking turns transferring our scribblings and musings to the chalkboard so they could all take notes.
I looked over at Doctor Brown, and he gave just gave me a "Who, me?" look.
I chuckled in embarrassment.
"Okay. Maybe we should do this as a group after all, and then you can all adjust it for how you wired yours. But I guess we need to use teamwork on the notes and explanations. Who followed how we put the table together?"
Bob, Jennifer, Mark, Jeff, and Mike said they were good on it, some of the others raised their hands hesitantly. There was a lot of doubt.
"I don't seem to do hexadecimal math in my head," George apologized. "Can someone explain it?"
Mike started scribbling on some scratch paper. "It's like this, --"
Doctor Brown suggested, "Mike, could you do that at the board for those who need some review?"
After a moment of hesitation, Mike stood up to the chalkboard and quickly wrote out a conversion table:
decimal | hexadecimal | binary | ||
---|---|---|---|---|
0 | : | $00 | = | 0000 0000 |
1 | : | $01 | = | 0000 0001 |
2 | : | $02 | = | 0000 0010 |
3 | : | $03 | = | 0000 0011 |
4 | : | $04 | = | 0000 0100 |
5 | : | $05 | = | 0000 0101 |
6 | : | $06 | = | 0000 0110 |
7 | : | $07 | = | 0000 0111 |
8 | : | $08 | = | 0000 1000 |
9 | : | $09 | = | 0000 1001 |
10 | : | $0A | = | 0000 1010 |
11 | : | $0B | = | 0000 1011 |
12 | : | $0C | = | 0000 1100 |
13 | : | $0D | = | 0000 1101 |
14 | : | $0E | = | 0000 1110 |
15 | : | $0F | = | 0000 1111 |
16 | : | $10 | = | 0001 0000 |
17 | : | $11 | = | 0001 0001 |
21 | : | $15 | = | 0001 0101 |
32 | : | $20 | = | 0010 0000 |
37 | : | $25 | = | 0010 0101 |
128 | : | $80 | = | 1000 0000 |
133 | : | $85 | = | 1000 0101 |
"We got groups of four binary digits on the right, and they match up with single digits of hexadecimal in the middle. It's not a coincidence. It's a rule."
After a bit of discussion, George just shrugged. "I guess I'm just not seeing something. Maybe we should keep going."
I concurred. "Mike can help you, and we'll be showing a lot of examples, I think. Let's see if moving ahead works."
"Joe."
"Julia?"
"Let me try." She stood up.
"I'm going to enjoy this."
She gave me a sharp look, but I just grinned.
"The LED's in our seven-segment displays are laid out to show the shapes of pieces of numbers when they're lit, okay?"
George nodded hesitantly.
"Let's ignore those shapes for now. Instead, we'll make each LED, each individual LED, a binary digit, or a bit. That's a place, or a column, or a position, in a binary number. If the LED lights, that's a binary one for that place in the number -- for that bit. If it doesn't light, that's a zero."
"I'm lo--"
Julia gave him an eyeroll.
"-- Lost, but I'll try to keep up anyway."
"There you go. So we take this seven-segment display and straighten out the LEDs in our minds, so they can form binary numbers that are not the same as the shapes when they make numbers. And we can use those numbers to figure out which bits of the port to set to one to make the display show the number."
"Maybe I'm seeing something."
"So the binary number that lights up the segments to make a '1' is zero-zero-one-zero, zero-zero-one-zero, which is hexadecimal two-two." She wrote "0010 0010" on the chalkboard, then turned and looked at me. "At least, as Joe keeps saying, in the circuit Joe and I have been making."
I nodded.
"In decimal," she continued, "that would be 34. But we aren't thinking in decimal. We don't care that 34 is smaller than 35 or bigger than 33. We use the hexadecimal numbers because they help us remember which LEDs are lit. It's easy ... well, sort-of easy to remember that two in binary is one-zero. Or, if you write it with four bits, zero-zero-one-zero."
George still looked doubtfully at Julia, but he said, "I think I'm seeing something now. Thanks. This might help me understand those examples Joe was talking about."
Julia gave me look that said, "I tried," and sat down.
"Thanks, Julia," I said. "I think that helps. Sometimes it takes a different approach."
After making new arrangements to make sure Julia would not be so busy taking notes that she couldn't think and ask questions, I started over, working through the elements of 6805 assembly language as I used them.
"'E-Q-U' is short for equate. It equates the label on the left to the expression on the right. Hopefully we don't need to know when the expression is evaluated, because I don't know and I don't want to waste time figuring that out."
Nobody complained about what I had said, so I continued
"When we write
BLT EQU $80 ; 1000 0000"that could mean bacon, lettuce, and tomato is flagged by bit seven, or it could mean the bottom left segment bit is bit seven."
That got some chuckles.
"'.OR.' is the logical-or operator. It performs a column-by-column logical or, keeping the column results in their columns. That means that'
ONET EQU BRT.OR.TRT"equates the label ONET to the result of 00100000 or-ed with 00000010, which is 00100010, or hexadecimal 22."
I wrote on the chalkboard,
0010 0000
0000 0010
-------------
0010 0010
"And if we put $22 on the segments port and hold the anode of one of the displays down to 0, it should make the top and bottom right segments light up, showing us a '1'. If we want to see that, we could try something like"
START"'LDA loads a small value into the accumulator, STA stores the value in the accumulator to memory or I/O space, BRA means branch always and forever, and it does so, looping to itself, letting us see the results. This is a CMOS 1468705, so I think we could use a WAIT instruction here, but this loop forever to itself will do what we need with most CPUs. So it's a good thing for everyone to see, at least once."
LDA #22
STA CATHODES
LDA #FE
STA ANODES
WAITLP
BRA WAITLP
I decided to stop and demonstrate it. I added the reset vectors, then asked Julia to type it in, assemble it, and burn it into her 68705, and power it up to run the short program. When it produced a 1 on the rightmost seven segment display, George and some of the other students seemed to gain a bit more confidence of what they were looking at
"Hopefully everybody's working out your own equate definitions for your own circuits while we do this. I guess we should put the definitions Julia and I came up with on the chalkboard, but remember yours will be somewhat different." And as I copied to the chalkboard, I added more comments, showing the expected bit values:
* BOTTOM, TOP, MIDDLE"The FCB that we use to construct the table of constants stands for 'Form Constant Byte or some such, and it is used to store a constant value into the program object code. By putting them into a table in the object code, we make the patterns available for look-up.
* LEFT, RIGHT, DECIMAL
* SEGMENT BIT T
BLT EQU $80 ; 1000 0000
BT EQU $40 ; 0100 0000
BRT EQU $20 ; 0010 0000
MT EQU $10 ; 0001 0000
TLT EQU $08 ; 0000 1000
TT EQU $04 ; 0000 0100
TRT EQU $02 ; 0000 0010
DT EQU $01 ; 0000 0001
*
BCUP EQU BLT.OR.BT.OR.BRT
* 1110 0000 $E0
TCAP EQU TRT.OR.TT.OR.TLT
* 0000 1110 $0E
ONET EQU BRT.OR.TRT
* 0010 0010 $22
TRCUP EQU TT.OR.TRT.OR.MT
* 0001 0110 $16
BLCUP EQU MT.OR.BLT.OR.BT
* 1101 0000 $D0
BRCUP EQU MT.OR.BRT.OR.BT
* 0111 0000 $70
TCUP EQU TLT.OR.MT.OR.TRT
* 0001 1010 $1A
TLCUP EQU TT.OR.TLT.OR.MT
* 0001 1100 $1C
BCAP EQU BLT.OR.BT.OR.BRT
* 1110 0000 $E0
VBAR EQU TLT.OR.BLT
* 1000 1000 $88
*
SEGTBL
FCB BCUP.OR.TCAP ; 0
FCB ONET ; 1
FCB TRCUP.OR.BLCUP ; 2
FCB TRCUP.OR.BRCUP ; 3
FCB TCUP.OR.BRT ; 4
FCB TLCUP.OR.BRCUP ; 5
FCB TLCUP.OR.BCUP ; 6
FCB TT.OR.ONET ; 7
FCB BCUP.OR.TCAP.OR.MT ; 8
FCB TCAP.OR.BRCUP ; 9
FCB TCAP.OR.BCAP ; A
FCB VBAR.OR.BRCUP ; b
FCB BLCUP ; c
FCB BLCUP.OR.ONET ; d
FCB TLCUP.OR.BLCUP ; E
FCB VBAR.OR.TLCUP ; F
"Now, if we shift the anode bit, we can light up one digit at a time, but it's going to happen so fast it will look like they're all lit up at once. The LSL instruction shifts the argument one bit to the left, so we'll use it to pick which which digit to light."
Eyes were glazing over, so I wrote another bit of demonstration code, directly using the constants I had defined earlier:
PAUSE"The PAUSE routine uses the X register as an idle counter. DEC counts X down one, and BNE loops back to count again until X is zero. 'B' for Branch. 'NE' for Not Equal, or in other words, not zero. I suppose I'll have to explain that more later. Anyway, we turn a digit on, then we pause for a bit so the human eye can register it."
DECX ; IDLE COUNT
BNE PAUSE
RTS
*
START
CLRX
LDA #FE
STA ANODES
LDA #ONET
STA CATHODES
BSR PAUSE ; LET PORT SETTLE
LSL ANODES
LDA #TCAP
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #VBAR
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #BLCUP
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #TRCUP
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #TCUP
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #BCAP
STA CATHODES
BSR PAUSE
BRA START
"And get your minds out of the gutter, guys, BRA really is a BRanch Always. so when we have displayed all the patterns, one place at a time, we go back and do it again.
Suzanne complained, "I suppose some male engineer thought that mnemonic up."
"You suppose right. Apparently more than one. I do not defend them. In a little bit, I'll show you how to use a macro definition to give that instruction a better mnemonic name."
"I don't suppose anyone will forget the original mnemonic," Bob commented, and Jennifer slapped him over the head.
Doctor Brown watched this in amusement, taking no sides.
Again, Julia typed it in, assembled it, and burned it, this time into a 68705 she borrowed from Jeff while hers was in the eraser.
She was rather dissatisfied with the cryptic output, so she got back on the computer and added equates for each digit, using the equates in the table itself:
N0 EQU BCUP.OR.TCAP ; 0Then she modified the test code to use her new equates:
N1 EQU ONET ; 1
N2 EQU TRCUP.OR.BLCUP ; 2
N3 EQU TRCUP.OR.BRCUP ; 3
N4 EQU TCUP.OR.BRT ; 4
N5 EQU TLCUP.OR.BRCUP ; 5
N6 EQU TLCUP.OR.BCUP ; 6
N7 EQU TT.OR.ONET ; 7
N8 EQU BCUP.OR.TCAP.OR.MT ; 8
N9 EQU TCAP.OR.BRCUP ; 9
NA EQU TCAP.OR.BCAP ; A
NB EQU VBAR.OR.BRCUP ; b
NC EQU BLCUP ; c
ND EQU BLCUP.OR.ONET ; d
NE EQU TLCUP.OR.BLCUP ; E
NF EQU VBAR.OR.TLCUP ; F
*
SEGTBL
FCB N0 ; $EE 1110 1110
FCB N1 ; $22 0010 0010
FCB N2 ; $D6 1101 0110
FCB N3 ; $76 0111 0110
FCB N4 ; $3A 0011 1010
FCB N5 ; $7C 0111 1100
FCB N6 ; $FC 1111 1100
FCB N7 ; $26 0010 0110
FCB N8 ; $FE 1111 1110
FCB N9 ; $7E 0111 1110
FCB NA ; $EE 1110 1110
FCB NB ; $F8 1111 1000
FCB NC ; $D0 1101 0000
FCB ND ; $F2 1111 0010
FCB NE ; $DC 1101 1100
FCB NF ; $9C 1001 1100
STARTAnd she tried it again, borrowing a 68705 from Mark this time.
CLRX
LDA #FE
STA ANODES
LDA #N0
STA CATHODES
BSR PAUSE ; LET PORT SETTLE
LSL ANODES
LDA #N1
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #N2
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #N3
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #N4
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #N5
STA CATHODES
BSR PAUSE
LSL ANODES
LDA #N6
STA CATHODES
BSR PAUSE
BRA START
I think everyone cheered.
"But I have a question," she said.
"Yeah?"
"I don't think my code is actually using the table in this test."
"True. And I could get a swelled head and imagine I taught you that, but I think you've done more figuring out than I've done teaching."
"Oh, give her a kiss," Winston said. "She deserves it."
"No es para ...," I began, but Julia shook her head just perceptively enough for me to see.
"Whether I reward him with a kiss or not is my business," she said.
Wolf whistles and other unnecessary noises of appreciation ensued, and Julia and I cleared our throats simultaneously, with lopsided grins.
Mike did not join in the circus.
"Back to work," Julia said.
I continued. "So now we need to try actually using the table. We'll use the X register to pick the pattern to display:"
ORG $40 ; VARIABLES"ORG means origin, and it sets the address where the next part is assembled. RMB Reserves a Memory Byte in low memory, which we will use instead of X as the idle loop counter. We label that byte PAUSER. CLR clears the variable in memory here, and DEC decrements it by 1, so it's much the same as using X for the idle count, just slower.
PAUSER RMB 1
ORG ROM ; CODE
PAUSE
CLR PAUSER
PAUSELP
DEC PAUSER
BNE PAUSELP
*
START
LDA #$FE
STA ANODES
LDX #1
SEC
DISPLP
LSL ANODES
LDA SEGTBL,X
STA CATHODES
BSR PAUSE
INCX
CPX #8
BNE DISPLP
BRA START
"The indexed addressing mode used in 'LDA SEGTBL,X' adds the constant address of the base of the SEGTBL table to the value in X and uses the result as the address from which we load the accumulator.
"With a 0 in X, the argument 'SEGTBL,X' points to the bit pattern to display a zero. With a 1 in X, it points to the bit pattern to display a one. And so forth."
I stopped to diagram it on the chalkboard:
SEGTBL,X | (@SEGTBL+X) | |||
SEGTBL+0 | : | 11101110 | (N0=$EE) | |
(X=1)=> | SEGTBL+1 | : | 00100010 | (N1=$22) |
SEGTBL+2 | : | 11010110 | (N2=$D6) | |
SEGTBL+3 | : | 01110110 | (N3=$76) | |
SEGTBL+4 | : | 00111010 | (N4=$3A) | |
SEGTBL+5 | : | 01111100 | (N5=$7C) | |
SEGTBL+6 | : | 11111100 | (N6=$FC) | |
SEGTBL+7 | : | 00100110 | (N7=$26) | |
SEGTBL+8 | : | 11111110 | (N8=$FE) | |
SEGTBL+9 | : | 01111110 | (N9=$7E) | |
SEGTBL+A | : | 11101110 | (NA=$EE) | |
SEGTBL+B | : | 11111000 | (NB=$F8) | |
SEGTBL+C | : | 11010000 | (NC=$D0) | |
SEGTBL+D | : | 11110010 | (ND=$F2) | |
SEGTBL+E | : | 11011100 | (NE=$DC) | |
SEGTBL+F | : | 10011100 | (NF=$9C) |
"So we start with X equal to 1, then count X up with INC each time through the loop, after we display the number in that digit for a fraction of a second.
"We're only displaying seven numbers, so we use CMP to CoMPare X to 8, and BNE Branches back to do another as long as X is Not Equal to 8 at that point in the loop."
I looked at Julia, and she nodded hesitantly.
"I think it sort of makes sense. Should we let someone else do the programming this time?"
Freddie volunteered, so Julia traded places with her to let her take a turn typing and burning, but we still used Julia's circuit so the wiring would be right. By this time, Julia's 68705 was erased and ready to use, so she used it, and this demonstration produced the numbers 1 through 7 on the displays.
When the test proved successful, Freddie returned to helping take notes.
Mark and Jeff were keeping track of how long each MCU was in the eraser.
(As I write this, I don't have hardware to make sure I'm not forgetting something, but the programs should look something like what I'm giving here.)
"Anybody who's not comfortable with all of that, try out some of your own variations later. For now we need to write the real display code. Bob, Jennifer, are you up to picking up from here, to give everyone a break from me?"
Bob looked questioningly at Jennifer, and they stood, hesitantly.
Jennifer asked, "I guess we need a variable to hold the number, and a routine to convert from binary to hexadecimal?"
I thought carefully how hard I wanted to push them, and actually stopped just long enough to pray for help, before responding with, "I wonder how much time we'll have to do conversions during the interrupt routines."
"Not much?" Bob asked.
Doctor Brown spoke up. "Before worrying about that, let's see what you would do."
I decided I agreed with Doctor Brown. "Go with what you have in mind and see how it works. I need to go deliver newspapers pretty soon."
They took over, and I sat down next to Julia.
She took my hand under the lab table and whispered, "This is hard!"
"You're not the only one who thinks so," I whispered back.
"Are we going to need to do decimal numbers?" Jennifer asked from the chalkboard.
"Somebody might, but, for now, let's just do hexadecimal," I suggested
Bob and Jennifer took separate panes of the chalkboard and both started writing:
ORG $40(Yes, I'm fudging a little, not showing the initialization code.)
WAITCT RMB 1 ; IDLE COUNTER
CMDOUT RMB 1 ; CMD to DSP
BYTOUT RMB 1 ; BYTE to DISP
ADROUT RMB 2 ; ADR TO DISP
*
ORG $80
* HI BIT DP
* CLOCKWISE FROM TOP
* LO BIT MIDDLE SEG
SEGTBL
FCB $7E ; 0 0111 1110
FCB $30 ; 1 0011 0000
FCB $6D ; 2 0110 1101
FCB $79 ; 3 0111 1001
FCB $33 ; 4 0011 0011
FCB $5B ; 5 0101 1011
FCB $5F ; 6 0101 1111
FCB $70 ; 7 0111 0000
FCB $7F ; 8 0111 1111
FCB $7B ; 9 0111 1011
FCB $77 ; A 0111 0111
FCB $1F ; b 0001 1111
FCB $3D ; d 0011 1101
FCB $0D ; c 0000 1101
FCB $4F ; E 0100 1111
FCB $47 ; F 0100 0111
*
*
BITTBL
FCB 1
FCB 2
FCB 4
FCB 8
FCB $10
FCB $20
FCB $40
FCB $80
*
DSPCMD
LDA CMDOUT
GTXNIB
ANDA #$0F
TAX
LDA SEGTBL,X
RTS
*
DSPBYT
* HI NIB
LDA BYTOUT
LSRA
LSRA
LSRA
LSRA
BSR GTXNIB
STA CATHOD
LDX #5
LDA BITTBL,X
STA ANODE
* LO NIB
LDA BYTOUT
BSR GTXNIB
BSR WAIT
STA CATHOD
LDX #4
LDA BITTBL,X
STA ANODE
BSR WAIT
RTS
*
DSPADR
*WAIT
CLR WAITCT
WAIT0
INC WAITCT
BNE WAIT0
RTS
*
INIT
* INIT PORTS
START
LDA #$0C
STA CMDOUT
* BSR DSPCMD
LDA #$5A
STA BYTOUT
BSR DSPBYT
LDA #$10
STA ADROUT
LDA #$00
STA ADROUT+1
* BSR DSPADR
BRA START
*
ORG $1FFE
FDB INIT
END
When they got to this point, Bob and Jennifer both put their chalk down and turned around, and Bob said, "Filling in the two undefined display routines feels awkward, and it's going to be a lot of modifying code as we copy, which is an easy place to make mistakes."
Doctor Brown spoke up again. "Let's go ahead and walk us through that and test it, and see if we get any good ideas while we're typing and testing."
Jennifer pointed out, "Our segments are wired differently from Joe's and Julia's."
I commented, "I think your wiring makes it a bit easier to visualize the connection between bits and display segments than the wiring I came up with for Julia."
Julia snickered and poked me in the ribs.
"Theirs does follow a more common pattern," Mike pointed out. "Mine uses the same as theirs."
Tanya asked, "Is WAIT a legal label?"
"Labels and op-code mnemonics are in a different symbol space in the assembler, so it's okay," I explained. "Might confuse humans, though."
"Maybe we should use WAITLP like you do," Bob continued. "Other than the wiring differences, we're just following the same program flow pattern you've been following. All we've added is splitting up the byte into four-bit halves, and shifting things into place, and masking the high bits off so the array reference into the table stays in the table."
Jennifer added, "The LSR instruction does a logical shift right, meaning it's dividing by two but ignoring the sign. It fills the top bit with a zero. The AND instruction masks off the top byte, for when you do the lookup without shifting first."
"I'm doing something completely different than that," Mike asserted.
"When Bob and Jennifer have tested theirs, how about you taking a turn, Mike?" I suggested.
He seemed a little surprised that I suggested it, but agreed.
And I excused myself to go deliver newspapers. Before I left, I mumbled something to Julia about hoping Mike had jumped ahead to just storing the segments in a display buffer, but she just shrugged her shoulders.
"Sorry, you've lost me again. Tell me what you mean when you get back."
By the time I got back, Mike was describing his first step.
Julia gave me an update in a low voice. "Bob and Jennifer got theirs working, but we all helped. Torrence noticed that their bit table was inverted before they burned their first program in, and the fix's on the chalkboard."
The corrected bit table looked like this:
BITTBL"They had a typing mistake bug, too, and Doctor Brown showed us how to play computer and do a group walk-through to find it."
FCB $FE
FCB $FD
FCB $FB
FCB $F7
FCB $EF
FCB $DF
FCB $BF
FCB $7F
"Valuable experience."
"Helped me a lot."
"Let's see what Mike's got."
Mike was describing how he planned to test his understanding of the built-in hardware timer by using it to interrupt the CPU so it could make the segments flash between 1 and E at a fairly precise one second rate. (Again, I'm fudging a little, not actually giving you his initialization code. Init code is easy to get wrong if you don't test, and I can't test. It's also fairly straightforward in cases such as this, if you can get the hardware and are inclined to try it yourself.)
ORG $40"Using the timer prescaler value of 64 and the timer count of 125, then counting a hundred twenty-five interrupts, we should get a count of 125 times 125 times 64, which is a million. So if the CPU clock is exactly one meghertz, this should be exactly a one second flash rate.
LONGP RMB 1
ORG $100
INIT
* SET UP PORTS
* SET TIMER PRESCALE TO 64
* SET TIMER COUNT TO 125
LDA #125
STA LONGP
LDA #$FE
STA ANODE
LDA #30 ; 1
STA CATHOD
WAIT
TIMINT
BCLR TIMCR7 ; INT FLAG
DEC LONGP
BNE TIMDUN
LDA #125
STA LONGP
LDA CATHOD
XORA #$FF ; 1 INVERTS TO E
STA CATHOD
TIMDUN
RTI
*
ORG $1FF6
FDB TIMINT; CMOS MODE TIMER INT
FDB TIMINT ; ORDINARY TIMER INT
FDB INIT ; INTERRUPT
FDB INIT ; SWI
FDB INIT ; $1FFF RESET
END
"WAIT clears the CPU's interrupt mask before it puts the CPU in a WAIT state, but lets the timer keep running.
"The exclusive-or with hex FF instruction toggles all the bits in the accumulator, which should show E and the decimal point. And we can see if the BCLR bit clear instruction works and clears the timer interrupt flag."
After Theresa, another of the more quiet students, typed the code in and burned it, Mike's test worked as advertised, and Mike proceeded with his next step.
"What I'm going to do is have a buffer for the digits to display. I'll just have the timer generate a one millisecond interval interrupt, and it will sequence through displaying each digit for a millisecond. I'm going to steal Bob and Jennifer's code for the bit table and the segment table, if they don't mind."
"No problemo."
And he proceeded to show his code:
ORG $40Burning the code in produced close to the desired results, but not quite, and we proceeded, as a group, to debug it, and shortly had it working.
CURDIG RMB 1 ; 1-7
DIGBUF RMB 7 ; 7 DISPLAYS
*
ORG $100
* BIT AND SEGMENT TABLES
TIMINT
BCLR TIMCR7
LDA CURDIG
ANDA #07 ; SAFE MASKING
STA CURDIG
TAX
LDA BITTBL,X
STA ANODE
LDX CURDIG
LDA DIGBUF,X
ANDA #$0F ; SAFE MASKING
TAX
LDA SEGTBL,X
STA CATHOD
RTI
*
START
LDA #5
STA DIGBUF
LDA #3
STA DIGBUF+1
LDA #7
STA DIGBUF+2
LDA #7
STA DIGBUF+3
LDA #3
STA DIGBUF+4
LDA #8
STA DIGBUF+5
LDA #0
STA DIGBUF+6
WAIT
It was getting close to dinner time, so I asked everyone, "Should I offer some wrap-up comments about interrupt routines now, or should we go home in a euphoria?"
Mike looked at me in resignation. "Hit me with it."
I laughed and looked at Doctor Brown, and he said, "Just keep it short."
So I turned to the students. "We've done some really good work today, keeping the steps small and working together to fix bugs. Doctor Brown will tell us again why bugs are good tomorrow, I think. A couple or three things to think about tonight -- Is it better to clear the timer interrupt flag at the front of the interrupt routine or the end? What could we do with Mike's code to keep the digits available to look at, but make the interrupt routine itself shorter? And how do we fit the keyboard code into the framework Mike has given us?"
I paused, deliberately, and then added, "By the way, I couldn't have paid Mike, Bob, or Jennifer to give us better code to work with."
*****
Julia leaned against my shoulder across the transmission well, looking out the window at the twilit sky.
"Either you aren't the jealous kind or you have supreme confidence about my feelings for you."
"I trust you to figure out what you want." I lifted my hand from the gearshift and gave her a quick hug.
"Supremely confident."
I chuckled. "And if I disagree, I'm going to be in a world of hurt."
She turned and bit my shoulder. Gently.
*****
After dinner and home evening, we sang my recital song in duet, English first, then Julia following along with my pronunciation as I sang in Japanese for a verse. I wrote out the Romanization, and we sang the Japanese together. (I've mentioned Latinization before. In Japanese, it's called ローマ字 -- Rōmaji -- or Romanization.) Then we sat down and worked on homework. After homework, Julia looking over my shoulder while I worked through the TMS 9940 documentation.
"I'm not seeing it."
"What?
"The description of the instruction to call a subroutine. I found the return instruction, but not the call, and I want to get a look at it."
Julia gave me a blank look.
"It's actually a full context switch on this processor, generating a linked list of contexts instead of a straight stack."
She raised her hands with a smile that said, "I have no idea what you are talking about."
I grinned back. "Just pretend like your listening to something that makes sense."
"Hah."
"I'm going to pretend I'm explaining it to you, but I'm explaining it to myself."
"Uh, huh." She snickered.
"The TMS 9900 has a really unusual register scheme. All the computational registers are actually in memory, pointed to by the working set register."
"Last week, I would have been lost when you said scheme and register."
"What's a register?"
"Registers are where the poor little thing does all those calculations, and RAM is where she stores her results after working so hard."
"Very good. The 9900 uses RAM for registers. And TI calls the RAM it uses for registers the context, or working set. And it can keep a link to the previous working set in a memory cell of the current context."
"I can pretend I might understand that someday."
We both laughed. "Thank you. Now you have to know where your registers are, so the 9900 has one real register that points to the working set. It's called WP."
"Working set pointer?"
"Careful. You might actually understand this."
"Hah."
"You also have to know where the instructions are, so the 9900 has a register for that. It's called IP."
"Instruction pointer."
"Nice. Anyway, when you call a new procedure or routine, you usually want to know how to get back to where you were. That's what the link to the previous context working set is."
"I could see that. Someday."
"So the 9900's call instruction holds onto the old IP and WP, loads a new WP to point to a new working set, and stores the old ones in the top of the new working set."
Julia frowned. "You know that almost makes sense."
"Almost. I don't think it's ideal. I haven't mentioned the status register. I think it's the status register. But it saves that, too."
"Now I'm lost again."
"That's okay. The status register is where it remembers such things as whether the last operation resulted in zero or a negative number. I want to see the instruction that sets up the new context frame, so I'm looking for the call instruction, and I can't find it. I can find the return, but not the call. It's called BLWP, for branch and link WP."
I thumbed through the datasheet pages again, with Julia looking over my shoulder again.
"These are jumps?" She said.
"Yeah. Conditional jumps. It's not there."
I thumbed back and forth a bit more.
"Single operand instructions. How many operands does this branch and link, uhm, WP instruction have?"
"That's actually what I want to find out."
"B for branch."
"Yeah."
"BL."
"Branch and link, but without WP. It's a quick call."
"BLWP," we said in unison.
"Op code 17."
"Where? I don't see any seventeen anywhere near BLWP."
"Binary." I pointed to it. "One zero zero zero one."
"Ah. Yeah." She shook her head.
Shortly I was satisfied for the night with what I had learned about the 9940, so I dug out the Forth implementation package.
"You're finally going to look at that other package?" Julia yawned.
"Been putting it off too long." I opened it up and scanned through it.
Julia fell asleep on my shoulder while I tried to make sense of it, and then I drifted off, as well. Giselle woke us up about 10:30, and I drove Julia home.
"So, what if I decide to reward you with a kiss?"
We had stopped on her front porch to talk.
"Who am I to turn down a reward?"
It was a nice, sweet reward, giving and getting, but not too much.
[Second version backed up at https://joel-rees-economics.blogspot.com/2020/06/bk01-33209-straits-status-display.html.
First version backed up at https://joel-rees-economics.blogspot.com/2020/06/bk-33209-straits-status-display.html.]