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

Using timing functions

  • 66 Replies
  • 25053 Views
Re: Using timing functions
« Reply #50 on: 15 / April / 2014, 19:08:21 »
Advertisements
More progress. I realised that, with the timing accuracy of the last test, there's really no need to use pulse-widths to transmit the data, it can just be bit-banged directly, as long as the start bit is synchronised beforehand (the slave will sample in the middle of each bit).
It's been quite a while, but IIRC for direct bit-banging you need to be able to sample at about 8x the bit speed for a reliable bit banging UART receiving an 8 bit byte.  So using the HP timer running at 1mSec means 8mSec/bit.
Ported :   A1200    SD940   G10    Powershot N    G16

Re: Using timing functions
« Reply #51 on: 16 / April / 2014, 03:40:18 »
Hi,

@Recyclojunk64:

where do you place your code for void master_send_bit()? And where do you call it from?
I mean what is the start action in the master to send the data to teh slave?

Yesterday my new oscilloscope arrived. If my 7 years old daughter will let me at the easterdays I will find some time to go ahead with my mikcorcontroller to steer the S110 project.
Problem for me right now is to understand the HP Timer stuff and find the correct place to add the code for sending commands from my mikroprocessor to S110. This must work in rec and play mode.
I have still to learn a lot ;-).


1st question:

Code: [Select]
_SetHPTimerAfterTimeout(0,master_wait_untill,master_send_bit,master_send_bit,0);

What are the parameters of _SetHPAfterTimeout and why two times master_send_bit as callback are entered here, what does the last 0 mean?

2nd question:
The HP Timer stuff in which trunk is it? What HP timer functions are available, I remember in one thread there were few?

Thanks again!
2 x IXUS 860IS 100c
2 x Powershot S110 103a

Re: Using timing functions
« Reply #52 on: 16 / April / 2014, 04:36:39 »
Quote
It's been quite a while, but IIRC for direct bit-banging you need to be able to sample at about 8x the bit speed for a reliable bit banging UART receiving an 8 bit byte.  So using the HP timer running at 1mSec means 8mSec/bit.
I'm not completely sure what you mean, if the slave samples the input at the middle of each bit sent from the master, it would work wouldn't it? The start bit will be syncronised and the timing accuracy of sending the bits is pretty good, and I'm only sending maybe 64 bits at the most.


Quote
where do you place your code for void master_send_bit()? And where do you call it from?
I mean what is the start action in the master to send the data to teh slave?
In wrappers.c, so that they get compiled as normal ARM code. srsa explained it better, I can't remember which thread though.

As for the start action, I'm still working on it right now. Here's what I have so far, init_LED_flasher is called from kbd.c on a certain button-press (for testing):

Code: [Select]
void init_LED_flasher()
{
    if (start_LED_flasher)
    {
        start_LED_flasher = 0;
        master_begin_transmission();
    }
}

int master_current_bit = 0;
int master_wait_untill = 65536;
void master_send_bit();
void master_begin_transmission();
void master_begin_transmission_();

unsigned short master_message_buffer = 54321; //Just a random number at the moment

void __attribute__((optimize("O0"))) master_begin_transmission()
{
    while (*(int*)0xc0242014 > 1024)
    {
        //wait till it's at the start, wrap will coded later
    }
    *((volatile int *) AF_LED_ADDRESS) = LED_ON; //Signal slave which will check every 10ms or so
    _SetHPTimerAfterTimeout(0,master_wait_untill,master_begin_transmission_,master_begin_transmission_,0);
    master_wait_untill+=1024;
}

void master_begin_transmission_()
{
    *((volatile int *) AF_LED_ADDRESS) = LED_OFF; //Signal slave, which will wait 1536uS before starting to sample the bits
    _SetHPTimerAfterTimeout(0,master_wait_untill,master_send_bit,master_send_bit,0);
}
   



void master_send_bit()
{
    if (master_message_buffer & (1 << master_current_bit)) //get the current bit
    {
        *((volatile int *) AF_LED_ADDRESS) = LED_ON;
    }
    else
    {
        *((volatile int *) AF_LED_ADDRESS) = LED_OFF;
    }
    if (master_current_bit < 16) //16 bits for now
    {
        master_current_bit++;
        master_wait_untill+=1024;
        _SetHPTimerAfterTimeout(0,master_wait_untill,master_send_bit,master_send_bit,0);
    }
    else
    {
        master_wait_untill = 65536; //set it back to how it was before
        start_LED_flasher = 1; //allow it to run again
    }
}
The number 65536 is unnescesarily high, but just for testing.




