Skip to content

eyalabraham/avr-pong

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

 pong.c

    video generator and "pong" game for AVR ATmega328p
    running at internal 8Mhz clock on NTSC TV input
 
 horizontal resolution
==================================================

use UART is SPI mode "20. USART in SPI Mode" pg.204
    
horizontal line time    63.5 uS
hsync and back porch    10.9 uS
                      ----------
net video time          52.6 uS

at 8MHz clock, UART in SPI mode runs at 4Mbps max, bit time is 0.25 uS

in 52.6 uS we can fit 208 bits -> pixels
convert to a byte count we get 26 bytes -> 208 pixels
                                          ------------

max rendering resolution can use 20 bytes for 160 horizontal pixels
    
the pong game will use 11 bytes at 2Mbps for 88 vertical pixels
    
 vertical resolution
==================================================

following the scan line logic on NES Nintendo systems
picture scan lines according to: http://wiki.nesdev.com/w/index.php/NTSC_video
 0    - 239   (240)   active picture video data
 240  - 244   (  5)   blank video
 245  - 247   (  3)   v-sync
 248  - 261   ( 14)   blank video
            --------
               262 lines

in pong, render each line 3 times. this will give 'taller' pixels to match their width
and will save RAM because the video buffer will be smaller:
 ( 240[lines] / 3 ) x 11 [bytes per line] = 880 bytes
 
the pong game will have a resolution of 80 horizontal pixels

 code structure using PWM method
==================================================

1.  Timer1 is configured as fast PWM, mode 14
    PWM frequency is set by ICR to get 63.5uSec
    'lo' pulse width is set by the value in OCR1A
    use inverting mode, OC1A will go 'lo' at BOTTOM and 'hi' on OCR1A compare match
    sync pulse will be on PB1 (OC1A)
2.  set to interrupt on overflow so ISR runs every 63.5uSec
    ISR increments scan line number, manages the PWM width through OCR1A, and
    hooks render routine or game routine as required
3.  vertical sync will use a simple method from the Nintendo reference above and will
    generate short 4.7uSec or long '0' pulses each about 58uSec wide on scan lines 245, 246 and 247
4.  during the v-sync + blank scan lines time (22 rows x 63.5uSec) the game() routine is hooked
    and we have about 1,300uSec (about 22 scan lines) to run our game before rendering restarts!
    during this time there is no need to worry about sync pulses because the Timer PWM takes care
    of the pulses and their accuracy...
    game() routine must finish before 22 scan lines and simply hook the idle() routine and exit

    when measured on a scope, the pong game() routine never uses more that 150uSec
    timing is done through an output port pin that toggels at the start and end of game()
    a full game is about 10% of the available time

  Audio beeps
==================================================

using Timer0 in Clear Timer on Compare Match (CTC) mode with the OC0A output
set to toggle upon reaching OCR0A value.
OCR0A value is set to produce the desired tones.
sound generation is managed by a simple state machine implemented with a
switch-case construct.

 IO pin assignments
==================================================

                            470
  (TXD) pin-3       o-----/\/\/\/-----+             Pixel video
                                      |
                            1K        |
  (OC1A) pin-15     o--+--/\/\/\/-----+-----------o SYNC+Pixel video signal to monitor/TV
                       |
                       +--------------------------o Scope external trigger
  
  (AD0) pin-23      o-----------------------------o Right 'paddle' center tap
  
  (AD1) pin-24      o-----------------------------o Left 'paddle' center tap
  
  (OC0A) pin-12     o-----------------------------o Audio out
  
  Issues/fixes
==================================================

1.  extra '1' level at start of video line. UART sends a '1' bit level
    just before starting to send pixel bits
    fixed by adding an inverter (74LS14) on the pixel output
    and pixel bytes sent out from the UART are first inverted (bitwise NOT).
    the default IO pin of the UART (PD1) changed to default value of '1'

2.  video image projected ok, lines and picture are a bit "wavy"
    possible fix would be to use an external clock or crystal

3.  only seeing 188 visible lines instead of 240?

4.  when moving one paddle the other paddle moves slightly in the same direction
    maybe conversion process or some other bug?
    Reading through application note "Atmel AVR126: ADC of megaAVR in Single Ended Mode"
    section "2.8 Analog input circuitry" it seems that the 1Mohm paddle potentiometers I am 
    using may have an impedance that is too high compared to the 10Kohm required... check.