These forums are now closed Forum Index These forums are now closed
Please see the new forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

24x24 LED Game of Life...
Goto page 1, 2  Next
 
Post new topic   Reply to topic    These forums are now closed Forum Index -> Creation Room
View previous topic :: View next topic  
Author Message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: Apr Tue 24, 2007 10:11 pm    Post subject: 24x24 LED Game of Life... Reply with quote

I guess you are never a true geek until you have written a Game of Life program. Cool
Just to stand out of all the other geeks, let's write it in 6502 Assembler on a computer most people never heard on and on top of that, add a homebrew hardware that took months to build. Very Happy

It's quite simple, hook up a 6522 VIA and map it to address $C040.
See thread, http://www.brielcomputers.com/phpBB2/viewtopic.php?t=190

Get an old ATX power supply (since I had one lying around) and convert it to a poor mans Lab supply.
http://www.wikihow.com/Convert-a-Computer-ATX-Power-Supply-to-a-Lab-Power-Supply

Then order some 8x8 LED units from China for $23 and wait one month to get them.
During this time, order free samples from http://www.maxim-ic.com/, it took me 4 months to get 10 Max7219... Rolling Eyes
They won't send you 10 of these puppies at once so just keep ordering...

Then get a few more parts for around $30 and spend another month soldering...
At the end, you will have a beautiful 24x24 LED display...

Testing the display:

The setup running game of life:

The not-so-easy-to-debug side of the board:


Here is a short Video I put on Photobucket:


Want your own replica ?
Check it out here => http://www.brielcomputers.com/replica1.html

And the 6502 assembler for your Replica,
Code:
; Game of Life on a 24x24 LED.

; Rules taken from Wikipedia, http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life...

; The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells,
; each of which is in one of two possible states, live or dead.
; Every cell interacts with its eight neighbours, which are the cells that are directly horizontally,
; vertically, or diagonally adjacent. At each step in time, the following transitions occur:

;   1. Any live cell with fewer than two live neighbours dies, as if by loneliness.
;   2. Any live cell with more than three live neighbours dies, as if by overcrowding.
;   3. Any live cell with two or three live neighbours lives, unchanged, to the next generation.
;   4. Any dead cell with exactly three live neighbours comes to life.

; The initial pattern constitutes the 'seed' of the system.
; The first generation is created by applying the above rules simultaneously to every cell in the seed--
; births and deaths happen simultaneously, and the discrete moment at which this happens is sometimes called a tick.
; (In other words, each generation is based entirely on the one before.)
; The rules continue to be applied repeatedly to create further generations.

; ========================================================================================

; My version has a 24x24 grid displayed on the screen.
; There is no editor so edit Grid1 and re-compile.

; Note that I have two grids 26x26 bytes, but I only use 24x24 bytes for game of life.
; This is to make the calculations simpler when calculating number of neighbours.
; I don't have to do any calculations for wrap around or anything like that.


; START @ $1000
      .org $1000

VIA      = $C040
VIA_IOB      = VIA      ; Input/Output register B
VIA_IOA      = VIA+1      ; Input/Output register A
VIA_DDRB   = VIA+2      ; Data Direction Port B
VIA_DDRA   = VIA+3      ; Data Direction Port A
VIA_T1CL   = VIA+4      ; T1 Low Order Counter
VIA_T1CH   = VIA+5      ; T1 High Order Counter
VIA_T1LL   = VIA+6      ; T1 Low Order Latches
VIA_T1LH   = VIA+7      ; T1 High Order Latches
VIA_T2CL   = VIA+8      ; T2 Low Order Counter
VIA_T2CH   = VIA+9      ; T2 High Order Counter
VIA_SR      = VIA+10   ; Shift Register
VIA_ACR      = VIA+11   ; Auxiliary Control Register
VIA_PCR      = VIA+12   ; Pheriperal Control Register
VIA_IFR      = VIA+13   ; Interrupt Flag Register
VIA_IER      = VIA+14   ; Interrupt Enable Register
VIA_IOA2   = VIA+15   ; Input/Output register A, No handshake

