diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..7dc2b0a --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,7 @@ +v1.3 + -Added print function + -Added general sendColumnBuffer + -Removed sendCustomSymbol (replaced with sendColumnBuffer) + -Added 'rotateIndividualDislay' option in the class declaration +v1.2 + -Started to keep track of changes. Anything before this would be a guess based on commit messages. Also started to track versions at 1.2 \ No newline at end of file diff --git a/README.md b/README.md index 181a57f..4665f95 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,8 @@ Link to the official guide can be found [here!](https://www.arduino.cc/en/Guide/ Follow the "Importing a .zip Library" section of the guide to import this library. ## To-Do -- Add documentation describing how the LED Matrix will be hooked up to the Arduino with drawings. -- Create examples demonstrating how to use the Python Generators and the library - Create more examples +- Have scrolling be able to be done from left to right ## Authors diff --git a/examples/4_Matrix_Bitmap/4_Matrix_Bitmap.ino b/examples/4_Matrix_Bitmap/4_Matrix_Bitmap.ino index cf4f1e0..dda631d 100644 --- a/examples/4_Matrix_Bitmap/4_Matrix_Bitmap.ino +++ b/examples/4_Matrix_Bitmap/4_Matrix_Bitmap.ino @@ -22,8 +22,8 @@ void setup(){ disp.begin(); // Set the LED's intensity. This value can be anywhere between 0 and 15. disp.setIntensity(0x02); - // Send the custom bitmap to the 4 matrices - disp.sendMatrixBuffer(TEST_BITMAP); + // Send the custom bitmap that is 32 columns wide (4 matrices * 8 columns each) starting at position #0 + disp.sendColumnBuffer(TEST_BITMAP, 4*8, 0); } // After void setup(), this code will run and loop forever. diff --git a/examples/Demo/Demo.ino b/examples/Demo/Demo.ino index 2f835f0..4e1ff19 100644 --- a/examples/Demo/Demo.ino +++ b/examples/Demo/Demo.ino @@ -13,11 +13,11 @@ simpleMatrix disp(4); /* Store the text to be displayed in memory The PROGMEM means that the text will be stored in the Arduino's -flash memory instead of RAM +flash memory instead of RAM. This means that you can a lot more stuff (~27000 characters available) */ const char text[] PROGMEM = "Hello World!"; -//Defines "textDelay" as 100. -#define textDelay 100 +//Defines "textDelay" as 25ms (Delay between when the display scroll by 1 pixel to the left). +#define textDelay 25 //This code will run only once when the Arduino is turned on. void setup(){ diff --git a/examples/Single_Matrix_Bitmap/Single_Matrix_Bitmap.ino b/examples/Single_Matrix_Bitmap/Single_Matrix_Bitmap.ino index c19c541..a5108a1 100644 --- a/examples/Single_Matrix_Bitmap/Single_Matrix_Bitmap.ino +++ b/examples/Single_Matrix_Bitmap/Single_Matrix_Bitmap.ino @@ -22,8 +22,8 @@ void setup(){ disp.begin(); // Set the LED's intensity. This value can be anywhere between 0 and 15. disp.setIntensity(0x02); - // Send the custom bitmap to the first matrix - disp.sendCustomSymbol(0, TEST_BITMAP); + // Send the custom bitmap that is 8 columns wide starting at position #0 + disp.sendColumnBuffer(TEST_BITMAP, 8, 0); } // After void setup(), this code will run and loop forever. diff --git a/keywords.txt b/keywords.txt index b969590..d45e715 100644 --- a/keywords.txt +++ b/keywords.txt @@ -17,11 +17,12 @@ clearDisplay KEYWORD2 fillDisplay KEYWORD2 scrollText KEYWORD2 scrollTextPROGMEM KEYWORD2 -sendMatrixBuffer KEYWORD2 +print KEYWORD2 setIntensity KEYWORD2 setPixel KEYWORD2 -sendCustomSymbol KEYWORD2 +sendColumnBuffer KEYWORD2 scrollBuffer KEYWORD2 +sendMatrixBuffer KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/library.properties b/library.properties index c2dc4ad..b4d6df2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Simple LED Matrix -version=1.2 +version=1.3 author=Jamal Bouajjaj maintainer=Jamal Bouajjaj sentence=A library for the MAX7219 and the MAX7221 Led display drivers. diff --git a/src/simple_matrix.cpp b/src/simple_matrix.cpp index 5c592eb..9281d4e 100644 --- a/src/simple_matrix.cpp +++ b/src/simple_matrix.cpp @@ -3,70 +3,74 @@ #include "font.h" /******************************************************************************** - simpleMatrix Library - This library is designed to handle all the low and high level functions for +simpleMatrix Library +This library is designed to handle all the low and high level functions for the MAX7219 LED Matrixes. - Originally designed for the University of New Haven's - Makerspace's Make-A-Sign Event. +Originally designed for the University of New Haven's + Makerspace's Make-A-Sign Event. Author: Jamal Bouajjaj ********************************************************************************/ +/******************************************************************************** +Constructor +********************************************************************************/ +//The library's constructor. Sets the internal _DL_PIN value to pin and +//sends the pin as an OUTPUT and turns it HIGH +simpleMatrix::simpleMatrix(int pin, bool rotateIndividualDislay = false){ + _DL_PIN = pin; + _ROTATE_INDIV_DISPLAY = rotateIndividualDislay; + pinMode(_DL_PIN,OUTPUT); + digitalWrite(_DL_PIN,HIGH); +} /******************************************************************************** Low Level Function ********************************************************************************/ //Sends a command to a single MS7219 void simpleMatrix::sendCommandtoOne(uint8_t command, uint8_t data, uint8_t display){ - uint8_t d[number_of_module*2]; //Array that containts data to be sent - d[2*display] = command; - d[(2*display)+1] = data; - digitalWrite(_DL_PIN,LOW); - for(int k=0;k> (i) << k; - } - } - for(int i=0;i<8;i++){_matrix[d][i] = temp[i];} - } - senddisplay(); -} - -//Sends a custom 8x8 bitmap that is column-addressed. Can scroll it from left to right -void simpleMatrix::sendCustomSymbol(int d, uint8_t *mat, bool scroll = false, int del = 0){ - if(d>number_of_module+1){ // If the matrix position is more than 1+ that current number, return - return; - } - uint8_t display[(number_of_module+1)*8]; - for(int i=0;i<(number_of_module+1)*8;i++){display[i] = 0;} // Set *display to 0 - for(int k=0;k<8;k++){ - display[k+(d*8)] = mat[k]; //Copy 8x8 bitmap to internal *display array - } - sendMatrixBuffer(display); - if(scroll==true){ - delay(del); - int location = (d*8)+8; //Sets the right-most location of the bitmap - while(1){ - for(int i=0;i<((number_of_module+1)*8)-1;i++){display[i] = display[i+1];} //Scrolls display - sendMatrixBuffer(display); - delay(del); - if(location==0){ //If the right-most location = 0, it means that the displays - break; //Has fully scrolled thru the bitmap, thus exit the while loop - } - location--; - } - } + for(int i=0;i> (i)) << (7-k); + }else{ + temp[i] |= ((_matrix[d][k] & bitmask_v) >> (i)) << (k); + } + } + } + for(int i=0;i<8;i++){_matrix[d][i] = temp[i];} + } + senddisplay(); } //Fills the display. Can fill all or some displays -void simpleMatrix::fillDisplay(int from=0, int to=(number_of_module-1)){ - for(int i=from;i<(to+1);i++){ - for(int k=0;k<8;k++){ - _matrix[i][k] = 0xFF; - } - } - senddisplay(); +void simpleMatrix::fillDisplay(int from=0, int to=(NUMBER_OF_MODULES-1)){ + for(int i=from;i<(to+1);i++){ + for(int k=0;k<8;k++){ + _matrix[i][k] = 0xFF; + } + } + senddisplay(); } //Clears the displays. Can clear all or some displays -void simpleMatrix::clearDisplay(int from=0, int to=(number_of_module-1)){ - for(int d=from;d<(to+1);d++){ - for(int i=0;i<8;i++){ - _matrix[d][i] = 0x00; - } - } - senddisplay(); +void simpleMatrix::clearDisplay(int from=0, int to=(NUMBER_OF_MODULES-1)){ + for(int d=from;d<(to+1);d++){ + for(int i=0;i<8;i++){ + _matrix[d][i] = 0x00; + } + } + senddisplay(); } //Sends and scrolls a text from left to right which is stored in Flash memory -void simpleMatrix::scrollTextPROGMEM(const char *text, int del){ - //Buffer will be 2 "immaginary" matrices right of the real one. - //This is to have the smooth scolling effect - const uint8_t charlenght = 6; //The lenght of each char including the lenght of the font. - uint8_t display[8*(number_of_module+2)]; //Internal display buffer - int buffer_location = 8*(number_of_module); //Location of the buffer in columns(right-most location) - int lettercount = 0; //How many letters we sent - int text_lenght = strlen(text); - for(int i=0;i<8*(number_of_module+2);i++){display[i] = 0x00;} //Sets *display to 0 - //Sends out letters in the "immaginary" matrices, which is 2 of them. - //The i-max is divided the multipled by char becuase when dividing, the MCU will round - //down, thus only sending out the number of characters that will fit the 2 "immaginary" matrices - for(int i=0;i<((2*8)/charlenght)*charlenght;i++){ //Send letter over the invisible displays - if((i%charlenght)>=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's - display[i+(number_of_module*8)] = 0x00; - } - else{ //Send out the font - display[i+(number_of_module*8)] = (font[ pgm_read_byte_near(text + (i/charlenght))-0x20 ][ i%charlenght ]); - } - buffer_location++; - } - lettercount = (2*8)/charlenght; //Record number of letters sent - sendMatrixBuffer(display); //Send out the display - while(1){ - delay(del); - for(int i=0;i<((number_of_module+2)*8)-1;i++){display[i] = display[i+1];} //Scrolls the display - sendMatrixBuffer(display); //Send out the display - buffer_location--; - if(buffer_location <= (8*number_of_module)){ //When the buffer location reaches the real matrices - if(lettercount < text_lenght){ //If the number of letters sent is less than the text lenght - for(int i=0;i=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's - display[i+(8*number_of_module)] = 0x00; - } - else{ //Send out the font - display[i+(8*number_of_module)] = (font[ pgm_read_byte_near(text + lettercount)-0x20 ][ i ]); - } - } - buffer_location += charlenght; //Increment buffer_location after character is sent - lettercount++; //Increment the nubmer of letters sent - } - else{ - display[buffer_location] = 0x00; //Sends 0's if we already send out all of letters - } - } - if(buffer_location == 0){ //When all the letters are scrolled and out of the matrix - break; //Break out of the while loop - } - } +void simpleMatrix::scrollTextPROGMEM(const char *text, int del, int start_from=(NUMBER_OF_MODULES*8)+1){ + print(text, start_from, true, true, del); } //Sends and scrolls a text from left to right -void simpleMatrix::scrollText(char *text, int del){ - //Buffer will be 2 "immaginary" matrices right of the real one. - //This is to have the smooth scolling effect - const uint8_t charlenght = 6; //The lenght of each char including the lenght of the font. - uint8_t display[8*(number_of_module+2)]; //Internal display buffer - int buffer_location = 8*(number_of_module); //Location of the buffer in columns(right-most location) - int lettercount = 0; //How many letters we sent - int text_lenght = strlen(text); - for(int i=0;i<8*(number_of_module+2);i++){display[i] = 0x00;} //Sets *display to 0 - //Sends out letters in the "immaginary" matrices, which is 2 of them. - //The i-max is divided the multipled by char becuase when dividing, the MCU will round - //down, thus only sending out the number of characters that will fit the 2 "immaginary" matrices - for(int i=0;i<((2*8)/charlenght)*charlenght;i++){ //Send letter over the invisible displays - if((i%charlenght)>=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's - display[i+(number_of_module*8)] = 0x00; - } - else{ //Send out the font - display[i+(number_of_module*8)] = (font[ text[i/charlenght]-0x20][ i%charlenght ]); - } - buffer_location++; - } - lettercount = (2*8)/charlenght; //Record number of letters sent - sendMatrixBuffer(display); //Send out the display - while(1){ - delay(del); - for(int i=0;i<((number_of_module+2)*8)-1;i++){display[i] = display[i+1];} //Scrolls the display - sendMatrixBuffer(display); //Send out the display - buffer_location--; - if(buffer_location <= (8*number_of_module)){ //When the buffer location reaches the real matrices - if(lettercount < text_lenght){ //If the number of letters sent is less than the text lenght - for(int i=0;i=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's - display[i+(8*number_of_module)] = 0x00; - } - else{ //Send out the font - display[i+(8*number_of_module)] = (font[ text[lettercount]-0x20][ i ]); - } - } - buffer_location += charlenght; //Increment buffer_location after character is sent - lettercount++; //Increment the nubmer of letters sent - } - else{ - display[buffer_location] = 0x00; //Sends 0's if we already send out all of letters - } - } - if(buffer_location == 0){ //When all the letters are scrolled and out of the matrix - break; //Break out of the while loop - } - } +void simpleMatrix::scrollText(char *text, int del, int start_from=(NUMBER_OF_MODULES*8)+1){ + print(text, start_from, false, true, del); +} + +//Sends text with an option to scoll it +void simpleMatrix::print(char *text, int start_from=0, bool is_text_progmem=false, bool scroll_text=false, int del=0){ + //Buffer will be 2 "immaginary" matrices right of the real one. + //This is to have the smooth scolling effect + uint8_t display[8*(NUMBER_OF_MODULES+2)]; //Internal display buffer + const uint8_t charlenght = 6; //The lenght of each char including the lenght of the font. + int text_lenght = strlen(text); + for(int i=0;i<8*(NUMBER_OF_MODULES+2);i++){display[i] = 0x00;} //Sets *display to 0 + int lettercount = 0; + //Sends out letters in the "immaginary" matrices, which is 2 of them. + //The i-max is divided the multipled by char becuase when dividing, the MCU will round + //down, thus only sending out the number of characters that will fit the 2 "immaginary" matrices + int i=0; + while(1){ + if((i%charlenght)>=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's + display[i+start_from] = 0x00; + } + else{ //Send out the font + if(is_text_progmem){ + display[i+start_from] = (font[ pgm_read_byte_near(text + (i/charlenght))-0x20 ][ i%charlenght ]); + } + else{ + display[i+start_from] = (font[ text[i/charlenght]-0x20][ i%charlenght ]); + } + } + + i++; + if((i%charlenght)==0){ //If the remainder of i%charlenght is more then 5(font size), send 0's + lettercount++; + } + if(((lettercount+1)*charlenght)+start_from >= 8*(NUMBER_OF_MODULES+2)){ + break; + } + + } + //int lettercount = i/charlenght; + int buffer_location = i + start_from; + sendMatrixBuffer(display); //Send out the display + + if(scroll_text){ + while(1){ + delay(del); + for(int i=0;i<((NUMBER_OF_MODULES+2)*8)-1;i++){display[i] = display[i+1];} //Scrolls the display + sendMatrixBuffer(display); //Send out the display + buffer_location--; + if(buffer_location <= (8*NUMBER_OF_MODULES)){ //When the buffer location reaches the real matrices + if(lettercount < text_lenght){ //If the number of letters sent is less than the text lenght + for(int i=0;i=5){ //If the remainder of i%charlenght is more then 5(font size), send 0's + display[i+(8*NUMBER_OF_MODULES)] = 0x00; + } + else{ //Send out the font + if(is_text_progmem){ + display[i+(8*NUMBER_OF_MODULES)] = (font[ pgm_read_byte_near(text + lettercount)-0x20 ][ i ]); + } + else{ + display[i+(8*NUMBER_OF_MODULES)] = (font[ text[lettercount]-0x20][ i ]); + } + } + } + buffer_location += charlenght; //Increment buffer_location after character is sent + lettercount++; //Increment the nubmer of letters sent + } + else{ + display[buffer_location] = 0x00; //Sends 0's if we already send out all of letters + } + } + if(buffer_location == 0){ //When all the letters are scrolled and out of the matrix + break; //Break out of the while loop + } + } + } +} + +// Function to scroll a buffer of any size +void simpleMatrix::scrollBuffer(uint8_t *mat, int del, int column, int start_from=(NUMBER_OF_MODULES*8)+1){ + sendColumnBuffer(mat, column, start_from, true, del); } -// Scolls a column-adressed buffer from right to left of x column (Better if it's a multiple of 8) -void simpleMatrix::scrollBuffer(uint8_t *mat, int del, int column){ - uint8_t display[(number_of_module+1)*8]; // Create buffer w/ 1 "immaginary" column + number of columns in matrix - for(int i=0;i<(number_of_module+1)*8;i++){display[i] = 0x00;} // Sets *display to 0 - display[(number_of_module*8)+1] = mat[0]; // Send the first array of the object's array to the matrix - int column_send = 1; // Counter to count the number of columns sent - sendMatrixBuffer(display); // Send out *display buffer - while(1){ - delay(del); // Delay by the inputed delay amount - for(int i=0;i<(number_of_module*8)+1;i++){display[i] = display[i+1];} // Scroll display - sendMatrixBuffer(display); // Send out *display buffer - // If the number of column sent is less than or equal to the number of columns in the array, - // send the array data, else send 0 - display[1+(number_of_module*8)] = (column_send <= (column-1)) ? mat[column_send] : 0x00; - // If the number of column sent is greater than the number of column in the array + the column size - // of the matrix, exit the while loop as it has scrolled thru the array and scrolled it out of frame - if(column_send > column+(number_of_module*8)){ - break; // Break out of the while loop - } - column_send++; // Increment the number of columns sent - } +// General function to send over a column-arrayed buffer. Can be scrolled or not, depending in preference +void simpleMatrix::sendColumnBuffer(uint8_t *mat, int column, int start_from=0, bool scroll=false, int del=0){ + uint8_t display[(NUMBER_OF_MODULES+1)*8]; // Create buffer w/ 1 "immaginary" column + number of columns in matrix + for(int i=0;i<(NUMBER_OF_MODULES+1)*8;i++){display[i] = _matrix_col[i];} // Sets *display to copy of current display + int column_send = 0; + for(int i=start_from;i<=(NUMBER_OF_MODULES*8)+1;i++){ + display[i] = mat[i-start_from]; + column_send++; + if(column_send == column){break;} + } + sendMatrixBuffer(display); // Send out *display buffer + if(scroll){ + while(1){ + delay(del); // Delay by the inputed delay amount + for(int i=0;i<(NUMBER_OF_MODULES*8)+1;i++){display[i] = display[i+1];} // Scroll display + sendMatrixBuffer(display); // Send out *display buffer + // If the number of column sent is less than or equal to the number of columns in the array, + // send the array data, else send 0 + display[1+(NUMBER_OF_MODULES*8)] = (column_send <= (column-1)) ? mat[column_send] : 0x00; + // If the number of column sent is greater than the number of column in the array + the column size + // of the matrix, exit the while loop as it has scrolled thru the array and scrolled it out of frame + if(column_send > column+(NUMBER_OF_MODULES*8)){ + break; // Break out of the while loop + } + column_send++; // Increment the number of columns sent + } + } } // Sets the intensity of all displays void simpleMatrix::setIntensity(int intensity){ - sendCommandtoAll(0x0A,intensity); //Set to max intensity + sendCommandtoAll(0x0A,intensity); //Set to max intensity } diff --git a/src/simple_matrix.h b/src/simple_matrix.h index 569fa6a..0826bc2 100644 --- a/src/simple_matrix.h +++ b/src/simple_matrix.h @@ -5,29 +5,32 @@ #include #include -#ifndef number_of_module -#define number_of_module 4 +#ifndef NUMBER_OF_MODULES +#define NUMBER_OF_MODULES 4 #endif class simpleMatrix{ - public: - simpleMatrix(int pin); - void begin(); - void clearDisplay(int from=0, int to=(number_of_module-1)); - void fillDisplay(int from=0, int to=(number_of_module-1)); - void scrollText(char *text, int del); - void scrollTextPROGMEM(const char *text, int del); - void sendMatrixBuffer(uint8_t *mat); - void setIntensity(int intensity); - void setPixel(int x, int y, int value); - void sendCustomSymbol(int d, uint8_t *mat, bool scroll = false, int del = 0); - void scrollBuffer(uint8_t *mat, int del, int column); - private: - uint8_t _matrix[(number_of_module)+2][8]; - int _DL_PIN; - void senddisplay(); //Sends the _matrix buffer - void sendCommandtoAll(uint8_t command, uint8_t data); - void sendCommandtoOne(uint8_t command, uint8_t data, uint8_t display); + public: + simpleMatrix(int pin, bool rotateIndividualDislay = false); + void begin(); + void clearDisplay(int from=0, int to=(NUMBER_OF_MODULES-1)); + void fillDisplay(int from=0, int to=(NUMBER_OF_MODULES-1)); + void scrollText(char *text, int del, int start_from=(NUMBER_OF_MODULES*8)+1); + void scrollTextPROGMEM(const char *text, int del, int start_from=(NUMBER_OF_MODULES*8)+1); + void print(char *text, int start_from=0, bool is_text_progmem=false, bool scroll_text=false, int del=0); + void setIntensity(int intensity); + void setPixel(int x, int y, int value); + void scrollBuffer(uint8_t *mat, int del, int column, int start_from=(NUMBER_OF_MODULES*8)+1); + void sendColumnBuffer(uint8_t *mat, int column, int start_from=0, bool scroll=false, int del=0); + void sendMatrixBuffer(uint8_t *mat); + private: + uint8_t _matrix[NUMBER_OF_MODULES+1][8]; + uint8_t _matrix_col[(NUMBER_OF_MODULES)*8]; // A copy of a column_addressed matrix + bool _ROTATE_INDIV_DISPLAY; + int _DL_PIN; + void senddisplay(); //Sends the _matrix buffer + void sendCommandtoAll(uint8_t command, uint8_t data); + void sendCommandtoOne(uint8_t command, uint8_t data, uint8_t display); }; #endif