Newbie with DMD display & needs to speed up loops

OLDmarty

Senior Member
Hi All,

While i'm a newbie to this forum, i've been into pics/picaxes for around 5+ years, although i've had a lot a looong gaps in between projects, so i'm FAR from being any kind of expert ;-)

I'm back into picaxes again, and great to see NEW versions with more options & higher speeds have been released.

At the moment, i'm playing with the 20X2, mainly because it didn't need an external xtal/resonator, and still achieves an internal clock rate of 64mhz.

My current project requires some specific timings, for instance a clock pulse that occurs at 100hz rate, while sending (shiftout'ing) a bunch of data along with some latch-enables etc etc.
I'm currently trying to drive a large (128x32) DMD-Dot Matrix Display as found in old 1990's pinball machines, and these displays have a particular timing cycle to keep refreshing the display.

Right now, i have some working code, that displays a dual-lined border around the outside of the entire display, but it's flickering at about a 5-10hz rate, and thats with SETFREQ set to "m64" too.
I have a bunch of gosubs that call up various patterns then return and pulse a few row/column latch signals etc etc, so i know i have a major issue with my timings & loops, i'm sure there's 100 better ways to achieve this, but for now i proved the point to myself that i'm AT LEAST sending the correct control codes AND data which displays on the DMD as expected, so i'm sort of 1/2 way there ;-)


The other thing, is this (border) test pattern is coded within the picaxe code to simply prove my tests.
The final project text (or graphics) library will need to be pulled in from an external (serial?) eeprom etc.

Here's some info on the DMD display itnerface and drive signals to help you understand what i need to do:
http://pinwiki.org/wiki/Dot_Matrix_Display


...and here's my code for now, this does WORK, but very flickery, clearly i'm not meeting the minimum speeds for the Row clock/dot clock etc.

For the sake of simplicity, and proving to myself my code (kind of) works, i haven't implemented any for..next loops or data arrays etc etc....something i need to get back into sooner or later ;-)
I also think i probably 'have to' use the allocated SPIout data/clock pins for better performance? (currently i assigned any pin on portB as data & clock for the shiftout command.

I know i've done a lot of things incorrectly, and happy to take it on the chin from the great guru's out there ;-)

I hope my comments are fairly obvious, please ask me to clarify "WHY" i did something this way or that way.....if anything is unclear.

Code:
'DMD Tester - Built on 20X2 Picaxe Board - upto 64MHz internal clock.
#picaxe 20x2

setfreq m64

symbol SERIALdata = B.7	'DMD "SERIAL Data" pin.		(OUTput portB.7) 
symbol DOTclock = B.6	'DMD "DOT Clock" pin.		(OUTput portB.6)
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)

symbol portall = outpinsB

dirsB = %11111111		'set PortB to all OUTPUTS

portall = $00	'setup PortB as above bits set/cleared....

GoTo start

'********************
'This displays a dual-lined border around the entire outside of the display.
'(The Dual-lines are seperated with a space between them, like the "=" symbol, creating a boxed-border).
'********************

'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 1
line1:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoSub DMDrow1
Return

'This writes 1 dot at the left side, then 14 bytes of empty spaces, the 1 more dots for the right side column.
'this is used for row 2 and row 31
line2:
B0=$80:B1=$00:B2=$00:B3=$00:B4=$00:B5=$00:B6=$00:B7=$00:B8=$00:B9=$00:B10=$00:B11=$00:B12=$00:B13=$00:B14=$00:B15=$01
GoSub row232
Return

'This writes 1 dot at the left side, a space, then 14 bytes of solid line, then 1 space and a dot for the right side column.
'this is used for row 3 and row 30
line3:
B0=$BF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FD
GoSub row232
Return

'This writes 2 dots at the left side, then 14 bytes of empty spaces, then 2 more dots for the right side column.
'this is used for all rows 4 to 29, repeated over...
line4:
B0=$A0:B1=$00:B2=$00:B3=$00:B4=$00:B5=$00:B6=$00:B7=$00:B8=$00:B9=$00:B10=$00:B11=$00:B12=$00:B13=$00:B14=$00:B15=$05
GoSub row232
Return


