Implementing an additional, high-priority thread for monitoring serial data - General Discussion and Assistance - CHDK Forum supplierdeeply

Implementing an additional, high-priority thread for monitoring serial data

  • 42 Replies
I'm looking once again at implementing RS232 into CHDK, but I lack the knowledge to do it:

In order to successfully read an RS232 packet at 4800 baud (my minimum target), the usb power level must be read at intervals of exactly 208.33us +/- 2us (this is the timing required to ensure no errors). Unfortunately, I have no idea how to add a thread of such high-priority [To be reliable, I think it would have to be given priority over almost all other functions] into the CHDK architecture. Can anyone point me in the right direction?

This page has more basic information on RS232, and the code below shows the simple C required to read an RS232 packet at 9600 baud into a PIC microprocessor - I am hoping to implement something similar.

Code: [Select]
void RxSerial (void) {

 ; Receives 1 start bit Lo, 9 data bits and 1 stop bit Hi at 9600 bps
 ; Byte time = 1.144 mS
 ; Bit  time = 104 uS (0.16% erro w/10 Mhz)
 ; False start bit check
 ; Start bit hunting timeout = 4*1.283ms
 ; Input  : none
 ; Output : Carry = 1 => success
 ;     rxBuf[0,1] = input byte +9th bit
 ;     Carry = 0 => error (timeout or stop bit=0)

char idx;

rxBuf[0] = 4; // 5.135 ms timeout
idx      = 0;

while (1)
while (RxD_pin) // input "high"
if ((-- idx)==0)
if (rxBuf[0]==0)
Carry = 0;

Delay_uSeg(40); // 1/2 bit delay (40*3+7)*0.4us=50.8us
if (RxD_pin)
continue; // false start bit detection

rxBuf[0] = 0x01; // 9 bits counter and reception buffer
rxBuf[1] = 0x00;

Delay_uSeg(81); // (81*3+7)*0.4us=100us
nop(); // 0.4us
nop(); // 0.4us
Carry = RxD_pin; // 1.2us bit read
rxBuf[0] = rr(rxBuf[0]); // 0.4us store and count
rxBuf[1] = rr(rxBuf[1]); // 0.4us
} // 1.2us
while (Carry==0);
Delay_uSeg(81); // (81*3+7)*0.4us=100us
nop(); // 0.4us
Carry = RxD_pin; // stop bit read
return; // 100 us availiable

I understand now (or think I do!) that there's no native threading support in the C language, so the approach I was suggesting would be - at best - very difficult to implement. A fallback solution, then:

When my_kbd_read_keys() is called, enter a loop that continuously checks the USB power level.
-If it goes high, the code interprets it as a start bit and attempts to parse the following logic levels as a data packet.
-If the USB power level stays low, the loop exits after a timeout duration (5ms?).

This should give the precise time resolution required without tying up the CPU for too long. Since the camera will only be listening for data for a short period of time it will be necessary to transmit a packet several times to ensure it is received, but this is not a big problem.

I have a few questions still though:

How long is a tick in CHDK? (eg from get_tick_count) Should it be consistent across all cameras? (DIGIC II/DIGIC III?)

What is the purpose of _kbd_pwr_on(),     _kbd_pwr_off()?


Offline GrAnd

  • ****
  • 916
  • [A610, S3IS]
    • CHDK
How long is a tick in CHDK? (eg from get_tick_count) Should it be consistent across all cameras? (DIGIC II/DIGIC III?)

1/1000 for all cameras (it's a timer).
CHDK Developer.

This is about the same approach I started out to investigate. Problem I found is that the USB signal is delayed -about- 50 ms after it is set on the port. Only solution would be to find a way to read the USB signal directly from a variable or port. It seem that the USB power signal is filtered via some procedure in the camera.

Gradually closing in on this. With modified code (continuously loops until it detects the rising edge or a 5ms timeout is reached) I'm now able to detect signals of 10ms duration even without an interrupt pulse, so if there is any power filtering it seems to be less severe on the A640 than fingalo's S3IS.

Interestingly, although get_tick_count returns values in ms, its resolution only seems to be 10ms.

Couldn't resist having a crack at this at lunchtime. The A640 can correctly detect a 208.33us bit (4800 baud). It's just down to the timing now.  :xmas

Success! I can now talk to my A640 (one byte at a time) at 4800 baud (faster speeds should be perfectly possible) with moderate reliability (because I'm only able to monitor the USB power levels for a limited time, errors are fairly inevitable - I'll have to fine tune the timing and add parity etc to deal with this) . This is a lot more usable than the serial demo I showed. With a little bit of work this makes an awful lot of applications feasible.  8)

Code to follow later tonight, I'll see if I can get it to behave in a more stable manner first.

check out this section from the wiki scrip tutorial discussion page on script timing.  I think any serial port monitoring for anything other than simple control codes would have to be done at a lower level than a uBasic script.

Thanks, Divalent, and you're right - the monitoring takes place in the CHDK source and updates a variable with the most recently decoded byte, which is then polled by the uBASIC routine. It's not going to be practical to monitor a constant stream of data - eg NMEA position data from a GPS - or indeed reliably capture a single packet, but it does make it extremely simple to send instructions to the camera from any serial equipped device that supports 4800 baud. I've still got a couple of timing issues to sort out.


Offline mx3

  • ****
  • 372
firmware dumper?
« Reply #9 on: 04 / December / 2007, 04:16:05 »
is it possible to make firmware dumper using this?
or it is one-way  transfer only?
skype: max_dtc. ICQ: 125985663, email: win.drivers(at)gmail, eVB decompiler


Related Topics