NerdKits - electronics education for a digital generation

You are not logged in. [log in]

Project Help and Ideas » Tetris game :D

October 18, 2010
by Hexorg
Hexorg's Avatar

Hello, everyone :D A year ago I got myself 300 RGB LEDs and built an array of them 16x16. Yesterday I finished the last part of the hardware part. SIPO registers with latches drive the onoff states of the LEDs, allowing me to have 8 Colors (including black), and an up-counter is responsible for switching rows. The Whole image fits into a 96 bytes array, and a code to blink the whole image is about 600 bytes :D

Then I hooked up the temperature sensor, and using that to generate a seed number for the pseudo-random number generator, and wrote a code to make lights turn random color every second. Looking at that colorful bliss, I realized that the screen will suit well for a tetris game, having 1 LED as 1 block. However, the way my program is written right now is this

Set current buffer to buffer 2
Go through all the pixels and assign random color to each in the buffer1;
for 1 second output current buffer to the screen 
flip buffers
repeat.

However, it takes a few microseconds to calculate all the random numbers, which makes the first row of the image glow much brighter for a split-second when the image is changing, because switching of the rows, etc. is happening in the "output current buffer to the screen" function. So I realized that I need to update screen on timer with interrupts rather then linearly.

So, I was thinking to use 8-bit timer with 1024 clock prescaler to disable output, change row and transfer the data on odd numbers of counter, and enable output on even numbers.

Is this the right way to do it? Is there a possibility for a vsync?

October 18, 2010
by Hexorg
Hexorg's Avatar

I love interrupts ^_^ I see many people looked, but not many answered. I did some research and rewrote the code to use interrupts. Rather, interrupt. Just by using ISR(SPI_STC_vect) I have set-up a (almost) 60Hz refresh rate, and a double image buffer :D Right now i'm timing 60Hz refresh rate using delay_ms() function, but I'm planning to rewrite that using timer interrupt, that way all processing time of the main function I can give to the manipulation of the game :)

If you guys have questions - you are welcome to ask :)

October 19, 2010
by hevans
(NerdKits Staff)

hevans's Avatar

This looks like a very neat project. I think a double buffered output refreshing at 60hz is definitely the right way to go about it. This also gives you the ability to do many other things around your display. Can't wait to see a video of it in action!

Humberto

October 19, 2010
by Hexorg
Hexorg's Avatar

Here's what I have so far. Video. Sorry for background noise, it's taken using my phone. It's just a pattern test. Each line is drawn using Bresenham's line algorithm. my main() function pretty much looks like this:

{
    setup();
    changePattern();
    waitForVSync();
    flipBuffers();
    delay_ms(33);
}
October 20, 2010
by mcai8sh4
mcai8sh4's Avatar

This is looking good! I think the end result may be quite special. Keep us all posted.

-Steve

October 23, 2010
by Hexorg
Hexorg's Avatar

Hey, i'm trying to implement text output right now. is there anyway to keep -j .data in avr-objcopy, and to use strings only from flash at the same time? I keep two 96-byte arrays as image buffers, because they change. But for text output i want to keep all strings in flash. Can I still use P_STR("bla bla bla")?

October 23, 2010
by bretm
bretm's Avatar

Yes, use pgmspace macros to manage data in flash, and plain C syntax for data in SRAM.

October 24, 2010
by Hexorg
Hexorg's Avatar

Awesome! I just uploaded data from the "terminus" font into the eeprom and here's the result so far :)

November 06, 2010
by Hexorg
Hexorg's Avatar

Game finished!!! Thanks everyone for help :D If anyone has more questions, i'll be glad to answer them. Here is the video.

November 06, 2010
by Rick_S
Rick_S's Avatar

All I can say is WOW!!! That is awesome! Is that controlled with the 168 or a 328? Also, did you use the default 14.7456Mhz NerdKit clock or a different one? Are you making the code available? :D

Great job,

Rick

November 06, 2010
by Hexorg
Hexorg's Avatar

ATmega168 with 14.7456MHz clock :) and yes, if you want the code I'll upload it somewhere tonight.

Drawing library in 150 lines Tetris library is 365 lines and main code is 550 lines

resulting code turned to be around 8kb, and seems there is still plenty of SRAM for additions.

November 06, 2010
by Hexorg
Hexorg's Avatar

Here's the code... it's still a bit buggy, i'd call it version 0.8

November 06, 2010
by Ralphxyz
Ralphxyz's Avatar

Hexorg, are you still limited to 8 colors? Why?

Ralph

November 06, 2010
by Hexorg
Hexorg's Avatar

I'm using shift registers to sink the current from LEDs. I did have 12bit PWM LED drivers, that would give me a lot of colors, but one image buffer would be 1152 bytes which is more then ATmega168 can hold in SRAM. With 8 colors image buffer shrinks down to 96 bytes, which allows me to program double buffered image output + VSync

November 06, 2010
by Rick_S
Rick_S's Avatar

Thanks for the code!... Now I'll have to look at it and see if I can understand it :D

November 07, 2010
by Hexorg
Hexorg's Avatar

Mr. Rick, if you cant understand part of code, just ask :) I did commented heavily in it, that should help too.

November 09, 2010
by jbremnant
jbremnant's Avatar

great stuff. congrats on getting posted on hackaday.com as well.

November 29, 2010
by weijiajun
weijiajun's Avatar

Fabulous job man! So if you were to use the ATmega328 instead of the 168, would that give you the memory upgrade you need to do the 12bit PWM?

November 30, 2010
by banerjen
banerjen's Avatar

Very nicely done mate. One could get a lot of ideas from your project.

Nandan.

November 30, 2010
by Hexorg
Hexorg's Avatar

weijiajun, I'm afraid not. See, with shift registers, I have 1 bit per color, that makes 3 bits per LED, 316 = 48 bits per 1 row, 4816 = 768 bits = 96 bytes per whole image, now if we have 12 bits per color: 12(bits) * 3(colors in LED) * 16(rows) * 16(columns) / 8 (bits in a byte) = 1152 bytes, and in the code I wrote is a double image buffer, so 1152*2 = 2304bytes, which is already more then ATmega328 can handle (only 2048bytes in I remember correctly)

When I get time and money, I was planning to buy a 64K external memory chip, ATmega328 (because I'll need a bigger program space), and redoing the whole screen into some sort of music visualization thing. I'm not really sure what exactly it will be yet, but I hope I'll finish it by next christmass (with the whole living in small city thing, just getting actual parts takes 1 to 2 months)

November 30, 2010
by weijiajun
weijiajun's Avatar

That sounds really exciting man, can't wait to see what you come up with for the music visualization.

December 20, 2011
by bluestang
bluestang's Avatar

I see that your code is deleted form the site by chance do you have it posted anywhere else?

Post a Reply

Please log in to post a reply.

Did you know that a motor is harder to turn when its terminals are shorted together? Learn more...