; VIA stuff
add      = $30      ; Address in Max7219
dat      = $31      ; Data for Address
units      = $32      ; LED units.
count      = $33      ; Counter
rows      = $34      ; Rows
cols      = $35      ; Columns
temp      = $36      ; Temp Storage
LEDGridl   = $37      ; Grid Pointer Low
LEDGridh   = $38      ; Grid Pointer High
temp2      = $39      ; Temp Storage 2

; Game Of Life Stuff
tick      = $40      ; Even use grid 1, Odd use grid 2
row_counter   = $41      ; count the rows to print.
GridLow      = $42      ; Grid pointer.
GridHi      = $43
WorkGridLow   = $44      ; Grid Pointer for work grid.
WorkGridHi   = $45
cell_count   = $46      ; Used to count cells.
moves      = $47      ; Just a few moves


MAIN
      LDA #$09      ; 9 UNITS, 24X24 ledS
      STA units
      JSR init_VIA      ; Init VIA
      JSR init_max7219   ; Inint Dispaly
      LDA #$00
      STA tick      ; Start with grid 1
      LDA #$00      ; 256 moves
      STA moves
MainLoop
      JSR LifeToLED      ; Conver Lif grid to LED grid
      JSR showGridData   ; Display it
      JSR next_tick      ; Calcualte next move in the Game of Life Universe.
      INC tick      ; Next tick
      JSR delay      ; Small delay
      DEC moves      ; Are we done yet ?
      BNE MainLoop      ; Nope, continue.

      RTS
      
delay      LDY #$80      ; Loop 256*128 times...
      LDX #$00
.dloop1      DEX
      BNE .dloop1
      DEY
      BNE .dloop1
      RTS
      
LifeToLED   LDA tick      ; Test which grid to print.
      AND #$01
      BNE .load_grid2
      LDA #<Grid1      ; Load Grid1 to pointer.
      STA GridLow
      LDA #>Grid1
      STA GridHi
      BRA .grid_loaded
.load_grid2   LDA #<Grid2      ; Load Grid2 to pointer.
      STA GridLow
      LDA #>Grid2
      STA GridHi
.grid_loaded   CLC         ; Clear carry so we can add 27 to the grid address.
      LDA GridLow
      ADC #27         ; Add 27 bytes, that means we are on the second row, second column.
      STA GridLow
      BCC .no_carry      ; If we got a carry, we need to increase the High byte.
      INC GridHi
.no_carry   LDA #<GridData      ; Pointer to LED Grid
      STA LEDGridl
      LDA #>GridData
      STA LEDGridh
      LDA #$08      ; Count 8 bit per byte.
      STA count
      LDY #0         ; Start at second row in grid, one byte in.
      STY cols      ; Since it's zero, set offset in LED grid as well.
      LDX #24         ; We want to set 24 LEDs per row.
      STX row_counter
.grid_loop2   LDA (GridLow),Y      ; Get byte in current grid.
      BEQ .setDead      ; If, zero it's a dead cell.
      SEC
      JSR updateLedGrid
      BRA .set_Done
.setDead   CLC
      JSR updateLedGrid
.set_Done   INY         ; Next byte.
      DEX         ; Count down column.
      BNE .grid_loop2      ; Are we done with this row ?
      CLC         ; Clear carry so we can add 26 to the grid address.
      LDA GridLow
      ADC #26         ; Add 26 bytes, that means we are on the next row, second column.
      STA GridLow
      BCC .no_carry2      ; If we got a carry, we need to increase the High byte.
      INC GridHi      
.no_carry2   LDY #0         ; Reset Y
      LDX #24         ; Reset column bytes
      DEC row_counter
      BNE .grid_loop2
      RTS

