I now have ported both the bit detector function and the interrupt service routine (ISR) to assembly language. The ISR was the one that I was the most keen on optimizing because the C compiler added a bunch of wasteful stack pushes/pops that I didn't need, but I also benefited from optimizing the main loop also because I was able to move a global variable from memory into a register which saved a few cycles.. and when talking about microseconds at 14.7 MHz, a few cycles are worth a lot!
I am excited to test out my new routine on real hardware.
Here is the ISR routine below. As you can see, it's pretty short. It gets activated when a read pulse is received from the 5.25" disk drive.
// this interrupt is triggered when a pulse (connected to INT6 pin) starts (active low)
.global INT6_vect
INT6_vect:
in sreg_save, _SFR_IO_ADDR(SREG) ; preserve flags
; When we store this cycle value to the timer, it will be at most 1 cycle off so it is pretty accurate
; I got this value by counting cycles in the simulator/debugger.
; I want the timer to be relative to the start of the pulse so it's easier to visualize in my head.
; The timer will not overflow within the time that it is useful to us.
ldi u8Timer, 12
out _SFR_IO_ADDR(TCNT0), u8Timer
clr bPulseOccurred ; this register should already be 0 in every case but I want to be safe and this only uses 1 cycle
inc bPulseOccurred ; let main loop know that a pulse started
; we need to wait for the pulse to end or else this ISR will get triggered again immediately
wait_pulse_end:
sbis _SFR_IO_ADDR(PINE), 6
rjmp wait_pulse_end
out _SFR_IO_ADDR(SREG), sreg_save ; restore flags
reti
No comments:
Post a Comment