ADC zooming along

Started by pitstock_kiwi April 12, 2006
Greetings

While Brendan and Jaya have been furiously writing emails I have been
working on my LPC2148 ADC code. Its taken me a while but I now have
it clocking out the ADC at a rate of 520 K samples per second. I am
over clocking the ADC a little at 5 Mhz but my noise is well within
my required spec. I didn't think it was possible as I always hit
about 320 K or so at best. My 512 pixel camera is now doing over 500
frame captures per second :)

The caputured frames are dispatch to the PC via the USB HID example.
I have not got the HID example to run very stable yet (has anyone ?).
I can send packets (64 byters) to the PC no problem at a fair rate
(5ms). Just when I send packets from the PC to the 2148 I
intermittently get a permanent code slow down and the USB stops
communication (but stays connected). If anyone knows the solution to
this I would be happy to hear it.

My Setup is:
Keil 3.31 using the ADS realview that came with it. ARM mode with no
optimising. Keil MCB2140 dev board with a ULINK.

Cheers
Keith

An Engineer's Guide to the LPC2100 Series

Keith,

You (and others) can relax - I'm back home now from a recent
business trip and already I can feel all the extra free time
draining away, so I won't be contributing as much for a while. Much
to some people's relief I'm sure.

As for your own problem, without more detail, all I can suggest are
some general pointers (which you're probably aware of anyway):

1. You've already done the 1st one, which is to ask here. I assume
you've also read the manuals and errata thoroughly?

2. You mention you're overclocking the ADC: is this some figure in
the manual you're exceeding? If so, I'd strongly recommend you
don't. The figure is there for a reason. Yes I know that in normal
conditions you'll probably get away with it (Philips are quite
conservative in their specs), but as you don't know what the effects
might be or when they might occur, it's asking for trouble.

3. You're driving the part quite hard at the rates you're talking
about, particularly if each ADC conversion is handled in an
interrupt. You may just be running out of MIPS, which can cause all
sorts of unpredictable behavior. A quick and dirty test to do is
turn on the optimizer (you mention it's off): this can have a big
effect on throughput. However, you're almost worse off if the
problem goes away when you try this, as you actually haven't proved
anything (unless the whole thing is just a quick-and-dirty project
to get some once-off results, in which case it doesn't matter).

4. After that, the only thing I can suggest is the normal methodical
approach: understand how your system is behaving (e.g. by putting in
extra counters, flags etc. to confirm things are happening when you
believe them to be, in the right order, that things aren't being
dropped or missed etc.). Once you've done that, work back from the
symptoms (which sounds difficult in your case), or alternatively
work forward by hypothesizing what might be going wrong, design a
test to check and verify. But then I'm sure you know all this
already.

As a final observation, high interrupt rates have a habit of
flushing out otherwise latent bugs in software: sounds like you have
a good test system for you software!

Some of this is stating the obvious, but hopefully there's something
of use for you (and others) there.

Brendan

--- In l..., "pitstock_kiwi" wrote:
>
> Greetings
>
> While Brendan and Jaya have been furiously writing emails I have
been
> working on my LPC2148 ADC code. Its taken me a while but I now
have
> it clocking out the ADC at a rate of 520 K samples per second. I
am
> over clocking the ADC a little at 5 Mhz but my noise is well
within
> my required spec. I didn't think it was possible as I always hit
> about 320 K or so at best. My 512 pixel camera is now doing over
500
> frame captures per second :)
>
> The caputured frames are dispatch to the PC via the USB HID
example.
> I have not got the HID example to run very stable yet (has
anyone ?).
> I can send packets (64 byters) to the PC no problem at a fair rate
> (5ms). Just when I send packets from the PC to the 2148 I
> intermittently get a permanent code slow down and the USB stops
> communication (but stays connected). If anyone knows the solution
to
> this I would be happy to hear it.
>
> My Setup is:
> Keil 3.31 using the ADS realview that came with it. ARM mode with
no
> optimising. Keil MCB2140 dev board with a ULINK.
>
> Cheers
> Keith
>
Keith,

As a final thought, you mention that you're USB interface isn't
stable. If one of your sub-systems isn't stable, your system is very
unlikely to function correctly. I'd recommend you get each sub-system
(ADC, USB etc.) rock-solid before bolting them all together.

Brendan

--- In l..., "pitstock_kiwi" wrote:

> I have not got the HID example to run very stable yet (has
anyone ?).
Hi Keith,

just a though, what is your VPBDIV value. If you left it at default 4,
this can be your trouble maker. Set it to 1 or 2. There were previous
posts of the USB module needing min. 18 MHz clock, afaik, that is
determined by both the AHB and the VPB bus. So, if running at /4, give
it a shot.

Bob

--- In l..., "pitstock_kiwi" wrote:
>
> Greetings
>
> While Brendan and Jaya have been furiously writing emails I have been
> working on my LPC2148 ADC code. Its taken me a while but I now have
> it clocking out the ADC at a rate of 520 K samples per second. I am
> over clocking the ADC a little at 5 Mhz but my noise is well within
> my required spec. I didn't think it was possible as I always hit
> about 320 K or so at best. My 512 pixel camera is now doing over 500
> frame captures per second :)
>
> The caputured frames are dispatch to the PC via the USB HID example.
> I have not got the HID example to run very stable yet (has anyone ?).
> I can send packets (64 byters) to the PC no problem at a fair rate
> (5ms). Just when I send packets from the PC to the 2148 I
> intermittently get a permanent code slow down and the USB stops
> communication (but stays connected). If anyone knows the solution to
> this I would be happy to hear it.
>
> My Setup is:
> Keil 3.31 using the ADS realview that came with it. ARM mode with no
> optimising. Keil MCB2140 dev board with a ULINK.
>
> Cheers
> Keith
>
pitstock_kiwi wrote:
> While Brendan and Jaya have been furiously writing emails I have been
> working on my LPC2148 ADC code. Its taken me a while but I now have
> it clocking out the ADC at a rate of 520 K samples per second. I am
> over clocking the ADC a little at 5 Mhz but my noise is well within
> my required spec. I didn't think it was possible as I always hit
> about 320 K or so at best. My 512 pixel camera is now doing over 500
> frame captures per second :)