updateLedGrid   ROL temp      ; Shift in LED.
      DEC count      ; 8 bits yet ?
      BNE ulgdone
      LDA #$08
      STA count      ; Reset counter
      STY temp2      ; Save Y
      LDY cols      ; Load offset in LED grid.
      LDA temp      ; Get LED data
      STA (LEDGridl),y   ; Store it in grid.
      INC cols      ; Increase offset.
      LDY temp2      ; Restore Y.
ulgdone      RTS


next_tick   LDA tick
      AND #$01
      BNE .load_grid2
      LDA #<Grid1      ; Load Grid1 to pointer.
      STA GridLow
      LDA #>Grid1
      STA GridHi
      LDA #<Grid2      ; Load Grid2 to Work grid pointer.
      STA WorkGridLow
      LDA #>Grid2
      STA WorkGridHi
      BRA .grid_loaded
.load_grid2   LDA #<Grid2      ; Load Grid2 to pointer.
      STA GridLow
      LDA #>Grid2
      STA GridHi
      LDA #<Grid1      ; Load Grid1 to Work grid pointer.
      STA WorkGridLow
      LDA #>Grid1
      STA WorkGridHi
.grid_loaded   CLC         ; We will count cells on Grid(Low/Hi) and put them on WorkGrid(Low/Hi).
      LDA WorkGridLow
      ADC #27         ; Add 27 bytes, that means we are on the second row, second column.
      STA WorkGridLow
      BCC .no_carry      ; If we got a carry, we need to increase the High byte.
      INC WorkGridHi
.no_carry   LDX #24         ; We want to scan 24 rows
      STX row_counter
grid_loop   JSR count_hood      ; Count neighbours.
      LDY #0         ; Zero Y      
      LDA cell_count      ; Get result
      CMP #02         ; Two cells ?
      BCC cell_dies      ; Less than two, cell dies.
      CMP #3         ; Three cells ?
      BEQ cell_birth      ; Three cells will come a life or stay alive, just put one there.
      BCS cell_dies      ; If more than 3 cells, it dies.
      LDY #27         ; We have two cells alive, copy cell from Grid(Low/Hi).
      LDA (GridLow),Y      ; Got the cell
      LDY #0         ; Form pos 27 on Grid(*) to WorkGrid(*).
      STA (WorkGridLow),Y   ; Store cell.   
      BRA cell_count_done   ; Continue on...
cell_dies   LDA #0         ; Cell dies, A = 0
      STA (WorkGridLow),Y   ; Store cell.   
      BRA cell_count_done   ; Continue on...
cell_birth   LDA #1         ; Cell was born, A = 1
      STA (WorkGridLow),Y   ; Store cell.   
cell_count_done   INC WorkGridLow      ; Next position
      BNE .no_inc1
      INC WorkGridHi
.no_inc1   INC GridLow      ; Next position
      BNE .no_inc2
      INC GridHi
.no_inc2   DEX         ; Next col.
      BNE grid_loop      ; Row not done, continue.
      LDX #24         ; Reset col counter.
      INC WorkGridLow      ; Next position, for each row we have to move Two spaces.
      BNE .no_inc3
      INC WorkGridHi
.no_inc3   INC GridLow      ; Next position 1 Grid
      BNE .no_inc4
      INC GridHi
.no_inc4   INC WorkGridLow      ; Next position 2 WorkGrid
      BNE .no_inc5
      INC WorkGridHi
.no_inc5   INC GridLow      ; Next position 2 Grid
      BNE .no_inc6
      INC GridHi
.no_inc6   DEC row_counter      ; Next row.
      BNE grid_loop      ; Row not done, continue.
      RTS
      
count_hood   LDY #0
      STY cell_count      ; Zero cell count.
      LDA (GridLow),Y      ; Y=0, neighbour top left.
      BEQ .no_add1
      INC cell_count
.no_add1   LDY #1
      LDA (GridLow),Y      ; Y=1, neighbour top middle.
      BEQ .no_add2
      INC cell_count
