MODIFIED Ledcontrol library

With this library, you can use Common ANODE displays if you want with
the Maxim 72xx chips!
This commit is contained in:
ww
2014-08-22 15:13:11 +02:00
parent 4f86010f19
commit bad4b99b8f
10 changed files with 1472 additions and 0 deletions

View File

@@ -0,0 +1,213 @@
/*
* LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "LedControl.h"
//the opcodes for the MAX7221 and MAX7219
#define OP_NOOP 0
#define OP_DIGIT0 1
#define OP_DIGIT1 2
#define OP_DIGIT2 3
#define OP_DIGIT3 4
#define OP_DIGIT4 5
#define OP_DIGIT5 6
#define OP_DIGIT6 7
#define OP_DIGIT7 8
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
if(numDevices<=0 || numDevices>8 )
numDevices=8;
maxDevices=numDevices;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
for(int i=0;i<64;i++)
status[i]=0x00;
for(int i=0;i<maxDevices;i++) {
spiTransfer(i,OP_DISPLAYTEST,0);
//scanlimit is set to max on startup
setScanLimit(i,7);
//decode is done in source
spiTransfer(i,OP_DECODEMODE,0);
clearDisplay(i);
//we go into shutdown-mode on startup
shutdown(i,true);
}
}
int LedControl::getDeviceCount() {
return maxDevices;
}
void LedControl::shutdown(int addr, bool b) {
if(addr<0 || addr>=maxDevices)
return;
if(b)
spiTransfer(addr, OP_SHUTDOWN,0);
else
spiTransfer(addr, OP_SHUTDOWN,1);
}
void LedControl::setScanLimit(int addr, int limit) {
if(addr<0 || addr>=maxDevices)
return;
if(limit>=0 || limit<8)
spiTransfer(addr, OP_SCANLIMIT,limit);
}
void LedControl::setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices)
return;
if(intensity>=0 || intensity<16)
spiTransfer(addr, OP_INTENSITY,intensity);
}
void LedControl::clearDisplay(int addr) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
offset=addr*8;
for(int i=0;i<8;i++) {
status[offset+i]=0;
spiTransfer(addr, i+1,status[offset+i]);
}
}
void LedControl::setLed(int addr, int row, int column, boolean state) {
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
int offset;
byte v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7 || value>15)
return;
offset=addr*8;
v=charTable[value];
if(dp)
v|=B10000000;
status[offset+digit]=v;
spiTransfer(addr, digit+1,v);
}
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
int offset;
byte index,v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7)
return;
offset=addr*8;
index=(byte)value;
if(index >127) {
//nothing define we use the space char
value=32;
}
v=charTable[index];
if(dp)
v|=B10000000;
status[offset+digit]=v;
spiTransfer(addr, digit+1,v);
}
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
//Create an array with the data to shift out
int offset=addr*2;
int maxbytes=maxDevices*2;
for(int i=0;i<maxbytes;i++)
spidata[i]=(byte)0;
//put our device data into the array
spidata[offset+1]=opcode;
spidata[offset]=data;
//enable the line
digitalWrite(SPI_CS,LOW);
//Now shift out the data
for(int i=maxbytes;i>0;i--)
shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
//latch the data onto the display
digitalWrite(SPI_CS,HIGH);
}

View File

@@ -0,0 +1,188 @@
/*
* LedControl.h - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LedControl_h
#define LedControl_h
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
/*
* Segments to be switched on for characters and digits on
* 7-Segment Displays
*/
const static byte charTable[128] = {
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000,
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
};
class LedControl {
private :
/* The array for shifting the data to the devices */
byte spidata[16];
/* Send out a single command to the device */
void spiTransfer(int addr, byte opcode, byte data);
/* We keep track of the led-status for all 8 devices in this array */
byte status[64];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
int SPI_CLK;
/* This one is driven LOW for chip selectzion */
int SPI_CS;
/* The maximum number of devices we use */
int maxDevices;
public:
/*
* Create a new controler
* Params :
* dataPin pin on the Arduino where data gets shifted out
* clockPin pin for the clock
* csPin pin for selecting the device
* numDevices maximum number of devices that can be controled
*/
LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
/*
* Gets the number of devices attached to this LedControl.
* Returns :
* int the number of devices on this LedControl
*/
int getDeviceCount();
/*
* Set the shutdown (power saving) mode for the device
* Params :
* addr The address of the display to control
* status If true the device goes into power-down mode. Set to false
* for normal operation.
*/
void shutdown(int addr, bool status);
/*
* Set the number of digits (or rows) to be displayed.
* See datasheet for sideeffects of the scanlimit on the brightness
* of the display.
* Params :
* addr address of the display to control
* limit number of digits to be displayed (1..8)
*/
void setScanLimit(int addr, int limit);
/*
* Set the brightness of the display.
* Params:
* addr the address of the display to control
* intensity the brightness of the display. (0..15)
*/
void setIntensity(int addr, int intensity);
/*
* Switch all Leds on the display off.
* Params:
* addr address of the display to control
*/
void clearDisplay(int addr);
/*
* Set the status of a single Led.
* Params :
* addr address of the display
* row the row of the Led (0..7)
* col the column of the Led (0..7)
* state If true the led is switched on,
* if false it is switched off
*/
void setLed(int addr, int row, int col, boolean state);
/*
* Set all 8 Led's in a row to a new state
* Params:
* addr address of the display
* row row which is to be set (0..7)
* value each bit set to 1 will light up the
* corresponding Led.
*/
void setRow(int addr, int row, byte value);
/*
* Set all 8 Led's in a column to a new state
* Params:
* addr address of the display
* col column which is to be set (0..7)
* value each bit set to 1 will light up the
* corresponding Led.
*/
void setColumn(int addr, int col, byte value);
/*
* Display a hexadecimal digit on a 7-Segment Display
* Params:
* addr address of the display
* digit the position of the digit on the display (0..7)
* value the value to be displayed. (0x00..0x0F)
* dp sets the decimal point.
*/
void setDigit(int addr, int digit, byte value, boolean dp);
/*
* Display a character on a 7-Segment display.
* There are only a few characters that make sense here :
* '0','1','2','3','4','5','6','7','8','9','0',
* 'A','b','c','d','E','F','H','L','P',
* '.','-','_',' '
* Params:
* addr address of the display
* digit the position of the character on the display (0..7)
* value the character to be displayed.
* dp sets the decimal point.
*/
void setChar(int addr, int digit, char value, boolean dp);
};
#endif //LedControl.h