Just curious because I'm working on something similar...

How are you triggering the ADC?
ADC burst mode looks a bit awkward because with (for example) 8-bit
resolution, the ADC takes a sample every 9 ADC clocks, which makes
it hard to get a nice round sampling rate.
I tried to synchronise the ADC to a timer. This works and I make
almost any sample rate I want, but it only works when the trigger
signal is sent out to a pin.

How are you storing the ADC data?
Just a tight loop polling the ADC? or a FIQ? something else?

Thanks in advance,
Bertrik
Bertrik wrote:
> Just curious because I'm working on something similar...
>
> How are you triggering the ADC?
Well I tried lots of different ways but found this line to be the
fastest in my case.

#define ADC_CLK_60_50 0x0B00 // 60MHz/12 = 5.0mhz
#define ADC_SEL1 0x02 // Select ADC n.1
#define ADC_PDN 0x00200000 // bit 21 Power down (1 for power)
#define ADC_START_NOW 0x01000000 // bit 24 Start ADC now

AD0CR = ADC_CLK_60_50 | ADC_SEL1 | ADC_PDN | ADC_START_NOW;

> ADC burst mode looks a bit awkward because with (for example) 8-bit
Yep, I dont trust burst mode because if an interrupt takes over would
you miss samples and hit over run? Not sure but what I have works nice.

> resolution, the ADC takes a sample every 9 ADC clocks, which makes
> it hard to get a nice round sampling rate.
> I tried to synchronise the ADC to a timer. This works and I make
> almost any sample rate I want, but it only works when the trigger
> signal is sent out to a pin.
Yep, been there done that, but you will only get 320k (from my testing,
I have been wrong before.) sample at best compared to the 500k+ I am
getting.

> How are you storing the ADC data?
I just use a for loop to loop through all the pixels

uint32_t tADC;
tADC = (AD0DR1 << 16) >> 22; // copy ADC out to get 10 bits.
cambuff[tIdx] = tADC; // store ADC in camera buffer.

> Just a tight loop polling the ADC? or a FIQ? something else?
I found that polling the done flag to be a waste of time. Limited me to
that 320 samples again. I figured we know how many clocks it takes for
a conversion so I just NOPed it plus some extras for pipeline things
that I dont know enough about

The dreaded inline assembly which works awesome for me. It doesnt use
any variables so thats good I guess.
e.g
#define NOP2 {__asm {nop}\
__asm {nop}}

Some people may want to pipe up and say I am doing it all wrong. I dont
care. That part of my project is complete and runs very fast within the
noise specs.

I also fixed my intermittent bug. It was a spurious intterrupt. When I
was starting the hardware camera shutter I was turning off the USB
interrupt. This caused the usual issues.

The fix I copied from here worked a treat.
VICDefVectAddr = (unsigned long) default_interrupt_handler;// spurious
interrupt handler

void default_interrupt_handler(void) __irq
{ // this does get called occasionally
return;
}

Cheers
Keith