/* Serial LED Display - see http://www.technoblogy.com/show?3US2 David Johnson-Davies - www.technoblogy.com - 23rd March 2022 ATtiny85 @ 8 MHz (internal oscillator; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ #include // Globals const int cs = 3; // Display CS pin; use 1 for ATtiny402 const int Brightness = 8; // Can be between 0 and 15 const int DP = 0x80; // Segment pattern for decimal point const int Space = 16; const int Minus = 17; const int Equals = 18; const uint8_t Segs[19] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, // 0 to 9 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47, // A to F 0x00, 0x01, 0x09 // space, minus, equals }; class SerialDisplay : public Print { public: void init(); size_t write(uint8_t); void clear(); void show(uint8_t, uint8_t); private: void cmd(uint8_t, uint8_t); uint8_t cur = 0; uint8_t last = 0; }; // Send a two-byte display command void SerialDisplay::cmd (uint8_t a, uint8_t d) { digitalWrite(cs, LOW); SPI.transfer(a); SPI.transfer(d); digitalWrite(cs, HIGH); } // Show a segment pattern on a particular display void SerialDisplay::show (uint8_t d, uint8_t pat) { cmd(8-d, pat); } // Clear display void SerialDisplay::clear () { for (int d=0; d<8; d++) show(d, Space); cur = 0; } // Initialise the display void SerialDisplay::init () { cmd(0xF, 0); // Test mode off cmd(0xB, 7); // 8 digits cmd(0x9, 0x00); // Decode segments cmd(0xA, Brightness); clear(); cmd(0xC, 1); // Enable display } // Write to the current cursor position 0 to 7 and handle scrolling size_t SerialDisplay::write (uint8_t c) { if (c == '\n') { cur = 0; // Return resets cursor return 1; } else if (c == ' ') { last = Segs[Space]; } else if (c == '.') { last = last | DP; // Decimal point on previous display if (cur != 0) cur--; } else if (c == '-') { last = Segs[Minus]; } else if (c == '=') { last = Segs[Equals]; } else if (c >= '0' && c <= '9') { // Digit last = Segs[c-'0']; } else if ((c|0x20)>='a' && (c|0x20)<='f') { // Hex digit, upper or lower case last = Segs[(c|0x20) -'a'+10]; } else if (c == 12) { // Clear display clear(); return 1; } else return 1; // Other characters don't print show(cur, last); if (cur < 7) cur++; return 1; } // Stopwatch Demo ********************************************** SerialDisplay Display; // Make a SerialDisplay instance unsigned long Start = millis(); void setup() { SPI.begin(); pinMode(cs,OUTPUT); Display.init(); } void loop() { int split = 1; unsigned long now = (millis() - Start)/10; int mins = (now/6000) % 60; int secs = (now/100) % 60; int centis = now % 100; Display.printf("%d %02d.%02d.%02d\n", split, mins, secs, centis); while ((millis() - Start)/10 == now); }