Friday, December 14, 2012

PONG (PIC12F1840)

UPDATE 13.0109:
That tune. It's. Stuck. In. My. Head...

A new update soon. I have a couple of bugs to squash.
UPDATE 12.1231:
I split out all of the NTSC stuff into it's own module - NTSC_Interface.INC and NTSC_Interface.ASM. Hopefully this makes for easier implementation of NTSC video in your projects. I also have ODD/EVEN fields implemented and the timings are _really_ tweaked to try to meet spec. The big LCD TV is working better (VSync locks now, data is clean, but there's a weird shifting of the line data), and everything else I have thrown at it works great, including my Sony LCD goggles.

PONG.ASM (V4.04):
Common.INC (V1.10):
NTSC_Interface.ASM (V1.00):
NTSC_Interface.INC (V1.00):

Enjoy - and Happy New Year!

UPDATE 12.1229:
In order to get the large LCD TV working, I've had to implement odd/even fields to the video generation. So - long story short - there's a lot of CRAP information out there on what the video signal is supposed to look like. I'm surprised I've had anything working, with the BAD information that I have been working from.

Happy ending? I'm close to getting absolutely correct video implemented, and it's all thanks to this webpage:

Which has wonderful timing diagrams like this:

Who knew there were SIX pulses in the midst of the vertical synchronization phase for NTSC video, not FIVE as some as said. And who would have thought it would make such a difference to the video quality! One must NOT mix up the timings for PAL/SECAM and NTSC, or bad things will happen.

You're welcome. Merry Christmas.

UPDATE 12.1228:
Version 4.01 of PONG is now released. It has COMPUTER mode for player 2. Just press and hold the PLAYER 1 BUTTON while powering up. A large 'C' should be in the upper right corner of the screen.

Also note - the player 1 joystick handling has been modified for the Tandy joystick (see pics below). The original code is still in the source, just commented out.

PONG.ASM (V4.01):
Common.INC (V1.10):

UPDATE 12.1228:
I crammed my second PONG board into an old Tandy joystick. Well, 'crammed' isn't really true, because there's plenty of room for the board, cables and Audio/Video jacks. Now the batteries? Those may post a problem. I'm just powering it from the PICKIT3 at the moment.

Top view. Looks like a normal Tandy joystick.

The front side, with the big red button that is original to the
Tandy joystick. Cheesy.

The right side, showing the ICSP header for programming
the PIC. I use this to power the device - at least until I figure
out what I am going to do for the batteries.

An upper view where you can see the joystick,
big red button, and the A/V connectors.

A view of the inside. The bottom is on the left, the top is on
the right. In the bottom, the A/V connectors are on the lower
left. The micro board is on the upper right. The top has the
original joystick and button that came with the device.

Another view of the inside.
The top is on the left, the bottom on the right.

Close up of the micro board. 1 PIC, 6 resistors.
I need to add a capacitor.

UPDATE 12.1228:
3 items:
  1. This PONG post has surpassed the Dual Die Emulator post in the number of views. Thank you all very much. And thanks again to Hack-A-Day for the link from their website.
  2. I've built another PONG board, one that is to be battery powered and self-contained in an old Tandy joystick. And after an hour of soldering, I programmed the part and - it works! So the first one wasn't a complete fluke. This should give hope to anyone else out there who is building this project.
  3. I'm programming in a mode for making player 2 a computer player. When I finish, I'll post the code for anyone who is interested.
UPDATE 12.1227:
I've been working on BREAK OUT and there's lots of lines with fixed, single pixels and I was having a heck of a time getting everything lined up and the video signal timings correct. I was tweaking my signal timing routine and adding NOPs all over the place and spending a LOT of time getting things right that would just break when I added code or changed the graphics.

So I finally broke down and started experimenting with using a interrupt service routine to control the video signal, with the timings based on TIMER0. It turned out great, so this morning a did a major overhaul of PONG and turned over control of all of the video signal timing to a TIMER0 ISR.

Oh my, I should have done this in the first place.

All of the 'Timing Fudge' comments with the associated NOPs are gone. You won't find stray NOPs anywhere except for placing pixels on a line - no more peppering the code with NOPs to get the sync width or line width correct. It is _so_ clean and rock solid now, and so easy to change and maintain, that it almost has me in tears to think of how much time I have spending pushing 250ns slices around in the code.

