AndersNielsen wrote:
If I throw a NOP in there it will sample every 8 cycles and the sampling will be even and simplify the math, right?
Yes I think so. You do also need to ensure the branch is not crossing a page boundary otherwise it costs an extra cycle.
But by this point the hardware timer is not really helping you as you're having to cycle-count anyway - you can instead just have A be a multiple of 5 and do:
Code:
sec ; 2 cycles
delayloop:
sbc #1 ; 2 cycles
bne delayloop ; 3 cycles, -1 the last time
Or move the "sec" into the loop and have A be a multiple of 7, or... lots of options of course!
The vdelay project at GitHub has some nice routines that perform precise delays of any duration above about 30 cycles:
https://github.com/bbbradsmith/6502vdel ... ay_short.sAll that said, one case where the hardware timer will work in your favour is if you set can it up during the start bit and have it automatically count down again from just the right value for subsequent bits - it removes some sources of accumulated drift during the byte and means you don't need to carefully cycle-count your byte reading loop, you just need to start the timer at the right time. If the hardware timer doesn't have VIA T1-like latches that you can use for automatically setting it to a new value when it hits zero, then you could maybe reset it with the correct bit-to-bit gap after each bit - however you lose a lot of the benefit.
Another option - if supported by the hardware - is to set the timer up as you are already doing for the start bit, but then just let it tick down through negative numbers after the start bit, without resetting it. Now you want to read the second bit when the timer reaches -13, the third when it reaches -26, the fourth at -39, etc - just subtracting 104/8 with each time. This is probably my favourite as it once again removes all possibility of drift during the course of a byte.
Code:
; store 0 in 'targetvalue' and set up timer to skip start bit
; ... then for each bit...
nextbit:
lda targetvalue ; starts at 0
waitforbit:
cmp READTDI ; compute targetvalue - TDI
sec ; for the upcoming sbc
bpl waitforbit ; positive => wait longer
sbc #13 ; next bit is 13*8 = 104 cycles after this one
sta targetvalue
; ... read bit, store bit, loop back to nextbit
waitforbit is an 8-cycle loop. The bit read timing may be off by +/-8us, but that should be OK and it won't lead to accumulated drift over the course of the byte. (Edit - it's probably less important for it to be an 8-cycle loop in this case as we've removed the need for precise cycle counting except between the interrupt and the point the timer register is loaded.)
(Another edit - by the way, a nice trick for shifting in exactly 8 bits is to initialise the target memory location with $80, then ROR the bits into it, and after each ROR, if the carry is clear, loop back for another bit. That single set bit will make its way along the byte, and ultimately terminate the read loop, without needing to also manipulate an index register.)