'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 32, but has a slightly less pulses required being the last row.
line32:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoSub row32
Return


DMDrow1:
GoSub sendrowout1
Return

row232:
GoSub sendrowout232
Return

row32:
GoSub sendrowout32
Return



sendrowout1:
shiftout DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
					' the "1" after DOTclock means MSBfirst, idles low...
					'Shiftout (write) the 16bytes (128bits) into Line 1 on the DMD.
PulsOut COLUMlatch, 1		'Latch the columns, putting info on Output (LED) display.
low DISPenable			'Disable the display.
high rowdata			'IF it's Row #1, then set this to a '1'
PulsOut ROWclock, 1		'Pulse the ROWclock, to advance to next row.
high DISPenable			'Re-Enable the display.
Return


sendrowout232:
ShiftOut DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
PulsOut COLUMlatch, 1		'Latch the columns, writing info on Output (LED) display.
low DISPenable			'Disable the display.
low rowdata				'IF it's Rows #2 to 31, then set this to a '0'
PulsOut ROWclock, 1		'Pulse the ROWclock, to advance to next row.
high DISPenable			'Re-Enable the display.
Return


sendrowout32:			'##### Row 32 does NOT need to pulsout the ROWclock, or that would be for a 33rd row #####.
ShiftOut DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
PulsOut COLUMlatch, 1		'Latch the columns, writing info on Output (LED) display.
Return


START:

GoSub line1		'Line 1 - Load the 16bytes (variables B0 to B15) with "Line 1" DATA.
GoSub line2		'Line 2 - Load the 16bytes (variables B0 to B15) with "Line 2" DATA.
GoSub line3		'Line 3 - Load the 16bytes (variables B0 to B15) with "Line 3" DATA.
GoSub line4		'Line 4 - Load the 16bytes (variables B0 to B15) with "Line 4" DATA.
GoSub line4		'Line 5 - Load the 16bytes (variables B0 to B15) with "Line 5" DATA.
GoSub line4		'Line 6 - Load the 16bytes (variables B0 to B15) with "Line 6" DATA.
GoSub line4		'Line 7 - Load the 16bytes (variables B0 to B15) with "Line 7" DATA.
GoSub line4		'Line 8 - 
GoSub line4		'Line 9
GoSub line4		'Line 10
GoSub line4		'Line 11
GoSub line4		'Line 12
GoSub line4		'Line 13
GoSub line4		'Line 14
GoSub line4		'Line 15
GoSub line4		'Line 16
GoSub line4		'Line 17
GoSub line4		'Line 18
GoSub line4		'Line 19
GoSub line4		'Line 20
GoSub line4		'Line 21
GoSub line4		'Line 22
GoSub line4		'Line 23
GoSub line4		'Line 24
GoSub line4		'Line 25
GoSub line4		'Line 26
GoSub line4		'Line 27
GoSub line4		'Line 28
GoSub line4		'Line 29
GoSub line3		'Line 30
GoSub line2		'Line 31
GoSub row32		'Line 32 - Load the 16bytes (variables B0 to B15) with "Line 32" DATA.


GoTo start

Thanx in advance,
Marty.
 
Last edited:

AllyCat

Senior Member
Hi Marty,

I haven't looked at your code in detail, but Subroutine Calls (or more specifically the Return) appear to be rather "slow" with the latest (M2, X2) chips. Have you seen this thread and my "new" testing method at #12?

Cheers, Alan.
 

Buzby

Senior Member
Hi Marty,

Welcome to the forum !.

You will get a *huge* increase in speed if you use the 20X2's hardware SPI instead of the bit-banging 'shiftout'.
See 'hspiout' in the manual.

Cheers,

Buzby
 

JimPerry

Senior Member
This might be a lot quicker - elimiminates a lot of GOSUBS - it's a start
Code:
'DMD Tester - Built on 20X2 Picaxe Board - upto 64MHz internal clock.
#picaxe 20x2

