Timer maths 28X1

dennis

Member
I have been having trouble understanding the timer maths. I would like the timer to count in milliseconds at 8 MHz.
At 8Mhz a minor tick takes 32us so 1ms would need 1000/31 or 31,25 mnor ticks. So compromising on 31 ticks should give 0.992 ms which is good enough. So the preload value should be 65536-31 or 65505. So after 0.992 seconds i would expect the timer to read 1000. In order to achieve a 1 second loop the timer should read 1000/0.992 or 1008. Something must be wrong with this logic because the code below takes 1,2 seconds per cycle timing the Led flashing with a stopwatch over 20 cycles. I realise that there must be some overhead inbetween reading and resetting the time but 200ms seems excessive - where have I gone wrong !

' 28x1 timer experiment


setfreq m8
symbol looptime = 1008

autoloop:
settimer 65505
timer = 0

high 4
pause 100
low 4
do
loop while timer<looptime
goto autoloop

 
 

Jeremy Leach

Senior Member
I've got some suspicions about Timer too, as posted in software feedback.

In your code the Timer variable is constantly being read in the do ...loop. I wouldn't think this would affect how it's value is updated, but you could get rid of the do loop, and calculate a further pause value = [1008 - (Timer value after flashing LED)] * 2. Just to see if it makes a difference.


Edited by - jeremy leach on 15/05/2007 22:57:30
 

Technical

Technical Support
Staff member
Timer was never designed to operate this quickly. It is primarily designed to count seconds (or half seconds etc), not at the single millisecond level. Quite simply at this speed major ticks occur so often that some minor ticks will be lost whilst all those major ticks are being processed. This will lead to error.

We will clarify in the next manual update 'timers design purpose'.


Edited by - Technical on 15/05/2007 23:49:43
 

Jeremy Leach

Senior Member
Ok, thanks for the clarification.

Other questions though:
1. When timer is set, does it set the minor tick to zero?

2. Does a command Timer = 0 set the minor tick to zero as well as the major?

3. Would it still be possible on a 28X1 to manipulate the Timer via code, as Hippy discovered on other Picaxes in order to get this resolution? (probably a question for Hippy!).
 

hippy

Technical Support
Staff member
Re : Manipulating 28X1 Timer SFR's

It should work as on the other PICAXE's with a Timer1. It seems like the 28X1 does what we were doing there, setting the required SFR's, then checking if the internal Timer Overflow flag has been set, incrementing the timer variable and ( perhaps ) restarting the on-chip timer at that time, although it is hopefully left to be free-running until the next SETTIMER command.

The question I cannot answer is whether a PICAXE 28X1 by default alters the timer SFR's even when they are not being used, regularly like the output ports are updated or when a timer overflow occurs. If it does, then user code will be battling with the firmware code.

I expect the 28X1 timer implementation is very similar to how we did it 'by hand'; SETTIMER setting the pre-scaler and other SFR's to deliver a timer overflow at the right repetitive rate, and enabling the overflow flag being checked by polling between commands being executed. If the flag is polled between commands, this would explain why timer is not accurate and loses time when the overflow rate is faster than command execution.

If the overflow flag is always checked and then cleared this would make it impossible for the user code to directly detect that flag reliably, although the firmware does also set the to_flag which would likely be just as good to use.

Some testing using the previous developed code should hopefully show what is and isn't possible, and Rev-Ed's fuller description will also likely explain timer operation in more detail.

If the 28X1 leaves all timer associated SFR's alone when SETTIMER and SERVO haven't been used, then everything should work just as it did before. I'll do some experiments.
 

Technical

Technical Support
Staff member
The timer function uses timer1 with a hardware prescaler of 8. This means a minor tick is (FOSC/4/8) clock cycles, which at 4MHz is every 8us.

During the minor tick overflow interrupt routine a software postscaler of x8 is implemented, which means that the major tick actually occurs every 8th minor tick overflow interrupt, so 8x8us gives an effective minor tick length of 64us.

'timer' (ie major tick counter) is not reset to 0 during the settimer command. This is because people may wish to preload it to a certain value (e.g. let timer = x) before starting the timer to make good use of the timer overflow flag (toflag) - e.g. to activate an 'setintflags' interrupt after a specific time period.

If you wish to reset it simply use 'let timer = 0'. This has no affect on prescalers etc, so to reset the timer it is always better to disable it first ie

settimer off
let timer = 0
settimer XXX

Registers are only updated during the settimer command.

Edited by - Technical on 16/05/2007 13:08:45
 

Jeremy Leach

Senior Member
Thanks, but is the minor tick counter set to 0 with the SetTimer command? For instance you might have major ticks set for every second, you use SetTimer and Timer=0 thinking that you are starting timing from 0, but the minor counter is just about to overflow and cause a major tick, so the first recorded second will actually be far quicker than it should be.

Just wanting to be clear on how it works - it's a great function to have use of.

Edited by - jeremy leach on 16/05/2007 13:16:31
 

Technical

Technical Support
Staff member
Upon settimer command the minor tick word is set to the preload value (not 0). If it was 0, or any other value rather than the preload value, the very first minor tick would be of corrupt length.

If you used the commands the wrong way around (settimer to start timer and then timer = 0) corruption can occur as the timer=0 statement may appear half way through some ticks. That is why you should always
disable timer (if running)
let timer = 0
then start timer

Edited by - Technical on 16/05/2007 15:18:45
 

Jeremy Leach

Senior Member
Ah sorry, I meant to the pre-load value not 0.

Good, you've confirmed settimer command sets the minor tick word to the preload value. Thanks.
 

