Friday, September 23, 2011

Easy speed

Probably the easiest speed gain I've every "hacked" together:

  if (sdCard_) return true;

By initalizing once and then returning true until rebooted, I gained an additional 26 Hz while streaming. This should be safe since the card is read-only and will not change size and/or require re-initialization during runtime... So now I'm counting 66 Hz and still loading animation data in the background.

Current speed (for 16 colors):
Loop 1 : Start to read,       7.354 ms
Loop 2 : Read 512 Bytes, 4.886 ms
Loop 3 : Read 512 Bytes, 4.879 ms
Loop 4 : Read 512 Bytes, 4.881 ms
Loop 5 : Read 512 Bytes, 4.880 ms
Loop 6 : Read 512 Bytes, 4.881 ms
Loop 7 : Read 512 Bytes, 4.879 ms
Loop 8 : Read 512 Bytes, 4.881 ms
Loop 9 : Read 512 Bytes and close, 4.881 ms

Actual video data is currently:
16 colors @   6 FPS   (Screen refresh is 66 Hz)
  8 colors @ 14 FPS   (Screen refresh is 96 Hz)

8 colors may be quite sufficient to create nice graphics, but of course - the more the merrier! I'm sure more can be done to improve the performance.
Stay tuned!

Wednesday, September 21, 2011

SD card - again

A little update -
It seems incremental updates DO work. That's good news!
I'm however quite stunned that the various parts of the reading take so much time...

Loop 1 : Starting...18.467 ms
Loop 2 : Read 512 Bytes, 16.303 ms
Loop 3 : Read 512 Bytes, 16.301 ms
Loop 4 : Read 512 Bytes, 16.309 ms
Loop 5 : Read 512 Bytes, 16.300 ms
Loop 6 : Read 512 Bytes, 16.304 ms
Loop 7 : Read 512 Bytes, 16.307 ms
Loop 8 : Read 512 Bytes, 16.303 ms
Loop 9 : Read 512 Bytes, 16.301 ms
Loop 10: Closing! 1.779 ms

Each loop requires a 10 ms SD.begin() call. So in practice, a data read is actually 'only' 6 ms.
So there's more to be done, but as I said - incremental updates are a good thing!



After a little tweaking I'm able to have a (somewhat) flickerfree loading in the background.
It runs at about 40 Hz and the video is loaded at between 5 and 10 fps depending on blocksize.

So, I can either A) limit the 110 Hz refresh to match the lower loading Hz, or B) Switch to fullscreen@40Hz when displaying video. Or probably C) only show animations on 2/3 of the display like newer Stern games. Or even D) depending on type of animation, load the frames in the background and display the animation when ready. This requires a maximum of 30 frames animation length since that's all the RAM I've got available.

All of the above assumes 16 color video. Smaller video size or fewer colors would contribute to a faster refreshrate.

Hopefully I can tweak the SD loading even more to bring up the refresh rate, since it also controls the brightness of the screen.

Tuesday, September 20, 2011

Those pesky SD cards...

I'm having slight progress with the SD-card reading programming.
I'm currently reading a full frame of animation 13 times per second. Time for some sloppy math!

Old code:   1 Byte @ 3.5 ms
New code:  1 Byte @ 0.01 ms

Unfortunately, this is too slow to be useful - but it is still a 350x improvement over the previous speed! IF it's possible to break down the reading over several frames this is not an issue. But I'm not sure how the SD-library responds to changes in the SPI-slaveselects during reading.

I could load one color-layer at a time (512 Bytes) directly into the drawbuffer during animations, which hopefully translates to around 6 ms per layer. That way the screen would still refresh fast enough to be considered flickerfree. It would only allow for videos with around 10 frames per second if all 16 colors are being used. There might be a FAT restriction on the number of files on the SD-card that prevents me from using this method however.

Another option could be to simply load a lot more data and "pause" the game during loading. 1 second of loading would load 23 frames of animation, and if playback speed is 15 fps it roughly sums up to 1.5 seconds of animation. But it's not really practical to pause the display and lights every now and then, and usually when the game allows a pause you'd often want more than 1.5 seconds of animation.

