Support up to 8 I2C Seven Segment Displays

This commit is contained in:
Khoa Ton 2020-07-11 23:16:29 -07:00
parent 04af1050e7
commit 833f47fd15
2 changed files with 65 additions and 32 deletions

View File

@ -559,7 +559,7 @@
#define MTX_ADDRESS7 0x00 // [DisplayAddress7] I2C address of seventh 8x8 matrix module
#define MTX_ADDRESS8 0x00 // [DisplayAddress8] I2C address of eigth 8x8 matrix module
#define USE_DISPLAY_SEVENSEG // [DisplayModel 11] [I2cDriver47] Enable sevenseg display (I2C 0x70-0x77) (<+11k code)
#define SEVENSEG_ADDRESS1 0x70 // [DisplayAddress1] I2C address of first sevenseg matrix module
// #define SEVENSEG_ADDRESS1 0x70 // No longer used. Use MTX_ADDRESS1 - MTX_ADDRESS8 instead to specify I2C address of sevenseg displays
// #define USE_DISPLAY_SH1106 // [DisplayModel 7] [I2cDriver6] Enable SH1106 Oled 128x64 display (I2C addresses 0x3C and 0x3D)
#endif // USE_I2C

View File

@ -28,20 +28,24 @@
#include <Adafruit_GFX.h>
#include <Adafruit_LEDBackpack.h> // Seven segment LED
Adafruit_7segment sevenseg = Adafruit_7segment();
Adafruit_7segment *sevenseg[8];
uint8_t sevensegs = 0;
uint8_t sevenseg_state = 0;
/*********************************************************************************************/
void SevensegWrite(void)
{
sevenseg.writeDisplay();
for (uint32_t i = 0; i < sevensegs; i++) {
sevenseg[i]->writeDisplay();
}
}
void SevensegClear(void)
{
sevenseg.clear();
for (uint32_t i = 0; i < sevensegs; i++) {
sevenseg[i]->clear();
}
SevensegWrite();
}
@ -50,8 +54,10 @@ void SevensegClear(void)
void SevensegInitMode(void)
{
sevenseg.setBrightness(Settings.display_dimmer);
sevenseg.blinkRate(0); // 0 - 3
for (uint32_t i = 0; i < sevensegs; i++) {
sevenseg[i]->setBrightness(Settings.display_dimmer);
sevenseg[i]->blinkRate(0);
}
SevensegClear();
}
@ -69,17 +75,25 @@ void SevensegInit(uint8_t mode)
void SevensegInitDriver(void)
{
if (!Settings.display_model) {
if (I2cSetDevice(SEVENSEG_ADDRESS1)) {
if (I2cSetDevice(Settings.display_address[0])) {
Settings.display_model = XDSP_11;
}
}
if (XDSP_11 == Settings.display_model) {
sevenseg_state = 1;
sevenseg.begin(SEVENSEG_ADDRESS1);
for (sevensegs = 0; sevensegs < 8; sevensegs++) {
if (Settings.display_address[sevensegs]) {
I2cSetActiveFound(Settings.display_address[sevensegs], "SevenSeg");
sevenseg[sevensegs] = new Adafruit_7segment();
sevenseg[sevensegs]->begin(Settings.display_address[sevensegs]);
} else {
break;
}
}
Settings.display_width = 4;
Settings.display_height = 1;
Settings.display_height = sevensegs;
SevensegInitMode();
}
@ -101,15 +115,34 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin
boolean hex=false;
boolean done=false;
boolean s=false;
uint8_t unit=y;
if ((unit>=sevensegs) || (unit<0)) {
unit=0;
}
for (int i=0; (str[i]!='\0') && (!done); i++) {
// [prefix(es) chars]digits
// [optional prefix(es) chars]digits
// Some combinations won't make sense.
// Reference: https://learn.adafruit.com/adafruit-led-backpack/1-2-inch-7-segment-backpack-arduino-wiring-and-setup
//
// Prefixes:
// x upcoming number decimal integer displayed as hex
// : turn on middle colon
// ^ turh on top left dot
// v turn on bottom left dot
// . turn on AM/PM/Degree dot
// s upcoming number is seconds, print as HH:MM or MM:SS
// z clear this display
//
// Some sample valid combinations:
// 787 -> 787
// x47 -> 2F
// st:241 -> 04:01
// sT241 -> 4 01
// 787 -> 787
// x47 -> 2F
// s:241 -> 04:01
// s241 -> 4 01
// s1241 -> 20:41
// z ->
// x88 -> 58
switch (str[i]) {
case 'x': // print given dec value as hex
hex = true;
@ -126,12 +159,6 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin
case '.': // print ampm
dots |= 0x10;
break;
case 'T': // print as time 12 format
t = true;
break;
case 't': // print as time 24 format
T = true;
break;
case 's': // duration in seconds
s = true;
break;
@ -149,6 +176,12 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin
number = atoi(str+i);
done = true;
break;
case 'z': // Clear this display
hasnumber=false;
dots=0;
s=false;
sevenseg[unit]->clear();
break;
default: // unknown format, ignore
break;
}
@ -171,17 +204,17 @@ void SevensegDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uin
if (hasnumber) {
if (hex) {
sevenseg.print(number, HEX);
sevenseg[unit]->print(number, HEX);
} else {
sevenseg.print(number, DEC);
sevenseg[unit]->print(number, DEC);
}
}
if (dots) {
sevenseg.writeDigitRaw(2, dots);
sevenseg[unit]->writeDigitRaw(2, dots);
}
sevenseg.writeDisplay();
sevenseg[unit]->writeDisplay();
}
/*********************************************************************************************/
@ -210,7 +243,7 @@ void SevensegTime(boolean time_24)
// Now print the time value to the display.
sevenseg.print(displayValue, DEC);
sevenseg[0]->print(displayValue, DEC);
// Add zero padding when in 24 hour mode and it's midnight.
// In this case the print function above won't have leading 0's
@ -218,15 +251,15 @@ void SevensegTime(boolean time_24)
if (time_24) {
if (hours == 0) {
// Pad hour 0.
sevenseg.writeDigitNum(1, 0);
sevenseg[0]->writeDigitNum(1, 0);
// Also pad when the 10's minute is 0 and should be padded.
if (minutes < 10) {
sevenseg.writeDigitNum(3, 0);
sevenseg[0]->writeDigitNum(3, 0);
}
}
if (hours < 10) {
// Always have 4 digits time
sevenseg.writeDigitNum(0, 0);
sevenseg[0]->writeDigitNum(0, 0);
}
} else {
// Identify and display AM/PM
@ -235,8 +268,8 @@ void SevensegTime(boolean time_24)
}
}
sevenseg.writeDigitRaw(2, dots |= ((second%2) << 1));
sevenseg.writeDisplay();
sevenseg[0]->writeDigitRaw(2, dots |= ((second%2) << 1));
sevenseg[0]->writeDisplay();
}
void SevensegRefresh(void) // Every second