setfreq m64

symbol SERIALdata = B.7	'DMD "SERIAL Data" pin.		(OUTput portB.7) 
symbol DOTclock = B.6	'DMD "DOT Clock" pin.		(OUTput portB.6)
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)

symbol portall = outpinsB

dirsB = %11111111		'set PortB to all OUTPUTS

portall = $00	'setup PortB as above bits set/cleared....

GoTo start

'********************
'This displays a dual-lined border around the entire outside of the display.
'(The Dual-lines are seperated with a space between them, like the "=" symbol, creating a boxed-border).
'********************

'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 1
line1:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoSub DMDrow1
Return

'This writes 1 dot at the left side, then 14 bytes of empty spaces, the 1 more dots for the right side column.
'this is used for row 2 and row 31
line2:
B0=$80:B1=$00:B2=$00:B3=$00:B4=$00:B5=$00:B6=$00:B7=$00:B8=$00:B9=$00:B10=$00:B11=$00:B12=$00:B13=$00:B14=$00:B15=$01
GoSub row232
Return

'This writes 1 dot at the left side, a space, then 14 bytes of solid line, then 1 space and a dot for the right side column.
'this is used for row 3 and row 30
line3:
B0=$BF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FD
GoSub row232
Return

'This writes 2 dots at the left side, then 14 bytes of empty spaces, then 2 more dots for the right side column.
'this is used for all rows 4 to 29, repeated over...
line4:
B0=$A0:B1=$00:B2=$00:B3=$00:B4=$00:B5=$00:B6=$00:B7=$00:B8=$00:B9=$00:B10=$00:B11=$00:B12=$00:B13=$00:B14=$00:B15=$05
'GoSub row232
Gosub sendrowout232
Return


'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 32, but has a slightly less pulses required being the last row.
line32:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoSub row32
Return


DMDrow1:
GoSub sendrowout1
Return

row232:
GoSub sendrowout232
Return

row32:
GoSub sendrowout32
Return



sendrowout1:
shiftout DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
					' the "1" after DOTclock means MSBfirst, idles low...
					'Shiftout (write) the 16bytes (128bits) into Line 1 on the DMD.
PulsOut COLUMlatch, 1		'Latch the columns, putting info on Output (LED) display.
low DISPenable			'Disable the display.
high rowdata			'IF it's Row #1, then set this to a '1'
PulsOut ROWclock, 1		'Pulse the ROWclock, to advance to next row.
high DISPenable			'Re-Enable the display.
Return


sendrowout232:
for b16 = 4 to 29
	ShiftOut DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
	PulsOut COLUMlatch, 1		'Latch the columns, writing info on Output (LED) display.
	low DISPenable			'Disable the display.
	low rowdata				'IF it's Rows #2 to 31, then set this to a '0'
	PulsOut ROWclock, 1		'Pulse the ROWclock, to advance to next row.
	high DISPenable			'Re-Enable the display.
next b16
Return


sendrowout32:			'##### Row 32 does NOT need to pulsout the ROWclock, or that would be for a 33rd row #####.
ShiftOut DOTclock, SERIALdata, 1, (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
PulsOut COLUMlatch, 1		'Latch the columns, writing info on Output (LED) display.
Return


START:

GoSub line1		'Line 1 - Load the 16bytes (variables B0 to B15) with "Line 1" DATA.
GoSub line2		'Line 2 - Load the 16bytes (variables B0 to B15) with "Line 2" DATA.
GoSub line3		'Line 3 - Load the 16bytes (variables B0 to B15) with "Line 3" DATA.
GoSub line4		'Line 4 - Load the 16bytes (variables B0 to B15) with "Line 4" DATA.

GoSub line3		'Line 30
GoSub line2		'Line 31
GoSub row32		'Line 32 - Load the 16bytes (variables B0 to B15) with "Line 32" DATA.


GoTo start
 
Last edited:

OLDmarty

Senior Member
Thanx for the Welcome, and the initial info...

@Alan - Thanx, i'll read the pdf in more detail, see if i can learn something ;-)

@Buzby - Yep, i figured i 'have to' move my pins onto the correct hspiout pins...it was around 2am when i finished coding/playing, and the last thing i wanted to do was drag out the soldering iron to move 2 or 3 pins around ;-)


Marty.
 

Buzby

Senior Member
.... and the last thing i wanted to do was drag out the soldering iron to move 2 or 3 pins around ....
That's why we always recommend using a breadboard at first, to prove the concept :)

It will be a cool bit of kit when you get it working smoothly.

Is it plasma or LED ?
 

OLDmarty

Senior Member
That's why we always recommend using a breadboard at first, to prove the concept :)
It will be a cool bit of kit when you get it working smoothly.
Is it plasma or LED ?
My breadboard is even harder to find than my soldering iron ;-)

The initial displays i played with are plasma, but needed -110v to run them, i opted for the LED version, which only needs 12v supply, and the 5v is done onboard.
I figured besides an interest in customising my own pinball machine, i'd also consider using these displays for a multitude of other pruposes being Large AND bright, such as calendar/clocks, ON-Air lights, cue/status lights, lap-counters/score boards for slot-car people, monitoring frequencies and/or callsigns for ham radio use etc....the list goes on.....(i have too many hobbies).

But first i need it to work ;-)

Regards,
Marty.
 

hippy

Technical Support
Staff member
As noted, HSPIOUT will give an increase in speed, also not making GOSUB calls to routines that simply GOSUB to another routine. Rather than having GOSUB calls the more you can make it repeated sequential code the better; it makes for a larger program but increases speed.

You have 32 x 16 bytes per frame, 512 bytes total, so at 1Hz refresh that's approx 2000us per byte, for 10Hz 200us, and a more desirable 50Hz is 39us, for 70Hz as the Wiki article suggest 28us. That might be achievable, and you could certainly get it faster than it is now.

Loading variables before outputting them adds some overhead. It would be better to load scratchpad memory once, then just output that data. On the 20X2 you only have 128 bytes of scratchpad, but the 28X2 and 40X2 have 1024. The 20X2 can certainly be used for proof of concept, even if it just repeats the same 128 bytes four times.
 

JimPerry

Senior Member
Thanx Jim, i'll try that out soon as i get back to my laptop and confirm operation....(as well as moving onto the hardware spi pins too).

Update: Sorry Jim, although it still works, it's about 5-10 times slower than my original code.
I see a 'scan' of the border being drawn, then wait 1sec to see it repaet again....whereas before i saw it redraw 5-10 times per second.

;-(

Marty.
I posted the wrong code at dirst check it now (I edited post)
 

OLDmarty

Senior Member
As noted, HSPIOUT will give an increase in speed, also not making GOSUB calls to routines that simply GOSUB to another routine. Rather than having GOSUB calls the more you can make it repeated sequential code the better; it makes for a larger program but increases speed.

You have 32 x 16 bytes per frame, 512 bytes total, so at 1Hz refresh that's approx 2000us per byte, for 10Hz 200us, and a more desirable 50Hz is 39us, for 70Hz as the Wiki article suggest 28us. That might be achievable, and you could certainly get it faster than it is now.

Loading variables before outputting them adds some overhead. It would be better to load scratchpad memory once, then just output that data. On the 20X2 you only have 128 bytes of scratchpad, but the 28X2 and 40X2 have 1024. The 20X2 can certainly be used for proof of concept, even if it just repeats the same 128 bytes four times.
Thanx Hippy, appreciated...

While the DMD datasheet mentions 70Hz refresh (and upto 200Hz), i figured i would settle in the middle at 100hz which seeemd a nice easy number to use for timing...

Yep, i figured scratchpad memory would be better, but i hadn't mastered that at the time, so the constant pre-loading of B0-B15 was used, once again simply to prove my coding for the short term...

I will continue (once code is updated) to use pre-defined values in scratchpad in the 20X2 to aid speed, along with the spi pins too...

Once everything is mastered, THEN, i will take the pre-loaded (libraries) outboard into external storage.

Thanx again,
Marty.
 

hippy

Technical Support
Staff member
A quick test with ...

Code:
#Picaxe 20X2
SetFreq M64
HSpiSetup SPIMODE00, SPIFAST
Do
  Toggle B.0
  HspiOut (B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15)
  PulsOut C.0, 1
  low C.0
  high C.0
  PulsOut C.0, 1
  high C.0
Loop
Gives 550us for 16 bytes, around 34us per bytes, which equates to 56Hz refresh rate.
 

Buzby

Senior Member
Hi Marty,

Your code is not optimum, things such as the redundant gosubs, but it is basically structured to run fast.

You will gain a little more speed by tidying it up, and pre-loading via the scratchpad will make a noticeable difference.

But the biggest improvement will come when you move to HSPI.

As hippy has tested, you will get refresh rates around 50Hz, which is plenty fast enough for smooth animation.

Your problem then will be getting the frame data updated quickly enough, not the display refresh rate.

Keep at it, it will be really cool when you finish. ( Cooler though if it was plasma ! )

Cheers,

Buzby
( A pinhead )
 

OLDmarty

Senior Member
Hi all,

Just clarifying my pins before i move over the the spi hardware pins, but on the 20X2, i *think* i should be using the following:
Port B.7 = "hspi sck" - SPI "Clock" (out to DMD display)
Port C.1 = "hspi sdo" - SPI "Data Out" (out to DMD display)

Further reading in the picaxe manual mentions the "hspi sdi" (input) pin must idle in the correct state (tied low?), before sdo can send OUT any data.
If sdi is idling in the wrong state (high instead of low) it's treated as an spi error condition and resets the picaxe after a few seconds??
Do i simply wire the sdi pin low? or does it need to alternate during certain sdo 'sends'??

Apologies, i haven't used spi pins before... ;-)
Marty.
 

westaust55

Moderator
@MArty,

as already mentioned, the number of gosubs and returns is a signficnat issue.
wher you have code like:
Code:
'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 1
line1:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoSub DMDrow1
Return
change those to
Code:
'This writes an entire solid line of 128 bits (16 bytes sent to make 128bits)
'this is used for row 1
line1:
B0=$FF:B1=$FF:B2=$FF:B3=$FF:B4=$FF:B5=$FF:B6=$FF:B7=$FF:B8=$FF:B9=$FF:B10=$FF:B11=$FF:B12=$FF:B13=$FF:B14=$FF:B15=$FF
GoTo DMDrow1
 

OLDmarty

Senior Member
Hi Marty,
Your problem then will be getting the frame data updated quickly enough, not the display refresh rate.
Yep, animations will be another can'o'worms......
I only know of 1 guy controlling a DMD via an FPGA, and another mob has produced a usb-to-dmd interface board, but they're not sharing what chip(set) they use....

I've been searching for people controlling DMDs with microcontroller for years, and finding a very low success rate, i think many people attemped, failed, and dropped it.....i'm trying to persist and "have a win" for once ;-)

I'm not entirely sure if picaxe is the answer, especially for the higher animated frame rates, i can't imagine i need to go 'up' to an alternate controller running in the 200-400mhz range???
I figured the 20x2 at 64mhz clock was going to smash it, compared to my previous design which was a pic 'f84 with 4mhz xtal (1mhz internal)....

Keep at it, it will be really cool when you finish. ( Cooler though if it was plasma ! )
Cheers,
Buzby
( A pinhead )

