The Rabbit Processor Timer B is misunderstood and poorly documented. This tech-note just covers some of the issues with timer B.
ZW provides samples for timer B. These are deceptively simple. They set up for a 92us interrupt on a 22mHz CPU. They seem to imply that by just using a different constant to load into the timer registers, a different period can be obtained. This is not true.
Timer B is a free running 10-bit counter. There are two match registers. It seems logical that the timer counts up to the match register and then resets to 0. This is not the case and would not support two match registers.
A match triggers an interrupt and the counter keeps counting. Having two match registers allows using the timer to generate a PWM signal by testing which match occurred.
In order to generate an interrupt on a consistent period, you will need to reload the match registers each time with a new value. Suppose you need an interrupt every 600 counts. You would need to load the match register with the following values:
528 .. and so on.
Basically you add 600 to the current match register and use a modulo 1024. To make this more difficult, the match register is stored as two bytes, the lower 8 bits in the low match reg and bits 8 and 9 in the topmost bits of the high match reg. This makes working with the values a bit difficult. It is best to do this in assembly:
ld hl,(last_match) ld a,0x3f ; set bits 8-13 so carry from low 8 bits or h ; propagates to bit 14 ld h,a ld de,(increment) ; this is preformatted as bits 98------76543210 add hl,de ; HL is new match value ld (last_match),hl ; save for next time
Timer B has several clock modes:
This increases the range of the timer. Note: Timer A1 may also be used by the serial ports.
I won't go into how to set up all of these modes. It is documented in the Rabbit manual. The timer ISR will need to be in assembly language for speed.
Now with the basics of how the timer works, the SHDesigns Timer B library can be used as an example. If you wish to write your own code to use the timer, this library can serve as an example on how to set up the timer in all of the clock modes and has an efficient ISR.
If you would rather not write Timer B code, you can just use the library. It can be used to call a user function from once every 20us down to once every 1500 seconds. All from a single init call; no assembly necessary. The Timer B library can be downloaded from the Free Libraries page.
One final note, when generating pulses on I/O pins from an ISR there will be jitter in the output due to the the latency of the interrupt. One way to avoid this is to set up the I/O port to be clocked on a Timer B match. When the ISR writes a value to the I/O pin, it is not output until the next match. This output always occurs one clock after the match occurs, so there is never any jitter due to interrupt latency. This also allows the timer ISR to be delayed by up to one time period due to other interrupts and times when interrupts are disabled. The pulses will always be jitter free.
Note: if you just need to generate a free-running clock, an unused serial port can be used with no software overhead. Look at the tech note Using a Serial Port to generate a continuous clock.