COSMAC LED Display Timer


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

Leave a comment

Your email address will not be published. Required fields are marked *