hippy

Technical Support
Staff member
Is this what we basically have ... ?
Code:
             SETTIMER OFF           SETTIMER number
Software          |                       |
- - - - - - - - - | - - - - - - - - - - - | - - - - - - - - - - - - - - - - - -
Hardware          |                       |
                  |                       |
        .---------'                       }-----------------------------------.
        |                                 |                                   |
        |     .--------.------------------{                                   |
        |     |        |                 \|/                                  |
        |     |        |          .----------------.                          |
       \|/   \|/       |          | Pre-Load Value |                          |
      .---------.      |          `----------------'                          |
      | R     S |      |                  |                                   |
      `----.----'      }-------------.    *<-----------.                      |
           :           | Clr     Clr |    |  Re-Load   |                      |
           :          \|/           \|/  \|/           |  Hidden Flag         |
.------.   /    .-------------.   .----------------.   |     __               |
| 1MHz |--O O-->| Divide by 8 |-->| Timer Hardware |---^--> |__| <------.     |
`------'        `-------------'   `----------------'  Set   |      Clr  |     |
                                                              |         |     |
                                                              |         |     |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | - - - - | - - |
Firmware                                                      |         |     |
                                                              |         |     |
        .-----------------------------------------------------^---------'     |
        |                                                                     |
        | ... Minor Tick       ... Major Tick                                 |
        |                     :                          toflag bit           |
        |    .-------------.  :   .----------------.         __               |
        `--->| Divide by 8 |----> | Timer Variable |------> |__| <----.-------'
         Inc `-------------' Inc  `--.-------------'  Set   |      Clr \
                                     | Read    /|\            |         |
                      .--------------'          | Set         |         |
                      |                         |             |         |
- - - - - - - - - - - | - - - - - - - - - - - - | - - - - - - | - - - - | - - -
Software              |                   .-----'         .---'         |
                     \|/                  |               |             |
               Let w0 = timer      Let timer = number     |      Let toflag = 0
                                                          |
                                                         \|/
                                                   If toflag = 1 Then
The bit I'm not clear about is when the timer variable divide by 8 is cleared.
 
Last edited:

Technical

Technical Support
Staff member
Wow, A* for your ascii art exam!

Yes, thats basically it.

1MHz clock input is dependant upon a 4MHz resonator - different speeds different values (rated value / 4).

Where you have 'hidden flag' that is actually a hardware interrupt (in PIC assembler PIR1,TMR1IF is set causing an TMR1IE interrupt), ie the PICAXE stops what it is currently doing and processes the timer1 minor tick interrupt. That is why very high preload values do not work very well, as the PICAXE ends up spending most of its time just processing the hardware interrupts.

Both pre and post scaler divide by 8s are reset at the same time, during the settimer command.

If setintflags is set appropriately the PICAXE interrupt will also occur when the toflag is set.

Edited by - Technical on 16/05/2007 16:44:42
 

hippy

Technical Support
Staff member
I'll take A+ because looking at it now I've cleared the hardware timer rather than pre-loaded it with SETTIMER, but you can tell I've done this before :)

With internal interrupts handling the 'hidden flag', I presume this means that an interrupt can occur <i>within </i> a command so ( ignoring jitter between activations ) timing should be very consistent for calls to the PICAXE Interrupt: routine. I also expect that interrupts are disabled during time critical critical such as SERIN and SEROUT etc which is where some 'loss' may occur.

For 'once a second timing' and similar this looks very useful, and like SETINT, it may be hard to get one's head round at first, but it looks to be easy to use once it's understood.

An additional question; do the 28X1 Beta's work as per the production releases with 5.1.1, or not, as I seem to be having problems with this code causing the Beta to continualy re-enter download mode -<code><pre><font size=2 face='Courier'>Symbol toflag = flag7 ' The timeout flag

SetTimer Off ' Stop the timer
SetIntFlags $80,$80 ' Interrupt on timeout
Timer=65535 ' First toggle will be in 1 sec
SetTimer 49910 ' Major tick every second
Do
' Other things here
Loop

Interrupt:
outpins = outpins ^ $FF ' Toggle all output pins
toflag = 0 ' Clear the timeout
Return </font></pre></code>

Edited by - hippy on 16/05/2007 17:22:59
 

hippy

Technical Support
Staff member
Jeremy : Good news and some not so good news.

Good news is that all my Timer1 code for the 18X runs okay on the 28X1. So it's possible to time commands etc as before, and polling the Timer Overflow flag can be used to set timed loops.

Not such good news with using the CCP1 hardware to generate a toggling output in the background to generate PWM, flash a LED or cause an interrupt as used in previous multitasking. Looks like something is altering the CCP1 SFR's and I'm also seeing data on the SERTXD line which I'm not using at all. Could be because it's a Beta or something else. That will need more investigation.
 

Jeremy Leach

Senior Member
Well I'm happy we can still call upon your previous ideas to time code accurately - I've already found it very useful.

It would be useful to be able to do the multi-tasking idea too, so I appreciate you taking the trouble to investigate.
 

Technical

Technical Support
Staff member
Hippy, the betas are considerably different to release, in fact setintflags is not in the beta firmware at all, so anything could happen! It would be best to send the beta's back for reprogramming to production firmware status.

As for CCP1 hacking, the pwm module is considerably different in the new chip so you will have to revisit the Microchip datasheets. Or use the hpwm and pwmout commands!

Edited by - Technical on 16/05/2007 20:29:40
 

hippy

Technical Support
Staff member
Thanks technical, I suspected that might be the case, with apparent problems not being faults in 28X1's.
 
Top