View File

@@ -0,0 +1,310 @@
/*
* LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "LedControl.h"
//the opcodes for the MAX7221 and MAX7219
#define OP_NOOP 0
#define OP_DIGIT0 1
#define OP_DIGIT1 2
#define OP_DIGIT2 3
#define OP_DIGIT3 4
#define OP_DIGIT4 5
#define OP_DIGIT5 6
#define OP_DIGIT6 7
#define OP_DIGIT7 8
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices, bool anode) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
if(numDevices<=0 || numDevices>8 )
numDevices=8;
maxDevices=numDevices;
anodeMode=anode;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
for(int i=0;i<64;i++) {
status[i]=0x00;
statusTransposed[i]=0x00;
}
for(int i=0;i<maxDevices;i++) {
spiTransfer(i,OP_DISPLAYTEST,0);
//scanlimit is set to max on startup
setScanLimit(i,7);
//decode is done in source
spiTransfer(i,OP_DECODEMODE,0);
clearDisplay(i);
//we go into shutdown-mode on startup
shutdown(i,true);
}
}
int LedControl::getDeviceCount() {
return maxDevices;
}
void LedControl::shutdown(int addr, bool b) {
if(addr<0 || addr>=maxDevices)
return;
if(b)
spiTransfer(addr, OP_SHUTDOWN,0);
else
spiTransfer(addr, OP_SHUTDOWN,1);
}
void LedControl::setScanLimit(int addr, int limit) {
if(addr<0 || addr>=maxDevices)
return;
if(limit>=0 || limit<8)
spiTransfer(addr, OP_SCANLIMIT,limit);
}
void LedControl::setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices)
return;
if(intensity>=0 || intensity<16)
spiTransfer(addr, OP_INTENSITY,intensity);
}
void LedControl::clearDisplay(int addr) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
offset=addr*8;
for(int i=0;i<8;i++) {
status[offset+i]=0;
}
if (anodeMode) {
transposeData(addr);
for(int i=0;i<8;i++) {
spiTransfer(addr, i+1, statusTransposed[offset+i]);
}
} else {
for(int i=0;i<8;i++) {
spiTransfer(addr, i+1, status[offset+i]);
}
}
}
void LedControl::setLed(int addr, int row, int column, boolean state) {
int offset;
byte val=0x00;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7 || column<0 || column>7)
return;
offset=addr*8;
val=B10000000 >> column;
if(state)
status[offset+row]=status[offset+row]|val;
else {
val=~val;
status[offset+row]=status[offset+row]&val;
}
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setRow(int addr, int row, byte value) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(row<0 || row>7)
return;
offset=addr*8;
status[offset+row]=value;
spiTransfer(addr, row+1,status[offset+row]);
}
void LedControl::setColumn(int addr, int col, byte value) {
byte val;
if(addr<0 || addr>=maxDevices)
return;
if(col<0 || col>7)
return;
for(int row=0;row<8;row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
void LedControl::setDigit(int addr, int digit, byte value, boolean dp) {
int offset;
byte v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7 || value>15)
return;
offset=addr*8;
v=charTable[value];
if(dp)
v|=B10000000;
status[offset+digit]=v;
if (anodeMode) {
//transpose the digit matrix
transposeData(addr);
//send the entire set of digits
for(int i=0;i<8;i++) {
spiTransfer(addr, i+1, statusTransposed[offset+i]);
}
} else {
spiTransfer(addr, digit+1, v);
}
}
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
int offset;
byte index,v;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7)
return;
offset=addr*8;
index=(byte)value;
if(index >127) {
//nothing defined we use the space char
value=32;
}
v=charTable[index];
if(dp)
v|=B10000000;
status[offset+digit]=v;
if (anodeMode) {
//transpose the digit matrix
transposeData(addr);
//send the entire set of digits
for(int i=0;i<8;i++) {
spiTransfer(addr, i+1, statusTransposed[offset+i]);
}
} else {
spiTransfer(addr, digit+1, v);
}
}
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
//Create an array with the data to shift out
int offset=addr*2;
int maxbytes=maxDevices*2;
for(int i=0;i<maxbytes;i++)
spidata[i]=(byte)0;
//put our device data into the array
spidata[offset+1]=opcode;
spidata[offset]=data;
//enable the line
digitalWrite(SPI_CS,LOW);
//Now shift out the data
for(int i=maxbytes;i>0;i--)
shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]);
//latch the data onto the display
digitalWrite(SPI_CS,HIGH);
}
void LedControl::transposeData(int addr) {
int offset=addr*8;
byte a0, a1, a2, a3, a4, a5, a6, a7,
b0, b1, b2, b3, b4, b5, b6, b7;
// Perform a bitwise transpose operation on an 8x8 bit matrix, stored as 8-byte array.
// We have to use the naive method because we're working on a 16-bit microprocessor.
// Load the array into eight one-byte variables.
a0 = status[offset];
a1 = status[offset+1];
a2 = status[offset+2];
a3 = status[offset+3];
a4 = status[offset+4];
a5 = status[offset+5];
a6 = status[offset+6];
a7 = status[offset+7];
// Magic happens. Credit goes to: http://www.hackersdelight.org/HDcode/transpose8.c.txt
b0 = (a0 & 128) | (a1 & 128)/2 | (a2 & 128)/4 | (a3 & 128)/8 |
(a4 & 128)/16 | (a5 & 128)/32 | (a6 & 128)/64 | (a7 )/128;
b1 = (a0 & 64)*2 | (a1 & 64) | (a2 & 64)/2 | (a3 & 64)/4 |
(a4 & 64)/8 | (a5 & 64)/16 | (a6 & 64)/32 | (a7 & 64)/64;
b2 = (a0 & 32)*4 | (a1 & 32)*2 | (a2 & 32) | (a3 & 32)/2 |
(a4 & 32)/4 | (a5 & 32)/8 | (a6 & 32)/16 | (a7 & 32)/32;
b3 = (a0 & 16)*8 | (a1 & 16)*4 | (a2 & 16)*2 | (a3 & 16) |
(a4 & 16)/2 | (a5 & 16)/4 | (a6 & 16)/8 | (a7 & 16)/16;
b4 = (a0 & 8)*16 | (a1 & 8)*8 | (a2 & 8)*4 | (a3 & 8)*2 |
(a4 & 8) | (a5 & 8)/2 | (a6 & 8)/4 | (a7 & 8)/8;
b5 = (a0 & 4)*32 | (a1 & 4)*16 | (a2 & 4)*8 | (a3 & 4)*4 |
(a4 & 4)*2 | (a5 & 4) | (a6 & 4)/2 | (a7 & 4)/4;
b6 = (a0 & 2)*64 | (a1 & 2)*32 | (a2 & 2)*16 | (a3 & 2)*8 |
(a4 & 2)*4 | (a5 & 2)*2 | (a6 & 2) | (a7 & 2)/2;
b7 = (a0 )*128| (a1 & 1)*64 | (a2 & 1)*32 | (a3 & 1)*16|
(a4 & 1)*8 | (a5 & 1)*4 | (a6 & 1)*2 | (a7 & 1);
// Assemble into output array.
statusTransposed[offset] = b0;
statusTransposed[offset+1] = b1;
statusTransposed[offset+2] = b2;
statusTransposed[offset+3] = b3;
statusTransposed[offset+4] = b4;
statusTransposed[offset+5] = b5;
statusTransposed[offset+6] = b6;
statusTransposed[offset+7] = b7;
}
void LedControl::setDirectDigit(int addr, int digit, byte value) {
int offset;
if(addr<0 || addr>=maxDevices)
return;
if(digit<0 || digit>7)
return;
offset=addr*8;
status[offset+digit]=value;
if (anodeMode) {
transposeData(addr);
for(int i=0;i<8;i++) {
spiTransfer(addr, i+1, statusTransposed[offset+i]);
}
} else {
spiTransfer(addr, digit+1, value);
}
}

View File

@@ -0,0 +1,217 @@
/*
* LedControl.h - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LedControl_h
#define LedControl_h
#if (ARDUINO >= 100)
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
/*
* Segments to be switched on for characters and digits on
* 7-Segment Displays
*/
const static byte charTable[128] = {
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
B01111111,B01111011,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B10000000,B00000001,B10000000,B00000000,
B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,
B01111111,B01111011,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00001000,
B00000000,B01110111,B00011111,B00001101,B00111101,B01001111,B01000111,B00000000,
B00110111,B00000000,B00000000,B00000000,B00001110,B00000000,B00000000,B00000000,
B01100111,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000
};
class LedControl {
private :
/* The array for shifting the data to the devices */
byte spidata[16];
/* Send out a single command to the device */
void spiTransfer(int addr, byte opcode, byte data);
/* We keep track of the led-status for all 8 devices in this array */
byte status[64];
/* We also keep track of the transposed version */
byte statusTransposed[64];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
int SPI_CLK;
/* This one is driven LOW for chip selectzion */
int SPI_CS;
/* The maximum number of devices we use */
int maxDevices;
/* Choose whether we're using common cathode or common anode displays */
bool anodeMode;
public:
/*
* Create a new controler
* Params :
* dataPin pin on the Arduino where data gets shifted out
* clockPin pin for the clock
* csPin pin for selecting the device
* numDevices maximum number of devices that can be controled
* anode false for common-cathode displays, true for common-anode displays
*/
LedControl(int dataPin, int clkPin, int csPin, int numDevices=1, bool anode=false);
/*
* Gets the number of devices attached to this LedControl.
* Returns :
* int the number of devices on this LedControl
*/
int getDeviceCount();
/*
* Set the shutdown (power saving) mode for the device
* Params :
* addr The address of the display to control
* status If true the device goes into power-down mode. Set to false
* for normal operation.
*/
void shutdown(int addr, bool status);
/*
* Set the number of digits (or rows) to be displayed.
* See datasheet for sideeffects of the scanlimit on the brightness
* of the display.
* Params :
* addr address of the display to control
* limit number of digits to be displayed (1..8)
*/
void setScanLimit(int addr, int limit);
/*
* Set the brightness of the display.
* Params:
* addr the address of the display to control
* intensity the brightness of the display. (0..15)
*/
void setIntensity(int addr, int intensity);
/*
* Switch all Leds on the display off.
* Params:
* addr address of the display to control
*/
void clearDisplay(int addr);
/*
* Set the status of a single Led.
* Params :
* addr address of the display
* row the row of the Led (0..7)
* col the column of the Led (0..7)
* state If true the led is switched on,
* if false it is switched off
*/
void setLed(int addr, int row, int col, boolean state);
/*
* Set all 8 Led's in a row to a new state
* Params:
* addr address of the display
* row row which is to be set (0..7)
* value each bit set to 1 will light up the
* corresponding Led.
*/
void setRow(int addr, int row, byte value);
/*
* Set all 8 Led's in a column to a new state
* Params:
* addr address of the display
* col column which is to be set (0..7)
* value each bit set to 1 will light up the
* corresponding Led.
*/
void setColumn(int addr, int col, byte value);
/*
* Display a hexadecimal digit on a 7-Segment Display
* Params:
* addr address of the display
* digit the position of the digit on the display (0..7)
* value the value to be displayed. (0x00..0x0F)
* dp sets the decimal point.
*/
void setDigit(int addr, int digit, byte value, boolean dp);
/*
* Display a character on a 7-Segment display.
* There are only a few characters that make sense here :
* '0','1','2','3','4','5','6','7','8','9','0',
* 'A','b','c','d','E','F','H','L','P',
* '.','-','_',' '
* Params:
* addr address of the display
* digit the position of the character on the display (0..7)
* value the character to be displayed.
* dp sets the decimal point.
*/
void setChar(int addr, int digit, char value, boolean dp);
/*
* Transpose data matrix for use with common-anode displays.
* Params:
* addr address of the display
*/
void transposeData(int addr);
/*
* Light up segments of a 7-segment display directly by passing a binary value.
* The eight bits of the byte each refer to a segment:
* Byte: 0 0 0 0 0 0 0 0
* Segments: DP A B C D E F G
* Params:
* addr address of the display
* digit the position of the character on the display (0..7)
* value the binary value to be displayed
*/
void setDirectDigit(int addr, int digit, byte value);
};
#endif //LedControl.h

