Interface protocol

The Dot Matrix Display (DMD) is a 32x16 array of high-brightness LEDs for visually striking effects. [Product Page]
Post Reply
edfield
Posts: 3
Joined: Wed Feb 06, 2013 3:08 pm

Interface protocol

Post by edfield » Wed Feb 06, 2013 3:21 pm

I want to drive a DMD (and several of them!) from my own electronics. Can anyone explain, or point me at, the interface protocol? I get that there are four address lines, which I think select one of 16 lines. Then there is clk, lat/sclk, Red data, Green data, OE (output enable?). So what do I do with them? I expect the info is here somewhere, but I cant find it!

Thanks for your help.

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: Interface protocol

Post by Aussie_Wombat » Thu Feb 07, 2013 10:52 am

Edfield,

As Tronixstuff said, that thread has some info... Here it is again, but with more detail..

I am using a Maximite monochrome (pic32) to power the DMD panels. Currently I have 9 panels in a 3x3 configuration.. I mirror the VGA display to the dmd panels. I use the MMBasic to code the VGA display..

I am also about to trial the color Maximite (8 colors), with the same code. Now all I need is an RGB DMD Panel....Freetronics ?????


' These are the pins I used for the dmd panel

DMD_A = 16 ' D6 on supplied DMDcon(nector)
DMD_B = 15 ' D7 on supplied DMDcon(nector)
DMD_OE = 14 ' D9 on supplied DMDcon(nector)
DMD_CLK = 20 ' D13 on supplied DMDcon(nector)
DMD_SCLK = 17 ' D8 on supplied DMDcon(nector)
DMD_R_Data = 19 ' D11 on supplied DMDcon(nector)
DMD_T_Data = 18 ' D12 on supplied DMDcon(nector)[not actually required]


'*******************************************************************************
' subroutine code required by dmd panel

Sub senddata1( a_pin , b_pin , displayrow , wide , down)
Pin(DMD_A)= a_pin
Pin(DMD_B)= b_pin
Pin(DMD_OE) = 1
junk1 = SpiDMD( videomemhi, videomemlo, displayrow, wide, down, DMD_T_Data, DMD_R_Data, DMD_CLK)
Pin(DMD_OE) = 0
Pin(DMD_SCLK) = 1
Pin(DMD_SCLK) = 0
End Sub
' end subroutine code required by DMD panel
'*******************************************************************************

'*****************************************************************************
' code required by DMD panel, interrupt called every 5 ms, total of 20 ms for full display
dmd_display:
On dmdcount GoTo loop1,loop2,loop3,loop4
loop1:
senddata1(1,1,0,displayswide,displaysdown) ' lines 1,5,9,13
dmdcount=2
GoTo loopend
loop2:
senddata1(0,0,1,displayswide,displaysdown) ' lines 2,6,10,14
dmdcount=3
GoTo loopend
loop3:
senddata1(1,0,2,displayswide,displaysdown) ' lines 3,7,11,15
dmdcount=4
GoTo loopend
loop4:
senddata1(0,1,3,displayswide,displaysdown) ' lines 4,8,12,16
dmdcount=1
loopend:
ireturn
' end code required by DMD panel
'********************************************************************************

And my C code for the SpiDMD() command in MMBasic .
I only added to the SPI() code(was 24 bit), written by Geoff Graham, the writer of MMBasic...http://www.geoffg.net