Don't worry, i'm mainly developing it on the LED DMD becuase it's low voltage and i can do it on my bench.
Absolutely nothing worse than leaning into a pinny to do development ;-(

Eventually i'll be using the regular plasma version DMD's, they're about 1/3rd of the price too ;-)

Marty.
 

Buzby

Senior Member
... I'm not entirely sure if picaxe is the answer, especially for the higher animated frame rates, ...
Use two PICAXES !.

An untried idea, but based on previous stuff I've done.

Keep the 20X2 ( or a PICAXE with bigger scratchpad ) as the DMD frame driver, and use HI2C to update the scratchpad in the background from another source.

This can be another PICAXE loaded with frames, and it just puts them out over I2C straight into the frame driver.
 

hippy

Technical Support
Staff member
A 28X2/40X2 may be ideal in this application with a second PICAXE or other device providing the animated frames via serial.

The DMD PICAXE can pull 512 bytes out of scratchpad and throw them to the screen, background serial can put the next 512 bytes of frame data in the other 512 bytes of scratchpad memory, the DMD PICAXE then only needs to decide which of the two sets in scratchpad it displays. If the animation rate is lower than the display refresh rate there shouldn't be too much interference between the two.

There's probably a bit more to that in making it work but it's a simple enough idea and should be feasible.
 

OLDmarty

Senior Member
Use two PICAXES !.

An untried idea, but based on previous stuff I've done.

Keep the 20X2 ( or a PICAXE with bigger scratchpad ) as the DMD frame driver, and use HI2C to update the scratchpad in the background from another source.

This can be another PICAXE loaded with frames, and it just puts them out over I2C straight into the frame driver.
That's certainly an option, i did similar things using 2 eproms back in the day, having one eprom as the 'patterns library' and the eprom driving it was the 'pattern controller'.


I did initially think that even if the picaxe handled the DMD nicely, there might not be enough musclepower leftover to process much else, other than monitoring a bit or 2 to tell the picaxe what to do to the DMD, as you suggested.
 

OLDmarty

Senior Member
A 28X2/40X2 may be ideal in this application with a second PICAXE or other device providing the animated frames via serial.

The DMD PICAXE can pull 512 bytes out of scratchpad and throw them to the screen, background serial can put the next 512 bytes of frame data in the other 512 bytes of scratchpad memory, the DMD PICAXE then only needs to decide which of the two sets in scratchpad it displays. If the animation rate is lower than the display refresh rate there shouldn't be too much interference between the two.

There's probably a bit more to that in making it work but it's a simple enough idea and should be feasible.

Yep, absolutely feasable and ultimately 'the way to go'....but for now..."baby steps" heheheehe.
 
Last edited:

Buzby

Senior Member
HSEROUT or HI2COUT ?

Which is better ?

FIGHT !


Well, with HI2COUT you could easily update a subset of the frame, because of the optional address parameter.

But which is faster ?

Time for some testing, but I'm not near my hardware :(
 

hippy

Technical Support
Staff member
:)

Is it the outputting or the inputting which is most important ?

I'd argue that for the DMD controller it would have overhead in reading the I2C while background serial would be handled inside the firmware with minimum overhead.

Not saying I2C is at all wrong, and it does solve some issues the serial solution would have. With the writer having two banks of I2C it could select which one to write to and which the DMD reads so the DMD is only every reading one fixed set of memory which makes it easier to implement. Writing also has zero impact on the DMD controller.
 

Buzby

Senior Member
Hi hippy,

Set the DMD driver as an I2C slave, then the scratchpad is updated without any user code.

Or have I been doing it wrong these last few years ?
 

Buzby

Senior Member
Hi hippy,

It seems we've hijacked Marty's thread, but once he's got the DMD driver running this discussion maybe relevant.

The downside with I2C slave is that the manual says the effective slave address space is only 256 bytes.
I have never tried writing beyond that, even though HI2COUT can send word addresses.

Is slave mode really limited to 256 bytes ?
 

hippy

Technical Support
Staff member
Yes, 256 bytes on 28X2 and 40X2, just 128 on 20X2. It's because it uses byte addressing in all cases.

It would be possible to parallel multiple X2's and they take it in turn to update the display, quarter / half each.
 

OLDmarty

Senior Member
Hi hippy,
It seems we've hijacked Marty's thread, but once he's got the DMD driver running this discussion maybe relevant.
No probs at all, at least my thread has inspired some thoughts bouncing around which will be handy as the project advances...

Marty.
 

Buzby

Senior Member
Hi hippy,

