SPLat Logo

Example (Advanced): Indexing semaphores

NOTICE: We are updating our website. For product enquiries and orders please contact us directly.
NOTICE: SPLat Controls has moved. We are now at 1/85 Brunel Rd, Seaford, 3198. map

Example (Advanced): Indexing semaphores

Some semaphore instructions can be used with the index register. This allows you to devise quite sophisticated schemes. The most likely use for indexing would be where you are writing a program that works on several identical channels, like maybe a 4-channel lighting control system.

The advantage of using indexed addressing is that the same code can be used for all 4 channels, with a huge reduction in the size of the code. The alternative would be to have 4 almost identical copies of the program running simultaneously. That can certainly be done, but becomes a headache if you need to make any changes.

The down-side is that the code becomes more complicated, and in particular that the planning of memory storage becomes absolutely crucial to the success.

In indexed semaphore instructions the index register is added to the base address argument (not to the semaphore number). That fits in very nicely with the concept that you use the index register as the channel number. Here are the memory allocation directives for a hypothetical 4-channel lighting control system:

;Start the indexed memory at location 76 (arbitrary!)
Sems0       mEQU      76      ;Room for 8 semaphores
Sems1       mEQU      77      ;Room for 8 semaphores
Sems2       mEQU      78      ;Room for 8 semaphores
Sems3       mEQU      79      ;Room for 8 semaphores
CycleCount0 mEQU      80      ;A single byte variable
CycleCount1 mEQU      81      ;A single byte variable
CycleCount2 mEQU      82      ;A single byte variable
CycleCount3 mEQU      82      ;A single byte variable

;Define the semaphore bits
semA        sEQU      0
semB        sEQU      1
semC        sEQU      2
semD        sEQU      3
semE        sEQU      4

;Define outputs
Lamp0       oEQU      10
Lamp1       oEQU      11
Lamp2       oEQU      12
Lamp3       oEQU      13

Given these definition, the following subroutine code will count down any non-zero cycle count for those channels whose semaphore D is true and turn on its output if it hits zero (probably a total nonsense operation, but what the heck!).

Nonsense:
            LoadI     4            ;Easier to work backwards, gets DEC'd B4 1st use
NonsLoop:
            ItoX                   ;Test index register
            RetIfZ                 ;R/ just did 0
            DecI
            iRecallS  semD,Sems0   ;This will access bit D of byte Sems0+Index
            GoIfF     NonsLoop     ;Loop back if the semaphore is false
            iRecall   CycleCount0  ;Get the I'th cycle counter
            Push                   ;Make a duplicate
            GoIfZ     NonsLoop     ;Loop back if already at zero
            DecX
            Push                   ;Make a duplicate
            iStore    CycleCount0  ;Save the new value
            GoIfNZ    NonsLoop     ;Loop if non-zero
            iON       Lamp0        ;turn on the lamp
            GoTo      NonsLoop     ;Go and process the next one

A couple of points about this code: