#picaxe 28X2
#no_table
#no_data
' Proof of Concept for the DMD_driver PICAXE.
' Receives frames from the DMD_Source PICAXE and refreshes the DMD
' Connections Source Driver
' C.0 -> C.0 SwitchPin
' C.1 <- C.1 DriverReady
' C.6 -> C.7 HSERout to HSERin
' C.4 Ground this HSPIin pin
' Tell terminal who I am
pause 4000 : sertxd("DMD_driver_v2",cr,lf)
' Run fast
'setfreq em32
setfreq em16
' HSER and HSPI pins, just for reference.
Symbol HSPI_CK = C.3
Symbol HSPI_DI = C.4
Symbol HSPI_DO = C.5
Symbol HSER_OT = C.6
Symbol HSER_IN = C.7
symbol ROWdata = B.5 'DMD "ROW Data" pin. (OUTput portB.5)
symbol ROWclock = B.4 'DMD "ROW Clock" pin. (OUTput portB.4)
symbol COLUMlatch = B.3 'DMD "COLUMN Latch" pin. (OUTput portB.3)
symbol DISPenable = B.2 'DMD "DISPLAY Enable" pin. (OUTput portB.2)
' Inputs
Symbol SwitchPin = PinC.0 ' Signal from source to switch frames
' Outputs
Symbol DriverReady = C.1 ' Signal to source indicating we a ready to accept a new frame
Symbol TestLED = C.2 ' Flashes when comms lost
' Bits
Symbol SwitchState = bit0 ' Current state of Switchpin
Symbol OldSwitch = bit1 ' Previous state of Switchpin
Symbol CommsLost = bit2 ' Set if no frames received from source within 'FrTimeout'.
' Bytes
Symbol Row = b1 ' Row counter for DMD refresh
Symbol TB1 = b2 ' Temporary byte for counters etc.
Symbol TB2 = b3 ' Temporary byte for counters etc.
' Words
Symbol FrameStart = W10 ' Start of current frame, 0 or 512 in scratchpad.
Symbol FrTimeout = W11 ' Timeout counter if no frames sent from source
Symbol TW1 = W12 ' Temporary word for counters etc.
' Setup background serial receive
' HSERSETUP B57600_32, 1
' Setup the HSPI
' #
' # Tweak to suit what the DMD needs
' #
HSPISETUP spimode11, spislow
Gosub GetDefaultFrames
CommsLost = 1
FrTimeout = 500
' Main loop
do
' Refresh the DMD display
ptr = FrameStart ' Set scratchpad pointer to current frame start address, 0 or 512
For Row = 1 to 32
'For Row = 1 to 32
If Row = 1 then
High RowData 'If it's Row #1, then set this to a '1'
else
Low RowData
Endif
low DISPenable 'Disable the display while loading.
HSPIOUT (@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc,@ptrinc)
PulsOut COLUMlatch, 1 'Latch the columns, putting info on Output (LED) display.
PulsOut ROWclock, 1 'Pulse the ROWclock, to advance to next row.
high DISPenable 'Re-Enable the display.
Next Row
Toggle DriverReady ' Tell source we are ready for a new frame.
' This pin cycles at half the DMD frame refresh rate, so it is a useful
' place to put a frequency meter..
' Check for command to switch frames
SwitchState = SwitchPin
If SwitchState <> OldSwitch then
hserptr = FrameStart ' Set serial pointer to fill current frame with next serial data
If FrameStart = 0 Then ' Change current displayed frame
Framestart = 512
else
FrameStart = 0
Endif
OldSwitch = SwitchState ' Remember switch state
CommsLost = 0 ' Clear comms lost stuff
FrTimeout = 0
Low TestLED
sertxd (" Rxed_",#@ptr) ' Debug
Endif
' Do comms lost stuff
if CommsLost = 0 then
' Timeout if no new frames received after 500 refreshes.
inc FrTimeout
If FrTimeout > 500 then
FrTimeout = 0
CommsLost = 1
Gosub GetDefaultFrames ' Gets a pair of default frames,
Endif
else
' Comms are lost, so toggle between buffers every 20 refreshes
inc FrTimeout
If FrTimeout > 20 then
FrTimeout = 0
toggle TestLED
If FrameStart = 0 Then ' Change current displayed frame
Framestart = 512
else
FrameStart = 0
Endif
endif
endif
loop ' Main loop
' Subroutines
' ===========
GetDefaultFrames:
' This is just some PoC code.
' It fills the first frame buffer scratchpad with the "Hello World" pattern Marty wrote,
' Then fills the second buffer with a bit-inverted copy of the first buffer.
' When CommsLost occurs the refresh will alternate between these two images.
ptr = 0 ' Set to start of scratchpad
' Row 1 - row 1 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8B,$E8,$20,$70,$08,$9C,$F2,$0F,$01,$11,$C1,$C0,$00,$00,$00,$00), @ptrinc
next
' Row 2 - row 2 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8A,$08,$20,$88,$08,$A2,$8A,$08,$81,$12,$22,$20,$00,$00,$00,$00), @ptrinc
next
' Row 3 - row 3 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8A,$08,$20,$88,$08,$A2,$8A,$08,$81,$10,$22,$20,$00,$00,$00,$00), @ptrinc
next
' Row 4 - row 4 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($FB,$C8,$20,$88,$08,$A2,$F2,$08,$81,$10,$C2,$20,$00,$00,$00,$00), @ptrinc
next
' Row 5 - row 5 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8A,$08,$20,$88,$0A,$A2,$A2,$08,$81,$10,$22,$20,$00,$00,$00,$00), @ptrinc
next
' Row 6 - row 6 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8A,$08,$20,$88,$0A,$A2,$92,$08,$80,$A2,$22,$20,$00,$00,$00,$00), @ptrinc
next
' Row 7 - row 7 of "Hello World"
For TB1 = 0 to 15
lookup TB1, ($8B,$EF,$BE,$70,$05,$1C,$8B,$EF,$00,$41,$C9,$C0,$00,$00,$00,$00), @ptrinc
next
'
For Row = 8 to 32
' Row 4 to 29 - 2 dots at the left side, then 14 bytes of empty spaces, then 2 more dots for the right side
For TB1 = 0 to 15
lookup TB1, ($00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00), @ptrinc
next
next
' Copy and invert into second buffer
TW1 = 0
ptr = 512
do
Get TW1, TB1
@ptrinc = TB1 XOR $FF
Inc TW1
loop until TW1 = 512
Return