#picaxe 20x2
' Conway's Game Of Life 16x32
' PaulRB
' Jun 2013
' Cell data locations in scratchpad
symbol Row00 = 0
symbol Row00b = 1
symbol Row01 = 2
symbol Row02 = 4
symbol Row03 = 6
symbol Row04 = 8
symbol Row05 = 10
symbol Row06 = 12
symbol Row07 = 14
symbol Row08 = 16
symbol Row09 = 18
symbol Row10 = 20
symbol Row11 = 22
symbol Row12 = 24
symbol Row13 = 26
symbol Row14 = 28
symbol Row15 = 30
symbol Row15b = 31
symbol Row16 = 32
symbol Row16b = 33
symbol Row17= 34
symbol Row18 = 36
symbol Row19 = 38
symbol Row20 = 40
symbol Row21 = 42
symbol Row22 = 44
symbol Row23 = 46
symbol Row24 = 48
symbol Row25 = 50
symbol Row26 = 52
symbol Row27 = 54
symbol Row28 = 56
symbol Row29 = 58
symbol Row30 = 60
symbol Row31 = 62
symbol Row31b = 63
symbol Row00copy = 64
'Variables holding data on neighbouring cells
symbol NeighbourN = w14
symbol NeighbourNW = w15
symbol NeighbourNE = w16
symbol CurrCells = w17
symbol NeighbourW = w18
symbol NeighbourE = w19
symbol NeighbourS = w20
symbol NeighbourSW = w21
symbol NeighbourSE = w22
'Variables used in calculating new cells
symbol tot1 = w8
symbol carry = w9
symbol tot2 = w10
symbol tot4 = w12
'General variables
symbol row = b4
symbol RowS = b5
symbol x = b6
symbol x2 = b7
'Pins controlling KS0108 Graphic LCD
symbol GLCD_RS = C.0 ' H = data, L = instruction
symbol GLCD_E = C.1
symbol GLCD_DATA = pinsB
symbol GLCD_CS1 = C.2
symbol GLCD_CS2 = C.3
'Other pins
symbol PushBtn = pinC.6
'Bit data for screen refresh
data 0, (%00000000, %00001111, %11110000, %11111111)
main:
setfreq m64
gosub initMatrix
dirsB = %11111111
pullup %00000010 'Pullup on C.6
high GLCD_CS1 : high GLCD_CS2
low GLCD_RS
GLCD_DATA = %00111111 : pulsout GLCD_E, 1 ' Enable display
GLCD_DATA = %11000000 : pulsout GLCD_E, 1 ' Scroll Position = 0
do
gosub generateMatrix
gosub outputMatrix
If PushBtn = 0 then
do loop until PushBtn = 1
gosub matrixIsBoring
end if
loop
outputMatrix:
'Send matrix data for display on GLCD
for x = 0 to 7
high GLCD_CS1 : high GLCD_CS2
low GLCD_RS
GLCD_DATA = %01000000 : pulsout GLCD_E, 1 ' Y = 0
GLCD_DATA = %10111000 | x : pulsout GLCD_E, 1 ' set X
high GLCD_RS
x2 = x + x
high GLCD_CS1 : low GLCD_CS2
for row = Row00 to Row31 step 2
get row, word w0
w0 = w0 >> x2 & %00000011
read b0, GLCD_DATA
pulsout GLCD_E, 1 : pulsout GLCD_E, 1 : pulsout GLCD_E, 1 : pulsout GLCD_E, 1
if row = Row15 then
low GLCD_CS1 : high GLCD_CS2
endif
next
next
return
initMatrix:
'Set up initial cells in matrix
w0 = %0000000000000000 : put Row00, word w0
w0 = %0000000000000000 : put Row01, word w0
w0 = %0000000000000000 : put Row02, word w0
w0 = %0000000000000000 : put Row03, word w0
w0 = %0000000000000000 : put Row04, word w0
w0 = %0000000000000000 : put Row05, word w0
w0 = %0000000000111000 : put Row06, word w0
w0 = %0000000000001000 : put Row07, word w0
w0 = %0000000000010000 : put Row08, word w0
w0 = %0000000000000000 : put Row09, word w0
w0 = %0000000000000000 : put Row10, word w0
w0 = %0011100000000000 : put Row11, word w0
w0 = %0010000000000000 : put Row12, word w0
w0 = %0001000000000000 : put Row13, word w0
w0 = %0000000000000000 : put Row14, word w0
w0 = %0000000000000000 : put Row15, word w0
w0 = %0000000000000000 : put Row16, word w0
w0 = %0000000000000000 : put Row17, word w0
w0 = %0000000000000000 : put Row18, word w0
w0 = %0000000000000000 : put Row19, word w0
w0 = %0000000000000000 : put Row20, word w0
w0 = %0000000000000000 : put Row21, word w0
w0 = %0000000000000000 : put Row22, word w0
w0 = %0000000000000000 : put Row23, word w0
w0 = %0000000000000000 : put Row24, word w0
w0 = %0000000000000000 : put Row25, word w0
w0 = %0000000000000000 : put Row26, word w0
w0 = %0000000000000000 : put Row27, word w0
w0 = %0000000000000000 : put Row28, word w0
w0 = %0000000000000000 : put Row29, word w0
w0 = %0000000000000000 : put Row30, word w0
w0 = %0000000000000000 : put Row31, word w0
return
matrixIsBoring:
get Row00, word w0 : w0 = w0 ^ %0000000000000010 : put Row00, word w0
get Row01, word w0 : w0 = w0 ^ %0000000000000100 : put Row01, word w0
get Row02, word w0 : w0 = w0 ^ %0000000000000111 : put Row02, word w0
return
generateMatrix:
'set up N, NW, NE, W & E neighbour data
get Row31, word w0
NeighbourN = w0
bit16 = bit0 : w0 = w0 >> 1 : bit15 = bit16 : NeighbourNW = w0
w0 = NeighbourN
bit16 = bit15 : w0 = w0 << 1 : bit0 = bit16 : NeighbourNE = w0
get Row00, word w0
put Row00copy, word w0 'copy row 0 to location after row 15 to remove need for wrap-around code in the loop
CurrCells = w0
bit16 = bit0 : w0 = w0 >> 1 : bit15 = bit16 : NeighbourW = w0
w0 = CurrCells
bit16 = bit15 : w0 = w0 << 1 : bit0 = bit16 : NeighbourE = w0
'Process each row
for row = Row00 to Row31 step 2
'Pick up new S, SW & SE neighbours
rowS = row + 2
get rowS, word NeighbourS
w0 = NeighbourS
bit16 = bit0 : w0 = w0 >> 1 : bit15 = bit16 : NeighbourSW = w0
w0 = NeighbourS
bit16 = bit15 : w0 = w0 << 1 : bit0 = bit16 : NeighbourSE = w0
'Any live cells at all in this region?
w0 = CurrCells | NeighbourN | NeighbourS ' | NeighbourNW | NeighbourNE | NeighbourW | NeighbourE | NeighbourSW | NeighbourSE (not needed for 16x16 grid)
if w0 > 0 then
'Count the live neighbours (in parallel) for the 16 current cells
'However, if total goes over 3, we don't care (see below), so counting stops at 4
tot1 = NeighbourN
tot2 = tot1 & NeighbourNW : tot1 = tot1 ^ NeighbourNW
carry = tot1 & NeighbourNE : tot1 = tot1 ^ NeighbourNE : tot4 = tot2 & carry : tot2 = tot2 ^ carry
carry = tot1 & NeighbourW : tot1 = tot1 ^ NeighbourW : tot4 = tot2 & carry | tot4 : tot2 = tot2 ^ carry
carry = tot1 & NeighbourE : tot1 = tot1 ^ NeighbourE : tot4 = tot2 & carry | tot4 : tot2 = tot2 ^ carry
carry = tot1 & NeighbourS : tot1 = tot1 ^ NeighbourS : tot4 = tot2 & carry | tot4 : tot2 = tot2 ^ carry
carry = tot1 & NeighbourSW : tot1 = tot1 ^ NeighbourSW : tot4 = tot2 & carry | tot4 : tot2 = tot2 ^ carry
carry = tot1 & NeighbourSE : tot1 = tot1 ^ NeighbourSE : tot4 = tot2 & carry | tot4 : tot2 = tot2 ^ carry
'Calculate the updated cells:
' <2 or >3 neighbours, cell dies
' =2 neighbours, cell continues to live
' =3 neighbours, new cell born
w0 = CurrCells | tot1 & tot2 &/ tot4
put row, word w0
end if
'Current cells (before update), E , W, SE, SW and S neighbours become new N, NW, NE, E, W neighbours and current cells for next loop
NeighbourN = CurrCells : NeighbourNW = NeighbourW : NeighbourNE = NeighbourE
NeighbourE = NeighbourSE : NeighbourW = NeighbourSW : CurrCells = NeighbourS
Next
return
end