MAX6979 (16 port LED driver) SPI

I'd like to use a MAX6979 (16 port LED driver) with an arduino, but i don't have a clue as to how i program it. I know it uses SPI.

Is there a datasheet somewhere?

http://datasheets.maxim-ic.com/en/ds/MAX6979.pdf

would i be able to use the MAX7219 library?
oh and thanks for changing the title, forgot to mention what it was ::slight_smile:

From what I'm reading in the datasheet the MAX6979 is just like any standard latched shift register, which is different from SPI. Checkout how to use the shiftout function of arduino. http://www.arduino.cc/en/Reference/ShiftOut

The main thing different from simply using shiftout is that you'll need to dedicate another pin to latch the data. What that means is that you setup your latch pin as low (zero) to start with, then clock in the 16 bits (one bit per output) to the 6979, then set the latch pin high (one) then low (zero) again to put the data you clocked onto the led outputs of the 6979. The actual led data is simply a low (zero) to turn on an led and high (one) to turn it off. So if you want leds 15 through 7 on and 6 through 0 off, the data would be 0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1.

The output enable pin can be tied to ground if you're only using the 6979 for one row of leds. If you're multiplexing you can using the output enable to run the display one row at a time with just one chip (assuming 16 columns). To do this you'd initially setup the output enable pin high, setup the latch enable pin low, clock the first row of 16 bits into the chip, power the first row of leds, latch the data (high followed by low), then set the output enable pin low. When it's time to switch to the next row you clock the data for then next row into the chip, set output enable high to disable the chip, switch the row power to the next row, latch the data into the chip (high followed by low) then set output enable low again. Clocking the next row of data before you switch rows or disable the output means your display will be smoother, brighter, and faster than disabling the chip first and clocking the data second.

You could also use pulse width modulation on the output enable pin to control the brightness of the row of pins, but the entire row at once rather than individual leds. The easy way to do this with the arduino would be to use an analog out pin connected to the 6979's output enable pin. Lower analog signal out = brighter display, higher analog out = dimmer display.

Hope I didn't overload you with information :wink:
Don't forget to read the data sheet about selecting your current setting resistor and other external components.
[edit]You'll want to use shift out as MSBFIRST for the 6979 [/edit]

Have fun with your project.
-Jon

Thanks for the info! I am planning to use it for an 8x8 bicolor led matrix. it has 16 cathodes (8 red, 8 green) and 8 anodes.
i plan to use 1 chip for both colors, is there anything wrong with that? How fast do i have to scan the leds? and how fast does the arduino shift out 16 bits?

So would I use a 16 bit int? and what should i do about the anodes? I have no other shift registers and i need some pins on my arduino

looking at the data sheet it say that the max6979 has MISO (Master in, Slave out), and MOSI (Master out, Slave in) lines IE SPI lines?

This chip would be ideal for using with 8x8 bicolor as you describe, just don't mix up the bits :wink:
If you want to run the display at 60hz you'd have to scan a new line every 2 milliseconds. (((1/60)/8)=0.00208 seconds)
I'm afraid I don't know how long the shiftout command takes to shift out 16bits, but i'm sure it's much less than 2milliseconds. Anyone else know this one?

Yes you would use a 16bit int, each bit representing a different led in the row. As far as the anodes, you'd have to use another shift register or a multiplexer like the 4051, see:Arduino Playground - 4051

I don't see MISO and MOSI in the data sheet madworm linked, i see DIN (data in) and DOUT (data out). The SPI protocol uses a chip select pin for each chip it will talk to and has to enable that before the chip will listen. It'd be like sending an interrupt to that chip to make it listen to the serial data. the max6979 is different, it is always listening as long as the data is being clocked. it then has to be latched to store the data to the led outputs. It's not quite the same as SPI.

[edit]Just noticed that the arduino learning area refers to SPI as synchronous protocol interface, however the atmega168 refers to SPI as serial peripheral interface. The two are not the same thing.[/edit]

for faster shifting i guess I'd need to use registers ie portb. but then id hard code my way into sticking with a certain set of pins, and not using library code :frowning:

I'd try it with the shift out code first and see if it's fast enough, but if it's not there's absolutely nothing wrong with direct port manipulation. As far as using a certain set of pins, once you have this thing wired up it's not like you'd really have much reason to change them so that shouldn't be a problem.

found shiftout (v10)

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, byte val)
{
      int i;

      for (i = 0; i < 8; i++)  {
            if (bitOrder == LSBFIRST)
                  digitalWrite(dataPin, !!(val & (1 << i)));
            else      
                  digitalWrite(dataPin, !!(val & (1 << (7 - i))));
                  
            digitalWrite(clockPin, HIGH);
            digitalWrite(clockPin, LOW);            
      }
}

Portb would be faster as digital write takes several CPU cycles

would this shift function worK? :o

#define clock B00000001 // Pin 8
#define data  B00000010 // Pin 9
void shiftOut16(uint16_t val) // edit from 8 bit data to unsigned 16 bit
{
      int i;

      for (i = 0; i < 16; i++)  {
            bool high = !!(val & (1 << (15 - i))); // EDIT fixed from 8 bit to 16 bit  :)
            (high) ? PORTB |= data: PORTB ^= data; // Edit portb needed capitalization 
            PORTB ^= clock; //  ;D Edit forgot = signs 
            PORTB ^= clock;
      }    
}

I haven't yet looked enough into port manipulation to say if your code would work at first glance, but one thing I do see is that you have !!(val & (1 << (7 - i))). That's written for an 8 bit byte. You'd want !!val & (1 << (15 - i))) for a 16 bit integer.

As far as the rest of the code, I'd need to read over bitmath and port access more. Anyone else have any suggestions for biojae?

I fixed some mistakes in the code

:cry:

void loop()
{
      digitalWrite(latch, LOW);
      digitalWrite(out1, HIGH); // Turn on pin for colum
      shiftOut(data, clock, MSBFIRST, rowr);
      //shiftOut(data, clock, MSBFIRST, row1g);
      digitalWrite(latch, HIGH);
      delay(1500);
}

This code does not work. it either lights up the whole row or none

Does anyone know the differences between the MAX6979AUG and the MAX6979ANG? because I have the ANG one, and the pinout in the data sheet may be wrong