Since it's a major change, PONG has been bumped up to V4.00.

PONG.ASM (V4.00):
Common.INC (V1.10):

UPDATE 12.1225:
I've started a new game for the PIC12F1840 - BREAK OUT. The new post is HERE if you are interested.

UPDATE 12.1224:
Ah, damn. There's always another bug.

While filming the V3.06 demo, I noticed that the ball would sometimes hit the upper sideline and not bounce off at an angle - it would just continue to follow the sideline until hit with a paddle, and then take off following the sideline to the other paddle, ad nauseum. Yeah, it bugged me, and I fixed it in my sleep last night. I was able to come into the lab this morning, go directly to the problem in the code and fix it. Nice. Weird, but nice.

Also, the _DEBUG_ option is set to FALSE, so there's no VSYNC flag pulse being generated on GPIO2.

And some timing fixes. And I added a blank and then two white lines after the Copyright, because it looks good.

PONG.ASM (V3.07):
Common.INC (V1.10):

Enjoy! And Merry Christmas!!!

UPDATE 12.1223:
Here's a semi-short movie of what you will get if you build this project:

If you do build it, I hope it's worth it :) Seriously, if you do build this project, I would enjoy and appreciate feedback and pics of your build.

Older updates and the orignal post after the break.

UPDATE 12.1223:
I'm going to call it a project and do a final release on V3.06. I could keep mucking around, adding things, breaking things, but it's in good shape right now. So - unless I find a major bug or someone else builds one of these things and finds something, I'm calling it FINAL.

PONG.ASM (V3.06):
Common.INC (V1.10):

Onward to the next project! Break-Out on the PIC? Tetris on the PIC? We'll see...

You know - I am using two GPIO pins to make a 2 bit DAC. I could use those for I2C instead - and if I could find one of those Nokia I2C displays, I could make a portable gaming system. Interesting. I could plug in Serial EEPROMs that interface via I2C - download software from them and FLASH the high page of program memory. It would be a way to change the software without reprogramming the PIC with the PICKIT2. Wow - lots of ideas floating around right now.

UPDATE 12.1223:
Everything is clean and tidy at this point, so it's time to release V3.05. The big change was a reduction of the screen size to 32x48, so that I could add blank lines before/after the data lines, so the video output would display well on CRT TVs. Before the change, the scores where half missing at the top of the screen, and the copyright was completely missing at the bottom of the screen. All added some minor gameplay changes: you can no long hold down the thumbstick button and continuous serve, a 'SERVICE' indicator is displayed next to the score of the player who's turn it is to serve (determined by who won the last point - first serve is gentlemen's decision). Court sidelines have been added since the court has been reduced in size. And just a lot of internal stuff that seems to creep in as I understand how the architecture of the game is supposed to be, and how it can fit in 60us chunks.


PONG.ASM (V3.05):
Common.INC (V1.10):

UPDATE 12.1222:Lots of changes - internal and with game functionality. I'm getting the bits and pieces in to put 'english' on the ball. I'm restructuring quite a bit of the code so it's a bit more dynamic. Example: The max size of the display is 56 lines (32x56 dots) - you can adjust one define in the code, and it will change the screen size and automatically put in blank lines so that the new screen size is centered on your TV and the video frame stays at 60hz. Ha! I'm having too much fun...

This is a 32x10 display. The paddles only have one pixel of movement. Ha!

I'm really happy that it all seems to work on the first shot - I thought it would dead bust at 10 pixels height. But - nope - still kicking.

I still have lots of work to do, so it will be a little while before a code drop.

UPDATE 12.1221:
New code, no game function changes - only internals. Most all procedures have been moved to the high page of program memory, which gives me lots of room for new functionality with the actual game (data memory limited, tho). Some of the vertical sync generation has been simplified / cleaned up. LOTS of comments added. The version number has been bumped to V3.03, and that is reflected at the bottom right of the screen. Common.INC has not changed, but is linked for completeness.

PONG.ASM (V3.03):
Common.INC (V1.10):


UPDATE 12.1221:
New code, semi-new look. The title has changed to "Pong For The 12F1840". And I added the software version number in the lower right of the screen, on the copyright line.

Internally, using the 16bit Timer1 didn't work out as well as I hoped. Using it didn't give me the added resolution I wanted (there's a _long_ reason for that), and it also added instructions / cycles to the code. The code is already cycle-packed and added-cycle sensitive, so I went back to the 8bit Timer0.

I also started moving non-timing critical procs to the high page of program memory, and also my large data tables. That gives me more room for code in the low page. More code means more features - right?

Here's a picture of the new title screen:

And here's the V3.02 source code:

PONG.ASM (V3.02):
Common.INC (V1.10):

If someone does build / program a PONG game of their own - one thing I need to warn you about. In order to get sound on a PIC that was ready fully loaded on it's GPIOs, I multitask GPIO1 between the right controller button and the audio output. Normally the GPIO is set as an output and I can play sounds on it, but when I want to check the button, I switch the GPIO to an input. In order to not confuse the low part of the sound frequency with a button press, I don't check the right button when noises are played. They are short and shouldn't really matter. BUT - if you press the right button and hold it down, it will force that line low and you will not hear any sounds until the button is released. Yeah, it's kinda funky, but it works and the project wouldn't have sound otherwise. Compromises. It's always compromises.

Things I want to add / improve:
1) Better collision detection.
2) Random angle on the serve.
3) English on the ball, so that you _could_ have the ball going horizontal line from one side to the other.
4) A winner's fanfare. And a winner's indication on the screen when the game is over.
5) A startup menu
6) A startup menu item where you can select human/computer for player 2.
7) A startup menu item where you can select the computer skill level - basically ball tracking.
8) A startup menu item where you can select game skill level - basically just a faster ball.
9) Some better sounds.