void fun_spidmd(void) {
WriteCoreTimer(0);
int timecount, displayswide, displaysdown, displayrow, display;
int spiloop, spiloop2;
int videomemHi, videomemLo, count, out;
int dmd12, dmd8, dmd4, dmd0;
int videomemLo12, videomemLo8, videomemLo4, videomemLo0;
int offset = HRes>>3; // vga 480/8=60
unsigned int b, in;
register unsigned int t;
unsigned int rx, tx, ck, rxn, txp, ckp;
volatile unsigned int *rxi, *txh, *txl, *c_leading, *c_trailing;
unsigned int speed = 0;
int bits = 32;
int mode = 0;

getargs(&ep, 15, ",");
if(argc != 15) error("Invalid syntax");
videomemHi = getinteger(argv[0]);
videomemLo = getinteger(argv[2]);
displayrow = getinteger(argv[4]);
displayswide = getinteger(argv[6]);
displaysdown = getinteger(argv[8]);
rx = getinteger(argv[10]);
tx = getinteger(argv[12]);
ck = getinteger(argv[14]);
if(rx < 1 || rx > NBRPINS || tx < 1 || tx > NBRPINS || ck < 1 || ck > NBRPINS) error("Invalid pin number");
if(ExtCurrentConfig[rx] != EXT_DIG_IN) error("Pin not configured for input");
if((ExtCurrentConfig[tx] != EXT_DIG_OUT && ExtCurrentConfig[tx] != EXT_OC_OUT) || (ExtCurrentConfig[ck] != EXT_DIG_OUT && ExtCurrentConfig[ck] != EXT_OC_OUT))
error("Pin not configured for output");

// get the port address for the I/O. Much faster than calling functions to perform the I/O.
rxi = GetPortAddr(rx, PORT); rxn = GetPinBit(rx);
txh = GetPortAddr(tx, LATSET); txl = GetPortAddr(tx, LATCLR); txp = 1 << GetPinBit(tx);

// get the port address for the clock. The clock polarity is inverted if mode 0 or 1 is used
if(mode == 0 || mode == 3) {
c_trailing = GetPortAddr(ck, LATSET); c_leading = GetPortAddr(ck, LATCLR);
} else {
c_trailing = GetPortAddr(ck, LATCLR); c_leading = GetPortAddr(ck, LATSET);
}
ckp = 1 << GetPinBit(ck);
for (spiloop = 0; spiloop < displayswide; spiloop++){
for (spiloop2 = displaysdown; spiloop2 > 0; spiloop2--){
display = (displayrow*offset) + ((offset*(spiloop2-1)) *16) + (spiloop *4);

videomemLo12 = videomemLo+(offset<<3)+(offset<<2) + display;
videomemLo8 = videomemLo+(offset<<3) + display;
videomemLo4 = videomemLo+(offset<<2) + display;
videomemLo0 = videomemLo + display;

for (count =0 ; count<4 ; count++){

b = 1 << (bits - 1);
t = in = 0;

dmd12 = *(char *)(videomemHi << 16 | (videomemLo12+(3-count)));
dmd12 ^= dmdMask;
dmd8 = *(char *)(videomemHi << 16 | (videomemLo8+(3-count)));
dmd8 ^= dmdMask;
dmd4 = *(char *)(videomemHi << 16 | (videomemLo4+(3-count)));
dmd4 ^= dmdMask;
dmd0 = *(char *)(videomemHi << 16 | (videomemLo0+(3-count)));
dmd0 ^= dmdMask;

out = dmd12 << 24 | dmd8 << 16 | dmd4 << 8 | dmd0;

while(b) {
// output the data on the leading edge of the clock
if(out & b)
*txh = txp; // output the next bit (if high)
else
*txl = txp; // output the next bit (if low)
*c_leading = ckp; // set the clock active - data out must be stable by now
nop;
nop;
if(speed) uSec(speed); // delay to get the right speed
// capture the input data on the trailing edge of the clock
in <<= 1; // shift up the input data
t = *rxi; // capture the input (the whole port actually)
*c_trailing = ckp; // set the clock to inactive - we must have sampled the input by now
in |= (t >> rxn) & 1; // get our bit of data and add it to the input word
if(speed) uSec(speed); // delay to get the right speed
b >>= 1; // shift down the mask bit for the output
}
}
}
}
if(mode == 0 || mode == 2) *c_leading = ckp; // reset the clock to inactive
timecount=ReadCoreTimer();
fret = (float)timecount; // returns time taken in nano seconds..
//fret = (float)in;
}

edfield
Posts: 3
Joined: Wed Feb 06, 2013 3:08 pm

Re: Interface protocol

Post by edfield » Mon Feb 11, 2013 8:39 pm

Thanks for the input, but I must admit that reverse-engineering the interface from someone else's software wasn't quite what I had in mind!

Soemone must know how the interface works - who wrote the library in the first place?

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: Interface protocol

Post by Aussie_Wombat » Tue Feb 12, 2013 8:22 am

Hey, I had to reverse engineer the library to get it to work on the maximite. If it is all too hard, then I am sorry some need it easy. Rather than give you some code to look at , that may be easier to understand, than the DMD library file, then maybe I should just spell it out in laymans terms for you.

D6 to D13 relate to the DMDCONnector..or Arduino pinout..

