Rectangular LEDS

It's trivial.

I posted this earlier:

formatting link

That's 128 LEDs via 3 ports on 2 mcp23017 I2C GPIO expander cards. Although that video demo only has a few LEDs on at a time, I can assure you that the code behind it is multiplexing all 128 LEDs. Each "pixel" is a green + red LED - it's pretending to be a

8x8x2 bit framebuffer there. The code to refresh the display runs as a thread in the background of your program -you just poke pixels into the 'frambeuffer' array.

It's using only a few % of the CPU to do that. Most of the time its waiting on the I2C bus - I am running it at 1Mhz in that demo.

This:

formatting link

is playing tones via software toggling of a GPIO pin. It's stuttering as I'm only playing the tone for 1/10 of a second before checking for a touch release.

This:

formatting link

is software PWM over 12 LEDs.

And so on.

Yes - and the reason behind that is nothing to do with anything but the Linux kernel driver for SPI having a rather high latency when starting a transfer. If you want to poke the hardware directly, you'll get 20x that.

8Khz sampling over SPI:

formatting link

8-bit ADC/DAC.

The max. SPI clock I've used reliably has been 32Mhz.

100Hz (and much more) is easily achievable in software with minimal CPU impact.

Gordon

Reply to
Gordon Henderson
Loading thread data ...

Are you saying you toss the SPI hardware and bit bang the I/O port at the bit level?

... AND still run all the other functions in the rPi?

--

Rick
Reply to
rickman

No. I use the Linux kernel drivers which have slowly been improving in recent years. However what you can do is drive the SPI hardware directly

- not bit-bang, but fill up the FIFO yourself, poke the command into the start register, poll the Tx complete flag and so on. Currently, the Linux kernel drivers achieve about 12K transfers/sec on small transfers - obviously with the size of the transfer increasing the overall transfer speed increases as latency then isn't a major factor.

I have a new SPI driver to go into wiringPi to do this as an alternative to the kernel driver, but it's not complete yet. The main issue then is that it will consume 100% cpu during the transfer - which might be OK for small 2-4 byte data exchanges between e.g. an ADC but somewhat sub-optimal when sending 250K bytes to a display.

One thing you can not accurately do in user-land is percise timing. This is due to the nature of the multi-user, multi-tasking operating system, however it's do-able if you write a kernel module. (So using an SPI device to accurately sample at 1K samples/sec is not going to work well - it will work, but jitter will be high)

My little record playback example works as it exchanges the same number of bytes to read as to write over the SPI bus and it runs at the max. speed I can push the SPI bus at - which in that example, ~2 years ago was just over 8K samples/sec. All I did was read & stire in a tight loop until I'd read in a few KB of samples, then play it back in a similarly tight loop. No timing in the loop.

Yes. I observed my software PWM driver using about 1% cpu per pin. There are hardware tricks to use all pins via a hybrid driver too which abuses a DMA channel and so uses virtually no CPU (but it steals a little bit of memory bandwidth) - all do-able from userland, but my code doesn't do that yet.

Gordon

Reply to
Gordon Henderson

I think the real shortcoming of the code I've seen so far is that it doesn't make full use of the hardware. I have not read all the details (partly because the docs are not 100% clear on the details) but it looks to me like the DMA should be able to handle all the data movements and if it can be coupled to a timer the timing should be a lot more deterministic (important for ADC/DAC use).

Essentially, it is better to just not use the software since the CPU is shared across every task running. But hardware is dedicated.

For the LED multiplexer DMA would be both optimal and straightforward. I'm just not sure how to tie it to a timer. If you have to trigger each DMA transfer with software I'm not sure that would be useful since it would need to run at kHz rates.

In your code how did you set the timing of your multiplexing?

--

Rick
Reply to
rickman

I'm not convinced. The SPI FIFO is 16 bytes deep. Most SPI transactions are going to be less than 16 bytes - e.g. to red a 12-bit ADC needs an SPI exchange of just 3 bytes.

The longer transactions take an interrupt every 16 bytes - and that's fine - I did a driver for an LCD display that used SPI and the overhead of sending a framebuffer to the display (about 240K bytes) was minimal.

So I fear you're chasing the wrong thing.

When I last looked at the kernel driver, it suggested there may be an issue with the hardware, so rather than kick off the transaction it kicked off a zero length transaction then released - and waited for the next interrupt to come in from the hardware to do the proper transaction - hence adding to the latenct. Fix that and it will fly.

Avoid premature optimisations...

Why not look at it?

cd git clone git://git.drogon.net/wiringPi

You'll find softPwm.c in there. There's no real magic.

Also look for the file 7segments.c - referenced in this article:

formatting link

Gordon

Reply to
Gordon Henderson

I don't think you understand some of the issues involved in using ADC/DACs. Look up simultaneous sampling. Multiple interrupts won't hack it.

I'm not sure what you mean. Even if you get the SPI driver running with less latency, the timing is horrible because of all the issues of doing this under a non-real time system. To control the multiplexing of the display being discussed also requires control of the timing, although no where near as good as ADC/DAC data. Still, the brightness of each LED is directly proportional to the time it is on. Give control of that to the software and I expect it will not look as good as the OP wants. Heck he is talking about using constant current sources. No point if the timing is not controlled.

Why not just tell me? What controls the timing of the multiplexing?

--

Rick
Reply to
rickman

I couldn't remember whether it did or not.

Good point, though I'll probably stick with I2C, since PICAXEs can act as I2C slaves and, if I go that way, I'd want the RPi to talk to more than one of them: they are quite a neat way of implementing the slave part of the non-clock control task I've mentioned.

--
martin@   | Martin Gregorie 
gregorie. | Essex, UK 
org       |
Reply to
Martin Gregorie

Sounds good. Thanks for that.

--
martin@   | Martin Gregorie 
gregorie. | Essex, UK 
org       |
Reply to
Martin Gregorie

C for me every time, except on PICAXEs or STAMPs.

--
martin@   | Martin Gregorie 
gregorie. | Essex, UK 
org       |
Reply to
Martin Gregorie

Good point. Thanks.

--
martin@   | Martin Gregorie 
gregorie. | Essex, UK 
org       |
Reply to
Martin Gregorie

I wrote some general purpose routines in VFX Forth for ARM Linux in user space and achieved toggle frequencies (low-high-low) in excess of 10 MHz. Using code for specific pins should give output in the range of 15-20 MHz. Using I2C or SPI at around 1MHz should be very doable.

Other data available supports these caims. Somewhere there's a comparison of many methods of bit-banging.

Stephen

--
Stephen Pelc, stephenXXX@mpeforth.com 
MicroProcessor Engineering Ltd - More Real, Less Time 
133 Hill Lane, Southampton SO15 5AF, England 
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691 
web: http://www.mpeforth.com - free VFX Forth downloads
Reply to
Stephen Pelc

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.