One of the SITCOM training computer prototypes
 SITCOM 85 Training Computer
 
 

Making the light walk up and down

Remember that sophisticated car that could talk back in the eighties? You must have seen it, because it is still re-run on several TV stations all over the world. Its name was KITT, and it had some very high-tech red lights scanning up and down in its bonnet. Well, it seemed high-tech at the time. I bet we can make something similar ourselves with nothing more than Sitcom and its standard I/O board.

Half of the program is already made, because we can make the light walk from left to right. If you have conducted the experiment at the bottom of the previous page you can even make it walk from right to left. All we have to do now is to combine these two versions of the program into one version that repeats the two sequences over and over.

 
   

;------------------------------------------------------------------------
;
; LESSON2C.ASM
;
; Walking up and down
;
;------------------------------------------------------------------------

            .IN   INIT01           Initialize the assembler

;------------------------------------------------------------------------
	
RELOAD      LXI   D,0111111111111111B Load both pattern in one go

WALKR       MOV   A,E              Output the bit pattern to port A
            OUT   PORTA
            MOV   A,D              Output the bit pattern to port B
            OUT   PORTB

            MVI   B,50             Load outer loop counter

DELAY1      MVI   C,250            Load inner loop counter

DELAY2      NOP                    Begin of inner loop
            NOP
            NOP
            NOP
            DCR   C                Decrement inner loop counter
            JNZ   DELAY2           Repeat until loop counter = 0

            DCR   B                Decrement outer loop counter
            JNZ   DELAY1           Repeat until loop counter = 0

            STC                    Set the carry
            MOV   A,D              Rotate pattern for port B first
            RAR
            MOV   D,A
            MOV   A,E              Then rotate pattern for port A
            RAR
            MOV   E,A

            JC    WALKR            Jump if it didn't fall out of port A

            LXI   D,1111111111111110B Load new pattern for both ports

WALKL       MOV   A,E              Output the bit pattern to port A
            OUT   PORTA
            MOV   A,D              Output the bit pattern to port B
            OUT   PORTB

            MVI   B,50             Load outer loop counter

DELAY3      MVI   C,250            Load inner loop counter

DELAY4      NOP                    Begin of inner loop
            NOP
            NOP
            NOP
            DCR   C                Decrement inner loop counter
            JNZ   DELAY4           Repeat until loop counter = 0

            DCR   B                Decrement outer loop counter
            JNZ   DELAY3           Repeat until loop counter = 0

            STC                    Set the carry
            MOV   A,E              Rotate pattern for port A first
            RAL
            MOV   E,A
            MOV   A,D              Then rotate pattern for port B
            RAL
            MOV   D,A

            JC    WALKL            Jump if it didn't fall out of port B
            JMP   RELOAD           Otherwise reload the bit patterns
 
 

There's nothing much to tell about this program that you haven't already seen. Basically it is a right roll program and a left roll program concatenated to each other, with some minor alterations at the junction and outer edges.

I have introduced one new instruction in this program, LXI. In fact LXI is the 16-bit version of MVI, and loads 2 registers with an immediate value at the same time. Hence one LXI instruction replaces the two MVI instructions of the previous program. Needless to say that the operand has to be 16-bit too.
The LXI instruction can only load register pairs BC, DE, HL and SP this way. LXI D,value loads the DE pair with value. The most significant byte ends up in D, while the least significant byte is stored in E.

