Arduino LCD Helicopter Game

Made this as a small train project with one of my new 128x64 LCD’s. It’s a simple helicopter game for the Arduino; Playable with just one button.

Watch a video here:
http://www.ardx.eu/2010/02/arduino-helicopter-game/

Pretty funny! Looks cool.

I have been thinking about getting one of these LCDs - it is hard to tell from the videos I have seen, but how is the refresh rate on these things? Ghosting, blurring, etc? How fast can you update an entire screen of pixel data?

I am curious because I have this bizarre idea to use an Arduino chip as a "controller" that would keep a page of display data in RAM (it should fit OK), then on command, blast the entire page to the LCD, while another Arduino would write to the controller Arduino to RAM (poor man's double buffer, in effect) - I was even thinking of running the controller Arduino @ 20 MHz - control interface would likely be via I2C.

It would all depend on how fast all those pixels from the RAM array could be written to the screen, though...

:)

thats pretty kool :)

Can you share the code? I'd love to show my parents this on the GLCD I have, and maybe do a 192x64 port :P

Regards, /me

@ARDX.eu I missed the original post, would love to see the code (and happy to help you debug it if you need a hand)

@cr0sh: these LCDs come with different controllers. For the KS0108 controllers I achieve render times <40 ms which is faster than the LCD can really follow. Of course I do not use the “standard” library for this. Instead I buffer everything in Ram and just copy it to the LCD. This is much faster but eats a lot of memory.

Cheers, Udo

Udo Klein:

Ok - so you -are- basically doing what I am talking about - that’s pretty cool.

My thoughts were to make a general purpose engine with the Arduino (well, an ATMega328 w/ bootloader), to handle sprites, tile mapping, scrolling, etc - and this “render engine hardware” could be sent commands and data via SPI or I2C by another Arduino or any uC, really. Perhaps such a device could be implemented as a “backpack” for the LCD.

That would make a pretty killer product; current serial backpacks either don’t have the speed, or have a limited library for graphics (enough for simple GUIs and the like, but not for games and “high speed” graphics creation).

Well, not really. My “driver” is very low level. It has less functionality than any other comparable driver. The only point is that it is extraordinary fast. Worst case is 40ms, best case <2ms. I was just hinting that you should consider to buffer your output in RAM. Since you will use the microcontroller as a graphics controller this should not be much of an issue.
With regard to the performance: I did no significant performance optimizations. Actually my goal was to have an as simple (and LCD independent) driver as possible. Since I figured that some LCDs can not be read I used the buffer approach. It then turned out that this gives impressive performance without any additional optimizations. If I would switch to assembler or start tuning it might get even faster. But then again it is already to fast for the display. As I said: worst case performance is currently 50 Hz :slight_smile:

I think it would be trivial to push it further by double buffering and only transfering bytes that actually changed. If you use a controller with 2k memory you might want to consider this.

I even found some displays (from EA) that come already with an controller. However the prices are prohibitve.

Cheers, Udo

Nice one Udo, I'm interested in the possibilities of your driver! For the people interested in the source, I have now published it on my blog: http://ardx.eu/

Still glitchy (didn't improve it this weekend) but I guess you guys are anxious to help me make it better ;) Have fun!

Well, my “driver” is very simple, as I said.

// frame buffer must be capable to store the contents of one screen
const uint16_t c_frame_buffer_size = 128*8;

const uint8_t c_frame_buffer_guard = 0xee;
typedef uint8_t frame_buffer[c_frame_buffer_size+1];

void frame_flush(frame_buffer buffer) {
      
      for (uint8_t row = 0; row < 8; ++row) {
            ks0108_GotoXY(0, row<<3);
            for (uint8_t col = 0; col < 128; ++col) {
                  ks0108_WriteData(*buffer);
                  ++buffer;
            }
      }
}

void frame_flush_dirty(int8_t min, int8_t max, frame_buffer buffer) {

      buffer += min * 128;
      for (uint8_t row = min; row <= max; ++row) {
            ks0108_GotoXY(0, row<<3);
            for (uint8_t col = 0; col < 128; ++col) {
                  ks0108_WriteData(*buffer);
                  ++buffer;
            }
      }
}

The rest of the stuff is from some existing ks0108 driver. I plan to replace this driver eventually. But right now I did not find the time.

With regard of the other parts of the driver: I do not understand the license terms. I think it is free but I am not sure → I will not publish it. In fact I will reimplement the “render one byte” part and dump the rest eventually. I started to implement some features that I need on top of this buffer approach. However this is not even close as complete as other drivers. So I think this it is not yet worth to be published.

Just a comment though: the buffer is one byte larger than one would expect. I store some “guard” byte there in order to figure out if my code overwrites what it should not overwrite. This costs 1 byte of memory and some CPU cycles but gives me peace of mind :wink:

Cheers, Udo

Hi,

I have tried to compile your code but I get the following error:

GLCD.Init(INVERTED);

GLCD was not declared in this scope. Do you have any suggestions?

Thanks, Ed

The rest of the "driver" is some even lower level code that pushed the bytes straigt to the LCD. I ripped it of from some KS0108 code I found somewhere on the internet. You would need to rip it off from some driver that works for your display. The code is not intended as some kind of "official" driver for anything. I just exhibits the fact that if you just copy a "framebuffer" directly to the hardware it will be extraordinary fast.

I could try to dig out the rest again but chances are that it won't work with your display. The reason is that this KS0108 code was not very good and that by now I changed this for a ST7565 display and corresponding code. (BTW: the ST7565 is much faster although it gets the data serial instead of parallel).

Since you already have a GLCD library that works with your display the easisest way would be to rip of this library for the direct hardware control.

Udo