It will also be interesting to see how long the system will last on 3 'AA' batteries. That's +4.5V initially. I'd also like to try running it on 2 'AA' batters - +3V initially - but I would have to adjust the two video resistors so I would still get a good 1V signal for WHITE at +3V or less. I know the screen starts to dim when the voltage gets to +3.5V.

UPDATE 12.1220:
Once again, I've been linked by Hack-A-Day. Thanks, gents!

A link to the article is HERE.

UPDATE 12.1220:
Thanks to the helpful readers out there - they have provided a clean way to distribute the code.

The main program is PIC-PONG.ASM - Version 3.01 is here:
A common file that I drop into every project - Common.INC - is here:

This is V3.01 - V3.02 (the current one) is a mess and will be posted as soon as I finish some major changes and do some cleanup. Major changes involve paging in program memory and using the 16bit Timer1 for timing signals.

UPDATE 12.1220:
I wanted enclosures for the PIC board and thumbsticks. As small as possible. The only things I could find around the Mad Lab were these plastic coffins, left over from Halloween candy. Heh. At least it's a bit more protected now. My mechanical skills suck now because of the strokes, as evidenced by the broken green coffin around the video/audio connectors. Ah, well - it works.

No schematic changes - but I am making some major changes to the code. Trying to get all of the 'fudge' out (NOPs strew about for timing fixes). I am attempting to use the 16bit timer for timing all of the signals. I tried to use Timer0 (8bit), but it was a colossal failure - the finest resolution was FOSC/4 (instruction clock) and the timings were so unstable and jittery that it really messed up the video output. Timer1 (16bit) can use FOSC, which in this case is 32Mhz, so hopefully it will work out better. Initial testing says it just might. So - when I get the code settled down again, I'll post it. Again, anyone have a good idea on how to post a LARGE code listing on blogger?

UPDATE 12.1219:
Hardware is up to V1.04 - I added a L AUDIO OUT and R AUDIO OUT jacks, with 2 resistors

Interesting. I am running the board on 3 button cells right now. Everything was okay until the voltage dropped below +3.5V. So I guess a 3 or 4 cell pack ('AA's or 'AAA's) will be okay.

Here's the first two pages of the new schematics and some pictures.

UPDATE 12.1219:
Hardware is up to V1.03 (I added a piezo) and software is up to V3.02. I have a working game - paddles, ball, scoring, clean video and now - even SOUND! Here's the new schematic - I'm only going to post page 1 as the other 4 pages had no changes:

And here's a rather longish (4 minutes) demo video:

I also renamed the project 'PIC-PONG', as I didn't want to step on the original PONG's toes. However - after I changed everything, I did a google search - and wouldn't you know that someone has already done a PONG game on a PIC16F29 (I think). And they call it 'PIC-PONG'. Grrrrr. I know the part they were using had a bunch more pins than the 12F1840, and they were doing something interesting with a PORT, using it as the shift out register. So - I guess their project is a "16F29 PIC-PONG" and  mine is a "12F1840 PIC-PONG".