View File

@@ -0,0 +1,228 @@
Common subdirectories: LedControl-unpatched/examples and LedControl/examples
diff -u LedControl-unpatched/LedControl.cpp LedControl/LedControl.cpp
--- LedControl-unpatched/LedControl.cpp 2008-10-14 02:21:21.000000000 -0700
+++ LedControl/LedControl.cpp 2012-09-02 01:24:35.000000000 -0700
@@ -35,20 +35,23 @@
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
-LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
+LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices, bool anode) {
SPI_MOSI=dataPin;
SPI_CLK=clkPin;
SPI_CS=csPin;
if(numDevices<=0 || numDevices>8 )
numDevices=8;
maxDevices=numDevices;
+ anodeMode=anode;
pinMode(SPI_MOSI,OUTPUT);
pinMode(SPI_CLK,OUTPUT);
pinMode(SPI_CS,OUTPUT);
digitalWrite(SPI_CS,HIGH);
SPI_MOSI=dataPin;
- for(int i=0;i<64;i++)
+ for(int i=0;i<64;i++) {
status[i]=0x00;
+ statusTransposed[i]=0x00;
+ }
for(int i=0;i<maxDevices;i++) {
spiTransfer(i,OP_DISPLAYTEST,0);
//scanlimit is set to max on startup
@@ -97,7 +100,16 @@
offset=addr*8;
for(int i=0;i<8;i++) {
status[offset+i]=0;
- spiTransfer(addr, i+1,status[offset+i]);
+ }
+ if (anodeMode) {
+ transposeData(addr);
+ for(int i=0;i<8;i++) {
+ spiTransfer(addr, i+1, statusTransposed[offset+i]);
+ }
+ } else {
+ for(int i=0;i<8;i++) {
+ spiTransfer(addr, i+1, status[offset+i]);
+ }
}
}
@@ -158,8 +170,16 @@
if(dp)
v|=B10000000;
status[offset+digit]=v;
- spiTransfer(addr, digit+1,v);
-
+ if (anodeMode) {
+ //transpose the digit matrix
+ transposeData(addr);
+ //send the entire set of digits
+ for(int i=0;i<8;i++) {
+ spiTransfer(addr, i+1, statusTransposed[offset+i]);
+ }
+ } else {
+ spiTransfer(addr, digit+1, v);
+ }
}
void LedControl::setChar(int addr, int digit, char value, boolean dp) {
@@ -173,14 +193,23 @@
offset=addr*8;
index=(byte)value;
if(index >127) {
- //nothing define we use the space char
+ //nothing defined we use the space char
value=32;
}
v=charTable[index];
if(dp)
v|=B10000000;
status[offset+digit]=v;
- spiTransfer(addr, digit+1,v);
+ if (anodeMode) {
+ //transpose the digit matrix
+ transposeData(addr);
+ //send the entire set of digits
+ for(int i=0;i<8;i++) {
+ spiTransfer(addr, i+1, statusTransposed[offset+i]);
+ }
+ } else {
+ spiTransfer(addr, digit+1, v);
+ }
}
void LedControl::spiTransfer(int addr, volatile byte opcode, volatile byte data) {
@@ -202,4 +231,73 @@
digitalWrite(SPI_CS,HIGH);
}
+void LedControl::transposeData(int addr) {
+ int offset=addr*8;
+ byte a0, a1, a2, a3, a4, a5, a6, a7,
+ b0, b1, b2, b3, b4, b5, b6, b7;
+
+ // Perform a bitwise transpose operation on an 8x8 bit matrix, stored as 8-byte array.
+ // We have to use the naive method because we're working on a 16-bit microprocessor.
+
+ // Load the array into eight one-byte variables.
+ a0 = status[offset];
+ a1 = status[offset+1];
+ a2 = status[offset+2];
+ a3 = status[offset+3];
+ a4 = status[offset+4];
+ a5 = status[offset+5];
+ a6 = status[offset+6];
+ a7 = status[offset+7];
+
+ // Magic happens. Credit goes to: http://www.hackersdelight.org/HDcode/transpose8.c.txt
+ b0 = (a0 & 128) | (a1 & 128)/2 | (a2 & 128)/4 | (a3 & 128)/8 |
+ (a4 & 128)/16 | (a5 & 128)/32 | (a6 & 128)/64 | (a7 )/128;
+ b1 = (a0 & 64)*2 | (a1 & 64) | (a2 & 64)/2 | (a3 & 64)/4 |
+ (a4 & 64)/8 | (a5 & 64)/16 | (a6 & 64)/32 | (a7 & 64)/64;
+ b2 = (a0 & 32)*4 | (a1 & 32)*2 | (a2 & 32) | (a3 & 32)/2 |
+ (a4 & 32)/4 | (a5 & 32)/8 | (a6 & 32)/16 | (a7 & 32)/32;
+ b3 = (a0 & 16)*8 | (a1 & 16)*4 | (a2 & 16)*2 | (a3 & 16) |
+ (a4 & 16)/2 | (a5 & 16)/4 | (a6 & 16)/8 | (a7 & 16)/16;
+ b4 = (a0 & 8)*16 | (a1 & 8)*8 | (a2 & 8)*4 | (a3 & 8)*2 |
+ (a4 & 8) | (a5 & 8)/2 | (a6 & 8)/4 | (a7 & 8)/8;
+ b5 = (a0 & 4)*32 | (a1 & 4)*16 | (a2 & 4)*8 | (a3 & 4)*4 |
+ (a4 & 4)*2 | (a5 & 4) | (a6 & 4)/2 | (a7 & 4)/4;
+ b6 = (a0 & 2)*64 | (a1 & 2)*32 | (a2 & 2)*16 | (a3 & 2)*8 |
+ (a4 & 2)*4 | (a5 & 2)*2 | (a6 & 2) | (a7 & 2)/2;
+ b7 = (a0 )*128| (a1 & 1)*64 | (a2 & 1)*32 | (a3 & 1)*16|
+ (a4 & 1)*8 | (a5 & 1)*4 | (a6 & 1)*2 | (a7 & 1);
+
+ // Assemble into output array.
+ statusTransposed[offset] = b0;
+ statusTransposed[offset+1] = b1;
+ statusTransposed[offset+2] = b2;
+ statusTransposed[offset+3] = b3;
+ statusTransposed[offset+4] = b4;
+ statusTransposed[offset+5] = b5;
+ statusTransposed[offset+6] = b6;
+ statusTransposed[offset+7] = b7;
+
+}
+
+void LedControl::setDirectDigit(int addr, int digit, byte value) {
+ int offset;
+
+ if(addr<0 || addr>=maxDevices)
+ return;
+ if(digit<0 || digit>7)
+ return;
+ offset=addr*8;
+ status[offset+digit]=value;
+ if (anodeMode) {
+ transposeData(addr);
+ for(int i=0;i<8;i++) {
+ spiTransfer(addr, i+1, statusTransposed[offset+i]);
+ }
+ } else {
+ spiTransfer(addr, digit+1, value);
+ }
+}
+
+
+
diff -u LedControl-unpatched/LedControl.h LedControl/LedControl.h
--- LedControl-unpatched/LedControl.h 2011-09-20 23:49:06.000000000 -0700
+++ LedControl/LedControl.h 2012-09-02 00:18:47.000000000 -0700
@@ -58,6 +58,8 @@
/* We keep track of the led-status for all 8 devices in this array */
byte status[64];
+ /* We also keep track of the transposed version */
+ byte statusTransposed[64];
/* Data is shifted out of this pin*/
int SPI_MOSI;
/* The clock is signaled on this pin */
@@ -66,6 +68,8 @@
int SPI_CS;
/* The maximum number of devices we use */
int maxDevices;
+ /* Choose whether we're using common cathode or common anode displays */
+ bool anodeMode;
public:
/*
@@ -75,8 +79,9 @@
* clockPin pin for the clock
* csPin pin for selecting the device
* numDevices maximum number of devices that can be controled
+ * anode false for common-cathode displays, true for common-anode displays
*/
- LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);
+ LedControl(int dataPin, int clkPin, int csPin, int numDevices=1, bool anode=false);
/*
* Gets the number of devices attached to this LedControl.
@@ -173,9 +178,25 @@
* dp sets the decimal point.
*/
void setChar(int addr, int digit, char value, boolean dp);
+
+ /*
+ * Transpose data matrix for use with common-anode displays.
+ * Params:
+ * addr address of the display
+ */
+ void transposeData(int addr);
+
+ /*
+ * Light up segments of a 7-segment display directly by passing a binary value.
+ * The eight bits of the byte each refer to a segment:
+ * Byte: 0 0 0 0 0 0 0 0
+ * Segments: DP A B C D E F G
+ * Params:
+ * addr address of the display
+ * digit the position of the character on the display (0..7)
+ * value the binary value to be displayed
+ */
+ void setDirectDigit(int addr, int digit, byte value);
};
#endif //LedControl.h
-
-
-

