Start from Day 0: Introduction here
I’ll first start off with some speed tests to see the maximum refresh rate achievable with the mbed, which has a 96 MHz ARM Cortex-M3 processor.
Interfacing the MCU to the TLC5947′s is interesting because the TLC5947′s run off 5V, but the MCU runs off 3.3V. The TLC5947 datasheet also states the maximum clock is 15 MHz when cascaded. I tested with 2 cascaded sticks (8x TLC5947), and found I can clock SPI to 24 MHz (maximum speed supported by the MCU)! With 3 cascaded sticks, only 16 MHz works. This is still pretty amazing because the MCU output is driving a large capacitive load with voltage logic levels mismatched. From looking at the scope captures, the difference in logic high amplitude between 16 MHz vs 24 MHz is very small, yet one fails and the other works. Even dialing down the TLC5947 voltage doesn’t fix anything until they’re brought to around 3.6V. All of this isn’t a huge deal, because SPI communication is at most 5% of the total time spent in each cycle.
The test is to cycle through all the hue’s for each LED, displaying a rainbow across the stick. Therefore a conversion must be done from HSV space to RGB space. Then to display each pixel, a gamma correction calculation must be performed for each color, since the human senses are logarithmic. This involves doing an exponential and a few floating point operations. How fast can the ARM perform these operations?
There are 3 sticks cascaded, for a total of 96 RGB LED’s — 288 pixels with 12-bit resolution. My optimized code refreshes at 256 Hz, which is great for a stationary display, but probably a bit on the low side for a rapidly moving one, like using it for a propeller clock. I noticed a few tricks that improved performance by about 20% total:
- Explicitly cast all constant floating point numbers into floats. Otherwise the C compiler will default them to doubles and the ARM will perform double calculations, which is slower.
- Turn division of floating point numbers into multiplication.
- When possible, use integers as an operand for floating point math. For example, if hue is a float,
hue / 60is actually faster thanhue * 0.0166667.
My messy benchmark code can be found here. P.S. the mbed interrupt API is really neat and simple to use.
I’m sure removing the floating point code entirely will greatly speed up the refresh rate, but this is harder to develop. Another thing to try is to use a lookup table to save the use of the exp() function and a floating point multiply. Just tried the LUT and got 600 Hz — pretty good improvement.
Then I converted the HSV to RGB code into pure integer math. This got it to 1590 Hz! Maybe the XMOS won’t be needed after all.
Tomorrow we’ll give the XMOS dev board a try, which has 1600 MIPS — almost 16x the speed of the mbed.



0 Responses to “RGB Propeller Clock: Day 1/5 — mbed Benchmarking”
Leave a Reply