Naturally I'd prefer to read an entire frame (4096 Bytes) in one go, since this allows me to easily add text and tweak the screen before displaying. I guess I'll have to experiment a little to find out how to solve this!

It may be time for me to fix the slow 'digitalWrite' of the Chipkit after all, something which I've sort of avoided until now... because it's boring!

Saturday, September 17, 2011

Graphics revised - check!

Finally got around and rewrote the graphics library.
It is by no means finished (the text adding is a mess) and will be revised in a future update, but for now I'm quite happy with the results!

1) Test image with scrolling starfield and 'MULTIBALL!'-text.
Unfortunately, the colors of the picture are washed out - they are much more vibrant in reality.
Don't judge a pinball by the skills of the photographer! ;)

What we are looking at is 16+1 colors, double-buffered, Speedy-Gonzales-100Hz magnificence!

Basically, the double buffering is just two buffers that each take turns in rendering. This means I can keep drawing the frontbuffer, or drawbuffer, while the backbuffer gets built. i.e I can keep logic at 30Hz while still rendering a flickerfree 100 Hz. This of course allows me to download new animation frames in the background and render them when they're completely loaded. Awesome!

Oh, and did I say I'm completely rebuilding the frame EVERY frame now? By limiting the rebuilding to 30Hz I get even more rendering-hertz to play with! Just a reminder, the Arduino could barely keep up drawing 5+1 colors at 52 Hz with everything else going on...

I've also added a couple of convenience functions such as addText, addTextLarge, addRect, fadeIn, fadeOut, fadeDisplay etc to make the programming of the display a little friendlier. The fadeDisplay function is particularly useful to print text over finished animation a´la modern Stern-games by dimming the rest of the screen and then draw the text over it.

No 'addLine' function you say?
Plotting a line is harder than one might think, if you want a decent looking one!
Check this for reference! Don't worry, I will be adding one in the future - at the moment I only need vertical/horizontal.

Wednesday, September 14, 2011

SD card reading - check!

The SD card reading is now started. And somewhat finalized.
The library I'm using however does not impress.

At the moment it is reading around 1 byte per 3.5 ms, which is mighty slow...
It should be able to read at least a couple of hundred times faster than that!
So, it's 'back to the drawingboard' for me as far as the SD card goes...

Sunday, September 11, 2011

Motherboard revised

I did a little work on the motherboard, including adding the third soundboard, 3.3->5V converter and SD-card reader. Behold!

1) From left, going clockwise: Soundboards (2 sfx, 1 music), Arduino Mega2560, "display adapter" (3.3V to 5V converter),   Chipkit Max32 + MUX shield, SD/MMC card reader.
It has a certain "scrapyard challenge"-feel to it, but it will be hidden from view anyway. And - should it come to the point where it bothers me a whole lot, the schematics for all the boards I've used are open source and available online so I could easily order a circuitboard with all the components integrated.

Adding a second sound effects card really made a difference. I'd thought it would be more subtle but being able to have multiple effects playing alongside music really adds to the experience. This also means I can have longer spoken phrases during the game without losing music or effects while doing so.

Saturday, September 10, 2011

Colors revised

Just got the new MCU (Chipkit Max32) to function correctly with my display.
I had a lot of trouble getting it to work, even contacted the developers and we confirmed I was doing right (programming wise). But the problem was the lower operating voltage of the Chipkit.

It only took a logic level 3.3V <-> 5V converter and a whole lot of patience to get it working!

No pictures yet, but the difference is spectacular: 16+1 colors and no flickering!
The 4X CPU speed of the Chipkit really shines here, and as an additional bonus, it seems I'm able to update the columns at 20 MHz speed instead of 5MHz, another speed increase of 400% right out of the box! I'm using regular digitalWrites with hardware SPI, so I figure I could push the refreshrate up a notch if needed.

Now I can focus on getting the display system back on track, continue on the serial communication, SD card reading, etc...

But I'd still say -
Chipkit, you sure were worth the trouble!