.no_add2   LDY #2
      LDA (GridLow),Y      ; Y=2, neighbour top right.
      BEQ .no_add3
      INC cell_count
.no_add3   LDY #26
      LDA (GridLow),Y      ; Y=26, neighbour to the left.
      BEQ .no_add4
      INC cell_count
.no_add4   LDY #28
      LDA (GridLow),Y      ; Y=28, neighbour to the right.
      BEQ .no_add5
      INC cell_count
.no_add5   LDY #52
      LDA (GridLow),Y      ; Y=52, neighbour to the bottom left.
      BEQ .no_add6
      INC cell_count
.no_add6   LDY #53
      LDA (GridLow),Y      ; Y=53, neighbour to the bottom middle.
      BEQ .no_add7
      INC cell_count
.no_add7   LDY #54
      LDA (GridLow),Y      ; Y=53, neighbour to the bottom middle.
      BEQ .no_add8
      INC cell_count
.no_add8   RTS


showGridData
      LDA #<GridData
      STA LEDGridl
      LDA #>GridData
      STA LEDGridh
      LDY #1      ; Start with row 1
      STY rows
      LDY #8
      sty count   ; Count 8 rows
      
sgdloop1   LDX rows   ; Row to X
      STX add      ; Store in address
      STX temp   ; Prepare to multiply by three
      CLC
      ROL temp
      LDA rows
      ADC temp
      ADC #47
      TAY      ; Y=(row*3) + 47, this is 9:th chars row.
      LDX #3      ; do three chars
      STX temp2   ; three times = 9 chars.

.loop1      LDA (LEDGridl),y
      STA dat
      JSR SendData
      DEY      ; point to previous chars byte.
      DEX      ; Three chars ?
      BNE .loop1
      
      TYA
      SEC
      SBC #21
      TAY      ; Y = Y - 21, move back 3 chars and compensate for the three rows already done.
      LDX #3      ; Three more chars to go.

      DEC temp2   ; did we do all 9 chars ?
      BNE .loop1
      
      JSR LatchData
      
      INC rows   ; Next row
      DEC count   ; Did we do them all ?
      BNE sgdloop1   ; Nope, recalculate etc...
      RTS

init_VIA   LDA #$FF   ; Make port A output.
      STA VIA_DDRA
      LDA #$00   ; Make ports low.
      STA VIA_IOA
      LDA VIA_ACR   ; Load ACR
      AND #$E3   ; Zero bit 4,3,2.
      ORA #$18   ; Shift out using Phi2
      STA VIA_ACR
      RTS

init_max7219   LDA #10      ; Intensity address
      STA add
      LDA #10      ; 10 out of 15
      STA dat
      JSR SendAllUnits
      JSR LatchData
      
      LDA #11      ; Scan limits (How many rows)
      STA add
      LDA #7      ; All 8 rows
      STA dat
      JSR SendAllUnits
      JSR LatchData

      LDA #9      ; Decode mode
      STA add
      LDA #0      ; No decoding, use all 8 bits as data
      STA dat
      JSR SendAllUnits
      JSR LatchData

      LDA #12      ; Shutdown register
      STA add
      LDA #1      ; No shutdown, normal operation
      STA dat
      JSR SendAllUnits
      JSR LatchData
      RTS

SendAllUnits   LDY units   ; Send same data to all units
sauloop      JSR SendData
      DEY
      BNE sauloop
      RTS

SendData   LDA add      ; Address for MAX7219
      STA VIA_SR   ; Shift it...
.wait1      LDA VIA_IFR   ; Are we done yet ?
      AND #$04
      BEQ .wait1   ; Nope, continue...
      LDA dat      ; Data for MAX7219
      STA VIA_SR   ; Shift it...
.wait2      LDA VIA_IFR   ; Are we done yet ?
      AND #$04
      BEQ .wait2   ; Nope, continue...
      RTS
      
