ISRTIMER.BAS Question

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

Post Reply
xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

ISRTIMER.BAS Question

Post by xor » Mon Nov 27, 2006 3:29 am

Using the Swordfish ISR Timer library is very fascinating. I recently wrote an accurate extended timer for a 48MHz PIC in another compiler that I would like to move to Swordfish...with some new enhancements possibly. My question revolves around the register saving process and this instruction:

Code: Select all

Timer.Items(Timer1).Interval = 100       // 100ms
Is this an accurate 100ms...to the nearest 83ns (w/48MHz clock)? A 16-bit timer count of -37,500 provides 100ms. Even so, it was necessary in the other compiler to compensate for machine cycles for the jump to interrupt, register saving, and reloading of the timer to get an accurate 100ms interrupt cycle.

Just wondering about the accuracy of the above interval.

Also, a second & thrid question. When setting, for instance, TMR1 = -20000, does the compiler interpret this as 65536 - 20000 (0 - 20000)? And, while I'm asking questions, is the loading TMR1H first, and then TMR1L next even though the form TMR1L.AsWord is used?

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Post by David Barker » Mon Nov 27, 2006 3:05 pm

> Just wondering about the accuracy of the above interval.

The ISRTimer module is just a general purpose module that allows you to have multiple 16 bit timers. The timeout math is correct, but the end result will be skewed by the time taken to process the interrupt iseft. In short, it is not (or meant to be) a precision timer. For example, you might want to flash and LED with one timer and scan a keypad with another whilst at the same time wating for serial input. In this example, the ISRTimer library would be ideal (TimB posted a module on the wiki which uses the ISRTimer module to scan a keypad and it works really well). However, much of the code is still valid if you want to create a precision timer.

> When setting, for instance, TMR1 = -20000, does the compiler
> interpret this as 65536 - 20000

Ideally, you need to load TMR1 with a positive word value (for example, 65536 - 20000 = 45536). If you try and load a negative constant value, you get a 'constant expression violates subrage bounds' error, because TMR1 is a word.

You can typecast of course. For example,

Code: Select all

timer = word(-20000)
which will force the compiler to stuff $B1E0 (45536) into TMR1

> loading TMR1H first, and then TMR1L next even though the
> form TMR1L.AsWord is used

Yes, high byte first. In the above example, the ASM generated is

Code: Select all

       
        MOVLW 177
        MOVWF _TMR1L#M0_U16H,0 <-- HIGH BYTE
        MOVLW 224
        MOVWF _TMR1L#M0_U16,0

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Mon Nov 27, 2006 10:10 pm

Just some comments on the ISRTimer modual

It uses a calculation that works out the interval based on the xtal freq. But this calculation fails once you get to > ~22mhz when you want a 100ms delay.

The issue is that the timer will roll-over before the 100ms is up, so your better off using pre-scalars etc but unless your xtal is right timing can suffer.

One trick when reloading is to add the reload to the timer this takes into account and delay before it gets to your code. Turn off the timer before you do so and then back on. This period will be known and will be constant.

Even if you have a long period before you get the cpu time as when your running high low interrupts it will correct its self.

BTW if you enable 16 bit read of timers READ THE DATA SHEET as it will trip you up.

The one I like best is to use TMR2 load a fre regs and set it going. Never have to reload again. If your xtal is right then timing will be 100% always.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Mon Nov 27, 2006 10:20 pm

Just noticed the "Yes, high byte first. In the above example, the ASM generated is"

That's neat!!

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Mon Nov 27, 2006 11:52 pm

David Barker wrote:The ISRTimer module is just a general purpose module that allows you to have multiple 16 bit timers. The timeout math is correct, but the end result will be skewed by the time taken to process the interrupt iseft. In short, it is not (or meant to be) a precision timer. For example, you might want to flash and LED with one timer and scan a keypad with another whilst at the same time wating for serial input. In this example, the ISRTimer library would be ideal (TimB posted a module on the wiki which uses the ISRTimer module to scan a keypad and it works really well). However, much of the code is still valid if you want to create a precision timer.
Thanks for that information. Is there an example (that I've likely overlooked) that will allow the management of a timer interrupt "manually"? I can set up the timer registers, it's the syntax of the interrupt handler where I could use some direction.
Ideally, you need to load TMR1 with a positive word value (for example, 65536 - 20000 = 45536). If you try and load a negative constant value, you get a 'constant expression violates subrage bounds' error, because TMR1 is a word.

You can typecast of course. For example,

Code: Select all

timer = word(-20000)
which will force the compiler to stuff $B1E0 (45536) into TMR1
Understood.
> loading TMR1H first, and then TMR1L next even though the
> form TMR1L.AsWord is used

Yes, high byte first. In the above example, the ASM generated is

Code: Select all

       
        MOVLW 177
        MOVWF _TMR1L#M0_U16H,0 <-- HIGH BYTE
        MOVLW 224
        MOVWF _TMR1L#M0_U16,0
Good job. :D

xor
Posts: 286
Joined: Sun Nov 05, 2006 1:15 pm
Location: NYC
Contact:

Post by xor » Tue Nov 28, 2006 12:06 am

TimB wrote:The one I like best is to use TMR2 load a fre regs and set it going. Never have to reload again. If your xtal is right then timing will be 100% always.
This is a great idea. I worry about 48MHz burning through the count too fast, but certainly worth a try at some level.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Tue Nov 28, 2006 7:42 am

I do through recommend you use the "add current Tmr Val to reload2 technique if your not already doing so.

This is what I use but with Daves High Byte Low Byte handling its more straight forward.

IntsOff
IntTemp.BYTE0 = Timer0.BYTE0
IntTemp.BYTE1 = Timer0.BYTE1
IntTemp = IntTemp + TMR0_VAL
TMR0H = IntTemp.BYTE1
TMR0L = IntTemp.BYTE0
IntsOn

Post Reply