/*
Code to Interface 8x8 Matrix in which
Rows are controlled by 74Hc595 Memory in Common Anode manner( Common + for all LEDS in a ROW) and
Columns are controlled by 74HC595 IC in Common Cathode manner( Common - for all LEDS in a COLUMN)
by www.playwithcircuit.com
Bit Banging code is used for communication with 74HC595 IC
*/
unsigned char alphabets[26][8] = {
{ 0x38, 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x00 }, //A 1
{ 0x78, 0x44, 0x44, 0x78, 0x44, 0x44, 0x78, 0x00 }, //B 2
{ 0x38, 0x44, 0x40, 0x40, 0x40, 0x44, 0x38, 0x00 }, //C 3
{ 0x78, 0x44, 0x44, 0x44, 0x44, 0x44, 0x78, 0x00 }, //D 4
{ 0x7C, 0x40, 0x40, 0x78, 0x40, 0x40, 0x7C, 0x00 }, //E 5
{ 0x7C, 0x40, 0x40, 0x78, 0x40, 0x40, 0x40, 0x00 }, //F 6
{ 0x38, 0x44, 0x40, 0x40, 0x5C, 0x44, 0x38, 0x00 }, //G 7
{ 0x44, 0x44, 0x44, 0x7C, 0x44, 0x44, 0x44, 0x00 }, //H 8
{ 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7c, 0x00 }, //I 9
{ 0x7C, 0x08, 0x08, 0x08, 0x48, 0x48, 0x38, 0x00 }, //J 10
{ 0x44, 0x48, 0x50, 0x60, 0x50, 0x48, 0x44, 0x00 }, //K 11
{ 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7C, 0x00 }, //L 12
{ 0x44, 0x6C, 0x54, 0x44, 0x44, 0x44, 0x44, 0x00 }, //M 13
{ 0x44, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x44, 0x00 }, //N 14
{ 0x38, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, //O 15
{ 0x78, 0x44, 0x44, 0x44, 0x78, 0x40, 0x40, 0x00 }, //P 16
{ 0x38, 0x44, 0x44, 0x44, 0x54, 0x4C, 0x3C, 0x00 }, //Q 17
{ 0x78, 0x44, 0x44, 0x44, 0x78, 0x44, 0x44, 0x00 }, //R 18
{ 0x38, 0x44, 0x40, 0x38, 0x04, 0x44, 0x38, 0x00 }, //S 19
{ 0x7C, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 }, //T 20
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00 }, //U 21
{ 0x44, 0x44, 0x44, 0x44, 0x44, 0x28, 0x10, 0x00 }, //V 22
{ 0x44, 0x44, 0x44, 0x44, 0x54, 0x6C, 0x44, 0x00 }, //W 23
{ 0x44, 0x44, 0x28, 0x10, 0x28, 0x44, 0x44, 0x00 }, //X 24
{ 0x44, 0x44, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00 }, //Y 25
{ 0x7C, 0x04, 0x08, 0x10, 0x20, 0x40, 0x7C, 0x00 }, //Z 26
};
#define DELAY delayMicroseconds(1);
#define ROW_CLOCK 12
#define ROW_DATA 11
#define ROW_LATCH 10
#define ROW_CLOCK_HIGH digitalWrite(ROW_CLOCK, HIGH);
#define ROW_CLOCK_LOW digitalWrite(ROW_CLOCK, LOW);
#define ROW_DATA_HIGH digitalWrite(ROW_DATA, HIGH);
#define ROW_DATA_LOW digitalWrite(ROW_DATA, LOW);
#define ROW_LATCH_HIGH digitalWrite(ROW_LATCH, HIGH);
#define ROW_LATCH_LOW digitalWrite(ROW_LATCH, LOW);
#define ROW_CLOCK_PULSE \
{ ROW_CLOCK_LOW DELAY ROW_CLOCK_HIGH } // this is used as clock pulse for row IC
#define ROW_LATCH_PULSE \
{ ROW_LATCH_LOW DELAY ROW_LATCH_HIGH } // this is used as latch pulse for row IC
#define COLUMN_CLOCK 7
#define COLUMN_DATA 6
#define COLUMN_LATCH 5
#define COLUMN_CLOCK_HIGH digitalWrite(COLUMN_CLOCK, HIGH);
#define COLUMN_CLOCK_LOW digitalWrite(COLUMN_CLOCK, LOW);
#define COLUMN_DATA_HIGH digitalWrite(COLUMN_DATA, HIGH);
#define COLUMN_DATA_LOW digitalWrite(COLUMN_DATA, LOW);
#define COLUMN_LATCH_HIGH digitalWrite(COLUMN_LATCH, HIGH);
#define COLUMN_LATCH_LOW digitalWrite(COLUMN_LATCH, LOW);
#define COLUMN_CLOCK_PULSE \
{ COLUMN_CLOCK_LOW DELAY COLUMN_CLOCK_HIGH } // this is used as clock pulse for row IC
#define COLUMN_LATCH_PULSE \
{ COLUMN_LATCH_LOW DELAY COLUMN_LATCH_HIGH } // this is used as latch pulse for row IC
void row_putbyte(unsigned char databyte);
byte fillscreen[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
byte clearscreen[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte diya[8] = { 0x10, 0x28, 0x28, 0x92, 0xFE, 0x82, 0x44, 0x38 };
byte smiley[8] = { 0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C };
byte heart[8] = { 0x00, 0x66, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, 0x18 };
byte arrow[8] = { 0x18, 0x0C, 0x06, 0xFF, 0xFF, 0x06, 0x0C, 0x18 };
byte sathiya[8] = { 0x9E, 0x90, 0x90, 0xFE, 0x12, 0x12, 0xF2, 0x00 };
byte om[8] = { 0x14, 0x68, 0x96, 0x19, 0xA1, 0x95, 0x52, 0x30 };
byte anar[8] = { 0x00, 0x44, 0x28, 0xD6, 0x10, 0x38, 0x7C, 0xFE };
byte candle[8] = { 0x10, 0x28, 0x28, 0x10, 0x38, 0x38, 0x38, 0x38 };
byte ladoo[8] = { 0x08, 0x14, 0x36, 0x49, 0x7F, 0x41, 0x3E, 0x00 };
byte charkhi_1[8] = { 0x10, 0x10, 0x18, 0x27, 0xE4, 0x18, 0x08, 0x08 };
byte charkhi_2[8] = { 0x02, 0x84, 0x58, 0x24, 0x24, 0x1A, 0x21, 0x40 };
byte diyaPattern[22] = {
0x30, 0x41, 0x42, 0x43, 0x33, 0x22, 0x12, 0x03,
0x14, 0x24, 0x44, 0x45, 0x36, 0x46, 0x56, 0x65,
0x74, 0x73, 0x72, 0x61, 0x50, 0x40,
};
byte smileyPattern[26] = {
0x02, 0x11, 0x20, 0x30, 0x40, 0x50, 0x61, 0x72,
0x73, 0x74, 0x75, 0x66, 0x57, 0x47, 0x37, 0x27,
0x16, 0x05, 0x04, 0x03, 0x22, 0x25, 0x42, 0x53,
0x54, 0x45
};
byte sathiyaPattern[26] = {
0x06, 0x05, 0x04, 0x03, 0x13, 0x23, 0x33, 0x43,
0x53, 0x63, 0x62, 0x61, 0x60, 0x00, 0x10, 0x20,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x46,
0x56, 0x66
};
void setup() {
//set pins to output so you can control the shift register and initially they should be HIGH
pinMode(ROW_CLOCK, OUTPUT);
pinMode(ROW_DATA, OUTPUT);
pinMode(ROW_LATCH, OUTPUT);
digitalWrite(ROW_CLOCK, HIGH);
digitalWrite(ROW_DATA, HIGH);
digitalWrite(ROW_LATCH, HIGH);
pinMode(COLUMN_CLOCK, OUTPUT);
pinMode(COLUMN_DATA, OUTPUT);
pinMode(COLUMN_LATCH, OUTPUT);
digitalWrite(COLUMN_CLOCK, HIGH);
digitalWrite(COLUMN_DATA, HIGH);
digitalWrite(COLUMN_LATCH, HIGH);
}
void loop() {
displayPattern(diyaPattern, 26, 20);
runStringLtoR("HAPPYDIWALI", 11, 10);
displayPattern(sathiyaPattern, 26, 10);
fillImageLong(candle, 50,1);
fillImageLong(anar, 50,0);
displayCharkhi(50);
}
void displayCharkhi(unsigned char displaytime) {
unsigned char counter=0;
do {
displayImage(charkhi_1, 10);
displayImage(charkhi_2, 10);
} while (counter++ < displaytime);
}
void row_putbyte(unsigned char databyte) {
char i;
for (i = 0; i < 8; i++) {
if ((databyte & 0x80) == 0x80) { // change data i.e send 8 bit of data over data line starting from MSB
ROW_DATA_HIGH
} else {
ROW_DATA_LOW
}
ROW_CLOCK_PULSE
databyte = databyte << 1; // left shift of data
}
}
void displayAlphabet(unsigned char alphabet, unsigned char displaytime) {
unsigned char alpha;
if (alphabet >= 65 && alphabet <= 90) {
alpha = alphabet - 65;
displayImage(alphabets[alpha], displaytime);
} else if (alphabet >= 97 && alphabet <= 122) {
alpha = alphabet - 97;
displayImage(alphabets[alpha], displaytime);
} else if (alphabet == 0x20)
displayImage(clearscreen, displaytime);
}
void runStringLtoR(unsigned char* displayString, unsigned char stringLength, unsigned char displaytime) {
char i, j, n;
unsigned char localImageBuffer[8] = { 0x00 };
unsigned char currentAlphabet[8] = { 0 };
unsigned char alphaIndex;
for (n = 0; n < stringLength; n++) {
// find the alphbet od string , find its index in alphabets[][] array and fill in the current Alphabet
if (displayString[n] >= 65 && displayString[n] <= 90) {
alphaIndex = displayString[n] - 65;
memcpy(currentAlphabet, alphabets[alphaIndex], 8);
} else if (displayString[n] >= 97 && displayString[n] <= 122) {
alphaIndex = displayString[n] - 97;
memcpy(currentAlphabet, alphabets[alphaIndex], 8);
} else {
memset(currentAlphabet, 0x00, 8);
}
for (j = 0; j < 8; j++) { // this loop is run for 8 times so that all colums is shited into localImageBuffer
// fill the current Alphabet into the local image buffer starting From its MSB
for (i = 0; i < 8; i++) {
localImageBuffer[i] = localImageBuffer[i] << 1; // first left current byte of local buffer shift by 1 bit
if (currentAlphabet[i] & (0x80)) {
localImageBuffer[i] |= 0x01; // Turn the LSB High
} else {
localImageBuffer[i] &= ~(0x01); // Turn the LSB LOW
}
currentAlphabet[i] = currentAlphabet[i] << 1; // left shift the current byte of current Alphabet
}
displayImage(localImageBuffer, displaytime);
}
}
}
void fillImageLong(unsigned char imagebuffer[8], unsigned char image_filling_time, char type) {
char i;
unsigned char localImageBuffer[8] = { 0x00 };
for (i = 0; i <= 7; i++) {
if (type) {
memcpy(localImageBuffer, imagebuffer, i + 1); // fill image top to botton
} else {
memcpy(localImageBuffer, imagebuffer, 8); // fill image completely into local buffer
memset(localImageBuffer, 0x00, 7 - i); // clear those ROWs which need needs to be off, from botton to top manner
}
displayImage(localImageBuffer, image_filling_time);
}
}
void displayPattern(unsigned char pattern[], unsigned char patternLength, unsigned char displaytime) {
unsigned char image[8] = { 0x00 };
char column, row, i;
// this loop puts the patterns bytes one by one as Most significant nibble is row and least significant nibble is column
for (i = 0; i < patternLength; i++) {
column = pattern[i] & 0x0F;
row = pattern[i] & 0xF0;
row = row >> 4;
image[row] |= 0x80 >> column;
displayImage(image, displaytime);
}
}
void displayImage(unsigned char imagebuffer[8], unsigned char displaytime) {
char row, column;
unsigned char counter = 0;
do {
display(imagebuffer);
} while (counter++ < displaytime);
}
void display(unsigned char staticDisplay[8]) {
char row, column;
for (row = 0; row < 8; row++) {
// We need to send byte to the columns in Left Most column first manner
// Hence we are sending the data MSB first and the bit shout be incerted as column is connected to Cathode(-).
for (column = 0; column < 8; column++) {
if ((staticDisplay[row] & (0x80 >> column))) {
COLUMN_DATA_LOW // to glow the LED it should be LOW, as column is connected to cathode
} else {
COLUMN_DATA_HIGH // to turn off the LED it should be HIGH, as column is connected to cathode
}
COLUMN_CLOCK_PULSE
}
COLUMN_LATCH_PULSE
// Now provide ROW data and turn On sigle ROW at a Time ROW is connected to Anode
row_putbyte((1 << row));
ROW_LATCH_PULSE
delay(1); // delay of 1 ms
// This is done becuse next LED which should glow it glows in previous ROW
// hence before changing the column data all LED off byte is sent
row_putbyte(0x00);
ROW_LATCH_PULSE
}
}