Using timing functions - page 3 - General Discussion and Assistance - CHDK Forum

Using timing functions

  • 66 Replies
  • 10557 Views
Re: Using timing functions
« Reply #20 on: 26 / March / 2014, 21:45:32 »
Advertisements
>Seems strange that its slower reading a timer than an A/D converter.
I didn't quite word that right. What I meant was that with reading both the temp input and the usec timer at the same time it goes at that speed. So reading the timer is still somewhat faster.

>Did you try polling the USB input bit and see how much that slows things down ?  ( get_usb_bit() )
With get_usb_bit() it goes much slower, at about 0.3 million per second. So if the USB bit is going to be read it will probably need to be read directly, although I do recall hearing it involves checking the keyboard state, is that where the USB input state is read from and not an MMIO?

>IIRC, the watchdog timer takes 4 or 5 seconds to kick it.
I probably should have mentioned this, but I did have to decrease the time down to 16777216 with reading the timer and temp input to prevent it from crashing after about that much time.


Quote
Then try passing 0 as the first argument (which is the time base).
Doesn't really seem to like me doing that. The LED comes on, and the camera crashes shortly after. Also tried messing around with different numbers but it always crashes just after turning the LED on.


*

Offline srsa_4c

  • ******
  • 3979
Re: Using timing functions
« Reply #21 on: 27 / March / 2014, 18:31:40 »
Quote
Then try passing 0 as the first argument (which is the time base).
Doesn't really seem to like me doing that. The LED comes on, and the camera crashes shortly after. Also tried messing around with different numbers but it always crashes just after turning the LED on.
Reminder: I'm still talking about SetHPTimerAfterTimeout. I see no reason why passing constants as (timing) arguments shouldn't work, unless you're trying to do something lengthy or call a function you shouldn't call. Can you get a romlog after such a crash?

*

Offline reyalp

  • ******
  • 12072
Re: Using timing functions
« Reply #22 on: 06 / April / 2014, 19:27:02 »
From the other thread
Quote
HP timer functions, they use a 20 bit hw counter, retrieved by GetCurrentMachineTime() aka *(int*)0xc0242014
It occurs to me that it could be quite useful to implement our own sub-10ms time function, for CHDK code and script. You could for example sleep with ~10ms granularity, and then use a busy loop to for a more precise time.

It would also be nice to be able to time some things with better than 10ms precision.