That's it for a while - I have things to do for Christmas. If I am back working on this project before the end of the year, it's because I ran out of things to do and I got bored.

NOTE: If you are using the PICKIT3 to program AND power this project - note that the PICKIT3 will affect the behavior of the right thumbstick and button. If you want to make sure everything is truly working correctly, unplug the PICKIT3 from the project and power your PONG board with an external power supply.

Oh, I owe you code. What is the best way to post code on blogger?

The rest of the original post and previous updates are below the fold.

UPDATE 12.1217:
It's been a long day, really getting to know the guts of video signals and how much I can push the PIC12F1840. For the actual game, I am using 32x56 resolution. But if you look at the very bottom line (the copyright I added), I can get 64x224 - but only when pushing bitmaps from program memory during 'special' data lines. I can't use the higher resolution for the game because - there just isn't enough data memory in the PIC to create a video buffer of the size required. I can barely squeeze out the video buffer for 32x56 mode.

I need to take a break for a day or so - I am deep fried to a crackly crunch.

UPDATE 12.1217:
Here's the updated schematics - V1.02, 5 pages.

 UPDATE 12.1217:
I've decided that trying to do all of the game computing in the first 5 blank half lines (30us each) of the vertical sync is foolish. 1st point: there are 60us blank lines at the end of the video field (before the vertical sync) and they provide a LOT of time for computing ball/paddle collisions, updating the ball/paddle positions on the screen, updating the score, etc. etc. 2nd point: the vertical sync half lines are very timing critical and messing with them causes no end of grief. I've found that if the last 60us blank lines, before vertical sync, stretch or shrink by a small bit, it doesn't affect the video quality. So - all the game computations are moved from vertical sync to the blank lines just _before_ vertical sync. Less hair pulling that way.

Another point: if you don't have a logic analyzer while doing this coding - you are insane. I am using an 8 channel USBee ZX LA module on the USB bus and I couldn't imagine trying to do without.

Also, I've added thumbsticks for paddle movement, instead of buttons for moving the paddles up/down. It gives me a Y axis value for the paddles and still a button to 'serve the ball' / 'restart the game' (which is 'press the thumbstick'). I'll update the schematics accordingly and post them later.

I have also just realized that I have no sound, nor a way to produce sound. So caught up with the video that I forgot all about that (beeps when the ball hits a paddle, buzzes when the ball is missed and someone scores, fanfair at the end of a game). I need to think about this.

When I get the code completed / cleaned up to my liking, I'll post that, too.

UPDATE 12.1216:
I updated the schematic just a _little_ bit - some minor changes to the hardware (trying to decide if all off the pull-up resistors are necessary), and added three sheets of video timing diagrams. We are now at V1.01.

UPDATE 12.1215:
Let's see - scoring is working, drawing the scores is working, ball/paddle collision detect is working, all of the video timings are worked out. Just need to work on a big list of little stuff.

I'm using 1059 or 4096 program words. I'm using ALL of the data memory, except for 16 bytes in the SHARED area (H'70'-H'7F'). Stack usage is minimal. I'm using all 6 GPIO pins on the part. No EEPROM is being used.

Other than not being happy with the character font (blocky and nasty) - I am happy otherwise. Oh - the ball could be one more pixel high (double the height). And I need to slow the ball down, it's a bit too fast. I had a fix in for that, but doing some other work broke it again. One more programming session should finish up the code.

The problem with code that has a lot of branches depending on logic or arithmetic - it varies the number of instructions executed. And all my timing is dependent on how many instructions are executed. So I have to do some ugly things to pad a procedure so that all of the scanlines are the same length. I do most of the game computations during the VSYNC phase of the video - there's no data to pump out, so there's 30us of computing time that can be consumed.


I'm generating a new post from here, because this project has expanded from just putting video on a TV set to actually creating a video game on a PIC12F1840. Since the resolution is low and the graphics are so blocky, I've decided to go old skool and recreate PONG.


  1. Is this open source project?
    Thank you.

  2. I will post the source code as soon as I 1) finish the current work and clean up the code and 2) find a good way to post the source code to blogger.

    Anyone have any ideas on #2, above?

  3. Put it up on GitHub and share it that way.

  4. pastebin was quick and easy for now. I'm got GitHub on my 'to-look-at' list for the future.