... It's because it uses byte addressing in all cases.
Well that's a candidate for the next firmware release. An optional i2cword parameter for the chips with big scratchpads.
( Not to get into another fight, but this is another example of where PIC hardware is outpacing PICAXE firmware. )

... It would be possible to parallel multiple X2's and they take it in turn to update the display, quarter / half each.
I'm sure we can come up with a one PICAXE solution, just need to think a bit harder !.

Overcoming the limitation in the I2C slave I think will add too much complexity to the DMD driver, so bin that idea.

The main problem with serial is the fact that the datastream will need aligning with the scratchpad.
( After a global reset everything should stay in step, but does it ever ? )

If we use a second PICAXE to store the frames then we can have a couple of digital IO as well as the serial out to the DMD driver.
These could then be used for some handshaking to keep things in step.

With 1024 bytes of scratchpad the DMD driver can hold two frames, each of 512 bytes.
The DMD is being continually refreshed from one of these frame buffers.

The 'source' PICAXE has a DO telling the DMD driver which of it's two frames to display.

When the DMD driver sees the DO change, it switches the displayed frame by doing two things :
1 - Set it's display refresh pointer to the start of the 'new' frame, i.e 512 or 0.
2 - Set hserptr to the start of the 'old' frame, i.e 0 or 512.
This sets the background serial to save received data in the 'old' frame.

It then toggles a pin to the 'source' to say it is ready for the next frame.

The 'source' then sends the next 512 bytes, and gets ready to toggle the DO telling the 'driver' to change frames.

When it is time to show the next frame the 'source' toggles the DO, the 'driver' sees it, switches frames, and the process repeats.

This mechanism means the 'driver' never tries to display a 'half and half' mixture of old and new.

It also means that if serial is slow, it just takes longer to fill the buffer, but it won't affect the display of the current frame.

Also, any loss of sync will be corrected in the next frame.

I'm fairly sure this will work, what do you think ?

Cheers,

Buzby
 

hippy

Technical Support
Staff member
I'm fairly sure this will work, what do you think ?
Should work, and could even be simpler, assuming it's all synched-up and working okay ...

Writing fills half the scratchpad a frame at a time 0-511 then 512-1023, then auto-rolls back round. The animator can therefore simply send 512 bytes for each frame and toggle the signal line. The DMD just needs to read that signal decide if it's displaying from 0 or from 512.

There might be a chance that the frame being displayed is also being written but that would just mean a change during the fame and shouldn't be noticeable.

If it's not a problem the DMD could just show 0-511, writer sends a 512 frame and 512 zeroes. No need for any signalling.
 

Buzby

Senior Member
... could even be simpler, assuming it's all synched-up and working okay ...
If it's not a problem the DMD could just show 0-511, writer sends a 512 frame and 512 zeroes. No need for any signalling.
If it was synched up these options would be fine and dandy, except think what happens with a *slow* serial, say 300 baud.
 

Buzby

Senior Member
Hi Marty,

I'm at my hardware now, and have spent a few hours writing some Proof of Concept code.

I used two 'old' 28X2 modules, so I can only run at 32MHz.
With this setup I get display refresh rates of nearly 40Hz.
New 28X2's can run at 64MHz.

The 'DMD_Driver' file contains the display refresh code.
It displays a frame from one 512 byte buffer, while the serial input fills the other.
When the serial transmission is complete the 'source' toggles the 'SwitchPin' which tells the 'driver' to swap buffers.
This gives a 'clean' transition between frames.
When the swap is complete the 'driver' toggles the 'DriverReady' pin to tell the 'source' it can send the next frame.
There is code missing relating to the DMD control bits, but it won't be difficult to add them.

The 'DMD_Source' file contains the code which sends the frames to the driver.
There is a dummy frame generator in it which will generate a sequence of unique frames for testing.
They won't look pretty, but they will prove the concept works.

This code is running slower than I expected, frames are only sent at 5 or 6Hz.
There maybe something I've done wrong, but at least it works.

I don't think a 20X2 is going to cut the mustard for this job. Not because of speed or code restrictions, but because of the small scratchpad.
Even with clever code I can't see any way to make a 20X2 refresh the display without having 'scraggies' as a new frame overwrites the old.