View File

@@ -0,0 +1,73 @@
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);
/* we always wait a bit between updates of the display */
unsigned long delaytime=250;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
/*
This method will display the characters for the
word "Arduino" one after the other on digit 0.
*/
void writeArduinoOn7Segment() {
lc.setChar(0,0,'a',false);
delay(delaytime);
lc.setRow(0,0,0x05);
delay(delaytime);
lc.setChar(0,0,'d',false);
delay(delaytime);
lc.setRow(0,0,0x1c);
delay(delaytime);
lc.setRow(0,0,B00010000);
delay(delaytime);
lc.setRow(0,0,0x15);
delay(delaytime);
lc.setRow(0,0,0x1D);
delay(delaytime);
lc.clearDisplay(0);
delay(delaytime);
}
/*
This method will scroll all the hexa-decimal
numbers and letters on the display. You will need at least
four 7-Segment digits. otherwise it won't really look that good.
*/
void scrollDigits() {
for(int i=0;i<13;i++) {
lc.setDigit(0,3,i,false);
lc.setDigit(0,2,i+1,false);
lc.setDigit(0,1,i+2,false);
lc.setDigit(0,0,i+3,false);
delay(delaytime);
}
lc.clearDisplay(0);
delay(delaytime);
}
void loop() {
writeArduinoOn7Segment();
scrollDigits();
}