LatchData   LDA #$01   ; Set Pin PA0 high
      STA VIA_IOA   ; This will load the data...
      LDA #$00   ; Set Pin PA0 Low
      STA VIA_IOA   ; Done loading the data, ready for more...
      RTS
      
GridData
      .BYTE $7E, $00, $00 ; 1
      .BYTE $7E, $00, $00 ; 2
      .BYTE $66, $00, $00 ; 3
      .BYTE $66, $3C, $00 ; 4
      .BYTE $0C, $3C, $00 ; 5
      .BYTE $0C, $66, $00 ; 6
      .BYTE $18, $66, $00 ; 7
      .BYTE $18, $66, $3C ; 8
      .BYTE $18, $66, $3C ; 9
      .BYTE $18, $3C, $66 ; 10
      .BYTE $18, $3C, $66 ; 11
      .BYTE $18, $66, $66 ; 12
      .BYTE $18, $66, $66 ; 13
      .BYTE $18, $66, $3E ; 14
      .BYTE $00, $66, $3E ; 15
      .BYTE $00, $3C, $06 ; 16
      .BYTE $00, $3C, $06 ; 17
      .BYTE $00, $00, $66 ; 18
      .BYTE $00, $00, $66 ; 19
      .BYTE $00, $00, $3C ; 20
      .BYTE $00, $00, $3C ; 21
      .BYTE $11, $00, $00 ; 22
      .BYTE $00, $11, $00 ; 23
      .BYTE $00, $00, $11 ; 24

;      .org $1300      ; For Debug

Grid1      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 1
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 2
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 3
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 4
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 5
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 6
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 7
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 8
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 9
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 10
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 11
      .BYTE 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 ; 12
      .BYTE 0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0 ; 13
      .BYTE 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 ; 14
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 15
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 16
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 17
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 18
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 19
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 20
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 21
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 22
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 23
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 24
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 25
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 26
   
;      .org $1600      ; For Debug

Grid2      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 1
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 2
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 3
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 4
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 5
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 6
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 7
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 8
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 9
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 10
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 11
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 12
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 13
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 14
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 15
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 16
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 17
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 18
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 19
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 20
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 21
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 22
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 23
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 24
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 25      
      .BYTE 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ; 26

Fixed bug in code 4/25, now it works better... Razz
4/25 Added Video link.
4/26 Added link to Replica Home page.


Last edited by fsafstrom on Apr Thu 26, 2007 10:09 am; edited 3 times in total
Back to top
View user's profile Send private message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: Apr Wed 25, 2007 12:06 am    Post subject: Reply with quote

I just had to take a break before I document how this thing works...

The 24x24 LED display is actually nine 8x8 LED units.
Each 8x8 unit is controlled by a MAX 7219 LED driver, if you look at the test I made, you can see how they are organized.
So that is basically LED unit 1-9 from top left to bottom right.
The Max 7219 keeps track of which LEDs I want to light up, so I only need to send the data once and then the chip will do the rest for me.
Each row (cathode) in the LED unit is connected to the digit section on the Max 7219 and each column (Anode) to the Segment section.
The Max 7219 accepts serial data so the chips are daisy chained together, however the clock and latch are parallel and goes to all chips in parallel.
Data basically flows from one chip to another so the most efficient way of sending data is to send 9 commands in a row and then latch it (tell the driver to use the data).
So when sending graphical data, you send 9 columns and then latch it.
Then row two, three and so on to row 8.

The VIA (6522) have a shift register so it's really doing a lot of work for me, all I need to do is load the shift register and tell it to send the data to the Max 7219.

Let me know if you have any questions or comments.

MAX 7219 Datasheet,
http://datasheets.maxim-ic.com/en/ds/MAX7219-MAX7221.pdf
Back to top
View user's profile Send private message
cheese1113



Joined: 13 Nov 2005
Posts: 91
Location: Reedley, CA

PostPosted: Apr Wed 25, 2007 12:21 pm    Post subject: Reply with quote

