diff --git a/CustomDevices b/CustomDevices new file mode 100644 index 00000000..e69de29b diff --git a/src/CommandMessenger.cpp b/src/CommandMessenger.cpp index 7015fefe..19bdd3b0 100644 --- a/src/CommandMessenger.cpp +++ b/src/CommandMessenger.cpp @@ -54,6 +54,7 @@ void attachCommandCallbacks() cmdMessenger.attach(kInitModule, LedSegment::OnInitModule); cmdMessenger.attach(kSetModule, LedSegment::OnSetModule); cmdMessenger.attach(kSetModuleBrightness, LedSegment::OnSetModuleBrightness); + cmdMessenger.attach(kSetModuleSingleSegment, LedSegment::OnSetModuleSingleSegment); #endif cmdMessenger.attach(kSetPin, Output::OnSet); diff --git a/src/MF_Segment/LedControl_dual.cpp b/src/MF_Segment/LedControl_dual.cpp index 31ffb64e..269f5110 100644 --- a/src/MF_Segment/LedControl_dual.cpp +++ b/src/MF_Segment/LedControl_dual.cpp @@ -5,6 +5,7 @@ // #include "LedControl_dual.h" +#include "allocateMem.h" // Segments to be switched on for characters and digits on 7-Segment Displays // bit/segment sequence: dABCDEFG @@ -73,7 +74,7 @@ enum { }; #ifdef LEDCONTROL_NO_BUF -uint8_t LedControl::rawdata[16] = {0}; +uint8_t *LedControl::rawdata; #endif // ======================================================================= @@ -132,15 +133,24 @@ uint8_t LedControl::rawdata[16] = {0}; // Digit sequence map for 6 digit displays const uint8_t digitmap[] = {2, 1, 0, 5, 4, 3}; -void LedControl::begin(uint8_t type, uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices) +bool LedControl::begin(uint8_t type, uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices) { _type = type; _dataPin = dataPin; _clkPin = clkPin; _csPin = csPin; + if (!FitInMemory(sizeof(uint8_t) * numDevices * 2)) + return false; + rawdata = new (allocateMemory(sizeof(uint8_t) * numDevices * 2)) uint8_t; + if (isMAX()) { - if ((numDevices - 1) > 7) numDevices = 8; + // make sure we have max 8 chips in the daisy chain + if (numDevices > 8) numDevices = 8; + + if (!FitInMemory(sizeof(uint8_t) * numDevices * 8)) + return false; + digitBuffer = new (allocateMemory(sizeof(uint8_t) * numDevices * 8)) uint8_t; maxUnits = numDevices; pinMode(_dataPin, OUTPUT); pinMode(_clkPin, OUTPUT); @@ -165,6 +175,8 @@ void LedControl::begin(uint8_t type, uint8_t dataPin, uint8_t clkPin, uint8_t cs brightness = MAX_BRIGHTNESS; shutdown(0, true); } + + return true; } void LedControl::shutdown(uint8_t addr, bool b) @@ -238,13 +250,48 @@ void LedControl::setChar(uint8_t addr, uint8_t digit, char value, bool dp, bool setPattern(addr, digit, v, sendNow); } +void LedControl::setSingleSegment(uint8_t subModule, uint8_t segment, uint8_t value, bool sendNow) +{ + uint8_t digit = segment >> 3; + uint8_t bitPosition = segment % 8; + uint8_t offset = subModule * 8; + + if (isMAX()) { + if (subModule >= maxUnits) return; + if (segment > 63) return; + if (value) { + digitBuffer[offset + digit] |= (1 << bitPosition); + } else { + digitBuffer[offset + digit] &= ~(1 << bitPosition); + } + spiTransfer(subModule, digit + 1, digitBuffer[offset + digit]); + } else { + if (subModule >= maxUnits) return; + if (segment >= maxUnits * 8) return; + // Same order as MAX72XX + // MAX72XX order is: dABCDEFG + // TM1637 order required: ABCDEFGd + bitPosition++; + if (bitPosition == 8) + bitPosition = 0; + if (value) { + rawdata[(maxUnits - 1) - digit] |= (1 << bitPosition); + } else { + rawdata[(maxUnits - 1) - digit] &= ~(1 << bitPosition); + } + if (sendNow) writeDigits(digit, 1); + } +} + void LedControl::setPattern(uint8_t addr, uint8_t digit, uint8_t value, bool sendNow) { if (digit > getDigitCount() - 1) return; uint8_t v; v = pgm_read_byte_near(charTable + (value & 0x7F)); if (isMAX()) { + uint8_t offset = addr * 8; if (value & 0x80) v |= 0x80; + digitBuffer[offset + digit] = v; spiTransfer(addr, digit + 1, v); // Always send immediately for MAX } else { // Original data for MAX has the bit sequence: dABCDEFG diff --git a/src/MF_Segment/LedControl_dual.h b/src/MF_Segment/LedControl_dual.h index 634dd1b4..4f9734e9 100644 --- a/src/MF_Segment/LedControl_dual.h +++ b/src/MF_Segment/LedControl_dual.h @@ -66,15 +66,13 @@ class LedControl uint8_t _dataPin = TYPE_UNDEFINED; uint8_t _clkPin = TYPE_UNDEFINED; uint8_t _csPin = TYPE_UNDEFINED; - // MAX: Number of chained units - // TM: Number of digits (4 or 6) #ifdef LEDCONTROL_NO_BUF // For TM, buffer can't be static (= shared): either we are building // the extended version (which adds a per-unit buffer instead of the static one) // or we are forced to resort to digit-by-digit output - static uint8_t rawdata[16]; + static uint8_t *rawdata; #else - uint8_t rawdata[16]; + uint8_t *rawdata; #endif uint8_t maxUnits = 0; // MAX: N. of chained units; TM: N. of digits @@ -82,6 +80,7 @@ class LedControl void setPattern(uint8_t addr, uint8_t digit, uint8_t value, bool sendNow = true); // MAX-specific + uint8_t *digitBuffer; // each digit must be stored in a buffer to be able to set single segments void setScanLimit(uint8_t addr, uint8_t limit); void spiTransfer(uint8_t addr, uint8_t opcode, uint8_t data); @@ -103,7 +102,7 @@ class LedControl public: LedControl(){}; - void begin(uint8_t type, uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices = 1); + bool begin(uint8_t type, uint8_t dataPin, uint8_t clkPin, uint8_t csPin, uint8_t numDevices = 1); bool isMAX(void) { return _type == LedSegment::TYPE_MAX72XX; } uint8_t getDeviceCount(void) { return (isMAX() ? maxUnits : 1); }; @@ -139,6 +138,16 @@ class LedControl // Ignored for MAX, or if LEDCONTROL_NO_BUF is defined. void setChar(uint8_t addr, uint8_t digit, char value, bool dp = false, bool sendNow = true); + // Display a Single Segment. + // Params: + // addr address of the display (ignored for TM) + // segment the segment to be set or unset + // value set or unset the Segment + // sendnow If false, buffers chars rather than sending them immediately (TM only; + // requires a sendAll() afterwards). + // Ignored for MAX, or if LEDCONTROL_NO_BUF is defined. + void setSingleSegment(uint8_t addr, uint8_t segment, uint8_t value, bool sendNow = true); + #ifndef LEDCONTROL_NO_BUF // Sends the whole (previously filled) buffer content. void sendAll(void) { writeBuffer(); }; diff --git a/src/MF_Segment/LedSegment.cpp b/src/MF_Segment/LedSegment.cpp index fa2c7c3b..00715997 100644 --- a/src/MF_Segment/LedSegment.cpp +++ b/src/MF_Segment/LedSegment.cpp @@ -27,8 +27,15 @@ namespace LedSegment { if (ledSegmentsRegistered == ledSegmentsRegistereds) return; + ledSegments[ledSegmentsRegistered] = MFSegments(); - ledSegments[ledSegmentsRegistered].attach(type, dataPin, csPin, clkPin, numDevices, brightness); + + if (!ledSegments[ledSegmentsRegistered].attach(type, dataPin, csPin, clkPin, numDevices, brightness)) + { + cmdMessenger.sendCmd(kStatus, F("Led Segment array does not fit into Memory")); + return; + } + ledSegmentsRegistered++; #ifdef DEBUG2CMDMESSENGER cmdMessenger.sendCmd(kDebug, F("Added Led Segment")); @@ -78,6 +85,22 @@ namespace LedSegment int brightness = cmdMessenger.readInt16Arg(); ledSegments[module].setBrightness(subModule, brightness); } + + void OnSetModuleSingleSegment() + { + uint8_t module = (uint8_t)cmdMessenger.readInt16Arg(); + uint8_t subModule = (uint8_t)cmdMessenger.readInt16Arg(); + char *segment = cmdMessenger.readStringArg(); // 0 to 63, multiple segments deliminited by '|' + uint8_t on_off = (uint8_t)cmdMessenger.readInt16Arg(); // 0 or 1 + + char *pinTokens = strtok(segment, "|"); + while (pinTokens != 0) { + uint8_t num = (uint8_t)atoi(pinTokens); + ledSegments[module].setSingleSegment(subModule, num, on_off); + pinTokens = strtok(0, "|"); + } + } + } // namespace // LedSegment.cpp diff --git a/src/MF_Segment/LedSegment.h b/src/MF_Segment/LedSegment.h index b3af44b8..914ef0c6 100644 --- a/src/MF_Segment/LedSegment.h +++ b/src/MF_Segment/LedSegment.h @@ -22,6 +22,7 @@ namespace LedSegment void OnInitModule(); void OnSetModule(); void OnSetModuleBrightness(); + void OnSetModuleSingleSegment(); } // LedSegment.h diff --git a/src/MF_Segment/MFSegments.cpp b/src/MF_Segment/MFSegments.cpp index c9575e17..a3351465 100644 --- a/src/MF_Segment/MFSegments.cpp +++ b/src/MF_Segment/MFSegments.cpp @@ -5,6 +5,7 @@ // #include "MFSegments.h" +#include "commandmessenger.h" MFSegments::MFSegments() { @@ -26,10 +27,20 @@ void MFSegments::display(uint8_t module, char *string, uint8_t points, uint8_t m } } +void MFSegments::setSingleSegment(uint8_t module, uint8_t segment, uint8_t on_off) +{ + if (_moduleCount == 0) + return; + + _ledControl.setSingleSegment(module, segment, on_off); + +} + void MFSegments::setBrightness(uint8_t module, uint8_t value) { if (_moduleCount == 0) return; + if (module < _moduleCount) { if (value) { _ledControl.setIntensity(module, value - 1); @@ -40,15 +51,20 @@ void MFSegments::setBrightness(uint8_t module, uint8_t value) } } -void MFSegments::attach(uint8_t type, uint8_t dataPin, uint8_t csPin, uint8_t clkPin, uint8_t moduleCount, uint8_t brightness) +bool MFSegments::attach(uint8_t type, uint8_t dataPin, uint8_t csPin, uint8_t clkPin, uint8_t moduleCount, uint8_t brightness) { - _ledControl.begin(type, dataPin, clkPin, csPin, moduleCount); + if (!_ledControl.begin(type, dataPin, clkPin, csPin, moduleCount)) + return false; + _moduleCount = moduleCount; + for (uint8_t i = 0; i < _moduleCount; ++i) { setBrightness(i, brightness); _ledControl.shutdown(i, false); _ledControl.clearDisplay(i); } + + return true; } void MFSegments::detach() diff --git a/src/MF_Segment/MFSegments.h b/src/MF_Segment/MFSegments.h index 81f4ca14..a33c5a47 100644 --- a/src/MF_Segment/MFSegments.h +++ b/src/MF_Segment/MFSegments.h @@ -14,11 +14,12 @@ class MFSegments public: MFSegments(); void display(uint8_t module, char *string, uint8_t points, uint8_t mask, bool convertPoints = false); - void attach(uint8_t type, uint8_t dataPin, uint8_t csPin, uint8_t clkPin, uint8_t moduleCount, uint8_t brightness); + bool attach(uint8_t type, uint8_t dataPin, uint8_t csPin, uint8_t clkPin, uint8_t moduleCount, uint8_t brightness); void detach(); void test(); void powerSavingMode(bool state); void setBrightness(uint8_t module, uint8_t value); + void setSingleSegment(uint8_t module, uint8_t segment, uint8_t on_off); private: LedControl _ledControl; diff --git a/src/commandmessenger.h b/src/commandmessenger.h index eddfd1a3..19580b38 100644 --- a/src/commandmessenger.h +++ b/src/commandmessenger.h @@ -45,6 +45,7 @@ enum { kDigInMuxChange, // 30 kSetStepperSpeedAccel, // 31 kSetCustomDevice, // 32 + kSetModuleSingleSegment, // 33 kDebug = 0xFF // 255 };