View File

@@ -0,0 +1,52 @@
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
***** Please set the number of devices you have *****
But the maximum default of 8 MAX72XX wil also work.
*/
LedControl lc=LedControl(12,11,10,8);
/* we always wait a bit between updates of the display */
unsigned long delaytime=500;
/*
This time we have more than one device.
But all of them have to be initialized
individually.
*/
void setup() {
//we have already set the number of devices when we created the LedControl
int devices=lc.getDeviceCount();
//we have to init all devices in a loop
for(int address=0;address<devices;address++) {
/*The MAX72XX is in power-saving mode on startup*/
lc.shutdown(address,false);
/* Set the brightness to a medium values */
lc.setIntensity(address,8);
/* and clear the display */
lc.clearDisplay(address);
}
}
void loop() {
//read the number cascaded devices
int devices=lc.getDeviceCount();
//we have to init all devices in a loop
for(int row=0;row<8;row++) {
for(int col=0;col<8;col++) {
for(int address=0;address<devices;address++) {
delay(delaytime);
lc.setLed(address,row,col,true);
delay(delaytime);
lc.setLed(address,row,col,false);
}
}
}
}

View File

@@ -0,0 +1,163 @@
//We always have to include the library
#include "LedControl.h"
/*
Now we need a LedControl to work with.
***** These pin numbers will probably not work with your hardware *****
pin 12 is connected to the DataIn
pin 11 is connected to the CLK
pin 10 is connected to LOAD
We have only a single MAX72XX.
*/
LedControl lc=LedControl(12,11,10,1);
/* we always wait a bit between updates of the display */
unsigned long delaytime=100;
void setup() {
/*
The MAX72XX is in power-saving mode on startup,
we have to do a wakeup call
*/
lc.shutdown(0,false);
/* Set the brightness to a medium values */
lc.setIntensity(0,8);
/* and clear the display */
lc.clearDisplay(0);
}
/*
This method will display the characters for the
word "Arduino" one after the other on the matrix.
(you need at least 5x7 leds to see the whole chars)
*/
void writeArduinoOnMatrix() {
/* here is the data for the characters */
byte a[5]={B01111110,B10001000,B10001000,B10001000,B01111110};
byte r[5]={B00111110,B00010000,B00100000,B00100000,B00010000};
byte d[5]={B00011100,B00100010,B00100010,B00010010,B11111110};
byte u[5]={B00111100,B00000010,B00000010,B00000100,B00111110};
byte i[5]={B00000000,B00100010,B10111110,B00000010,B00000000};
byte n[5]={B00111110,B00010000,B00100000,B00100000,B00011110};
byte o[5]={B00011100,B00100010,B00100010,B00100010,B00011100};
/* now display them one by one with a small delay */
lc.setRow(0,0,a[0]);
lc.setRow(0,1,a[1]);
lc.setRow(0,2,a[2]);
lc.setRow(0,3,a[3]);
lc.setRow(0,4,a[4]);
delay(delaytime);
lc.setRow(0,0,r[0]);
lc.setRow(0,1,r[1]);
lc.setRow(0,2,r[2]);
lc.setRow(0,3,r[3]);
lc.setRow(0,4,r[4]);
delay(delaytime);
lc.setRow(0,0,d[0]);
lc.setRow(0,1,d[1]);
lc.setRow(0,2,d[2]);
lc.setRow(0,3,d[3]);
lc.setRow(0,4,d[4]);
delay(delaytime);
lc.setRow(0,0,u[0]);
lc.setRow(0,1,u[1]);
lc.setRow(0,2,u[2]);
lc.setRow(0,3,u[3]);
lc.setRow(0,4,u[4]);
delay(delaytime);
lc.setRow(0,0,i[0]);
lc.setRow(0,1,i[1]);
lc.setRow(0,2,i[2]);
lc.setRow(0,3,i[3]);
lc.setRow(0,4,i[4]);
delay(delaytime);
lc.setRow(0,0,n[0]);
lc.setRow(0,1,n[1]);
lc.setRow(0,2,n[2]);
lc.setRow(0,3,n[3]);
lc.setRow(0,4,n[4]);
delay(delaytime);
lc.setRow(0,0,o[0]);
lc.setRow(0,1,o[1]);
lc.setRow(0,2,o[2]);
lc.setRow(0,3,o[3]);
lc.setRow(0,4,o[4]);
delay(delaytime);
lc.setRow(0,0,0);
lc.setRow(0,1,0);
lc.setRow(0,2,0);
lc.setRow(0,3,0);
lc.setRow(0,4,0);
delay(delaytime);
}
/*
This function lights up a some Leds in a row.
The pattern will be repeated on every row.
The pattern will blink along with the row-number.
row number 4 (index==3) will blink 4 times etc.
*/
void rows() {
for(int row=0;row<8;row++) {
delay(delaytime);
lc.setRow(0,row,B10100000);
delay(delaytime);
lc.setRow(0,row,(byte)0);
for(int i=0;i<row;i++) {
delay(delaytime);
lc.setRow(0,row,B10100000);
delay(delaytime);
lc.setRow(0,row,(byte)0);
}
}
}
/*
This function lights up a some Leds in a column.
The pattern will be repeated on every column.
The pattern will blink along with the column-number.
column number 4 (index==3) will blink 4 times etc.
*/
void columns() {
for(int col=0;col<8;col++) {
delay(delaytime);
lc.setColumn(0,col,B10100000);
delay(delaytime);
lc.setColumn(0,col,(byte)0);
for(int i=0;i<col;i++) {
delay(delaytime);
lc.setColumn(0,col,B10100000);
delay(delaytime);
lc.setColumn(0,col,(byte)0);
}
}
}
/*
This function will light up every Led on the matrix.
The led will blink along with the row-number.
row number 4 (index==3) will blink 4 times etc.
*/
void single() {
for(int row=0;row<8;row++) {
for(int col=0;col<8;col++) {
delay(delaytime);
lc.setLed(0,row,col,true);
delay(delaytime);
for(int i=0;i<col;i++) {
lc.setLed(0,row,col,false);
delay(delaytime);
lc.setLed(0,row,col,true);
delay(delaytime);
}
}
}
}
void loop() {
writeArduinoOnMatrix();
rows();
columns();
single();
}

View File

@@ -0,0 +1,28 @@
#######################################
# Syntax Coloring Map For LedControl
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
LedControl KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
shutdown KEYWORD2
setScanLimit KEYWORD2
setIntensity KEYWORD2
clearDisplay KEYWORD2
setLed KEYWORD2
setRow KEYWORD2
setColumn KEYWORD2
setDigit KEYWORD2
setChar KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################