Since the hardware counter wraps nearly (but not exactly  >:( ) once a second, it would be nice to have some higher level function to deal with this. Perhaps something like: http://pubs.opengroup.org/onlinepubs/009695399/functions/gettimeofday.html

I was curious what level of precision I would get reading this from lua:
Code: [Select]
con 11> c
connected: Canon PowerShot D10, max packet size 512
con 4> =t={} for i=1,100 do local t0,t1=peek(0xc0242014),peek(0xc0242014) table.insert(t,t1-t0) end return t
5:return:table:{[1]=11,[2]=8,[3]=8,[4]=8,[5]=7,[6]=8,[7]=7,[8]=8,[9]=7,[10]=9,[11]=8,[12]=7,[13]=7,[14]=8,[15]=8,[16]=8,
[17]=8,[18]=8,[19]=8,[20]=8,[21]=7,[22]=7,[23]=8,[24]=14,[25]=7,[26]=7,[27]=8,[28]=8,[29]=7,[30]=7,[31]=8,[32]=8,[33]=7,
[34]=7,[35]=7,[36]=7,[37]=7,[38]=8,[39]=7,[40]=8,[41]=8,[42]=8,[43]=7,[44]=8,[45]=7,[46]=8,[47]=8,[48]=7,[49]=10,[50]=8,
[51]=7,[52]=8,[53]=8,[54]=7,[55]=8,[56]=7,[57]=8,[58]=7,[59]=7,[60]=8,[61]=7,[62]=8,[63]=8,[64]=7,[65]=8,[66]=8,[67]=7,[
68]=8,[69]=8,[70]=8,[71]=8,[72]=8,[73]=8,[74]=12,[75]=7,[76]=8,[77]=7,[78]=8,[79]=7,[80]=8,[81]=7,[82]=7,[83]=8,[84]=7,[
85]=8,[86]=7,[87]=8,[88]=7,[89]=8,[90]=8,[91]=7,[92]=8,[93]=7,[94]=8,[95]=7,[96]=8,[97]=7,[98]=7,[99]=10,[100]=8,}
con 5> dis
___> c
connected: Canon PowerShot A540, max packet size 512
con> =t={} for i=1,100 do local t0,t1=peek(0xc0242014),peek(0xc0242014) table.insert(t,t1-t0) end return t
1:return:table:{[1]=22,[2]=17,[3]=18,[4]=17,[5]=16,[6]=18,[7]=15,[8]=16,[9]=15,[10]=18,[11]=16,[12]=15,[13]=15,[14]=16,[
15]=15,[16]=16,[17]=15,[18]=17,[19]=16,[20]=15,[21]=15,[22]=16,[23]=15,[24]=38,[25]=16,[26]=15,[27]=16,[28]=15,[29]=15,[
30]=15,[31]=15,[32]=15,[33]=1535,[34]=19,[35]=16,[36]=15,[37]=15,[38]=15,[39]=15,[40]=15,[41]=15,[42]=15,[43]=16,[44]=16
,[45]=16,[46]=15,[47]=15,[48]=15,[49]=31,[50]=16,[51]=16,[52]=15,[53]=15,[54]=15,[55]=15,[56]=15,[57]=15,[58]=15,[59]=15
,[60]=15,[61]=15,[62]=15,[63]=15,[64]=15,[65]=15,[66]=19,[67]=15,[68]=15,[69]=15,[70]=15,[71]=15,[72]=15,[73]=16,[74]=36
,[75]=16,[76]=15,[77]=15,[78]=16,[79]=15,[80]=15,[81]=15,[82]=15,[83]=19,[84]=16,[85]=15,[86]=15,[87]=15,[88]=15,[89]=16
,[90]=15,[91]=16,[92]=15,[93]=15,[94]=15,[95]=16,[96]=15,[97]=15,[98]=15,[99]=31,[100]=16,}
con 1> dis
___> c
connected: Canon PowerShot ELPH 130 IS, max packet size 512
con> =t={} for i=1,100 do local t0,t1=peek(0xc0242014),peek(0xc0242014) table.insert(t,t1-t0) end return t
1:return:table:{[1]=11,[2]=9,[3]=8,[4]=8,[5]=7,[6]=182,[7]=9,[8]=7,[9]=8,[10]=7,[11]=8,[12]=7,[13]=7,[14]=8,[15]=8,[16]=
9,[17]=8,[18]=8,[19]=7,[20]=8,[21]=7,[22]=7,[23]=8,[24]=15,[25]=7,[26]=7,[27]=7,[28]=8,[29]=8,[30]=7,[31]=8,[32]=8,[33]=
7,[34]=8,[35]=8,[36]=8,[37]=8,[38]=7,[39]=8,[40]=7,[41]=7,[42]=8,[43]=7,[44]=8,[45]=7,[46]=8,[47]=8,[48]=7,[49]=11,[50]=
7,[51]=7,[52]=8,[53]=7,[54]=8,[55]=8,[56]=7,[57]=8,[58]=7,[59]=8,[60]=7,[61]=8,[62]=7,[63]=8,[64]=7,[65]=8,[66]=8,[67]=8
,[68]=7,[69]=8,[70]=7,[71]=7,[72]=7,[73]=8,[74]=13,[75]=8,[76]=7,[77]=8,[78]=8,[79]=7,[80]=8,[81]=7,[82]=7,[83]=8,[84]=8
,[85]=8,[86]=7,[87]=8,[88]=7,[89]=8,[90]=8,[91]=8,[92]=7,[93]=8,[94]=7,[95]=8,[96]=7,[97]=8,[98]=8,[99]=10,[100]=8,}
Don't forget what the H stands for.

Re: Using timing functions
« Reply #23 on: 06 / April / 2014, 19:45:56 »
It would also be nice to be able to time some things with better than 10ms precision.
Strange you should mention this now - I've been working on this today somewhat. 

I have a UART style receiver coded in Lua that uses the new HP timer to receive a 16 bit packet via the USB 5V line in under 80 mSec.  Great for talking to a cheap external uC (Arduino etc) that does not have a USB master protocol stack.

But with the current encoding scheme, to have one camera send 16 bits to another,  I need a way to generate 2 and 5 mSec duration pulses accurately while transmitting.   Started to play with set_yield() to keep the transmit function running for the 80 mSec transmit window.  But a fast timer would help a lot too so I was looking at GetCurrentMachineTime() .

The goal here is to see if I can do all the "high speed" communications in a Lua script so that we don't need to add specialized C functions that the user cannot then tweak for a specific application ( more bits, less bits,  different baud rate etc) without a lot of predefined setup parameters.

I was curious what level of precision I would get reading this from lua:
The A540 seems to run at a different speed than the other two cameras ?  As I posted earlier,  I've wondered if some cameras actually run the kbd task (and thus the script engine) on a 20 mSec tic time rather than 10 mSec.  That would explain some of the strange timing values reported.
« Last Edit: 06 / April / 2014, 19:58:26 by waterwingz »
Ported :   A1200    SD940   G10    Powershot N    G16


*

Offline reyalp

  • ******
  • 12072
Re: Using timing functions
« Reply #24 on: 06 / April / 2014, 20:00:43 »
The A540 seems to run at a different speed than the other two cameras ?
It's well established that the digic 2 CPU is slower. The other two are digic 4, though the elph130 is faster than D10 in some areas (edit: USB is significantly faster, for example).

The times above should mostly reflect the time it takes to actually execute the peek() call in lua (~8us on digic 4, ~15 on digic 2) plus some outliers from interrupts or Lua yield (I didn't use set_yield in this test)

This means that for lua, there probably wouldn't be much point in < 100us precision, but that would still be a lot better than the 10ms get_tick_count.

Quote
  As I posted earlier,  I've wondered if some cameras actually run the kbd task (and thus the script engine) on a 20 mSec tic time rather than 10 mSec.  That would explain some of the strange timing values reported.
Have you looked at physw_sleep_delay?
Even where the sleep time is 10ms, it's certainly not guaranteed kbd_task will run at exactly 10ms intervals.

edit:
Nano, micro? whatever!
« Last Edit: 06 / April / 2014, 20:14:11 by reyalp »
Don't forget what the H stands for.

*

Offline srsa_4c

  • ******
  • 3979
Re: Using timing functions
« Reply #25 on: 08 / April / 2014, 18:06:06 »
It occurs to me that it could be quite useful to implement our own sub-10ms time function, for CHDK code and script. You could for example sleep with ~10ms granularity, and then use a busy loop to for a more precise time.

It would also be nice to be able to time some things with better than 10ms precision.

Since the hardware counter wraps nearly (but not exactly  >:( ) once a second, it would be nice to have some higher level function to deal with this. Perhaps something like: http://pubs.opengroup.org/onlinepubs/009695399/functions/gettimeofday.html
We could also use a separate hw counter. If the information here is correct, the 0xc0210xxx timers do have a "reload value" (I guess that means they can wrap upon reaching a specified count). The a3200 firmware only uses one of these timers, there are some generic support routines (they can be found by searching for 0xc0210000). I have even found them in the sx280 firmware (I was curious).
Since the "Restart" fw function specifically halts this (0xc0210200) counter, we may need to do the same if we ever start to use one (not sure why it's halted, maybe related to its interrupt).

Re: Using timing functions
« Reply #26 on: 11 / April / 2014, 07:17:39 »
Wasn't really sure which thread this should go in, but it's somewhat related to timing.

The following code was run once at the press of a button on both my S110 and SX40.
Code: [Select]
void delay_test()
{

    long variable_to_increment = 0;
    while (variable_to_increment < 1073741824)
    {
        variable_to_increment++;
    }
    if (variable_to_increment > 1073741820) //Just to be sure the above isn't somehow skipped
    {
        *((volatile int *) AF_LED_ADDRESS) = LED_ON;
    }
}
And the LED turns on immediately on both those cameras. (The previous test that was similar to this was done on the ixus 65)
And if it's modified so that the LED turns on before it counts to that number, and turns off afterwards, it barely blinks on long enough to see it. Also, if I add msleep(1) and change the repetitions down to 100, it will blink briefly.

I've also had problems with the following, which is meant to wait until reaches a certain time. But instead it just freezes (not the live preview) if wait_until_this_time is larger than the time at 0xc0242014 (of course it is set lower than 2^20).
do { } while (*(int*)0xc0242014 < wait_until_this_time);

Any ideas of what could be wrong in these cases?

Re: Using timing functions
« Reply #27 on: 11 / April / 2014, 10:36:21 »
And the LED turns on immediately on both those cameras. (The previous test that was similar to this was done on the ixus 65)
Is "variable_to_increment" local to the function in one case and global in the other? This will change the compiled code and speed a lot.  The compiler might even optimize the loop out completely.
Ported :   A1200    SD940   G10    Powershot N    G16


Re: Using timing functions
« Reply #28 on: 11 / April / 2014, 11:09:30 »
Quote
Is "variable_to_increment" local to the function in one case and global in the other? This will change the compiled code and speed a lot.  The compiler might even optimize the loop out completely.
It's local to the function edit: actually I just looked at the old one and realised it isn't so I'll make it global for this one and see if it works. /edit. I also tried it with for (i=0; i < 16777215; i++) and some other stuff.

But so it's possible then that the compiler might realise that all it needs to do to get out of the loop is to set variable_to_increment to 1073741824 and just get rid of the loop?
I also had put unread_variable = *(short*)0xc090004a; in it and that made no difference, so perhaps the compiler even realised that that wasn't necessary and got rid of it aswell? I will try something else and see if I can get it to actually delay.
« Last Edit: 11 / April / 2014, 11:13:25 by Recyclojunk64 »

*

Offline srsa_4c

  • ******
  • 3979
Re: Using timing functions
« Reply #29 on: 11 / April / 2014, 11:19:19 »
But so it's possible then that the compiler might realise that all it needs to do to get out of the loop is to set variable_to_increment to 1073741824 and just get rid of the loop?
I also had put unread_variable = *(short*)0xc090004a; in it and that made no difference, so perhaps the compiler even realised that that wasn't necessary and got rid of it aswell? I will try something else and see if I can get it to actually delay.
No need to guess, locate your functions in core/main.bin.dump or post that file here.
You could try to put
Code: [Select]
asm volatile ("nop\n");inside you loop, that might stop the compiler from optimizing it out.

 

Related Topics