If you look very carefully there is a small error in this program (don't look at the program, look at the behaviour of the LEDs). Do you notice that the time the left most and right most LEDs are on is twice the time of the other LEDs. Try to find out why by studying the program carefully.
The easiest remedy to this little problem is to shift the values of both LXI instructions by one bit. The first LXI instruction should get the value 1011111111111111B, while the second one gets value 1111111111111101B. This will do the trick, with one minor side effect, directly after reset the left LED will be skipped. We'll settle for this little side effect for now.

 
 

It's not the real thing yet!

Although this program appears to work in a similar way as the real Kitt scanner, it is still not the real thing. I remember that with the real Kitt scanner a total of 3 LEDs were on at the same time, walking up and down. At each corner the direction is reversed if only one LED is left on.
If we want to mimic this effect, we need another approach. We can't use the Carry flag to change directions anymore. Our next program will have 3 adjacent lights walk up and down the 16 LEDs, changing direction when only one light is left on.

 
   

;------------------------------------------------------------------------
;
; LESSON2D.ASM
;
; A Kitt scanner
;
;------------------------------------------------------------------------

            .IN   INIT01           Initialize the assembler

;------------------------------------------------------------------------

            MVI   D,00011111B      Initialize pattern
            MVI   E,11111111B
            MOV   H,E
            MOV   L,E

WALKR       MOV   A,E              Output the bit pattern to port A
            OUT   PORTA
            MOV   A,D              Output the bit pattern to port B
            OUT   PORTB

            MVI   B,50             Load outer loop counter

DELAY1      MVI   C,250            Load inner loop counter

DELAY2      NOP                    Begin of inner loop
            NOP
            NOP
            NOP
            DCR   C                Decrement inner loop counter
            JNZ   DELAY2           Repeat until loop counter = 0

            DCR   B                Decrement outer loop counter
            JNZ   DELAY1           Repeat until loop counter = 0

            MOV   A,L              See if we have to change direction
            ANI   01000000B
            JZ    GOLEFT           We must if b6 is a 0!
GORIGHT     STC                    Set the carry
            MOV   A,H              Rotate entire pattern, including
            RAR                     the extra carry byte
            MOV   H,A
            MOV   A,D
            RAR
            MOV   D,A
            MOV   A,E
            RAR
            MOV   E,A
            MOV   A,L
            RAR
            MOV   L,A

            JMP   WALKR            Always jump back to WALKR

;------------------------------------------------------------------------

WALKL       MOV   A,E              Output the bit pattern to port A
            OUT   PORTA
            MOV   A,D              Output the bit pattern to port B
            OUT   PORTB

            MVI   B,50             Load outer loop counter

DELAY3      MVI   C,250            Load inner loop counter

DELAY4      NOP                    Begin of inner loop
            NOP
            NOP
            NOP
            DCR   C                Decrement inner loop counter
            JNZ   DELAY4           Repeat until loop counter = 0

            DCR   B                Decrement outer loop counter
            JNZ   DELAY3           Repeat until loop counter = 0

            MOV   A,H              See if we have to change direction
            ANI   000000010B
            JZ    GORIGHT          We must if b1 is a 0!
GOLEFT      STC                    Set the carry
            MOV   A,L              Rotate entire pattern, including
            RAL                     the extra carry byte
            MOV   L,A
            MOV   A,E
            RAL
            MOV   E,A
            MOV   A,D
            RAL
            MOV   D,A
            MOV   A,H
            RAL
            MOV   H,A

            JMP   WALKL            Always jump back to WALKL
 
 

Most of this program is a direct copy of the lesson2c.asm program, so I will restrict myself to the differences.

The first difference is during initialization, where two extra bytes are initialized (in registers H and L). These two bytes will function as a multi-bit Carry. In fact each byte can hold the bits that roll out of the left and right edges of the visible part of the shift operation.

Just after the first double delay loop we find a completely changed Roll Right sequence of instructions. First of all the right most (hidden) byte of the roll registers is copied to the Accu, where a new instruction does something with it. This new instruction ANI will AND the value of the Accu immediately with the value following as operand.
An AND function will "logically AND" two 8-bit operands with each other. This means that if two aligning bits are both "1", the resulting bit will be "1". Otherwise the resulting bit will be "0".
Looking at our example, most bits in the result will become "0" because most bits of one of the operands are "0". Except for bit b6, which is ANDed by a "1" in the mask. This means that that bit will remain as it was in the L register.
So, if b6 is "0", the total result after the AND instruction will be 000H, and the Zero flag will be set. This will cause the following JZ instruction to jump to the GOLEFT label, effectively changing the roll direction. If b6 was "1", the total result after the AND instruction will not be 000H, thus the following JZ instruction will be ignored.
Bit b6 will only be "0" if two of the lights have rolled out of the right edge of the bar.

OK, suppose we didn't change direction yet, so we are now just behind the JZ GOLEFT instruction. What comes next looks very familiar, but instead of rolling just 2 registers we now have to roll all 4. The two extra registers are the ones holding the hidden bits at either side of the light bar.

After rolling all 4 bytes we can jump back to WALKR. We don't have to check if we have to change direction, because we already did.

The part of the program below the division line hides no more secrets, and does basically the same for the opposite direction.

 
 

Experiment tip:
The program above shows 3 adjacent LEDs walking up and down. Now alter the program to make 5 LEDs walk in a similar fashion, changing direction when only 1 light remains visible.

 
  Continue with Lesson 3 - Subroutines
 
  [Home] [Latest News] [Essentials] [Hardware] [The Build] [Programs] [Projects] [Downloads]
 
  Made in the UK