Quote
Yesterday my new oscilloscope arrived. If my 7 years old daughter will let me at the easterdays I will find some time to go ahead with my mikcorcontroller to steer the S110 project.
What oscilloscope did you get? I'm going to write the accompanying code for the slave today hopefully, if it works it should be able to listen to a microcontroller fairly well (as long as the microcontroller's clock is accurate enough)

Quote
What are the parameters of _SetHPAfterTimeout and why two times master_send_bit as callback are entered here, what does the last 0 mean?
See here. The last zero doesn't mean anything, apparently it doesn't do anything.

Quote
The HP Timer stuff in which trunk is it? What HP timer functions are available, I remember in one thread there were few?
I think they're already in there but if not just add this to wrappers.c (or just add whatever's not there)
Code: [Select]
extern int _SetTimerAfter(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
extern int _SetTimerWhen(int time, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
extern int _CancelTimer(int);
extern int _SetHPTimerAfterNow(int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
extern int _SetHPTimerAfterTimeout(int time_base, int delay, int(*good_cb)(int, int), int(*bad_cb)(int, int), int whatever);
extern int _CancelHPTimer(int);

And you will need to add these to stubs_entry_2.S if they aren't already there:
Code: [Select]
NHSTUB(SetTimerAfter, )
NHSTUB(SetTimerWhen, )
NHSTUB(CancelTimer, )
NHSTUB(SetHPTimerAfterNow, )
NHSTUB(SetHPTimerAfterTimeout, )
NHSTUB(CancelHPTimer, )
you will need to find the addresses for them from the functions by address.csv file. They are different from the ones on mine as the firmware version is different, so I backspaced them.

Re: Using timing functions
« Reply #53 on: 16 / April / 2014, 06:22:10 »
Hi Recylojunk64,

thanks for quick reply.

Quote
What oscilloscope did you get?

I bought a Voltcraft MSO-5102B, this is a 2 analog channel oscilloscope with a bandwidth of 100MHz and samplingrate of 1 GB/s (1 channel) and 500MS/s (2 channel).
Further it has a built in 16 channel logic analyzer. I think behind there is Tectronix DSO because I have a very old one from Tectronix and the physical buttons, menues and software of Voltcraft are quite similar.
I think it will be quite useful for my current project ;-).

Here is a link to the english manual:

http://www.produktinfo.conrad.com/datenblaetter/100000-124999/122482-an-01-en-VOLTCRAFT_MSO_5102B_DIGI_SPEICHEROSZIL_.pdf

With your and waterwingz information I think I will have a lot to do hopefully I will get some results during the easter holidays...

Thanks so far!
« Last Edit: 16 / April / 2014, 06:26:22 by mr.burns »
2 x IXUS 860IS 100c
2 x Powershot S110 103a


*

Offline srsa_4c

  • ******
  • 4451
Re: Using timing functions
« Reply #54 on: 16 / April / 2014, 16:45:00 »
Quote
What are the parameters of _SetHPAfterTimeout and why two times master_send_bit as callback are entered here, what does the last 0 mean?
See here. The last zero doesn't mean anything, apparently it doesn't do anything.
That parameter (named 'whatever') is what the timer callbacks will get as second parameter (it will be passed unchanged). It can help if you re-use the same timer callback function.

Re: Using timing functions
« Reply #55 on: 16 / April / 2014, 19:50:04 »
That parameter (named 'whatever') is what the timer callbacks will get as second parameter (it will be passed unchanged). It can help if you re-use the same timer callback function.
FWIW, it's used in the HP timer code in the dev trunk ( platform/generic/wrappers.c ) to pass the current timer interval.  This allows the script function enable_highspeed_usb() to pass different timing intervals through to the interrupt callback code.
Ported :   A1200    SD940   G10    Powershot N    G16

Re: Using timing functions
« Reply #56 on: 19 / April / 2014, 13:21:36 »
Been a little busy lately, but I managed to get the slave code done (actually it's just a modified version of the master code). Wraps have been done aswell, so the only delay before transmitting will be how long it takes to alert the slave that the transmission will be sent (which is dependent on how often the slave checks the input line).

As for how it works, well I sent a 32 bit packet over it several times, and it didn't become corrupted. I could still add error-detection/correction if necessary (probably in the form of a bit-sum or whatever they're called, and if there's an error it will either alert the user, or request a new packet if the slave also has a photo-diode over it's LED).


As some cameras (mostly superzooms) have 32 bits of focus, I will probably need to be sending more than 32 bits over to the slave. I'm guessing the easiest way to do this would be to send two separate 32-bit packets, probably with a sync-signal inbetween.

Anyway, I'll refine and clean up the code and probably do a bit more testing, then the transmission part of this project should be finished, most likely tomorrow morning. It should also be useful for other applications, such as communicating with a microcontroller. One thing I forgot to test today was transmission speeds faster than 1 bit per ms, but they will likely work aswell (I'll test them tomorrow), but this speed should be suitable for most purposes.

Re: Using timing functions
« Reply #57 on: 20 / April / 2014, 14:41:15 »
I've done a bit more testing, and found it somewhat unreliable with speeds faster than one bit per millisecond. A quick check on the scope for what the slave was seeing on it's LED showed that the problems were caused by the not-steep-enough gradient when the LED turned off and the input went high. Most likely a combination of the limited current available to 'pull up' the ADC's input and some capacitance from somewhere (probably a small capacitor to filter out spikes from the ADC's sampling). Modifying the code to make the sync pulse a falling edge instead (LED turning on) did help, but I'll have to test it properly tomorrow (I'll upload a photo of the scope screen then aswell)