That is awesome! I think that there is potential for games with this set up!!
_________________
Max Wooden
Back to top
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: Apr Wed 25, 2007 3:14 pm    Post subject: Reply with quote

Yes, there will soon be a LED Pong game, maybe with a SID 6581 for sound effects or a SoundGin...
IF I can get the SoundGin to work that is, they don't seem to work to well on solderless breadboards... Sad
Back to top
View user's profile Send private message
cheese1113



Joined: 13 Nov 2005
Posts: 91
Location: Reedley, CA

PostPosted: Apr Wed 25, 2007 5:57 pm    Post subject: Reply with quote

You made Hack A Day! http://www.hackaday.com/2007/04/25/my-motors-finally-came-extra/
_________________
Max Wooden
Back to top
View user's profile Send private message Send e-mail AIM Address Yahoo Messenger MSN Messenger
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: Apr Wed 25, 2007 9:10 pm    Post subject: Reply with quote

I actually sent the link to Hack a day...
I'm glad they picked it up.

Here is a short Video I put on Photobucket:
Back to top
View user's profile Send private message
ethan



Joined: 02 May 2007
Posts: 1

PostPosted: May Wed 02, 2007 12:21 pm    Post subject: Reply with quote

Very nice. I can probably figure it out the hard way by inspecting the code, but how did you attach the 6522 to the array of 7219s? I'm guessing CB2 is data-in to the first 7219, but what are the other pin assignments?

Thanks and congrats on this. I need to track down a pile of LED matrices. I already have a few 7219s on hand.

-ethan
Back to top
View user's profile Send private message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: May Wed 02, 2007 2:14 pm    Post subject: Reply with quote

Hi Ethan,

The Load data (pin 12) on Max 7219 is connected to PA0 (pin 2) on the 6522.
Clock (pin 13) on Max 7219 is connected to CB1 (pin 18 ) on the 6522.
Data In (pin 1) on Max 7219 is connected to CB2 (pin 19) on the 6522.

The VIA (6522) is setup with port A as output and for the shift register to shift out at the pace of Phi2.

Code:
init_VIA   LDA #$FF   ; Make port A output.
      STA VIA_DDRA
      LDA #$00   ; Make ports low.
      STA VIA_IOA
      LDA VIA_ACR   ; Load ACR
      AND #$E3   ; Zero bit 4,3,2.
      ORA #$18   ; Shift out using Phi2
      STA VIA_ACR
      RTS

To send (or shift out) data, simply store the value you want to shift out in VIA_SR.
Then wait for bit 2 to be set in the VIA_IFR, that means the shift out is done.
Code:
SendData   LDA add      ; Address for MAX7219
      STA VIA_SR   ; Shift it...
.wait1      LDA VIA_IFR   ; Are we done yet ?
      AND #$04
      BEQ .wait1   ; Nope, continue...

Then latch the data by setting the Load pin high and then low again.
Code:
LatchData   LDA #$01   ; Set Pin PA0 high
      STA VIA_IOA   ; This will load the data...
      LDA #$00   ; Set Pin PA0 Low
      STA VIA_IOA   ; Done loading the data, ready for more...
      RTS


That's it, have fun...

/Bamse
Back to top
View user's profile Send private message
logjam



Joined: 15 May 2007
Posts: 14

PostPosted: May Tue 15, 2007 1:17 am    Post subject: Reply with quote

I LOVE a project with LEDs! Smile

Here is a picture of mine:

Front: http://www.stockly.com/images2/060129-LED_Display_Front_2718.jpg

Back: http://www.stockly.com/images2/060129-LED_Display_Back_2716.jpg

Legs: http://www.stockly.com/images2/060129-Weight_of_39584_Legs_2696.jpg

I have not built the driver circuits. I only finished it to win a bet (which had no wagers). I averaged 3.5 hours per 990 LED board. Smile

I plan to make a new one with finer pitch LED MODULES. Like your modules, with a .3" pitch. My display has a .4 inch pitch.

