├── .gitignore ├── extras ├── Alphabet.odg ├── datasheets │ ├── TM1638.pdf │ ├── 74HC595.pdf │ ├── TM1636-English.pdf │ └── TM1637-Chinese.pdf └── img │ ├── MAX7219-8-digit-dot.jpg │ ├── TM1637-4-digit-colon.jpg │ ├── TM1637-4-digit-dot-colon.jpg │ ├── TM1638-8-digit-dot-16-key.jpg │ ├── TM1638-8-digit-dot-led-key.jpg │ ├── TM1636-4-digit-dot-colon-shield.png │ └── TM1638-8-digit-dot-8-led-8key-large.jpg ├── .travis.yml ├── library.properties ├── keywords.txt ├── examples ├── FunPrintLevel │ └── FunPrintLevel.ino ├── ExtClock │ └── ExtClock.ino ├── Basic │ └── Basic.ino ├── PrintNumber │ └── PrintNumber.ino ├── SerialPrint │ └── SerialPrint.ino ├── LowLevel │ └── LowLevel.ino ├── ExtScoreboard │ └── ExtScoreboard.ino └── FunPrintAll │ └── FunPrintAll.ino ├── src ├── SevenSegmentExtended.h ├── SevenSegmentAsciiMap.cpp ├── SevenSegmentFun.h ├── SevenSegmentExtended.cpp ├── SevenSegmentAsciiMap.h ├── SevenSegmentFun.cpp ├── SevenSegmentTM1637.cpp └── SevenSegmentTM1637.h ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | libraries 3 | sketches 4 | /.project 5 | *.h.gch 6 | .vscode -------------------------------------------------------------------------------- /extras/Alphabet.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/Alphabet.odg -------------------------------------------------------------------------------- /extras/datasheets/TM1638.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/datasheets/TM1638.pdf -------------------------------------------------------------------------------- /extras/datasheets/74HC595.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/datasheets/74HC595.pdf -------------------------------------------------------------------------------- /extras/img/MAX7219-8-digit-dot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/MAX7219-8-digit-dot.jpg -------------------------------------------------------------------------------- /extras/img/TM1637-4-digit-colon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1637-4-digit-colon.jpg -------------------------------------------------------------------------------- /extras/datasheets/TM1636-English.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/datasheets/TM1636-English.pdf -------------------------------------------------------------------------------- /extras/datasheets/TM1637-Chinese.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/datasheets/TM1637-Chinese.pdf -------------------------------------------------------------------------------- /extras/img/TM1637-4-digit-dot-colon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1637-4-digit-dot-colon.jpg -------------------------------------------------------------------------------- /extras/img/TM1638-8-digit-dot-16-key.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1638-8-digit-dot-16-key.jpg -------------------------------------------------------------------------------- /extras/img/TM1638-8-digit-dot-led-key.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1638-8-digit-dot-led-key.jpg -------------------------------------------------------------------------------- /extras/img/TM1636-4-digit-dot-colon-shield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1636-4-digit-dot-colon-shield.png -------------------------------------------------------------------------------- /extras/img/TM1638-8-digit-dot-8-led-8key-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bremme/arduino-tm1637/HEAD/extras/img/TM1638-8-digit-dot-8-led-8key-large.jpg -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | before_install: 3 | - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" 4 | - sleep 3 5 | - export DISPLAY=:1.0 6 | - wget https://downloads.arduino.cc/arduino-1.8.12-linux64.tar.xz 7 | - tar xf arduino-1.8.12-linux64.tar.xz 8 | - sudo mv arduino-1.8.12 /usr/local/share/arduino 9 | - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino 10 | install: 11 | - ln -s $PWD /usr/local/share/arduino/libraries/SevenSegmentTM1637 12 | script: 13 | - arduino --verify --board arduino:avr:uno --pref sketchbook.path="$PWD" $PWD/examples/Basic/Basic.ino 14 | notifications: 15 | email: 16 | on_success: change 17 | on_failure: change 18 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SevenSegmentTM1637 2 | version=1.1.1 3 | author=Bram Harmsen 4 | maintainer=Bram Harmsen 5 | sentence=Library for using a 4 digit seven segment display with TM1636 or TM1637 driver IC 6 | paragraph=Extensive library for controlling a 4 digit seven segment display. This library inherent the Print class and uses the LCDAPI 1.0. For example you can use all normal Print methods like: print() and println(). From the LCDAPI among others begin(), clear(), home(), setCursor() and setBacklight() are implementend. On top of these regular functionality a segerate fun class which adds more features can be used. For example a bombtimer(), nightrider() and bouncingBall() method can be used when using the fun class. 7 | category=Display 8 | url=https://github.com/bremme/arduino-tm1637 9 | architectures=avr 10 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For SevenSegmentTM1637 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | SevenSegmentTM1637 KEYWORD1 10 | SevenSegmentExtended KEYWORD1 11 | SevenSegmentFun KEYWORD1 12 | 13 | ####################################### 14 | # Methods and Functions (KEYWORD2) 15 | ####################################### 16 | 17 | init KEYWORD2 18 | begin KEYWORD2 19 | write KEYWORD2 20 | clear KEYWORD2 21 | home KEYWORD2 22 | setCursor KEYWORD2 23 | setBacklight KEYWORD2 24 | setContrast KEYWORD2 25 | on KEYWORD2 26 | off KEYWORD2 27 | blink KEYWORD2 28 | setColonOn KEYWORD2 29 | getColonOn KEYWORD2 30 | setPrintDelay KEYWORD2 31 | encode KEYWORD2 32 | shiftLeft KEYWORD2 33 | printRaw KEYWORD2 34 | command KEYWORD2 35 | comReadByte KEYWORD2 36 | comWriteByte KEYWORD2 37 | comStart KEYWORD2 38 | comStop KEYWORD2 39 | comAck KEYWORD2 40 | printTime KEYWORD2 41 | printNumber KEYWORD2 42 | printDualCounter KEYWORD2 43 | printLevelVertical KEYWORD2 44 | printLevelHorizontal KEYWORD2 45 | scrollingText KEYWORD2 46 | snake KEYWORD2 47 | nightrider KEYWORD2 48 | bombTimer KEYWORD2 49 | bouchingBall KEYWORD2 50 | printBall KEYWORD2 51 | print4Bit KEYWORD2 52 | 53 | 54 | ####################################### 55 | # Constants (LITERAL1) 56 | ####################################### 57 | -------------------------------------------------------------------------------- /examples/FunPrintLevel/FunPrintLevel.ino: -------------------------------------------------------------------------------- 1 | #include "SevenSegmentTM1637.h" 2 | #include "SevenSegmentExtended.h" 3 | #include "SevenSegmentFun.h" 4 | 5 | // define clock and digital input pins 6 | #define PIN_CLK 4 7 | #define PIN_DIO 5 8 | 9 | // initialize TM1637 Display objects 10 | SevenSegmentFun display(PIN_CLK, PIN_DIO); 11 | 12 | 13 | void setup() { 14 | // initialize the display 15 | display.begin(); 16 | } 17 | 18 | void loop() { 19 | 20 | // increase level from 0 to 100 21 | for (uint8_t i=0; i <= 100; i+=25) { 22 | display.printLevelVertical(i); 23 | delay(100); 24 | }; 25 | // decrease level from 100 to 0 26 | for (int8_t i=100; i >=0; i-=25) { 27 | display.printLevelVertical(i); 28 | delay(100); 29 | } 30 | 31 | // initialize horizontal level counters 32 | int8_t i,j,k,l; 33 | uint8_t levels[4]; 34 | 35 | 36 | // repeat 5 times 37 | for ( uint8_t r=0; r < 4; r++) { 38 | // increae i and k, decrease j and l 39 | for (i=0,j=100,k=0,l=100; i <= 100; i+=33, j-=33, k+=33, l-=33) { 40 | levels[0] = i; levels[1] = j; levels[2] = k; levels[3] = l; 41 | display.printLevelHorizontal(levels); 42 | delay(100); 43 | } 44 | // increae j and l, decrease i and k 45 | for (i=100,j=0,k=100,l=0; i >= 0; i-=33, j+=33, k-=33, l+=33) { 46 | levels[0] = i; levels[1] = j; levels[2] = k; levels[3] = l; 47 | display.printLevelHorizontal(levels); 48 | delay(100); 49 | } 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/SevenSegmentExtended.h: -------------------------------------------------------------------------------- 1 | #ifndef SevenSegmentExtended_H 2 | #define SevenSegmentExtended_H 3 | 4 | #if ARDUINO >= 100 5 | #include 6 | #else 7 | #include 8 | #endif 9 | 10 | #include "SevenSegmentTM1637.h" 11 | 12 | class SevenSegmentExtended : public SevenSegmentTM1637 { 13 | 14 | public: 15 | SevenSegmentExtended(uint8_t pinClk, uint8_t pinDIO); 16 | /* Prints given time to the display 17 | @param [in] hour hours or minutes 18 | @param [in] min minutes or seconds 19 | */ 20 | void printTime(uint8_t hour, uint8_t min, bool blink = false, uint16_t blinkDelay = TM1637_DEFAULT_CLOCK_BLINK_DELAY); 21 | /* Prints given time to the display 22 | @param [in] t time given as an int, e.g. 1643 prints 16:43 23 | */ 24 | void printTime(uint16_t t, bool blink = false, uint16_t blinkDelay = TM1637_DEFAULT_CLOCK_BLINK_DELAY); 25 | /* Prints a number and aligns it (right by default) 26 | 27 | Can print both positive and negative numbers. When the the number is larger then 9999 28 | it will roll over to 0, the same happens for a negative number smaller then -999. 29 | 30 | @param [in] number the number to print to the display 31 | @param [in] alignRight (optional) set to true to alightright (default) 32 | @param [in] rollOver (optional) set to true make the number rollover*/ 33 | void printNumber(int16_t number, bool zeroPadding = false, bool rollOver = false, bool alignRight = true); 34 | /* Print two one or two digit numbers to the display 35 | * Prints a number to the left and right of the display 36 | * 37 | @param [in] leftCounter the number on the left side of the display 38 | @param [in] rightcounter the numnber on the right side of the display 39 | @param [in] zeroPadding optional: pad counters with zero 40 | */ 41 | void printDualCounter(int8_t leftCounter, int8_t rightCounter, bool zeroPadding = false); 42 | 43 | }; 44 | #endif 45 | -------------------------------------------------------------------------------- /examples/ExtClock/ExtClock.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Clock example example (Extended class example) 3 | 4 | Display a clock on the display. For this demo you can add a speed multiplier to make the clock run faster. For a real clock you want to use a delay of 1 min or even use a Real Time Clock module (RTC) 5 | 6 | The circuit: 7 | * connect TM1637 pin CLK to Arduino pin D4 8 | * connect TM1637 pin DIO to Arduino pin D5 9 | * connect TM1637 pin Vcc to Arduino pin 5V 10 | * connect TM1637 pin GND to Arduino pin GND 11 | 12 | Created 25 September 2015 13 | By Bram Harmsen 14 | 15 | https://github.com/bremme/arduino-tm1637 16 | 17 | */ 18 | // include the SevenSegmentTM1637 library 19 | #include "SevenSegmentTM1637.h" 20 | #include "SevenSegmentExtended.h" 21 | 22 | /* initialize global TM1637 Display object 23 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 24 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 25 | */ 26 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 27 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 28 | SevenSegmentExtended display(PIN_CLK, PIN_DIO); 29 | 30 | const unsigned int clockSpeed = 10000; // speed up clock for demo 31 | 32 | // run setup code 33 | void setup() { 34 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 35 | display.begin(); // initializes the display 36 | display.setBacklight(100); // set the brightness to 100 % 37 | delay(1000); // wait 1000 ms 38 | }; 39 | 40 | // run loop (forever) 41 | void loop() { 42 | 43 | byte hours = 14; // initialize hours 44 | byte minutes = 39; // initialize minutes 45 | 46 | for ( ; hours < 24; hours++) { // count hours up to 24 47 | for ( ; minutes < 60; minutes++) { // count minutes up to 59 48 | display.printTime(hours, minutes, true); // display time 49 | delay(60000 / clockSpeed); // clock delay ms 50 | }; 51 | minutes = 0; // reset minutes 52 | }; 53 | }; 54 | -------------------------------------------------------------------------------- /examples/Basic/Basic.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Basic usage example 3 | 4 | Demonstrated some of the basic functionality of the library. Initialize the display, 5 | set the backlight brightness, print some text, count from 0 to 100 and 6 | print and blink some text. 7 | 8 | Note: make sure to set your serial monitor to line end: NEW LINE! 9 | 10 | The circuit: 11 | * connect TM1637 pin CLK to Arduino pin D4 12 | * connect TM1637 pin DIO to Arduino pin D5 13 | * connect TM1637 pin Vcc to Arduino pin 5V 14 | * connect TM1637 pin GND to Arduino pin GND 15 | 16 | Created 25 September 2015 17 | By Bram Harmsen 18 | 19 | https://github.com/bremme/arduino-tm1637 20 | 21 | */ 22 | 23 | // include the SevenSegmentTM1637 library 24 | #include "SevenSegmentTM1637.h" 25 | 26 | /* initialize global TM1637 Display object 27 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 28 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 29 | */ 30 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 31 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 32 | SevenSegmentTM1637 display(PIN_CLK, PIN_DIO); 33 | 34 | // run setup code 35 | void setup() { 36 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 37 | display.begin(); // initializes the display 38 | display.setBacklight(100); // set the brightness to 100 % 39 | display.print("INIT"); // display INIT on the display 40 | delay(1000); // wait 1000 ms 41 | }; 42 | 43 | // run loop (forever) 44 | void loop() { 45 | display.print("LOOP"); // display LOOP on the display 46 | delay(1000); // wait 1000 ms 47 | display.print("COUNTING SOME DIGITS");// print COUNTING SOME DIGITS 48 | display.clear(); // clear the display 49 | for (uint8_t i=0; i < 100; i++) { // loop from 0 to 100 50 | display.print(i); // display loop counter 51 | delay(100); // wait 100 ms 52 | }; 53 | display.clear(); // clear the display 54 | display.print("SUCC"); // print SUCC for success 55 | display.blink(); // blink SUCC 56 | delay(1000); // wait 1000 ms 57 | }; 58 | -------------------------------------------------------------------------------- /src/SevenSegmentAsciiMap.cpp: -------------------------------------------------------------------------------- 1 | #include "SevenSegmentAsciiMap.h" 2 | 3 | // store an ASCII Map in PROGMEM (Flash memory) 4 | const uint8_t AsciiMap::map[] PROGMEM = { 5 | TM1637_CHAR_SPACE, 6 | TM1637_CHAR_EXC, 7 | TM1637_CHAR_D_QUOTE, 8 | TM1637_CHAR_POUND, 9 | TM1637_CHAR_DOLLAR, 10 | TM1637_CHAR_PERC, 11 | TM1637_CHAR_AMP, 12 | TM1637_CHAR_S_QUOTE, 13 | TM1637_CHAR_L_BRACKET, 14 | TM1637_CHAR_R_BRACKET, 15 | TM1637_CHAR_STAR, 16 | TM1637_CHAR_PLUS, 17 | TM1637_CHAR_COMMA, 18 | TM1637_CHAR_MIN, 19 | TM1637_CHAR_DOT, 20 | TM1637_CHAR_F_SLASH, 21 | TM1637_CHAR_0, // 48 (ASCII) 22 | TM1637_CHAR_1, 23 | TM1637_CHAR_2, 24 | TM1637_CHAR_3, 25 | TM1637_CHAR_4, 26 | TM1637_CHAR_5, 27 | TM1637_CHAR_6, 28 | TM1637_CHAR_7, 29 | TM1637_CHAR_8, 30 | TM1637_CHAR_9, 31 | TM1637_CHAR_COLON, 32 | TM1637_CHAR_S_COLON, 33 | TM1637_CHAR_LESS, 34 | TM1637_CHAR_EQUAL, 35 | TM1637_CHAR_GREAT, 36 | TM1637_CHAR_QUEST, 37 | TM1637_CHAR_AT, 38 | TM1637_CHAR_A, // 65 (ASCII) 39 | TM1637_CHAR_B, 40 | TM1637_CHAR_C, 41 | TM1637_CHAR_D, 42 | TM1637_CHAR_E, 43 | TM1637_CHAR_F, 44 | TM1637_CHAR_G, 45 | TM1637_CHAR_H, 46 | TM1637_CHAR_I, 47 | TM1637_CHAR_J, 48 | TM1637_CHAR_K, 49 | TM1637_CHAR_L, 50 | TM1637_CHAR_M, 51 | TM1637_CHAR_N, 52 | TM1637_CHAR_O, 53 | TM1637_CHAR_P, 54 | TM1637_CHAR_Q, 55 | TM1637_CHAR_R, 56 | TM1637_CHAR_S, 57 | TM1637_CHAR_T, 58 | TM1637_CHAR_U, 59 | TM1637_CHAR_V, 60 | TM1637_CHAR_W, 61 | TM1637_CHAR_X, 62 | TM1637_CHAR_Y, 63 | TM1637_CHAR_Z, 64 | TM1637_CHAR_L_S_BRACKET, // 91 (ASCII) 65 | TM1637_CHAR_B_SLASH, 66 | TM1637_CHAR_R_S_BRACKET, 67 | TM1637_CHAR_A_CIRCUM, 68 | TM1637_CHAR_UNDERSCORE, 69 | TM1637_CHAR_A_GRAVE, // 96 (ASCII) 70 | TM1637_CHAR_a, 71 | TM1637_CHAR_b, 72 | TM1637_CHAR_c, 73 | TM1637_CHAR_d, 74 | TM1637_CHAR_e, 75 | TM1637_CHAR_f, 76 | TM1637_CHAR_g, 77 | TM1637_CHAR_h, 78 | TM1637_CHAR_i, 79 | TM1637_CHAR_j, 80 | TM1637_CHAR_k, 81 | TM1637_CHAR_l, 82 | TM1637_CHAR_m, 83 | TM1637_CHAR_n, 84 | TM1637_CHAR_o, 85 | TM1637_CHAR_p, 86 | TM1637_CHAR_q, 87 | TM1637_CHAR_r, 88 | TM1637_CHAR_s, 89 | TM1637_CHAR_t, 90 | TM1637_CHAR_u, 91 | TM1637_CHAR_v, 92 | TM1637_CHAR_w, 93 | TM1637_CHAR_x, 94 | TM1637_CHAR_y, 95 | TM1637_CHAR_z, 96 | TM1637_CHAR_L_ACCON, // 123 (ASCII) 97 | TM1637_CHAR_BAR, 98 | TM1637_CHAR_R_ACCON, 99 | TM1637_CHAR_TILDE // 126 (ASCII) 100 | }; -------------------------------------------------------------------------------- /src/SevenSegmentFun.h: -------------------------------------------------------------------------------- 1 | #ifndef SevenSegmentFun_H 2 | #define SevenSegmentFun_H 3 | 4 | #if ARDUINO >= 100 5 | #include 6 | #else 7 | #include 8 | #endif 9 | 10 | #include "SevenSegmentTM1637.h" 11 | #include "SevenSegmentExtended.h" 12 | 13 | // COMPILE TIME USER CONFIG //////////////////////////////////////////////////// 14 | #define TM1637_SNAKE_DEFAULT_DELAY 50 // Snake step delay ms 15 | #define TM1637_BOUNCING_BALL_DEFAULT_DELAY 100 // Bouncing ball delay ms 16 | #define TM1637_NIGHTRIDER_DEFAULT_DELAY 200 // Nightrider delay ms 17 | // 18 | // A 19 | // --- 20 | // * F | | B 21 | // X -G- 22 | // * E | | C 23 | // --- 24 | // D 25 | // X defines the colon (dots) and only applies to byte 1 (second from left) 26 | // BXGFEDCBA 27 | 28 | #define TM1637_CHAR_VERT_LEVEL_I0 B00110000 // | one bar left 29 | #define TM1637_CHAR_VERT_LEVEL_0I B00000110 // | one bar right 30 | #define TM1637_CHAR_VERT_LEVEL_II B00110110 // || two bars 31 | 32 | #define TM1637_CHAR_HOR_LEVEL_0 B00000000 33 | #define TM1637_CHAR_HOR_LEVEL_1 B00001000 34 | #define TM1637_CHAR_HOR_LEVEL_2 B01001000 35 | #define TM1637_CHAR_HOR_LEVEL_3 B01001001 36 | 37 | #define TM1637_CHAR_SNAKE_0 B00000001 38 | #define TM1637_CHAR_SNAKE_1 B00000010 39 | #define TM1637_CHAR_SNAKE_2 B00000100 40 | #define TM1637_CHAR_SNAKE_3 B00001000 41 | #define TM1637_CHAR_SNAKE_4 B00010000 42 | #define TM1637_CHAR_SNAKE_5 B00100000 43 | 44 | #define TM1637_CHAR_BALL_HIGH B01100011 45 | #define TM1637_CHAR_BALL_LOW B01011100 46 | 47 | class SevenSegmentFun : public SevenSegmentExtended { 48 | public: 49 | SevenSegmentFun(uint8_t pinClk, uint8_t pinDIO); 50 | void printLevelVertical(uint8_t level, bool leftToRight = true); 51 | void printLevelVertical(uint8_t level, bool leftToRight, uint8_t symbol); 52 | void printLevelHorizontal(uint8_t levels[4]); 53 | void scrollingText(const char* str, uint8_t repeats); 54 | void snake(uint8_t repeats = 1, uint16_t d = TM1637_SNAKE_DEFAULT_DELAY); 55 | void nightrider(uint8_t repeats = 10, uint16_t d = TM1637_NIGHTRIDER_DEFAULT_DELAY, uint8_t symbol = TM1637_CHAR_VERT_LEVEL_II); 56 | void bombTimer(uint8_t hours, uint8_t min, uint16_t speed = 60); 57 | void bombTimer(uint8_t hours, uint8_t min, uint16_t speed, char* str); 58 | void bouncingBall(uint16_t moves, uint16_t d, bool runForever = false); 59 | void printBall(const int8_t x, const int8_t y); 60 | void print4Bit(const uint8_t x, const uint8_t y, uint8_t symbol); 61 | 62 | private: 63 | }; 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /examples/PrintNumber/PrintNumber.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Printing numbers example 3 | 4 | Demonstrate a couple different ways nubers can be printed: positive, negative, 5 | with padding and with rollover. 6 | 7 | 8 | The circuit: 9 | * connect TM1637 pin CLK to Arduino pin D4 10 | * connect TM1637 pin DIO to Arduino pin D5 11 | * connect TM1637 pin Vcc to Arduino pin 5V 12 | * connect TM1637 pin GND to Arduino pin GND 13 | 14 | Created 22 June 2020 15 | By Bram Harmsen 16 | 17 | https://github.com/bremme/arduino-tm1637 18 | 19 | */ 20 | 21 | // include the SevenSegmentTM1637 library 22 | #include "SevenSegmentTM1637.h" 23 | #include "SevenSegmentExtended.h" 24 | 25 | /* initialize global TM1637 Display object 26 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 27 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 28 | */ 29 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 30 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 31 | SevenSegmentExtended display(PIN_CLK, PIN_DIO); 32 | 33 | // run setup code 34 | void setup() { 35 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 36 | display.begin(); // initializes the display 37 | display.setBacklight(100); // set the brightness to 100 % 38 | display.print("INIT"); // display INIT on the display 39 | delay(1000); // wait 1000 ms 40 | }; 41 | 42 | // run loop (forever) 43 | void loop() { 44 | 45 | // print positive numbers 46 | display.print("PRINT POSITIVE NUMBERS"); 47 | delay(1000); // wait 1000 ms 48 | for (int16_t number=0; number < 2000; number++) { 49 | display.printNumber(number); 50 | delay(1); 51 | }; 52 | 53 | // print negative numbers 54 | display.print("PRINT NEGATIVE NUMBERS"); 55 | delay(1000); // wait 1000 ms 56 | for (int16_t number=0; number > -999; number--) { 57 | display.printNumber(number); 58 | delay(2); 59 | }; 60 | 61 | // print with positive with zero padding 62 | display.print("PRINT POSITIVE NUMBERS WITH PADDING"); 63 | delay(1000); // wait 1000 ms 64 | for (int16_t number=0; number < 2000; number++) { 65 | display.printNumber(number, true); 66 | delay(1); 67 | }; 68 | 69 | // print with rollover (e.g. 10000 -> 0, 10001 -> 1) 70 | display.print("PRINT POSITIVE NUMBERS WITH ROLLOVER"); 71 | delay(1000); // wait 1000 ms 72 | for (int16_t number=0; number < 20000; number+=250) { 73 | display.printNumber(number, false, true); 74 | delay(50); 75 | }; 76 | }; 77 | -------------------------------------------------------------------------------- /examples/SerialPrint/SerialPrint.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Serial Print example 3 | 4 | Prints text typed to the Serial Monitor on the display. Connect an Arduino to a TM1637 4 digit 7-segment display. Connect the wires as descibed below. Run the sketch and open the Serial Monitor. Set the the speed to 9600 baud, set the line ending to Newline. Now type some text and press enter, the text will be displayed on the 7-segment display. 5 | 6 | Note: make sure to set your serial monitor to line end: NEW LINE! 7 | 8 | The circuit: 9 | * connect TM1637 pin CLK to Arduino pin D4 10 | * connect TM1637 pin DIO to Arduino pin D5 11 | * connect TM1637 pin Vcc to Arduino pin 5V 12 | * connect TM1637 pin GND to Arduino pin GND 13 | 14 | Created 25 September 2015 15 | By Bram Harmsen 16 | 17 | http://url/of/online/tutorial.cc 18 | 19 | */ 20 | 21 | // include the SevenSegmentTM1637 library 22 | #include "SevenSegmentTM1637.h" 23 | 24 | /* initialize global TM1637 Display object 25 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 26 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 27 | */ 28 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 29 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 30 | SevenSegmentTM1637 display(PIN_CLK, PIN_DIO); 31 | 32 | // define a fixed buffer size for receiving characters via Serial 33 | const byte BUFFER_SIZE = 128; 34 | char serialBuffer[BUFFER_SIZE]; // initialize global serial buffer 35 | 36 | // run setup code 37 | void setup() { 38 | display.begin(); // initializes the display 39 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 40 | Serial.println(F("Enter some text followed by ENTER")); 41 | Serial.println(F("also make sure to set the line ending to Newline (\\n)")); 42 | }; 43 | 44 | // run loop (forever) 45 | void loop() { 46 | // if received new serial data, print to display 47 | if ( receivedSerialString() ) { 48 | display.print(serialBuffer); // Print received serial data to display 49 | Serial.print(F("Echo:\t")); // Echo serial data back to Serial Monitor 50 | Serial.println(serialBuffer); 51 | }; 52 | }; 53 | 54 | // Read in bytes from Serial Monitor and return true is ether the serialBuffer is full or a Newline character is received 55 | bool receivedSerialString() { 56 | static unsigned int i=0; // init static counter to keep track of count 57 | 58 | while( Serial.available() ) { // check if new data arrived 59 | 60 | if ( i == BUFFER_SIZE-1) { // if buffer is full RETURN true 61 | serialBuffer[i] = '\0'; // add termination char 62 | i = 0; 63 | Serial.println(F("Buffer full!")); 64 | return true; 65 | }; 66 | 67 | char c = Serial.read(); // read new char from serial port 68 | 69 | if ( c == '\n') { // if new line RETURN true 70 | serialBuffer[i] = '\0'; // add termination char 71 | i = 0; 72 | return true; 73 | } else { 74 | serialBuffer[i] = c; // add received character to buffer 75 | } 76 | i++; // increase counter 77 | }; 78 | return false; // default RETURN false 79 | }; 80 | -------------------------------------------------------------------------------- /examples/LowLevel/LowLevel.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Low level (advanced) example 3 | 4 | In this example the display is controlled by the low level command function. 5 | See SevenSegmentTM1637.h for more details on how the protocol actually works and which commands it accepts. 6 | 7 | The circuit: 8 | * connect TM1637 pin CLK to Arduino pin D4 9 | * connect TM1637 pin DIO to Arduino pin D5 10 | * connect TM1637 pin Vcc to Arduino pin 5V 11 | * connect TM1637 pin GND to Arduino pin GND 12 | 13 | Created 25 September 2015 14 | By Bram Harmsen 15 | 16 | https://github.com/bremme/arduino-tm1637 17 | 18 | */ 19 | 20 | // include the SevenSegmentTM1637 library 21 | #include "SevenSegmentTM1637.h" 22 | 23 | /* initialize global TM1637 Display object 24 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 25 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 26 | */ 27 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 28 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 29 | SevenSegmentTM1637 display(PIN_CLK, PIN_DIO); 30 | 31 | // run setup code 32 | void setup() { 33 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 34 | }; 35 | 36 | void loop() { 37 | // set brightness 38 | uint8_t setDisplayCmd = B10000000; // bit 6,7 39 | uint8_t brightnessBits = B111; // bit 0,1,2 (7 = max) 40 | uint8_t displayOnBit = B1000; // bit 3 41 | // construct complete command 42 | uint8_t command = setDisplayCmd | brightnessBits | displayOnBit; 43 | 44 | // turn display on and set brightness to max (7) 45 | bool ack = display.command(command); 46 | // print acknowledged? 47 | Serial.println(ack); 48 | 49 | // write init to display using automatic address 50 | uint8_t setDataCmd = B01000000; // bit 6,7 51 | ack = display.command(setDataCmd); 52 | Serial.println(ack); 53 | 54 | uint8_t setAddrCmd = B11000000; // bit 6,7 set addr to 0 55 | uint8_t dataI = B00000110; // I 56 | uint8_t dataN = B00110111; // N 57 | uint8_t dataT = B01111000; // T 58 | 59 | uint8_t commands[5]; 60 | commands[0] = setAddrCmd; 61 | commands[1] = dataI; 62 | commands[2] = dataN; 63 | commands[3] = dataI; 64 | commands[4] = dataT; 65 | 66 | ack = display.command(commands, 5); 67 | Serial.println(ack); 68 | delay(1000); 69 | 70 | // dim display 71 | brightnessBits = B001; // bit 0,1,2 level=1; 72 | command = setDisplayCmd | brightnessBits | displayOnBit; 73 | display.command(command); 74 | delay(1000); 75 | 76 | // set back to full brightness 77 | brightnessBits = B111; // bit 0,1,2 (7 = max) 78 | command = setDisplayCmd | brightnessBits | displayOnBit; 79 | display.command(command); 80 | delay(1000); 81 | 82 | // write characters to display in non auto mode 83 | setDataCmd |= 1 << 2; // bit 2 control auto/manual address 84 | ack = display.command(setDataCmd); 85 | Serial.println(ack); 86 | 87 | commands[1] = B01110111; 88 | commands[2] = B01111111; 89 | commands[3] = B00111001; 90 | commands[4] = B01011110; 91 | 92 | for (uint8_t i = 1; i < 5; i++) { 93 | commands[1] = commands[i]; // set character 94 | display.command(commands, 2); // write character to display 95 | commands[0]++; // increase address 96 | } 97 | delay(1000); 98 | 99 | // set back to auto address mode 100 | setDataCmd &= ~(1 << 2); // bit 2 control auto/manual address 101 | ack = display.command(setDataCmd); 102 | Serial.println(ack); 103 | 104 | // clear display 105 | commands[0] = setAddrCmd; 106 | commands[1] = 0; commands[2] = 0;commands[3] = 0; commands[4] = 0; 107 | 108 | // clear display 109 | display.command(commands, 5); 110 | delay(1000); 111 | } 112 | -------------------------------------------------------------------------------- /src/SevenSegmentExtended.cpp: -------------------------------------------------------------------------------- 1 | #include "SevenSegmentExtended.h" 2 | 3 | 4 | SevenSegmentExtended::SevenSegmentExtended(uint8_t pinClk, uint8_t pinDIO) : 5 | SevenSegmentTM1637(pinClk, pinDIO) 6 | { }; 7 | 8 | void SevenSegmentExtended::printTime(uint16_t t, bool blink, uint16_t blinkDelay) { 9 | uint16_t max = 2359; 10 | t = ( t > max)?max:t; 11 | 12 | uint8_t hour = t / 100; 13 | t -= (hour * 100); 14 | uint8_t min = t; 15 | printTime(hour, min, blink); 16 | }; 17 | 18 | void SevenSegmentExtended::printTime(uint8_t hour, uint8_t min, bool blink, uint16_t blinkDelay) { 19 | 20 | bool colonWasOn = getColonOn(); 21 | setColonOn(true); 22 | 23 | uint8_t buffer[4]; 24 | 25 | buffer[0] = encode(int16_t(hour / 10)); 26 | buffer[1] = encode(int16_t(hour % 10)); 27 | buffer[2] = encode(int16_t(min / 10)); 28 | buffer[3] = encode(int16_t(min % 10)); 29 | 30 | printRaw(buffer, 4, 0); 31 | 32 | // turn colon off and on again 33 | if (blink) { 34 | delay(blinkDelay); 35 | setColonOn(false); 36 | printRaw(buffer[1],1); 37 | delay(blinkDelay); 38 | setColonOn(true); 39 | printRaw(buffer[1],1); 40 | } 41 | 42 | setColonOn(colonWasOn); 43 | 44 | }; 45 | 46 | void SevenSegmentExtended::printNumber(int16_t number, bool zeroPadding, bool rollOver, bool alignRight) { 47 | const int16_t maxNumber = 9999; 48 | const int16_t minNumber = -999; 49 | bool positive = true; 50 | 51 | // get and store sign 52 | if (number < 0) { 53 | positive = false; 54 | }; 55 | 56 | // roll over if rollOver is set to true 57 | if (rollOver == true) { 58 | if (positive == true) { 59 | number = number % int16_t(10000); 60 | } else { 61 | number = -1 * ((-1 * number) % 1000); 62 | } 63 | // limit number by default 64 | } else { 65 | number = number > maxNumber?maxNumber:number; 66 | number = number < minNumber?minNumber:number; 67 | } 68 | 69 | // clear the display first 70 | clear(); 71 | 72 | // align left is the default behavior, just forward to print 73 | if (alignRight == false) { 74 | print(number); 75 | return; 76 | } 77 | 78 | if (positive == false) { 79 | number *= -1; 80 | print("-"); 81 | } 82 | 83 | if (number > 999) { 84 | setCursor(0, 0); 85 | } else if (number > 99) { 86 | if (zeroPadding == true) {print('0');} 87 | setCursor(0, 1); 88 | } else if (number > 9) { 89 | if (zeroPadding == true) {print(F("00"));} 90 | setCursor(0, 2); 91 | } else { 92 | if (zeroPadding == true) {print(F("000"));} 93 | setCursor(0, 3); 94 | }; 95 | 96 | print(number); 97 | }; 98 | 99 | // positive counter 0..99, negative counter 0..-9 100 | void SevenSegmentExtended::printDualCounter(int8_t leftCounter, int8_t rightCounter, bool zeroPadding) { 101 | 102 | int8_t max = 99; 103 | int8_t min = -9; 104 | uint8_t zeroByte = encode('0'); 105 | 106 | leftCounter = (leftCounter > max)?max:leftCounter; 107 | leftCounter = (leftCounter < min)?min:leftCounter; 108 | rightCounter = (rightCounter > max)?max:rightCounter; 109 | rightCounter = (rightCounter < min)?min:rightCounter; 110 | 111 | bool colonWasOn = getColonOn(); // get current state 112 | setColonOn(true); // turn on the colon 113 | home(); // set cursor to zero 114 | 115 | if ( leftCounter < 10 && leftCounter >= 0) { 116 | if ( zeroPadding ) { 117 | printRaw(zeroByte,1); 118 | setCursor(0,1); 119 | } else { 120 | // print colon 121 | printRaw(TM1637_COLON_BIT,1); 122 | }; 123 | }; 124 | print(leftCounter); 125 | 126 | if ( rightCounter < 10 && rightCounter >= 0) { 127 | if ( zeroPadding ) { 128 | printRaw(zeroByte,2); 129 | } 130 | uint8_t pos = 2; 131 | printRaw(0,pos); 132 | setCursor(0,3); 133 | } else { 134 | setCursor(0,2); 135 | } 136 | print(rightCounter); 137 | 138 | // set to previous state 139 | setColonOn(colonWasOn); 140 | }; 141 | -------------------------------------------------------------------------------- /examples/ExtScoreboard/ExtScoreboard.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Dual counter example (Extended class example) 3 | 4 | You could do many things with a dual counter. This example demoonstrates a scoreboard. Two players rol a dice every round, the player with the highest score wins the round. The number of rounds won are displayed on the scoreboard. Once one of the players reaches a maximum score the game is over. At the end of the game a player won message or draw will be displayed. 5 | 6 | The circuit: 7 | * connect TM1637 pin CLK to Arduino pin D4 8 | * connect TM1637 pin DIO to Arduino pin D5 9 | * connect TM1637 pin Vcc to Arduino pin 5V 10 | * connect TM1637 pin GND to Arduino pin GND 11 | 12 | Created 25 September 2015 13 | By Bram Harmsen 14 | 15 | https://github.com/bremme/arduino-tm1637 16 | 17 | */ 18 | 19 | // include the SevenSegmentTM1637 library 20 | #include "SevenSegmentTM1637.h" 21 | #include "SevenSegmentExtended.h" 22 | 23 | /* initialize global TM1637 Display object 24 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 25 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 26 | */ 27 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 28 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 29 | SevenSegmentExtended display(PIN_CLK, PIN_DIO); 30 | 31 | // sets the maximum score for the game 32 | const byte maxScore = 10; 33 | 34 | // run setup code 35 | void setup() { 36 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 37 | display.begin(); // initializes the display 38 | display.setBacklight(100); // set the brightness to 100 % 39 | delay(1000); // wait 1000 ms 40 | randomSeed(analogRead(0)); // get a random seed for throwing dices 41 | }; 42 | 43 | // run loop (forever) 44 | void loop() { 45 | 46 | byte playerOneScore = 0; // initialize player one score 47 | byte playerTwoScore = 0; // initialize player two score 48 | bool gameEnd = false; // initialize gameEnd? 49 | 50 | display.print("START NEW GAME "); // Start a new round 51 | delay(500); // delay 1000 ms 52 | display.clear(); // clear the display 53 | 54 | while( !gameEnd ) { // play till the end of the game 55 | 56 | byte playerOneTurn = rollDice(); // player one rolls a dice 57 | byte playerTwoTurn = rollDice(); // player two rolls a dice 58 | 59 | if ( playerOneTurn > playerTwoTurn ) { // player one had a higher dice 60 | playerOneScore++; // increase player one's score 61 | } else if ( playerOneTurn < playerTwoTurn ){ 62 | playerTwoScore++; // increase player two's score 63 | } else { // player one and two had same score 64 | display.clear(); 65 | display.print("SAME"); 66 | display.blink(); 67 | display.clear(); 68 | } 69 | // update scoreboard 70 | display.printDualCounter(playerOneScore, playerTwoScore); 71 | delay(500); 72 | 73 | // check if game has ended (player one or two's score >= maxScore) 74 | if ( (playerOneScore >= maxScore || playerTwoScore >= maxScore) ) { 75 | gameEnd = true; // game has ended 76 | printGameEnd(); // print end game message 77 | break; // break from while loop (jump out) 78 | }; 79 | 80 | }; 81 | 82 | // check who won 83 | if ( playerOneScore > playerTwoScore ) { 84 | printPlayerWon(1); // player one won 85 | } else if ( playerOneScore < playerTwoScore ){ 86 | printPlayerWon(2); // player two won 87 | } else { 88 | display.clear(); display.print("DRAW"); // draw 89 | display.blink(); display.clear(); 90 | }; 91 | }; 92 | 93 | // roll a dice: random rumber fom 0 to 5 + 1 = 0 to 6 94 | byte rollDice() { 95 | return (random(6) + 1); 96 | } 97 | 98 | // print winning player message 99 | void printPlayerWon(byte player) { 100 | display.clear(); 101 | char winText[] = "PLAYER x WON "; 102 | winText[7] = (char)player + '0'; 103 | display.print(winText); 104 | delay(500); 105 | display.clear(); 106 | }; 107 | 108 | // print end game message 109 | void printGameEnd(void) { 110 | display.clear(); 111 | display.print("GAME END "); 112 | display.blink(); 113 | delay(500); 114 | }; 115 | -------------------------------------------------------------------------------- /examples/FunPrintAll/FunPrintAll.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Fun Print all example 3 | 4 | This is a demonstration off a lot of the possibilities of the Fun superclass 5 | 6 | The circuit: 7 | * connect TM1637 pin CLK to Arduino pin D4 8 | * connect TM1637 pin DIO to Arduino pin D5 9 | * connect TM1637 pin Vcc to Arduino pin 5V 10 | * connect TM1637 pin GND to Arduino pin GND 11 | 12 | Created 25 September 2015 13 | By Bram Harmsen 14 | 15 | https://github.com/bremme/arduino-tm1637 16 | 17 | */ 18 | 19 | // include the SevenSegmentTM1637 library 20 | #include "SevenSegmentTM1637.h" 21 | #include "SevenSegmentExtended.h" 22 | #include "SevenSegmentFun.h" 23 | 24 | /* initialize global TM1637 Display object 25 | * The constructor takes two arguments, the number of the clock pin and the digital output pin: 26 | * SevenSegmentTM1637(byte pinCLK, byte pinDIO); 27 | */ 28 | const byte PIN_CLK = 4; // define CLK pin (any digital pin) 29 | const byte PIN_DIO = 5; // define DIO pin (any digital pin) 30 | SevenSegmentFun display(PIN_CLK, PIN_DIO); 31 | 32 | 33 | // run setup code 34 | void setup() { 35 | Serial.begin(9600); // initializes the Serial connection @ 9600 baud 36 | display.begin(); // initializes the display 37 | display.setBacklight(100); // set the brightness to 100 % 38 | delay(1000); // wait 1000 ms 39 | }; 40 | 41 | // run loop (forever) 42 | void loop() { 43 | 44 | // vertical level (e.g. audio volume) 45 | introDuceNextDemo("AUDIO VOLUME DEMO"); 46 | audioVolume(); 47 | 48 | // bouncing ball 49 | introDuceNextDemo("BOUNCING BALL DEMO"); 50 | unsigned int numMoves = 100; unsigned int timeDelay = 100; 51 | display.bouncingBall(numMoves, timeDelay); 52 | 53 | // scrolling text 54 | introDuceNextDemo("SCROLLING TEXT DEMO"); 55 | byte repeats = 2; 56 | display.scrollingText("ARDUINO TM1637 FUN", repeats); 57 | 58 | // nightrider 59 | introDuceNextDemo("REMEMBER KIT? NIGHTRIDER DEMO"); 60 | repeats = 4; 61 | display.nightrider(repeats); 62 | 63 | // snake 64 | introDuceNextDemo("SNAKE DEMO"); 65 | display.snake(repeats); 66 | 67 | // horizontal level (e.g equalizer) 68 | introDuceNextDemo("EQUALIZER DEMO"); 69 | equalizer(); 70 | 71 | // bomb timer 72 | introDuceNextDemo("GET READY FOR THE BOMB"); 73 | byte hours = 5; byte min = 16; unsigned int speed = 10000; 74 | display.bombTimer(hours, min, speed, " RUN "); 75 | delay(1000);; 76 | }; 77 | 78 | // Demo for displaying a vertical level, for example audio volume, battery charge etc. 79 | void audioVolume() { 80 | 81 | for (byte repeats=0; repeats < 2; repeats++) { 82 | for (byte level=0; level < 125; level+=25) { 83 | display.printLevelVertical(level); 84 | delay(200); 85 | }; 86 | for (byte level=100; level != 0; level-=25) { 87 | display.printLevelVertical(level); 88 | delay(200); 89 | }; 90 | } 91 | 92 | // maybe try another symbol instead of default | | 93 | byte symbol = display.encode((byte)0); 94 | bool leftToRight = false; // print the other direction 95 | 96 | 97 | for (byte repeats=0; repeats < 2; repeats++) { 98 | for (byte level=0; level < 125; level+=25) { 99 | display.printLevelVertical(level, leftToRight, symbol); 100 | delay(200); 101 | if ( level == 100 ) { 102 | display.blink(); 103 | } 104 | }; 105 | for (byte level=100; level != 0; level-=25) { 106 | display.printLevelVertical(level, leftToRight, symbol); 107 | delay(200); 108 | }; 109 | } 110 | // 0, 25, 50, 75, 100 111 | 112 | } 113 | 114 | void equalizer() { 115 | // initialize horizontal level counters 116 | char i,j,k,l; 117 | byte levels[4]; 118 | 119 | // repeat 5 times 120 | for ( byte r=0; r < 4; r++) { 121 | // increae i and k, decrease j and l 122 | for (i=0,j=100,k=0,l=100; i <= 100; i+=33, j-=33, k+=33, l-=33) { 123 | levels[0] = i; levels[1] = j; levels[2] = k; levels[3] = l; 124 | display.printLevelHorizontal(levels); 125 | delay(100); 126 | } 127 | // increae j and l, decrease i and k 128 | for (i=100,j=0,k=100,l=0; i >= 0; i-=33, j+=33, k-=33, l+=33) { 129 | levels[0] = i; levels[1] = j; levels[2] = k; levels[3] = l; 130 | display.printLevelHorizontal(levels); 131 | delay(100); 132 | } 133 | } 134 | } 135 | 136 | void introDuceNextDemo(char* str) { 137 | display.print(str); 138 | delay(500); 139 | } 140 | -------------------------------------------------------------------------------- /src/SevenSegmentAsciiMap.h: -------------------------------------------------------------------------------- 1 | #ifndef SevenSegmentAsciiMap_H 2 | #define SevenSegmentAsciiMap_H 3 | 4 | #include 5 | 6 | // ASCII MAPPINGS 7 | #define TM1637_CHAR_SPACE B00000000 // 32 (ASCII) 8 | #define TM1637_CHAR_EXC B00000110 9 | #define TM1637_CHAR_D_QUOTE B00100010 10 | #define TM1637_CHAR_POUND B01110110 11 | #define TM1637_CHAR_DOLLAR B01101101 12 | #define TM1637_CHAR_PERC B00100100 13 | #define TM1637_CHAR_AMP B01111111 14 | #define TM1637_CHAR_S_QUOTE B00100000 15 | #define TM1637_CHAR_L_BRACKET B00111001 16 | #define TM1637_CHAR_R_BRACKET B00001111 17 | #define TM1637_CHAR_STAR B01011100 18 | #define TM1637_CHAR_PLUS B01010000 19 | #define TM1637_CHAR_COMMA B00010000 20 | #define TM1637_CHAR_MIN B01000000 21 | #define TM1637_CHAR_DOT B00001000 22 | #define TM1637_CHAR_F_SLASH B00000110 23 | #define TM1637_CHAR_0 B00111111 // 48 24 | #define TM1637_CHAR_1 B00000110 25 | #define TM1637_CHAR_2 B01011011 26 | #define TM1637_CHAR_3 B01001111 27 | #define TM1637_CHAR_4 B01100110 28 | #define TM1637_CHAR_5 B01101101 29 | #define TM1637_CHAR_6 B01111101 30 | #define TM1637_CHAR_7 B00000111 31 | #define TM1637_CHAR_8 B01111111 32 | #define TM1637_CHAR_9 B01101111 33 | #define TM1637_CHAR_COLON B00110000 34 | #define TM1637_CHAR_S_COLON B00110000 35 | #define TM1637_CHAR_LESS B01011000 36 | #define TM1637_CHAR_EQUAL B01001000 37 | #define TM1637_CHAR_GREAT B01001100 38 | #define TM1637_CHAR_QUEST B01010011 39 | #define TM1637_CHAR_AT B01011111 40 | #define TM1637_CHAR_A B01110111 // 65 (ASCII) 41 | #define TM1637_CHAR_B B01111111 42 | #define TM1637_CHAR_C B00111001 43 | #define TM1637_CHAR_D TM1637_CHAR_d 44 | #define TM1637_CHAR_E B01111001 45 | #define TM1637_CHAR_F B01110001 46 | #define TM1637_CHAR_G B00111101 47 | #define TM1637_CHAR_H B01110110 48 | #define TM1637_CHAR_I B00000110 49 | #define TM1637_CHAR_J B00001110 50 | #define TM1637_CHAR_K B01110101 51 | #define TM1637_CHAR_L B00111000 52 | #define TM1637_CHAR_M B00010101 53 | #define TM1637_CHAR_N B00110111 54 | #define TM1637_CHAR_O B00111111 55 | #define TM1637_CHAR_P B01110011 56 | #define TM1637_CHAR_Q B01100111 57 | #define TM1637_CHAR_R B00110011 58 | #define TM1637_CHAR_S B01101101 59 | #define TM1637_CHAR_T TM1637_CHAR_t 60 | #define TM1637_CHAR_U B00111110 61 | #define TM1637_CHAR_V B00011100 62 | #define TM1637_CHAR_W B00101010 63 | #define TM1637_CHAR_X TM1637_CHAR_H 64 | #define TM1637_CHAR_Y B01101110 65 | #define TM1637_CHAR_Z B01011011 66 | #define TM1637_CHAR_L_S_BRACKET B00111001 // 91 (ASCII) 67 | #define TM1637_CHAR_B_SLASH B00110000 68 | #define TM1637_CHAR_R_S_BRACKET B00001111 69 | #define TM1637_CHAR_A_CIRCUM B00010011 70 | #define TM1637_CHAR_UNDERSCORE B00001000 71 | #define TM1637_CHAR_A_GRAVE B00010000 72 | #define TM1637_CHAR_a B01011111 // 97 (ASCII) 73 | #define TM1637_CHAR_b B01111100 74 | #define TM1637_CHAR_c B01011000 75 | #define TM1637_CHAR_d B01011110 76 | #define TM1637_CHAR_e B01111011 77 | #define TM1637_CHAR_f TM1637_CHAR_F 78 | #define TM1637_CHAR_g B01101111 79 | #define TM1637_CHAR_h B01110100 80 | #define TM1637_CHAR_i B00000100 81 | #define TM1637_CHAR_j B00001100 82 | #define TM1637_CHAR_k TM1637_CHAR_K 83 | #define TM1637_CHAR_l B00110000 84 | #define TM1637_CHAR_m TM1637_CHAR_M 85 | #define TM1637_CHAR_n B01010100 86 | #define TM1637_CHAR_o B01011100 87 | #define TM1637_CHAR_p TM1637_CHAR_P 88 | #define TM1637_CHAR_q TM1637_CHAR_Q 89 | #define TM1637_CHAR_r B01010000 90 | #define TM1637_CHAR_s TM1637_CHAR_S 91 | #define TM1637_CHAR_t B01111000 92 | #define TM1637_CHAR_u B00011100 93 | #define TM1637_CHAR_v B00011100 94 | #define TM1637_CHAR_w TM1637_CHAR_W 95 | #define TM1637_CHAR_x TM1637_CHAR_X 96 | #define TM1637_CHAR_y B01100110 97 | #define TM1637_CHAR_z TM1637_CHAR_Z 98 | #define TM1637_CHAR_L_ACCON B01111001 // 123 (ASCII) 99 | #define TM1637_CHAR_BAR B00000110 100 | #define TM1637_CHAR_R_ACCON B01001111 101 | #define TM1637_CHAR_TILDE B01000000 // 126 (ASCII) 102 | 103 | class AsciiMap { 104 | public: 105 | const static uint8_t map[96]; 106 | }; 107 | // static const uint8_t asciiMap[96]; 108 | 109 | #endif -------------------------------------------------------------------------------- /src/SevenSegmentFun.cpp: -------------------------------------------------------------------------------- 1 | #include "SevenSegmentFun.h" 2 | 3 | const PROGMEM uint8_t levelVerticalMap[4] = { 4 | TM1637_CHAR_HOR_LEVEL_0, 5 | TM1637_CHAR_HOR_LEVEL_1, 6 | TM1637_CHAR_HOR_LEVEL_2, 7 | TM1637_CHAR_HOR_LEVEL_3 8 | }; 9 | 10 | SevenSegmentFun::SevenSegmentFun(uint8_t pinClk, uint8_t pinDIO) : 11 | SevenSegmentExtended(pinClk, pinDIO) 12 | { 13 | randomSeed(analogRead(0)); 14 | }; 15 | 16 | // 9 levels ( 0, 12.5, 25, 37.4, 50, 62.5, 75.0, 87.5, 100) 17 | void SevenSegmentFun::printLevelVertical(uint8_t level, bool leftToRight) { 18 | 19 | level = (level > 100?100:level); 20 | float levelScale = (100 / (TM1637_MAX_COLOM * 2.0)); 21 | 22 | uint8_t barsOn = float(level) / levelScale; 23 | 24 | uint8_t d = leftToRight == true?0:TM1637_MAX_COLOM-1; 25 | 26 | for (uint8_t i=0; i < TM1637_MAX_COLOM; i++) { 27 | if (barsOn - (2 * (i + 1)) >= 0) { 28 | _rawBuffer[d] = TM1637_CHAR_VERT_LEVEL_II; 29 | } else if (barsOn - (2 * (i + 1)) >= 1) { 30 | _rawBuffer[d] = (leftToRight == true)?TM1637_CHAR_VERT_LEVEL_I0:TM1637_CHAR_VERT_LEVEL_0I; 31 | } else { 32 | _rawBuffer[d] = 0; 33 | } 34 | if (leftToRight == true) {d++;} 35 | else {d--;}; 36 | }; 37 | printRaw(_rawBuffer, TM1637_MAX_COLOM, 0); 38 | }; 39 | 40 | 41 | void SevenSegmentFun::printLevelVertical(uint8_t level, bool leftToRight, uint8_t symbol) { 42 | level /= (100 / TM1637_MAX_COLOM); 43 | level = (level > TM1637_MAX_COLOM)?TM1637_MAX_COLOM:level; 44 | 45 | for( uint8_t i=0; i < TM1637_MAX_COLOM;i++) { 46 | if ( ( i < level && leftToRight ) || ( i >= ( TM1637_MAX_COLOM - level ) && !leftToRight) ) { 47 | _rawBuffer[i] = symbol; 48 | } else { 49 | _rawBuffer[i] = 0; 50 | } 51 | }; 52 | 53 | printRaw(_rawBuffer, TM1637_MAX_COLOM, 0); 54 | 55 | }; 56 | 57 | void SevenSegmentFun::nightrider(uint8_t repeats, uint16_t d, uint8_t symbol) { 58 | 59 | uint8_t buffer[((TM1637_MAX_COLOM * 2) - 1)] = {0, }; 60 | 61 | for ( uint8_t i= 0; i < ((TM1637_MAX_COLOM * 2) - 1); i++) { 62 | if ( i == (TM1637_MAX_COLOM - 1) ) { 63 | buffer[i] = symbol; 64 | } else { 65 | buffer[i] = 0; 66 | } 67 | }; 68 | 69 | for( int8_t r=0; r < repeats; r++) { 70 | for (int8_t i = (TM1637_MAX_COLOM - 1); i > 0; i--) { 71 | printRaw( &buffer[i],4,0); 72 | delay(d); 73 | }; 74 | for ( int8_t i = 0; i < (TM1637_MAX_COLOM - 1); i++) { 75 | printRaw( &buffer[i], TM1637_MAX_COLOM, 0); 76 | delay(d); 77 | }; 78 | } 79 | } 80 | // 5 levels ( 0, 33, 66, 100) 81 | void SevenSegmentFun::printLevelHorizontal( uint8_t levels[4] ) { 82 | for (uint8_t i=0; i < TM1637_MAX_COLOM;i++) { 83 | levels[i] /= (100 / 3); 84 | levels[i] = ( levels[i] > 3)?3:levels[i]; 85 | _rawBuffer[i] = pgm_read_byte_near(levelVerticalMap + levels[i]); 86 | }; 87 | printRaw(_rawBuffer, TM1637_MAX_COLOM, 0); 88 | } 89 | 90 | void SevenSegmentFun::scrollingText(const char* str, uint8_t repeats) { 91 | 92 | uint8_t buffer[TM1637_MAX_CHARS]; 93 | 94 | size_t length = encode(&buffer[3], str, TM1637_MAX_CHARS); 95 | 96 | uint8_t paddingBegin = TM1637_MAX_COLOM - 1; 97 | uint8_t totalPadding = (2 * paddingBegin) + 1; 98 | 99 | // padd with three spaces in front 100 | for(uint8_t i=0; i < paddingBegin; i++) { 101 | buffer[i] = 0; 102 | }; 103 | // padd with four spaces at the end (empty scree) 104 | for(uint8_t i = length + paddingBegin; i < length + totalPadding ; i++) { 105 | buffer[i] = 0; 106 | }; 107 | 108 | for( ; repeats != 0; repeats--) { 109 | printRaw(buffer, length + totalPadding); 110 | if ( repeats > 250 ) { // more than 250 -> forever 111 | repeats++; 112 | } 113 | }; 114 | } 115 | 116 | void SevenSegmentFun::snake(uint8_t repeats, uint16_t d) { 117 | 118 | uint8_t outerEdges = (4 * TM1637_MAX_LINES) + (TM1637_MAX_COLOM * 2); 119 | uint8_t widthEdged = (TM1637_MAX_COLOM * 2); 120 | 121 | // number of repeats/rounds 122 | for ( uint8_t r=0; r < repeats; r++) { 123 | // 12 steps for all outer edges 124 | for (uint8_t i=0; i < outerEdges; i++) { 125 | for (uint8_t j=0; j < TM1637_MAX_COLOM; j++) { 126 | 127 | // set segments 128 | // top edges 129 | if ( i == j) { 130 | _rawBuffer[j] =TM1637_CHAR_SNAKE_0; 131 | } 132 | // top right edge 133 | else if ( i == TM1637_MAX_COLOM && j == 3) { 134 | _rawBuffer[j] =TM1637_CHAR_SNAKE_1; 135 | } 136 | // bottom left edge 137 | else if ( i == (TM1637_MAX_COLOM + 1) && j == 3) { 138 | _rawBuffer[j] =TM1637_CHAR_SNAKE_2; 139 | } 140 | // bottom edges 141 | else if ( i + j == (widthEdged + 1) ) { 142 | _rawBuffer[j] =TM1637_CHAR_SNAKE_3; 143 | } 144 | // bottom left edge 145 | else if ( i == (widthEdged + 2) && j == 0) { 146 | _rawBuffer[j] =TM1637_CHAR_SNAKE_4; 147 | } 148 | // top left edge 149 | else if ( i == (widthEdged + 3) && j == 0) { 150 | _rawBuffer[j] =TM1637_CHAR_SNAKE_5; 151 | } else { 152 | _rawBuffer[j] = 0; 153 | }; 154 | }; 155 | printRaw(_rawBuffer, 4, 0); 156 | delay(d); 157 | } 158 | 159 | }; 160 | } 161 | 162 | void SevenSegmentFun::bombTimer(uint8_t hours, uint8_t min, uint16_t speed) { 163 | 164 | // maximum speed is 60000 -> 1min per ms 165 | speed = (speed > 60000)?60000:speed; 166 | uint16_t d = 60000 / speed; 167 | 168 | // copy start minute 169 | int8_t m = min; 170 | int8_t h; 171 | for ( h=hours; h >= 0; h--) { 172 | for ( ; m >= 0; m--) { 173 | printTime((uint8_t)h, (uint8_t)m); 174 | delay(d); 175 | }; 176 | m = 59; // reset minute timer 177 | }; 178 | blink(); 179 | }; 180 | 181 | void SevenSegmentFun::bombTimer(uint8_t hours, uint8_t min, uint16_t speed, char* str) { 182 | bombTimer(hours, min, speed); 183 | print(str); 184 | blink(); 185 | }; 186 | 187 | void SevenSegmentFun::bouncingBall(uint16_t moves, uint16_t d, bool runForever) { 188 | 189 | int8_t wallRight = TM1637_MAX_COLOM - 1; 190 | int8_t wallBottom = TM1637_MAX_LINES; 191 | 192 | // start at top left 193 | int8_t x = 0; int8_t y = 0; 194 | int8_t newX; int8_t newY; 195 | // default speed is 1 x right and 2 y down 196 | int8_t vx = 1; int8_t vy = 1; 197 | bool flipVx = false; bool flipVy = false; 198 | 199 | // print initial state 200 | printBall(x, y); 201 | 202 | for ( ; moves != 0; moves--) { 203 | 204 | newX = x + vx; 205 | newY = y + vy; 206 | 207 | // check if ball has hit the wall 208 | if (newX > wallRight || newX < 0 ) { 209 | vx = vx * -1; 210 | newX = x + vx; 211 | // random flip other direction as well 212 | flipVy = (random(3) == 1); 213 | }; 214 | 215 | if ( newY > wallBottom || newY < 0) { 216 | vy = vy * -1; 217 | newY = y + vy; 218 | // random flip other direction as well 219 | flipVx = (random(3) == 1); 220 | }; 221 | 222 | if ( flipVy ) { 223 | newY = y; 224 | } else if ( flipVx ) { 225 | newX = x; 226 | }; 227 | // set new coordinates 228 | x = newX; y = newY; 229 | 230 | printBall(x, y); 231 | delay(d); 232 | 233 | if (runForever) { 234 | moves++; 235 | }; 236 | }; 237 | } 238 | 239 | void SevenSegmentFun::printBall( const int8_t x, const int8_t y ) { 240 | // uint8_t buffer[4] = {0,0,0,0}; 241 | // buffer[x] = (y > 0)?TM1637_CHAR_BALL_LOW:TM1637_CHAR_BALL_HIGH; 242 | // printRaw(buffer); 243 | 244 | uint8_t symbol = (y > 0)?TM1637_CHAR_BALL_LOW:TM1637_CHAR_BALL_HIGH; 245 | 246 | print4Bit(x, y, symbol); 247 | 248 | }; 249 | 250 | void SevenSegmentFun::print4Bit( const uint8_t x, const uint8_t y, uint8_t symbol) { 251 | uint8_t buffer[4] = {0,0,0,0}; 252 | buffer[x] = symbol; 253 | printRaw(buffer); 254 | } 255 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SevenSegmentTM1637 Arduino Library 2 | 3 | * master  [![Build Status](https://travis-ci.org/bremme/arduino-tm1637.svg?branch=master)](https://travis-ci.org/bremme/arduino-tm1637) 4 | * develop [![Build Status](https://travis-ci.org/bremme/arduino-tm1637.svg?branch=develop)](https://travis-ci.org/bremme/arduino-tm1637) 5 | 6 | 7 | Arduino library for controlling a TM163x based 7-segment display module. These modules are sold under various names by various suppliers. For example: 8 | 9 | * [Seed Studio: Grove 4 digit display](http://www.seeedstudio.com/depot/grove-4digit-display-p-1198.html) 10 | * [Ebay: 4 Bits Digital Tube LED TM1637](http://www.ebay.com/sch/i.html?_odkw=4+Bits+Digital+Tube+LED&_osacat=0&_from=R40&_trksid=p2045573.m570.l1313.TR0.TRC0.H0.X4+Bits+Digital+Tube+LED+TM1637.TRS0&_nkw=4+Bits+Digital+Tube+LED+TM1637&_sacat=0) 11 | * [DealExtreme: LED 4-Digit Display Module](http://www.dx.com/s/TM1637) 12 | 13 | They come in different sizes, colors and there is a clock (with a colon) and decimal (with four decimal dots) display variant. But the most common one is the red 0.36" clock version, this is also the cheapest one (you can get those for about $1.50). I've written this library using the above module, if I get my hands on any of the other variants I might add some specific code, for example to print floats on the decimal version. 14 | 15 | ![TM1637](extras/img/TM1637-4-digit-colon.jpg) 16 | 17 | # Hardware setup 18 | 19 | | TM1637 PIN | Arduino PIN | Description | 20 | |------------|------------------|---------------------| 21 | | CLK | Any digital pin | Clock | 22 | | DIO | Any digital pin | Digital output | 23 | | VCC | 5V | Supply voltage | 24 | | GND | GND | Ground | 25 | 26 | 27 | # Installation 28 | 29 | Like any other Arduino library this library is installed by copying the files into a directory on the Arduino IDE search path. Most common is to put all files in a director in `your sketch folder/libraries/SevenSegmentTM1637/`. See [installing additional Arduino libraries](https://www.arduino.cc/en/Guide/Libraries) for more information. 30 | 31 | # Usage 32 | 33 | This library uses the [LCD API v1.0](http://playground.arduino.cc/Code/LCDAPI) so you can use the same functions/methods using this library as any lcd library which conforms to the LCD API. Furthermore this library (like described in the LCD API) inherent the Print class (See [Serial.print()](https://www.arduino.cc/en/Serial/Print) and for more details [Print.h](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h)). This means that you can use all Print class functions/methods like you're used to when you're doing `Serial.print("Something")` or `Serial.print(128, BIN)` for example. 34 | 35 | ## Basic methods 36 | 37 | * `SevenSegmentTM1637(clkPin, dioPin)`Creates a display object 38 | * `init()` Initializes the display 39 | * `print(value)` Prints anything to the display (e.g. a string, number..) 40 | * `clear()` Clears the display (and resets cursor) 41 | * `home()` Resets cursor 42 | * `setCursor(row, col)` Set the cursor to specified position 43 | * `setBacklight(value)` Sets the brightness of the display 44 | * `on()` Turn the display on (set brightness to default) 45 | * `off()` Turns the display off (set brightness to zero) 46 | * `blink()` Blinks what ever is on the display 47 | * `setColonOn(bool)` Sets the colon in the middle of the display 48 | * `setPrintDelay(time)` Sets the delay when printing more than 4 characters 49 | 50 | ## Advanced methods 51 | 52 | * `encode()` Encodes a single digit, single char or char array (C string) 53 | * `printRaw()` Prints raw byte(s) to the display 54 | * `command()` Sends one or more raw byte commands to the display 55 | 56 | ## Low level methods 57 | 58 | * `comStart()` Serial communication start command 59 | * `comWriteByte(bytes)` Serial communication send byte command 60 | * `comAck()` Serial communication get acknowledged command 61 | * `comStop()` Serial communication stop command 62 | 63 | If you still want or need more functionality, I've included two super classes: 64 | 65 | * `SevenSegmentExtended()` Extends the base class with more usefull functions. 66 | * `SevenSegmentFun()` Even more extensions for fun. 67 | 68 | If you use any of these super classes, you will also get all the basic, advanced and low level methods as well. If you use the fun class extension you will get the extended class methods as well. 69 | 70 | ## Extended class extra methods 71 | 72 | * `SevenSegmentExtended(clkPin, dioPin)` Creates a display object 73 | * `printTime(hour, min, [blink], [blinkDelay])` Prints the time to the display 74 | * `printTime(time, [blink], [blinkDelay])` Prints the time to the display 75 | * `printDualCounter(leftValue, rightValue)` Prints two digits to the display 76 | 77 | ## Fun class extra methods 78 | 79 | * `SevenSegmentFun(clkPin, dioPin)` Creates a display object 80 | * `printLevelVertical(level, [leftToRight])` Print 0-100% (2 steps per digit) vertical level e.g. volume, battery 81 | * `printLevelVertical(level, leftToRight, symbol)` Print 0-100% (1 step per digit) vertical level using custom symbol 82 | * `printLevelHorizontal(levels[])` Prints 4 horizontal levels e.g. equalizer 83 | * `scrollingText()` Prints text and (keeps) scrolling 84 | * `snake()` Classic snake demo 85 | * `nightrider()` Nightrider Kit demo 86 | * `bombTimer()` Count down a (bomb) timer 87 | * `bouncingBall()` Bouncing ball demo 88 | 89 | For more extended information on what arguments all above functions accept and return see the header files of the classes (SevenSegmentTM1637.h, SevenSegmentExtended.h and SevenSegmentFun.h). 90 | 91 | # Trouble shooting 92 | 93 | * Some boards might not have enough power on their 5V pin. In that case try to use an external 5V power supply. People reported that the ESP8266 might be one of those boards. 94 | 95 | # Todo 96 | 97 | * Refactor library to make it more modular and support more chips 98 | + Add support for all TM16xx chips (most should already work) 99 | + Add support for MAX7219 displays 100 | + Add support for TM74HC595 displays 101 | 102 | # Changelog 103 | 104 | + 09-07-2020 version 1.1.1 105 | + Bug fixes 106 | + fixed a typo in SevenSegmentFun.h file 107 | + 04-07-2020 version 1.1.0 108 | + Improved `printLevelVertical()` using [pablo-lp](https://github.com/pablo-lp) suggestions 109 | + The default `printLevelVertical()` can diplay twice the number of levels now (e.g. 9 levels for a defaulf 4 digit display) 110 | + Add configurable blink delay when using the `printTime` methods (thanks to [simoneluconi](https://github.com/simoneluconi)) 111 | + Added a new `printNumber()` method to make it easier to print right aligned numbers 112 | + Thanks [dan2600](https://github.com/dan2600), [Bilick88](https://github.com/Bilick88), [jasonacox](https://github.com/jasonacox) for your suggestions. 113 | + Bug fixes 114 | + Merge PR from [berendkleinhaneveld](https://github.com/berendkleinhaneveld) to fix some compiler warnings 115 | + Merge PR from [facelessloser](https://github.com/facelessloser) Remove some `Serial.prinln()` calls 116 | + Merge PR from [RAnders00](https://github.com/RAnders00) Fix incorrect repsonse from `comReadByte()` 117 | + Merge PR from [per1234](https://github.com/per1234) Use correct separator in `keywords.txt` 118 | + 04-11-2016 version 1.0.4 119 | + Fixed bombTimer not counting down to zero (thanks to [foons](https://github.com/fooons) for opening an issue) 120 | * 22-05-2016 version 1.0.3 121 | + add support for all AVR MCU's (thanks to [per1234](https://github.com/per1234)) 122 | * 08-05-2016 version 1.0.2 123 | + fixed digitalHigh() macro for non AVR boards (thanks to [per1234](https://github.com/per1234)) 124 | * 28-09-2015 version 1.0.1 125 | + fixed folder structure to comply with Arduino library 1.5 rev 2 specifications 126 | * 28-09-2015 version 1.0.0 127 | + First release 128 | 129 | 130 | # Note 131 | 132 | I spend quite a bit of time to build this library. I hope it will be useful to others. I decided to publish it, although there still might be small bugs. If you find one, just let me know and I will try to fix it. If you have any other suggestion, don't hesitate to contact me. 133 | 134 | # Sources 135 | 136 | I've looked at many sources while constructing this library, bassicly all alternative Arduino TM1637 libraries and some AVR TM1637 libraries. While doing so I've found some really nice improvements compared to other implementations. For example, most libraries use a really low clock speed (~50us), I've tested with clock speeds as low as 1us and the chip still seems to respond well. Furthermore, from the (Chinese) datasheet it seems that you always have to perform three operation when communicating with the IC; set some configuration, set the address and send 1-4 digit data and set the display brightness. I've found out that this is not the case, you can do all of those separately if you want. 137 | 138 | Still without all these fine examples it would have taken me a lot more time to figure out the inner workings of this IC! 139 | 140 | Sources: 141 | * http://blog.3d-logic.com/2015/01/21/arduino-and-the-tm1637-4-digit-seven-segment-display/ 142 | * http://www.arduino.md/hardware/lcd-and-leds/0-36-led-display-4-digit-red/ 143 | * https://brainy-bits.com/tutorials/4-bits-7-segment-led-display-with-arduino/ 144 | 145 | 146 | #### Keywords 147 | 148 | People will probably Google for keywords when looking for a driver, so here are some: 149 | 150 | ```TM1637 TM1636 library Arduino Led Driver 4 Digit Bits Digital LED Tube module LCD API Print.h Print class API display LCD AVR Atmega``` 151 | -------------------------------------------------------------------------------- /src/SevenSegmentTM1637.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "SevenSegmentTM1637.h" 3 | 4 | 5 | SevenSegmentTM1637::SevenSegmentTM1637(uint8_t pinClk, uint8_t pinDIO) : 6 | _pinClk(pinClk), 7 | _pinDIO(pinDIO) 8 | { 9 | // setup pins 10 | pinAsOutput(_pinClk); 11 | pinAsOutput(_pinDIO); 12 | digitalHigh(_pinClk); 13 | digitalHigh(_pinDIO); 14 | 15 | // setup defaults 16 | setCursor(0, TM1637_DEFAULT_CURSOR_POS); 17 | setPrintDelay(TM1637_DEFAULT_PRINT_DELAY); 18 | setColonOn(TM1637_DEFAULT_COLON_ON); 19 | setBacklight(TM1637_DEFAULT_BACKLIGHT); 20 | 21 | // write command SET_DATA (Command1) Defaults 22 | command( 23 | TM1637_COM_SET_DATA | 24 | TM1637_SET_DATA_WRITE | 25 | TM1637_SET_DATA_A_ADDR | 26 | TM1637_SET_DATA_M_NORM 27 | ); 28 | 29 | 30 | 31 | }; 32 | 33 | // Print API /////////////////////////////////////////////////////////////////// 34 | // single byte 35 | size_t SevenSegmentTM1637::write(uint8_t byte) { 36 | TM1637_DEBUG_PRINT(F("write byte:\t")); TM1637_DEBUG_PRINTLN((char)byte); 37 | 38 | size_t n = 0; 39 | if ( _cursorPos == _numCols ) { 40 | shiftLeft(_rawBuffer, _numCols); 41 | _rawBuffer[_cursorPos] = encode( (char)byte ); 42 | // buffer, length, position 43 | printRaw( _rawBuffer, _numCols, 0); 44 | ++n; 45 | }; 46 | 47 | if (_cursorPos < _numCols) { 48 | _rawBuffer[_cursorPos] = encode( (char)byte ); 49 | // buffer, length, position 50 | printRaw( _rawBuffer, _cursorPos+1, 0); 51 | setCursor(1, _cursorPos + 1); 52 | ++n; 53 | } 54 | return n; 55 | } 56 | 57 | // null terminated char array 58 | size_t SevenSegmentTM1637::write(const char* str) { 59 | TM1637_DEBUG_PRINT(F("write char*:\t")); TM1637_DEBUG_PRINTLN(str); 60 | uint8_t encodedBytes[4]; 61 | 62 | encode(encodedBytes, str, 4); 63 | uint8_t i =4; 64 | while( str[i] != '\0' ) { 65 | printRaw(encodedBytes); 66 | shiftLeft(encodedBytes, 4); 67 | encodedBytes[3] = encode( str[i] ); 68 | i++; 69 | if ( i == TM1637_MAX_CHARS) { 70 | break; 71 | } 72 | } 73 | return i; 74 | }; 75 | 76 | // byte array with length 77 | size_t SevenSegmentTM1637::write(const uint8_t* buffer, size_t size) { 78 | TM1637_DEBUG_PRINT(F("write uint8_t*:\t(")); 79 | for(size_t i=0; i < size; i++) { 80 | TM1637_DEBUG_PRINT((char)buffer[i]); 81 | TM1637_DEBUG_PRINT(i == size -1?F(""):F(", ")); 82 | } 83 | TM1637_DEBUG_PRINT(F(") ")); 84 | TM1637_DEBUG_PRINT(size); 85 | 86 | uint8_t encodedBytes[TM1637_MAX_CHARS]; 87 | 88 | if ( size > TM1637_MAX_CHARS) { 89 | size = TM1637_MAX_CHARS; 90 | } 91 | size_t length = encode(encodedBytes, buffer, size); 92 | TM1637_DEBUG_PRINT(F(" (")); TM1637_DEBUG_PRINT(length); TM1637_DEBUG_PRINT(F(", ")); 93 | TM1637_DEBUG_PRINT(_cursorPos); TM1637_DEBUG_PRINTLN(F(")")); 94 | printRaw(encodedBytes, length, _cursorPos); 95 | return length; 96 | }; 97 | 98 | // Liquid cristal API 99 | void SevenSegmentTM1637::begin(uint8_t cols, uint8_t rows) { 100 | _numCols = cols; 101 | _numRows = rows; 102 | clear(); 103 | }; 104 | 105 | void SevenSegmentTM1637::init(uint8_t cols, uint8_t rows) { 106 | begin(cols, rows); 107 | } 108 | 109 | void SevenSegmentTM1637::clear(void) { 110 | uint8_t rawBytes[4] = {0,0,0,0}; 111 | printRaw(rawBytes); 112 | home(); 113 | }; 114 | 115 | void SevenSegmentTM1637::home(void) { 116 | setCursor(0, 0); 117 | }; 118 | 119 | void SevenSegmentTM1637::setCursor(uint8_t row, uint8_t col) { 120 | col = (col > TM1637_MAX_COLOM -1)?TM1637_MAX_COLOM-1:col; 121 | _cursorPos = col; 122 | 123 | }; 124 | 125 | void SevenSegmentTM1637::setBacklight(uint8_t value) { 126 | value = (value > 100 )?100:value; // 0..100 brightness 127 | // Store the backlight value 128 | _backLightValue = value; 129 | // scale backlight value to 0..8 130 | value /= 10; // 0..10 131 | value = (value > 8 )? 8:value; // only 8 levels and off 132 | uint8_t cmd = TM1637_COM_SET_DISPLAY;; 133 | switch ( value ) { 134 | case 0: 135 | cmd |= TM1637_SET_DISPLAY_OFF; 136 | break; 137 | case 1: 138 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_1; 139 | break; 140 | case 2: 141 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_2; 142 | break; 143 | case 3: 144 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_4; 145 | break; 146 | case 4: 147 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_10; 148 | break; 149 | case 5: 150 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_11; 151 | break; 152 | case 6: 153 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_12; 154 | break; 155 | case 7: 156 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_13; 157 | break; 158 | case 8: 159 | cmd |= TM1637_SET_DISPLAY_ON | TM1637_SET_DISPLAY_14; 160 | break; 161 | }; 162 | #if TM1637_DEBUG 163 | bool ack = command(cmd); 164 | TM1637_DEBUG_PRINT(F("SET_DISPLAY:\t")); TM1637_DEBUG_PRINTLN(( 165 | cmd 166 | ), BIN); 167 | TM1637_DEBUG_PRINT(F("Acknowledged:\t")); TM1637_DEBUG_PRINTLN(ack); 168 | #else 169 | command(cmd); 170 | #endif 171 | }; 172 | 173 | void SevenSegmentTM1637::setContrast(uint8_t value) { 174 | setBacklight(value); 175 | } 176 | 177 | void SevenSegmentTM1637::on(void) { 178 | setBacklight(TM1637_DEFAULT_BACKLIGHT); 179 | }; 180 | 181 | void SevenSegmentTM1637::off(void) { 182 | setBacklight(0); 183 | clear(); 184 | }; 185 | 186 | // SevenSegmentTM1637 public methods 187 | void SevenSegmentTM1637::blink(uint8_t blinkDelay, uint8_t repeats, uint8_t maxBacklight, uint8_t minBacklight) { 188 | for (uint8_t i=0; i < repeats; i++) { 189 | setBacklight(minBacklight); // turn backlight off 190 | delay(blinkDelay); 191 | setBacklight(maxBacklight); // turn backlight on 192 | delay(blinkDelay); 193 | } 194 | // restore backlight 195 | setBacklight(_backLightValue); 196 | } 197 | 198 | void SevenSegmentTM1637::setPrintDelay(uint16_t printDelay) { 199 | _printDelay = printDelay; 200 | }; 201 | 202 | bool SevenSegmentTM1637::getColonOn(void) { 203 | return (_colonOn); 204 | }; 205 | 206 | void SevenSegmentTM1637::setColonOn(bool setToOn) { 207 | _colonOn = setToOn; 208 | } 209 | void SevenSegmentTM1637::printRaw(uint8_t rawByte, uint8_t position) { 210 | uint8_t cmd[2]; 211 | cmd[0] = TM1637_COM_SET_ADR | position; 212 | cmd[1] = rawByte; 213 | if (position == 1) { cmd[1]|=(_colonOn)?TM1637_COLON_BIT:0; }; 214 | command(cmd, 2); 215 | }; 216 | 217 | void SevenSegmentTM1637::printRaw(const uint8_t* rawBytes, size_t length, uint8_t position) { 218 | // if fits on display 219 | if ( (length + position) <= _numCols) { 220 | uint8_t cmd[5] = {0, }; 221 | cmd[0] = TM1637_COM_SET_ADR | (position & B111); // sets address 222 | memcpy(&cmd[1], rawBytes, length); // copy bytes 223 | 224 | // do we have to print a colon? 225 | if ( position < 2 ) { // printing after position 2 has never a colon 226 | if ( position == 0 && length >= 2) { 227 | // second index is the colon 228 | cmd[2] |= (_colonOn)?TM1637_COLON_BIT:0; 229 | } else { 230 | // first index is the colon 231 | cmd[1] |= (_colonOn)?TM1637_COLON_BIT:0; 232 | } 233 | } 234 | // TM1637_DEBUG_PRINT(F("ADDR :\t")); TM1637_DEBUG_PRINTLN(cmd[0],BIN); 235 | // TM1637_DEBUG_PRINT(F("DATA0:\t")); TM1637_DEBUG_PRINTLN(cmd[1],BIN); 236 | command(cmd, length+1); // send to display 237 | } 238 | // does not fit on display, need to print with delay 239 | else { 240 | // First print 1-4 characters 241 | uint8_t numtoPrint = _numCols - position; 242 | printRaw(rawBytes, numtoPrint, position); 243 | delay(_printDelay); 244 | 245 | // keep printing 4 characters till done 246 | uint8_t remaining = length - numtoPrint + 3; 247 | uint8_t i = 1; 248 | while( remaining >= _numCols) { 249 | printRaw(&rawBytes[i], _numCols, 0); 250 | delay(_printDelay); 251 | remaining--; 252 | i++; 253 | }; 254 | } 255 | 256 | }; 257 | 258 | // Helpers 259 | uint8_t SevenSegmentTM1637::encode(char c) { 260 | if ( c < ' ') { // 32 (ASCII) 261 | return 0; 262 | } 263 | return pgm_read_byte_near(AsciiMap::map + c - ' '); 264 | }; 265 | 266 | uint8_t SevenSegmentTM1637::encode(int16_t d) { 267 | // can only encode single digit 268 | if ( d > 9 || d < 0) { 269 | return 0; 270 | }; 271 | return pgm_read_byte_near(AsciiMap::map + d + '0' - ' '); 272 | }; 273 | 274 | size_t SevenSegmentTM1637::encode(uint8_t* buffer, const char* str, size_t bufferSize) { 275 | size_t i; 276 | 277 | for (i=0; i < bufferSize; i++) { 278 | if (str[i] == '\0' ) { 279 | return i; 280 | } 281 | buffer[i] = encode( str[i] ); 282 | }; 283 | return i; 284 | } 285 | 286 | size_t SevenSegmentTM1637::encode(uint8_t* buffer, const uint8_t* byteArr, size_t bufferSize) { 287 | size_t i; 288 | 289 | for (i=0; i < bufferSize; i++) { 290 | buffer[i] = encode( (char)byteArr[i] ); 291 | }; 292 | return i; 293 | } 294 | 295 | void SevenSegmentTM1637::shiftLeft(uint8_t* buffer, size_t length) { 296 | for (uint8_t i=0; i < length ; i++) { 297 | buffer[i] = buffer[i+1]; 298 | } 299 | } 300 | 301 | // SevenSegmentTM1637 LOW LEVEL 302 | bool SevenSegmentTM1637::command(uint8_t cmd) const{ 303 | return command(_pinClk, _pinDIO, cmd); 304 | }; 305 | 306 | bool SevenSegmentTM1637::command(uint8_t pinClk, uint8_t pinDIO, uint8_t cmd) { 307 | comStart(pinClk, pinDIO); 308 | comWriteByte(pinClk, pinDIO,cmd); 309 | bool acknowledged = comAck(pinClk, pinDIO); 310 | comStop(pinClk, pinDIO); 311 | return acknowledged; 312 | } 313 | 314 | bool SevenSegmentTM1637::command(const uint8_t* commands, uint8_t length) const { 315 | return command(_pinClk, _pinDIO, commands, length); 316 | }; 317 | 318 | bool SevenSegmentTM1637::command(uint8_t pinClk, uint8_t pinDIO, const uint8_t* commands, uint8_t length) { 319 | bool acknowledged = true; 320 | comStart(pinClk, pinDIO); 321 | for (uint8_t i=0; i < length;i++) { 322 | comWriteByte(pinClk, pinDIO, commands[i]); 323 | acknowledged &= comAck(pinClk, pinDIO); 324 | }; 325 | comStop(pinClk, pinDIO); 326 | return acknowledged; 327 | } 328 | 329 | uint8_t SevenSegmentTM1637::comReadByte(void) const { 330 | uint8_t readKey = 0; 331 | 332 | comStart(); 333 | comWriteByte(TM1637_COM_SET_DATA | TM1637_SET_DATA_READ); 334 | comAck(); 335 | 336 | pinAsInput(_pinDIO); 337 | digitalHigh(_pinDIO); 338 | delayMicroseconds(5); 339 | 340 | for ( uint8_t i=0; i < 8; i++) { 341 | 342 | readKey >>= 1; 343 | digitalLow(_pinClk); 344 | delayMicroseconds(30); 345 | 346 | digitalHigh(_pinClk); 347 | 348 | if ( isHigh(_pinDIO) ) { 349 | readKey = readKey | B10000000; 350 | }; 351 | 352 | delayMicroseconds(30); 353 | 354 | 355 | }; 356 | pinAsOutput(_pinDIO); 357 | comAck(); 358 | comStop(); 359 | return readKey; 360 | }; 361 | 362 | void SevenSegmentTM1637::comWriteByte(uint8_t command) const{ 363 | comWriteByte(_pinClk, _pinDIO, command); 364 | }; 365 | 366 | void SevenSegmentTM1637::comWriteByte(uint8_t pinClk, uint8_t pinDIO, uint8_t command) { 367 | // CLK in bits 368 | for ( uint8_t i=0; i < 8; i++) { 369 | digitalLow(pinClk); // CLK LOW 370 | 371 | if ( command & B1) { 372 | digitalHigh(pinDIO);// DIO HIGH 373 | } else { 374 | digitalLow(pinDIO); // DIO LOW 375 | } 376 | delayMicroseconds(TM1637_CLK_DELAY_US); 377 | 378 | command >>= 1; 379 | 380 | digitalHigh(pinClk); // CLK HIGH 381 | delayMicroseconds(TM1637_CLK_DELAY_US); 382 | }; 383 | } 384 | 385 | void SevenSegmentTM1637::comStart(void) const { 386 | comStart(_pinClk, _pinDIO); 387 | }; 388 | 389 | void SevenSegmentTM1637::comStart(uint8_t pinClk, uint8_t pinDIO) { 390 | digitalHigh(pinDIO); // DIO HIGH 391 | digitalHigh(pinClk); // CLK HIGH 392 | delayMicroseconds(TM1637_CLK_DELAY_US); 393 | 394 | digitalLow(pinDIO); // DIO LOW 395 | } 396 | 397 | void SevenSegmentTM1637::comStop(void) const { 398 | comStop(_pinClk, _pinDIO); 399 | }; 400 | 401 | void SevenSegmentTM1637::comStop(uint8_t pinClk, uint8_t pinDIO) { 402 | digitalLow(pinClk); // CLK LOW 403 | delayMicroseconds(TM1637_CLK_DELAY_US); 404 | 405 | digitalLow(pinDIO); // DIO LOW 406 | delayMicroseconds(TM1637_CLK_DELAY_US); 407 | 408 | digitalHigh(pinClk); // CLK HIGH 409 | delayMicroseconds(TM1637_CLK_DELAY_US); 410 | 411 | digitalHigh(pinDIO); // DIO HIGH 412 | } 413 | 414 | bool SevenSegmentTM1637::comAck(void) const { 415 | return comAck(_pinClk, _pinDIO); 416 | }; 417 | 418 | bool SevenSegmentTM1637::comAck(uint8_t pinClk, uint8_t pinDIO) { 419 | bool acknowledged = false; 420 | 421 | digitalLow(pinClk); // CLK LOW 422 | pinAsInputPullUp(pinDIO); // DIO INPUT PULLUP (state==HIGH) 423 | delayMicroseconds(TM1637_CLK_DELAY_US); 424 | 425 | acknowledged = isLow(pinDIO);// Ack should pull the pin low again 426 | 427 | digitalHigh(pinClk); // CLK HIGH 428 | delayMicroseconds(TM1637_CLK_DELAY_US); 429 | 430 | digitalLow(pinClk); // CLK LOW 431 | pinAsOutput(pinDIO); 432 | 433 | return acknowledged; 434 | } 435 | -------------------------------------------------------------------------------- /src/SevenSegmentTM1637.h: -------------------------------------------------------------------------------- 1 | /* 2 | SevenSegmentTM1637 - class to control a 4 digit seven segment display with a TM1636 or TM1637 driver IC 3 | Created by Bram Harmsen, September 25, 2015 4 | Released into the public domain. 5 | Licence: GNU GENERAL PUBLIC LICENSE V2.0 6 | 7 | # Changelog 8 | 9 | v1.0 25-10-2015 10 | v1.1 04-07-2020 11 | 12 | */ 13 | 14 | #ifndef SevenSegmentTM1637_H 15 | #define SevenSegmentTM1637_H 16 | 17 | #include 18 | #include "SevenSegmentAsciiMap.h" 19 | 20 | // COMPILE TIME USER CONFIG //////////////////////////////////////////////////// 21 | #define TM1637_DEBUG false // true for serial debugging 22 | #define TM1637_BEGIN_DELAY 500 // ms 23 | #define TM1637_PRINT_BUFFER_SIZE 128 // lower if you don't need it 24 | 25 | // Default values ////////////////////////////////////////////////////////////// 26 | #define TM1637_DEFAULT_PRINT_DELAY 300 // 300 ms delay between characters 27 | #define TM1637_DEFAULT_BLINK_DELAY 50 // ms 28 | #define TM1637_DEFAULT_CLOCK_BLINK_DELAY 500 // the default delay for when using printTime 29 | #define TM1637_DEFAULT_BLINK_REPEAT 10 30 | #define TM1637_DEFAULT_CURSOR_POS 0 // 0-MAX-1 (e.g 3) 31 | #define TM1637_DEFAULT_COLON_ON false // 32 | #define TM1637_DEFAULT_BACKLIGHT 100 // 0..100 33 | 34 | #define TM1637_MAX_LINES 1 // number of display lines 35 | #define TM1637_MAX_COLOM 4 // number of coloms (digits) 36 | #define TM1637_MAX_CHARS 128 37 | 38 | // PROGRAM CONFIG (ONLY CHANGE WHEN YOU KNOW WHAT YOU RE DOING:)//////////////// 39 | #define TM1637_CLK_DELAY_US 5 // clock delay for communication 40 | // mine works with 1us, perhaps increase if display does not function ( tested upto 1ms) 41 | 42 | 43 | // COMMANDS //////////////////////////////////////////////////////////////////// 44 | #define TM1637_COM_SET_DATA B01000000 // 0x40 (1) Data set 45 | #define TM1637_COM_SET_ADR B11000000 // 0xC0 (2) Address command set 46 | #define TM1637_COM_SET_DISPLAY B10000000 // 0x80 (3) Display control command set 47 | 48 | // Data set (1) (use logical OR to contruct complete command) 49 | #define TM1637_SET_DATA_WRITE B00000000 // Write data to the display register 50 | #define TM1637_SET_DATA_READ B00000010 // Read the key scan data 51 | #define TM1637_SET_DATA_A_ADDR B00000000 // Automatic address increment 52 | #define TM1637_SET_DATA_F_ADDR B00000100 // Fixed address 53 | #define TM1637_SET_DATA_M_NORM B00000000 // Normal mode 54 | #define TM1637_SET_DATA_M_TEST B00100000 // Test mode 55 | 56 | // Address settings (2) (use logical OR to contruct complete command) 57 | #define TM1637_SET_ADR_00H B0000000 // addr 00 58 | #define TM1637_SET_ADR_01H B0000001 // addr 01 59 | #define TM1637_SET_ADR_02H B0000010 // addr 02 60 | #define TM1637_SET_ADR_03H B0000011 // addr 03 61 | #define TM1637_SET_ADR_04H B0000100 // addr 04 (only TM1637) 62 | #define TM1637_SET_ADR_05H B0000101 // addr 05 (only TM1637) 63 | // The command is used to set the display register address; if the address is set to 0C4H or higher, the data is ignored, until the effective address is set; when the power is on, the default is set to 00H address. 64 | 65 | // Display control command set (use logical OR to consruct complete command) 66 | #define TM1637_SET_DISPLAY_1 B0000000 // Pulse width 1/16 (0.0625) (0) 67 | #define TM1637_SET_DISPLAY_2 B0000001 // Pulse width 2/16 (0.0625) (1) 68 | #define TM1637_SET_DISPLAY_4 B0000010 // Pulse width 4/16 (0.0625) (2) 69 | #define TM1637_SET_DISPLAY_10 B0000011 // Pulse width 10/16 (0.0625) (3) 70 | #define TM1637_SET_DISPLAY_11 B0000100 // Pulse width 11/16 (0.0625) (4) 71 | #define TM1637_SET_DISPLAY_12 B0000101 // Pulse width 12/16 (0.0625) (5) 72 | #define TM1637_SET_DISPLAY_13 B0000110 // Pulse width 13/16 (0.0625) (6) 73 | #define TM1637_SET_DISPLAY_14 B0000111 // Pulse width 14/16 (0.0625) (7) 74 | #define TM1637_SET_DISPLAY_OFF B0000000 // OFF 75 | #define TM1637_SET_DISPLAY_ON B0001000 // ON 76 | // there are a total of 8 brighness values, plus off 77 | 78 | // PROTOCOL SPECIFICATION 79 | /* 80 | * Structure 81 | * START COMMAND ACK STOP set config or display 82 | * START ADR_CMD DATA ACK STOP sets single digit 83 | * START ADR_CMD DATA0 .. DATAN ACK STOP sets multiple digits when in auto mode 84 | * 85 | * There are basicly three things you can do: 86 | * 1. Set some configuration values 87 | * - read/write mode, auto/manual address, normal/test mode 88 | * 2. Set a (starting) address followed by 1 or N data bytes 89 | * 3. Set the display brightness (pwm) 0-7 and on or off 90 | * 91 | * From the datasheet it might seem that you always have to perform all three commands; setting configuration, setting address and data bytes and display. I'v tested this and this is not true. You can just set only one of these three. But ofcourse you have to make sure that your configuration is set properly. For example if you haven't set the configuration to automatic addresses, you can't just send out 4 data bytes, it won't work. Simlilair, if your display is off and you write some data to it, it won't display. On the other hand most default setting are what you want most of the time. 92 | 93 | */ 94 | 95 | class SevenSegmentTM1637 : public Print { 96 | 97 | public: 98 | // LIQUID CRISTAL API /////////////////////////////////////////////////////// 99 | // See http://playground.arduino.cc/Code/LCDAPI for more details. 100 | 101 | /* Constructor 102 | @param [in] pinClk clock pin (any digital pin) 103 | @param [in] pinDIO digital output pin (any digital pin) 104 | */ 105 | SevenSegmentTM1637(uint8_t pinClk, uint8_t pinDIO); 106 | /* Initializes the display 107 | * Initializes the display, sets some text and blinks the display 108 | 109 | @param [in] cols optional: number of coloms (digits) 110 | @param [in] rows optional: number of rows 111 | */ 112 | void init(uint8_t cols = TM1637_MAX_COLOM, uint8_t rows = TM1637_MAX_LINES); 113 | /* Implemented for compatibility, see begin() above */ 114 | void begin(uint8_t cols = TM1637_MAX_COLOM, uint8_t rows = TM1637_MAX_LINES); 115 | // Print class inheritance /////////////////////////////////////////////////// 116 | // See https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h for more details 117 | /* This library inherent the Print class, this means that all regular print function can be used. For example: 118 | * printing a number: print(78) 119 | * printint a number in BIN, OCT, HEX..: print(78, BIN) 120 | * printing a float: print(2.85) 121 | * printing a PROGMEM c string: print(F("Arduino")) 122 | * 123 | * Also the more low level write() function can be used. (Actually all print function eventually call one of these write methods, every class that wants to inherent from the Print class needs to implement these) 124 | */ 125 | size_t write(uint8_t byte); 126 | size_t write(const char* str); 127 | size_t write(const uint8_t* buffer, size_t size); 128 | 129 | /* Clears the display 130 | * Writes zero to all digits and segments, display off. 131 | */ 132 | void clear(void); 133 | /* Sets the cursor position to zero 134 | */ 135 | void home(void); 136 | /* Sets the cursor position to a specfic position 137 | * 138 | @param [in] col colomn (position) 139 | */ 140 | void setCursor(uint8_t row, uint8_t col); 141 | // Liquid cristal optional ////////////////////////////////////////////////// 142 | /* Sets the display backlight 143 | * The display has 8 PWM modes and an off mode. The function accepts a value from 0 to 100, where 80-100 are the same; full brighness. 144 | 145 | @param [in] value brightness value (0..80(100)) 146 | */ 147 | void setBacklight(uint8_t value); 148 | /* Sets the display contrast (identical to brightness) 149 | * This function is mainly for compatibility with the LCD API 150 | */ 151 | void setContrast(uint8_t value); 152 | 153 | /* Turns the display ON 154 | * Identical to setting the brightness to the default value. 155 | */ 156 | void on(void); 157 | /* Turns the display ON 158 | * Identical to setting the brightness to zero and clearing the display. 159 | */ 160 | void off(void); 161 | 162 | // SevenSegmentTM1637 METHODS /////////////////////////////////////////////// 163 | /* Blink the last printed text 164 | * 165 | @param [in] blinkDelay optional: blink delay in ms 166 | @param [in] repeats optional: number of blink repeats 167 | */ 168 | void blink(uint8_t blinkDelay = TM1637_DEFAULT_BLINK_DELAY, uint8_t repeats = TM1637_DEFAULT_BLINK_REPEAT, uint8_t maxBacklight=100, uint8_t minBacklight=0); 169 | 170 | // getters and setters /////////////////////////////////////////////////////// 171 | /* Turn the colon on or off 172 | * When turing the colon on, the next displayed text/numbers will have a colon 173 | @param [in] setToOn sets the colon to on or off 174 | */ 175 | void setColonOn(bool setToOn); 176 | /* Get the currrent colon setting 177 | */ 178 | bool getColonOn(void); 179 | /* Sets the delay for scrolling text 180 | * When printing more than four characters/ the display will scroll, this setting determines the scrolling speed in ms 181 | @param [in] printDelay the print delay in ms 182 | */ 183 | void setPrintDelay(uint16_t printDelay); 184 | 185 | // helpers ////////////////////////////////////////////////////////////////// 186 | /* Encodes a character to sevensegment binairy 187 | * 188 | @param [in] c a character to encode 189 | */ 190 | uint8_t encode(char c); 191 | /* Encodes a single digit to sevensegment binairy 192 | * 193 | @param [in] d a digit to encode 194 | */ 195 | uint8_t encode(int16_t d); 196 | /* Encodes a null terminated c string (char array) to sevensegment binairy 197 | * 198 | @param [out] buffer holds the encodes char array 199 | @param [in] str the c string to encode 200 | @param [in] bufferSize the size/length of the buffer 201 | */ 202 | size_t encode(uint8_t* buffer, const char* str, size_t bufferSize); 203 | /* Encodes a byte array to sevensegment binairy 204 | * 205 | @param [out] buffer holds the encodes char array 206 | @param [in] byteArr the byte array to encode 207 | @param [in] bufferSize the size/length of the buffer 208 | */ 209 | size_t encode(uint8_t* buffer, const uint8_t* byteArr, size_t arrSize); 210 | /* Shift an array one position to the left 211 | @param [out] buffer the buffer to be shifted 212 | @param [in] length the length to the buffer 213 | */ 214 | void shiftLeft(uint8_t* buffer, size_t length); 215 | 216 | // SevenSegmentTM1637 low level methods (use when you know what you're doing) 217 | /* Prints raw (encoded) bytes to the display 218 | * A 219 | * ___ 220 | * * F | | B 221 | * X -G- 222 | * * E | | C 223 | * ___ 224 | * D 225 | * Bit: 76543210 226 | * Segment: XGFEDCBA 227 | * 228 | * For example to print an H, you would set bits BCEFG, this gives B01110110 in binary or 118 in decimal or 0x76 in HEX. 229 | * Bit 7 (X) only applies to the second digit and sets the colon 230 | */ 231 | /* Print raw (binary encodes) bytes to the display 232 | @param [in] rawBytes Array of raw bytes 233 | @param [in] length optional: length to print to display 234 | @param [in] position optional: Start position 235 | */ 236 | void printRaw(const uint8_t* rawBytes, size_t length = 4, uint8_t position = 0); 237 | /* Print raw (binary encodes) bytes to the display 238 | @param [in] rawByte Raw byte 239 | @param [in] position optional: Start position 240 | */ 241 | void printRaw(uint8_t rawByte, uint8_t position); 242 | /* Write command to IC TM1637 243 | @param [in] cmd command to send 244 | @return acknowledged? command was (successful) acknowledged 245 | */ 246 | bool command(uint8_t cmd) const; 247 | bool command(const uint8_t* command, uint8_t length) const; 248 | /* Read bytes from IC TM1637 249 | * The IC also can read the state of a keypad? TODO untested 250 | */ 251 | uint8_t comReadByte(void) const; 252 | /* Write a single command to the display 253 | @param [in] cmd command to send 254 | */ 255 | void comWriteByte(uint8_t command) const; 256 | /* Send start signal 257 | * Send the start signal for serial communication 258 | */ 259 | void comStart(void) const; 260 | /* Send stop signal 261 | * Send the stop signal for serial communication 262 | */ 263 | void comStop(void) const; 264 | /* Get command acknowledged 265 | * Get acknowledge signal (command was succesful received) 266 | */ 267 | bool comAck(void) const; 268 | 269 | /* Static version of low level function 270 | * If using more than one display, this saves some space since these methods will be shared among all instances/objects of the class 271 | */ 272 | static bool command(uint8_t pinClk, uint8_t pinDIO, uint8_t cmd); 273 | static bool command(uint8_t pinClk, uint8_t pinDIO, const uint8_t* command, uint8_t length); 274 | static void comStart(uint8_t pinClk, uint8_t pinDIO); 275 | static void comWriteByte(uint8_t pinClk, uint8_t pinDIO, uint8_t command); 276 | static bool comAck(uint8_t pinClk, uint8_t pinDIO); 277 | static void comStop(uint8_t pinClk, uint8_t pinDIO); 278 | protected: 279 | const uint8_t _pinClk; // clock pin 280 | const uint8_t _pinDIO; // digital out pin 281 | uint8_t _numCols; // number of columns 282 | uint8_t _numRows; // number of rows 283 | 284 | uint8_t _backLightValue; // brightness of the display (0..100) 285 | uint8_t _cursorPos; // current cursor position 286 | uint16_t _printDelay; // print delay in ms (multiple chars) 287 | uint8_t _colonOn; // colon bit if set 288 | uint8_t _rawBuffer[TM1637_MAX_COLOM];// hold the last chars printed to display 289 | }; 290 | 291 | 292 | #define TM1637_COLON_BIT B10000000 293 | 294 | // debug macros for debugging 295 | #if TM1637_DEBUG 296 | #define TM1637_DEBUG_BEGIN(x) Serial.begin(x) 297 | #define TM1637_DEBUG_PRINT(...) Serial.print(__VA_ARGS__) 298 | #define TM1637_DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) 299 | #define TM1637_DEBUG_WRITE(x) Serial.write(x) 300 | #define TM1637_DEBUG_MESSAGE(...) \ 301 | Serial.print(millis()); \ 302 | Serial.print(F("\t")); \ 303 | Serial.print(__VA_ARGS__); 304 | #define TM1637_DEBUG_MESSAGELN(...) \ 305 | TM1637_DEBUG_MESSAGE(__VA_ARGS__) \ 306 | Serial.println(); 307 | #else 308 | #define TM1637_DEBUG_BEGIN(x) 309 | #define TM1637_DEBUG_PRINT(...) 310 | #define TM1637_DEBUG_PRINTLN(...) 311 | #define TM1637_DEBUG_WRITE(x) 312 | #define TM1637_DEBUG_MESSAGE(x) 313 | #define TM1637_DEBUG_MESSAGELN(x) 314 | #endif 315 | 316 | // arduino:standard variant direct port access macros for more speed ( communication is ~us) 317 | #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) 318 | #define portOfPin(P) \ 319 | ( ((P) >= 0 && (P) < 8)? &PORTD:( ((P) > 7 && (P) < 14) ? &PORTB: &PORTC ) ) 320 | #define ddrOfPin(P) \ 321 | ( ((P) >= 0 && (P) < 8)? &DDRD: ( ((P) > 7 && (P) < 14) ? &DDRB: &DDRC ) ) 322 | #define pinOfPin(P) \ 323 | ( ((P) >= 0 && (P) < 8)? &PIND: ( ((P) > 7 && (P) < 14) ? &PINB: &PINC ) ) 324 | 325 | #define pinIndex(P) ( (uint8_t)( P > 13 ? P-14: P&7 ) ) 326 | #define pinMask(P) ( (uint8_t)( 1 << pinIndex(P) ) ) 327 | 328 | #define pinAsInput(P) *(ddrOfPin(P) ) &= ~pinMask(P) 329 | #define pinAsInputPullUp(P) *(ddrOfPin(P) ) &= ~pinMask(P);digitalHigh(P) 330 | #define pinAsOutput(P) *(ddrOfPin(P) ) |= pinMask(P) 331 | #define digitalLow(P) *(portOfPin(P)) &= ~pinMask(P) 332 | #define digitalHigh(P) *(portOfPin(P)) |= pinMask(P) 333 | #define isHigh(P) ( ( *( pinOfPin(P) ) & pinMask(P) ) > 0 ) 334 | #define isLow(P) ( ( *( pinOfPin(P) ) & pinMask(P) ) == 0 ) 335 | #define digitalState(P) ((uint8_t)isHigh(P)) 336 | #else 337 | #define pinAsOutput(P) pinMode(P, OUTPUT) 338 | #define pinAsInput(P) pinMode(P, INPUT) 339 | #define pinAsInputPullUp(P) pinMode(P, INPUT_PULLUP) 340 | #define digitalLow(P) digitalWrite(P, LOW) 341 | #define digitalHigh(P) digitalWrite(P, HIGH) 342 | #define isHigh(P) (digitalRead(P) == 1) 343 | #define isLow(P) (digitalRead(P) == 0) 344 | #define digitalState(P) digitalRead(P) 345 | #endif 346 | 347 | #endif 348 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | --------------------------------------------------------------------------------