The code is attached.

Have fun,

Buzby
 

Attachments

OLDmarty

Senior Member
Thanx Buzby for your hard work, well appreciated ;-)

I'm flexible with design, so i don't have any problem with the type of picaxe required and/or 'how many' etc....
Sadly, i only have one 28x2 here, and a few (now) on mail-order which will arrive next week, all local stores have runout.....damn damn damn!

I may still buy a 2nd 'starter kit' just to get the 28x2 chip for the weekends trials, although it's the earlier 28x2 (18f2520), but it'll help prove things for now...


I wonder (for the finalised design) that we should focus more on the patterns/frames data in an external eeprom of sorts...this may free up a lot of the current scratchpad issues? and resort back to single-pic design ???

My initial thought was simply 1 picaxe controlling an external storage (eprom/eeprom or SDcard etc) while processing some control inputs which decide which 'page' of the external memory would be squirted out to the DMD,..but i do understand if a single picaxe might not cut it, so a 2nd picaxe will be required as a controller that handles the external signals (such as a digital clock code input) which then lazily tells the DMD-drive picaxe what data to send to DMD.

I'll continue to play with your coding as PoC, then move forward to the next stage with external mem.

Regards,
Marty.
 

Buzby

Senior Member
Hi Marty,

Concentrate on the 'driver' code, don't worry about the 'source' till later, I've more ideas for that.

The driver should, hopefully, work once you put the DMD control bits in.
I've not got a DMD, so I can't try it properly. It's difficult to see what the display will look like just by looking at the HSPIout waveform on a crappy 'scope !.

If it does work it should do the following :
After power up wait for 4 seconds, then start the screen refresh. The screen will be blank during this time because the buffer is full of zeros.
After 500 refreshes ( about 10 seconds ) it should load the default images, and start toggling between the two.
( I should have put the call to get the default images before starting the refresh, then you wouldn't have to wait so long to see a result. )

I'll try to find a cheap DMD somewhere, any ideas ?

Cheers,

Buzby
 

JimPerry

Senior Member

Buzby

Senior Member
Yep !, That's the one I saw as well.

It is an LCD with orange backlight, a poor man's plasma.

Still way to expensive for a play. The plasma/LED versions are on www.pinled.de , between 199 and 499 euros !.

I am currently restoring a pinball, but it is from pre-DMD days, so I've no real excuse to buy one.
 

OLDmarty

Senior Member
Thanx Buzby,

I'm just tweaking together a vero-board with 2of 28X2's on it now, and doing the final inter-pic wiring in preparation for the source AND driver pics running whenever...

DMD's are pricey, but also inconveniently used high voltages, it's probably easier to have a full machine nearby to run the DMD from ;-)
Even the LED DMD i have cost $500aud, although i only got it because i did some labour for a pinny shop, and decided to take the DMD instead of payment ;-)

I do intend to start taking small video-clips of your code in action, just so you can see how good/bad it's working etc, it'll probably give you a more pinpointed area of code to work on,...i'll keep reburning the pics and re-doing video's to give you the feedback of your changes....

Regards,
Marty.
 

Buzby

Senior Member
Don't wire the 'source' device yet, just get the 'driver' working.

The 'source' might change dramatically - I've got a cunning plan !
 

OLDmarty

Senior Member
OK, i've just finished migrating the 20x2 code across to my new (stripboard) 28x2 board. (which has 2of 28x2's on it).
I've just proven my original (slow) code is controlling the DMD to prove all my wiring/pinouts/programming interface is all ok.....so far so good.

Tomorrow i'll then move my original wiring onto the correct SPI pins to observe better performance, and move towards the recent 'buzby code' trials ;-)

NOTE:
At the moment, i only have 4Mhz resonators, i couldn't find anything higher speed today in local shops, but i've ordered assorted 4/8/10/16Mhz resonators coming in next week along with the higher speed (64mhz) 28X2's as well....

Videos to follow....

Marty.
 
Top