I built it for my Altair and Apple-1. The only thing I know is ALL the LEDs are in correctly and all light up. Smile
Back to top
View user's profile Send private message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: May Tue 15, 2007 9:20 pm    Post subject: Reply with quote

Now that's an LED display... Wink

I'm not sure I dare to ask, but how many LED's is in that display ?
Back to top
View user's profile Send private message
logjam



Joined: 15 May 2007
Posts: 14

PostPosted: May Tue 15, 2007 11:25 pm    Post subject: Reply with quote

19,008. It is 192x99, or 24x9 characters of 8x11 pixels.

I thought I'd be able to refresh 30 rows when I made the boards. I did some tests with my LEDs and found that I could only do a little over 10. I decided to refresh 11 rows at once since that is how many rows are in one character. The display will be refreshed as 1728x11.

I'm thinking about a different display of about 64x48. This display would display greyscale data. I took some movies I had and converted them to 64x48 greyscale. You have to squint to see them, but it was pretty good!

64x48 greyscale is 3072 bytes per frame. 4 bits of gray scale might be enough, so we could get 1536 bytes per frame.

It would be fun to use the Apple 1 as a source for the streaming video. Smile It would take 15-30k per second so the 6502 would have no time to do anything but receive frames...
Back to top
View user's profile Send private message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: May Wed 16, 2007 11:06 am    Post subject: Reply with quote

Very impressive...

What kind of hardware do you use to drive the LED's ?
The MAX7219 "only" handles 8x8 LED's so my guess would be some kind of custom hardware...

By the way, I calculated my power requirement to be 3 Amps for the 575 LED's with full intensity.
For 19008 LED's that would translate into 100 Amps for the whole board... Wink

On the other hand, I never measured the actual consumption so I could be way off...
Back to top
View user's profile Send private message
logjam



Joined: 15 May 2007
Posts: 14

PostPosted: May Thu 17, 2007 3:02 am    Post subject: Reply with quote

Not off... Smile

I found a 5V 90A power supply here:
http://www.surpluscenter.com/item.asp?UID=2007051702510729&item=15-1050&catname=electric

There is also a new 5v 100A or even 150A supply for $168 or $295

http://www.power-factor-1st.com/shop/enclosed-switching-power-supplies/g2-series/page2.html

So it should be around as bright as a 500W light bulb all said and done... Which over the area of the entire panel shouldn't be TOO bright...

My driver circuits are here:

http://www.stockly.com/images2/060121-Root_1_1.PDF

Each DriverBlock.sch is one of these:

http://www.stockly.com/images2/060121-DriverBlock_1_1.PDF

I have not sketched out the design for the 11 row drivers. They are basically the same thing except I will be using MOSFETs instead of those ULN2803s.

I have a 574 latch so that the entire row of LEDs changes at once instead of seeing a possible "wipe" of the display as new line data is clocked in. Possibly a waste, possibly not. This display is not like yours. I have to actually multiplex the LEDs myself. The MAX chip does that for you. I'm probably going to use an FPGA to do all of the bit twiddling and then have the display appear to the computer as "memory". A bit in memory would show up as one LED. This also allows for interesting things like "seeing" a program run as its memory space changes! Smile
Back to top
View user's profile Send private message
logjam



Joined: 15 May 2007
Posts: 14

PostPosted: May Thu 17, 2007 3:06 am    Post subject: Reply with quote

That Root.sch I posted is for 64 columns. There are 1728 columns total. There are an estimated 8,000 solder joints in the driver boards. I am not looking forward to that.
Back to top
View user's profile Send private message
fsafstrom



Joined: 26 Dec 2006
Posts: 155
Location: San Antonio, Texas

PostPosted: Nov Wed 28, 2007 9:00 am    Post subject: Reply with quote

I saw that this thread passed 10 000 views, kewl...

Let's hope that at least one or two people got interested enough in the Replica to buy one... Cool
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    These forums are now closed Forum Index -> Creation Room All times are GMT - 5 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group