1. Lines 1,5,9,13 you set D6 to 1 (high) and D7 to 1 (high).
2. Set D9 to 1(high)
3. Send the four lines of 32 bit data (per panel) down the Tx line (D11) using Clk (D13) to clock each bit. NOTE A bit value of 1 is OFF , A bit value of 0 is ON. LSB -> MSB (I think) . line 13 first then 9, then 5, then 1....
[ Just like using an eight bit shift register - 74 HC 595, 16 of these chips are on the back of the DMD Panel. 4 for each line sent..]
4. Set D9 to 0 (low)
5. Set D8 to 1 (high)
6. Set D8 to 0 (low)
7. wait 5 ms
8. Lines 2,6,10,14 you set D6 to 0 (low) and D7 to 0 (low).
9. Repeat as per 2 . to 7. but for lines 2,6,10,14
10. Lines 3,7,11,15 you set D6 to 1 (high) and D7 to 0 (low).
11. Repeat as per 2 . to 7. but for lines 3,7,11,15
12. Lines 4,8,12,16 you set D6 to 0 (low) and D7 to 1 (high).
13. Repeat as per 2 . to 7. but for lines 4,8,12,16

How you store and manipulate the data, to be displayed is up to you.

R-Data is used, but G-Data and D-Data are not used and are for future expansion me thinks... Maybe a tri-color panel
[edit] Someone correct me If I am wrong . [edit]
Regards Dennis...

42n8
Posts: 46
Joined: Wed Dec 26, 2012 8:10 pm
Location: Auckland, NZ

Re: Interface protocol

Post by 42n8 » Wed Feb 13, 2013 10:24 am

edfield wrote:Thanks for the input, but I must admit that reverse-engineering the interface from someone else's software wasn't quite what I had in mind!

Soemone must know how the interface works - who wrote the library in the first place?
Adding to the info Denis gave you, there is a schematic diagram with a good translation from Simplified Chinese and a shorter explanation here as well ...

viewtopic.php?f=26&t=704

Regards

42n8
Posts: 46
Joined: Wed Dec 26, 2012 8:10 pm
Location: Auckland, NZ

Re: Interface protocol

Post by 42n8 » Wed Feb 13, 2013 10:33 am

Aussie_Wombat wrote:Hey, I had to reverse engineer the library to get it to work on the maximite....

R-Data is used, but G-Data and D-Data are not used and are for future expansion me thinks... Maybe a tri-color panel
Regards Dennis...
Dennis,
I'm using the PIC equivalent of the G and D signals as additional row select lines, which gives me a true 32 x 32 bit cascadable display.


Regards

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: Interface protocol

Post by Aussie_Wombat » Wed Feb 13, 2013 11:44 am

Cool. I am looking at getting a tri-color panel from china to reverse engineer. Says it is for video, not message, but I will give it a go.. So many panels to choose from.. Get some with 3mm spacing instead of ten mm...

Dennis

edfield
Posts: 3
Joined: Wed Feb 06, 2013 3:08 pm

Re: Interface protocol

Post by edfield » Fri Feb 15, 2013 12:44 pm

Dennis,
Thanks for the simpler explanation. with that and the schematic I can see how it works now.

FWIW, it's not that I want it "easy", or even that I'm a "layman", it's just that I've got better things to do with my time than re-invent the wheel... :D

THey're actually similar in principle to the full colour displays available from adafruit in the USA: http://www.adafruit.com/products/607
There's some helpful documentation on their site.

One of my questions was how fast can you clock the data through these things. Adafruit suggest theirs work up to about 50MHz, which wont be a problem under software control, but is useful to know if you're driving them directly from hardware.

regards

42n8
Posts: 46
Joined: Wed Dec 26, 2012 8:10 pm
Location: Auckland, NZ

Re: Interface protocol

Post by 42n8 » Fri Feb 15, 2013 4:04 pm

One of my questions was how fast can you clock the data through these things. Adafruit suggest theirs work up to about 50MHz, which wont be a problem under software control, but is useful to know if you're driving them directly from hardware.
Trick of the trade...

The simplest way to get throughput information isn't to look at what similar products might do. That's probably too time consuming unless you have used those products before and can make a direct comparison.

The best method is to look at the data sheets for the various devices taking note of the "typical" operating frequency. The slowest device limits the maximum throughput and you have the answer in just a few minutes.

Regards

Post Reply