Introduction to the COSMAC LED Display Timer
For this post, I used the CDP1802 Microprocessor kit. The 1802 processor was on several space missions. This includes Gallileo craft which explored Jupiter. This kit has several nice features for learning purposes. It has an LED display, and you can add an LCD display. By far, the LCD is easier to use for beginners. However, I liked the appearance of the 6 digit display. For this timer, I just based it on the processor scan. The kit also has a 10uS interrupt tick that you can use. This might give more accurate results. Additionally, it has 8 led’s that you can address “directly”. It’s a COSMAC, so I guess that would technically be indirectly, but still very easy to use.
In this program, I’ve used EF1 to start and stop the timer. EF2 resets the timer. (There are four EF pins on the processor for direct inputs.) You can adjust memory location 8080 to calibrate the timer in this program. Obviously, a higher value will make the timer run slower. On the other hand, a lower value will make the timer run faster.
The eight LED’s will display the number of seconds (0 to 9)
About the COSMAC
The COSMAC has 16 registers, and relies heavily on indirect addressing. That is to say, when you need to operate on a memory cell, you just load the address of that memory cell into one of the 16 registers (16 bits each). When you execute a command such as an STR (store accumulator), you will specify the register number that contains the memory location that you wish to save data to. The D register is the accumulator. DF is the carry flag. It’s quite different from other processors such as the 6502. You need to develop a different way of thinking to be able to use the COSMAC efficiently.
About the Logic for the COSMAC LED Display Timer
Basically, I used register RC, and loaded different memory locations from 8300-8305. The problem with the LED display is that straight values do not work. You have to determine what bits to turn on to create a particular pattern on the screen. The buffers start with 0BDH, which represents a zero. As the timer runs, it will increment the memory cells at 8300 to 8305.
Each numeric position has a separate memory cell. When displaying a number, the Values array has a look up table. This table contains the bit patter of each number 0-1. We simply load in the start of the values array for a particular digit. We’ll find out what number we need to display from 8300 to 8305. We’ll add this value to the start of the values array, and then we have the code that represents this number. At this point, we just load that code into the buffer for that digit.
There are better ways to write this program, I’m sure. With my knowledge and experience with the COSMAC, though, I built this program the best I could. It does seem to be stable.
I started with the display program in Wichit Sirichote’s book, and then just built it from there. It’s been accurate to about 3 thousands of a percent. That means that in 1000 seconds, I’ve gained 3 seconds. That’s OK though, because the more logic I add, the more accurate it will be to a certain point.
Loading the Program
I used the A18 Assembler to build an Intel hex file. I will paste that to the bottom of this post. Basically, you just need to set up your terminal for a 10ms character delay. Be sure your terminal is connecting to the 1802, then press reset, then load. After that, you can paste the intel hex file into your terminal. Once it’s done loading, just hit PC to go to memory location 8000. That is where this program starts. Then hit GO.
GPIO1: EQU 7000H
SEGMENT: EQU 7102H
DIGIT: EQU 7101H
HUNDREDTHS: EQU 8300H
TENTHS: EQU 8301H
ONES: EQU 8302H
TENS: EQU 8303H
HUNDREDS: EQU 8304H
THOUSANDS: EQU 8305H
FREERUN: EQU 8306H
EFLAGS: EQU 8307H
BREAK: EQU 2756H
org 8000H ;have to start somewhere ...
R0 EQU 0
R1 EQU 1
R2 EQU 2
R3 EQU 3
R4 EQU 4
R5 EQU 5
R6 EQU 6
R7 EQU 7
R8 EQU 8
R9 EQU 9
RA EQU 10
RB EQU 11
RC EQU 12
RD EQU 13
RE EQU 14
RF EQU 15
START: LOAD R3, DELAY
LOAD R4, SEGMENT
LOAD R5, DIGIT
LOAD RF, FREERUN
LDI 00H
STR RF
LOAD RE, GPIO1
LDI 00H
LOAD RD, EFLAGS
LDI 00H
STR RD
LOAD RC, HUNDREDTHS
LDI 00H
STR RC
LOAD RC, TENTHS
LDI 00H
STR RC
LOAD RC, ONES
LDI 00H
STR RC
LOAD RC, TENS
LDI 00H
STR RC
LOAD RC, HUNDREDS
LDI 00H
STR RC
LOAD RC, THOUSANDS
LDI 00H
STR RC
REQ
MAIN: LOAD RA, BUFFER5
LOAD R9, VALUES
LBR CHKEF1
CONT2: BNQ CONT
SEX RF
LDI 01H
ADD
STR RF
XRI 1FH ;CALIBRATE
LBZ COUNT
CONT: LOAD RB, SCAN_DIGIT
LDI 6
PLO R8 ;LOOP COUNT
LOOP: LDN RB ;GET DIGIT CONTROL
XRI 0FFH ;COMPLEMENT IT
STR R5 ;WRITE TO DIGIT
LDN RA ;GET BYTE FROM BUFFER
STR R4 ;WRITE TO SEGMENT
SEP R3 ;DELAY
LDI 0 ;TURN OFF DISPLAY
STR R4
INC RA
INC RB
DEC R8
GLO R8
BNZ LOOP ;UNTIL 6 DIGITS
BR MAIN
RET_DELAY: SEP R0
DELAY: LDI 1
PLO R7
DELAY1: DEC R7
GLO R7
BNZ DELAY1
BR RET_DELAY
BUFFER5: DB 0BDH
BUFFER4: DB 0BDH
BUFFER3: DB 0BDH
BUFFER2: DB 0BDH
BUFFER1: DB 0BDH
BUFFER0: DB 0BDH
SCAN_DIGIT: DB 20H, 10H, 8, 4, 2, 1
VALUES: DB 0BDH, 030H, 09BH, 0BAH, 036H, 0AEH, 0AFH, 038H, 0BFH, 03EH
LIHNTH: LBR IHNTH
ZERO: BN2 LIHNTH
UNCZRO: LOAD RC, HUNDREDTHS
LDI 00H
STR RC
LOAD RC, TENTHS
LDI 00H
STR RC
LOAD RC, ONES
LDI 00H
STR RC
LOAD RC, TENS
LDI 00H
STR RC
LOAD RC, HUNDREDS
LDI 00H
STR RC
LOAD RC, THOUSANDS
LDI 00H
STR RC
LBR UPDB
COUNT: LDI 00H
STR RF
IHNTH: LOAD RC, HUNDREDTHS
SEX RC
LDI 02H
ADD ;INCREMENT TIMER
STR RC ;RC NOW CONTAINS THE HUNDREDTHS VALUE
LDN RC
XRI 0AH
LBZ ITNTH
LBR UPDB
ITNTH: LOAD RC, HUNDREDTHS
LDI 0H
STR RC ;RC NOW CONTAINS A ZERO
LOAD RC, TENTHS
SEX RC
LDI 01H
ADD
STR RC ;RD NOW CONTAINS THE TENTHS VALUES
LDN RC
XRI 0AH
LBZ IONES
LBR UPDB
IONES: LOAD RC, TENTHS
LDI 0H
STR RC ;RC NOW CONTAINS A ZERO
LOAD RC, ONES
SEX RC
LDI 01H
ADD
STR RC ;RD NOW CONTAINS THE ONES VALUES
LDN RC
XRI 0AH
LBZ ITENS
LBR UPDB
ITENS: LOAD RC, ONES
LDI 0H
STR RC ;RC NOW CONTAINS A ZERO
LOAD RC, TENS
SEX RC
LDI 01H
ADD
STR RC ;RD NOW CONTAINS THE TENS VALUES
LDN RC
XRI 0AH
LBZ IHUN
LBR UPDB
IHUN: LOAD RC, TENS
LDI 0H
STR RC ;RC NOW CONTAINS A ZERO
LOAD RC, HUNDREDS
SEX RC
LDI 01H
ADD
STR RC ;RD NOW CONTAINS THE HUNDREDS VALUES
LDN RC
XRI 0AH
LBZ ITHOU
LBR UPDB
ITHOU: LOAD RC, HUNDREDS
LDI 0H
STR RC ;RC NOW CONTAINS A ZERO
LOAD RC, THOUSANDS
SEX RC
LDI 01H
ADD
STR RC ;RD NOW CONTAINS THE THOUSANDS VALUES
LDN RC
XRI 0AH
LBZ UNCZRO
LBR UPDB
CONT1: LBR CONT
UPDB: NOP
UHNTH: LOAD R9, VALUES
LOAD RC, HUNDREDTHS
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR HUNDREDTHS
LOAD R6, BUFFER0
LDN R9
STR R6
UTNTHS: LOAD R9, VALUES
LOAD RC, TENTHS
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR TENTHS
LOAD R6, BUFFER1
LDN R9
STR R6
UONES: LOAD R9, VALUES
LOAD RC, ONES
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR ONES
LOAD R6, BUFFER2
LDN R9
STR R6
STR RE
UTENS: LOAD R9, VALUES
LOAD RC, TENS
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR TENS
LOAD R6, BUFFER3
LDN R9
STR R6
UHNDRD: LOAD R9, VALUES
LOAD RC, HUNDREDS
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR HUNDREDS
LOAD R6, BUFFER4
LDN R9
STR R6
UTHOU: LOAD R9, VALUES
LOAD RC, THOUSANDS
SEX RC
GLO R9
ADD
PLO R9 ;R9 NOW SET TO WHERE WE NEED DATA FOR THOUSANDS
LOAD R6, BUFFER5
LDN R9
STR R6
CHKEF1: B2 EF2P
BN1 RSFLAG
LDN RD
BZ ACTOK
LBR CONT2
ACTOK: BQ RESQ
LBR SETQ
RSFLAG: LDI 00H
STR RD
LBR CONT2
RESQ: REQ
LDI 01H
STR RD
LBR CONT2
SETQ: SEQ
LDI 01H
STR RD
LBR CONT2
EF2P: REQ
LBR UNCZRO
END
Additionally, here is the Intel Hex file for this program:
:20800000F880B3F89AA3F871B4F802A4F871B5F801A5F883BFF806AFF8005FF870BEF8002D
:20802000AEF800F883BDF807ADF8005DF883BCF800ACF8005CF883BCF801ACF8005CF88387
:20804000BCF802ACF8005CF883BCF803ACF8005CF883BCF804ACF8005CF883BCF805ACF82D
:20806000005C7AF880BAF8A3AAF880B9F8AFA9C08234397EEFF801F45FFB1FC280F7F880FF
:20808000BBF8A9ABF806A80BFBFF550A54D3F800541A1B28883A873063D0F801A727873ACB
:2080A0009D3099BDBDBDBDBDBD201008040201BD309BBA36AEAF38BF3EC080FA3DB9F883F8
:2080C000BCF800ACF8005CF883BCF801ACF8005CF883BCF802ACF8005CF883BCF803ACF8B5
:2080E000005CF883BCF804ACF8005CF883BCF805ACF8005CC081A2F8005FF883BCF800ACA8
:20810000ECF802F45C0CFB0AC2810EC081A2F883BCF800ACF8005CF883BCF801ACECF801F4
:20812000F45C0CFB0AC2812BC081A2F883BCF801ACF8005CF883BCF802ACECF801F45C0C3F
:20814000FB0AC28148C081A2F883BCF802ACF8005CF883BCF803ACECF801F45C0CFB0AC295
:208160008165C081A2F883BCF803ACF8005CF883BCF804ACECF801F45C0CFB0AC28182C05A
:2081800081A2F883BCF804ACF8005CF883BCF805ACECF801F45C0CFB0AC280BEC081A2C0C0
:2081A000807EC4F880B9F8AFA9F883BCF800ACEC89F4A9F880B6F8A8A60956F880B9F8AFE4
:2081C000A9F883BCF801ACEC89F4A9F880B6F8A7A60956F880B9F8AFA9F883BCF802ACECEC
:2081E00089F4A9F880B6F8A6A609565EF880B9F8AFA9F883BCF803ACEC89F4A9F880B6F893
:20820000A5A60956F880B9F8AFA9F883BCF804ACEC89F4A9F880B6F8A4A60956F880B9F84A
:20822000AFA9F883BCF805ACEC89F4A9F880B6F8A3A6095635573C430D323EC08072314972
:1B824000C08250F8005DC080727AF8015DC080727BF8015DC080727AC080BE0D
:00825B0122
For more information, visit the COSMAC Category Page!
— Ricky Bryce