As mentioned in the last blog entry, timing is cricical down to the cycle. In order to make sure all branches of code execute in the exact same amount of time I’ve created a delay macro. This isn’t an optimal method, I’m sure there are ways to reduce the number of bytes this uses however it does the job, at least it does after a little debugging.
; DELAY for a specified number of clock cycles ; EXPECTS: ; "counter" 1 byte variable defined DELAY MACRO clocks ; eat up clock cycles 10 at a time IF ( (clocks / 10)> 0) mov counter, #(clocks / 10) ; 2 :loop jmp $ + 1 ; 3 jmp to next instruction jmp $ + 1 ; 3 jmp to next instruction djnz counter, :loop ; 2/4 (4 if <> zero) ; 10 cycles per loop, 8 for last loop ENDIF ; handle remaining delay 1-9 using nops IF ( (clocks // 10)> 0) REPT (clocks // 10) NOP ; 1 ENDR ENDIF ENDM
After coding the above delay macro, I programmed it into the SX52 and put the SXkey into debug mode which allows you to single step the processor one instruction at a time and view the programs memory/registers and flags. Using various delays of 1, 7, 10, 14 etc I noticed the NOP repeat was only generating a single nop rather than the expected number, this turned out to be because of a missing ENDR directive
The following screenshot (click for a larger view) shows the debugger running the DELAY(14) code and circled in red is the lone NOP instruction. A simple mistakebut one I’m glad I caught early. I might have wasted hours debugging video code later on.
With the delay loop out of the way, it’s time to make a start on generating accurate h/v signals. Hopefully by the end of tonight.