But anyway, here is the code for both the receiving and transmitting end. I didn't really get a chance today to give it a thorough testing, but it seems to work fine at one bit per millisecond. Slave and master will get the same code, but the appropriate function will be called in each case. Any comments about what could be done better or what might likely cause problems would be appreciated.


I'll get a thorough test done tomorrow to decide whether or not it's worth doing the error correction (but I guess I probably should anyway).

Oh, and for some reason the S110 doesn't like its HP timers running with too short a delay, which was what caused a lot of problems when trying to write the transmission code originally. Though this shouldn't be a problem with the attached code.


*

Offline reyalp

  • ******
  • 14080
Re: Using timing functions
« Reply #58 on: 20 / April / 2014, 16:10:58 »
Oh, and for some reason the S110 doesn't like its HP timers running with too short a delay, which was what caused a lot of problems when trying to write the transmission code originally. Though this shouldn't be a problem with the attached code.
If you can be more specific about the symptoms and "too short a delay" that might be helpful for people who want to do this kind of thing in the future.
Don't forget what the H stands for.

Re: Using timing functions
« Reply #59 on: 23 / April / 2014, 14:48:47 »
Oh, and for some reason the S110 doesn't like its HP timers running with too short a delay, which was what caused a lot of problems when trying to write the transmission code originally. Though this shouldn't be a problem with the attached code.
If you can be more specific about the symptoms and "too short a delay" that might be helpful for people who want to do this kind of thing in the future.
On trying to recreate the problem, it seems to work alright now. I think it could have been when a HP timer ran a function that contained a wait-loop, under certain conditions (can't remember what). But if I run into it again I'll post it here. The symptom was the camera just crashing.



Success! The transmission code is now finished, and works well at 1 bit per ms. A trial of 1000 transmissions showed only 5 errors, three were one-bit errors and the other two were completely corrupted (probably missynched or something). One error in 200 probably isn't worth actual error-correction, so I just gave it a checksum error detection (so that it won't try to apply the corrupted values, the user will be alerted and will have to repress half-press).

Here is a photo of the slow response time of a rising curve that I mentioned earlier. But it isn't really a problem as it's still reasonably steep at 1/3 way up (which is where the threshold is). Also, the bits do tend to move around slightly (haven't measured exactly how much, maybe 0.1ms or so), I think this is more likely what causes the bit errors. At 2 bits per second, errors maybe about 1 in 20, so probably not worth going any faster that 1 bit per millisecond.


(first pulse is the sync pulse, the code has since been changed so that it syncs on a falling edge instead)



I've commented and cleaned up (to the best of my abilities that is) the code so it should be easier to follow. There's no reason why one cam can't act as a master and slave simultaneously for duplex communication.

 

Related Topics