From 2db58eb1d7164300ca310e76f7422f04402b25e5 Mon Sep 17 00:00:00 2001 From: Gaby Goldman <82763943+GabyGold67@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:23:21 +0200 Subject: [PATCH] v1.3.0 Draft --- README.md | 85 +++++++------- keywords.txt | 6 +- library.json | 2 +- library.properties | 2 +- src/SevenSeg-74HC595.cpp | 242 ++++++++++++++++++++++++++++----------- src/SevenSeg-74HC595.h | 39 ++++++- 6 files changed, 261 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index 39c5a91..99052f5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ Originally developed to easily display numeric and text data on the cheap and po ![4-Bits LED Digital Tube Module](https://github.com/GabyGold67/FourBitLedDigitalTube/blob/master/extras/4-BitsLedDigitalTubeModule01.jpg "4-Bits LED Digital Tube Module") ## Ease of use: -Instance the class passing just 3 parameters (the 3 pins connected to the display module), notify the object and it's ready to go: start ``.print()``ing the data to the display. There's no need of even setting those pin modes. +_ Instance the class passing just 3 parameters (the 3 pins connected to the display module) +_ Notify the object and it's ready to go +_ start ``.print()``ing the data to the display. +There's no need of even setting the pin modes. ## Flexibility: Integers, floating point or strings they'll show as long as the display is capable of doing so in a trustworthy way. If you need to represent a percentage or level of completeness a ``.gauge()`` and a ``.doubleGauge()`` methods are included to represent them in a "Old Motorola brick cell phones' style". The library is capable of managing a correct representation even in differently wired displays by letting configure the order in wich the digits are connected to the registers. @@ -38,6 +41,8 @@ The first mechanism frees the user from the load of calling the refreshing metho |**gauge()**|int **level** (, char **label**)| ||double **level** (, char **label**)| |**getDigitsQty()**|None| +|**getDspValMax()**|None| +|**getDspValMin()**|None| |**getInstanceNbr()**|None| |**getMaxBlinkRate()**|None| |**getMinBlinkRate()**|None| @@ -224,7 +229,7 @@ false: Otherwise, being that the **level** parameter was out of range and/or the --- ### **getDigitsQty**(); ### Description: -Returns an unsigned short integer value indicating the the quantity of digits, or ports, the display have as indicated at the object instantiation. Each time the class is instantiated the object is created with the needed resources and the range of values are calculated based on the dspDigits parameter, and that value is the returned by this method. +Returns an unsigned short integer value indicating the the quantity of digits, or ports, the display have as declared at the object instantiation. Each time the class is instantiated the object is created with the needed resources and the range of values are calculated based on the dspDigits parameter, and that value is the one returned by this method. ### Parameters: **None** ### Return value: @@ -232,6 +237,28 @@ The unsigned short number indicating the quantity of digits of the instantiated ### Use example: **`uint8_t portsQty = myLedDisp.getDigistsQty();`** +--- +### **getDspValMax**(); +### Description: +Returns a long integer value indicating the greatest displayable number according to the quantity of digits, or ports, the display have as indicated at the object instantiation. +### Parameters: +**None** +### Return value: +The integer number indicating the maximum value that the display might display acording to the quantity of digits of the instantiated display. +### Use example: +**`long maxLimit = myLedDisp.getDspMax();`** + +--- +### **getDspValMin**(); +### Description: +Returns a long integer value indicating the smallest displayable number according to the quantity of digits, or ports, the display have as indicated at the object instantiation. +### Parameters: +**None** +### Return value: +The integer number indicating the minimum value that the display might display acording to the quantity of digits of the instantiated display. +### Use example: +**`long minLimit = myLedDisp.getDspMin();`** + --- ### **getInstanceNbr**(); ### Description: @@ -344,9 +371,8 @@ Displays an integer value as long as the length representation fits the availabl **zeroPad:** Boolean, optional parameter (if not specified the default value, false, will be assumed), indicates if the heading free spaces of the integer right aligned displayed must be filled with zeros (true) or spaces (false). In the case of a negative integer the spaces or zeros will fill the gap between the '-' sign kept in the leftmost position, and the first digit. ### Return value: true: If the value could be represented. -false: Otherwise, and the display will be blanked. - -### Use example (on a 4-bits display): +false: Otherwise, and the display will be blanked. +### Use example: **`myLedDisp.print(12);`** //Displays '**``12 ``**' on a 4 digits display **`myLedDisp.print(12, true);`** //Displays '**`` 12``**' on a 4 digits display **`myLedDisp.print(12, true, true);`** //Displays '**``0012``**' on a 4 digits display @@ -365,7 +391,7 @@ Displays a floating point value as long as the length representation fits the av **zeroPad:** Boolean, optional parameter (if not specified the default value, false, will be assumed), indicates if the heading free spaces of the value right aligned displayed must be filled with zeros (true) or spaces (false). In the case of a negative value the spaces or zeros will fill the gap between the '-' sign kept in the leftmost position, and the first digit. ### Return value: true: If the value could be represented. -false: Otherwise, and the display will be blanked. +false: Otherwise, and the display will be blanked. ### Use example (on a 4-bits display): **`myLedDisp.print(1.2, 2);`** //Displays '**``1.20 ``**' **`myLedDisp.print(1.2, 2, true);`** //Displays '**`` 1.20``**' @@ -378,7 +404,7 @@ false: Otherwise, and the display will be blanked. --- ### **refresh**(); ### Description: -Refreshes the display, **all available digits per call**, the method takes care of registering which digit was redrawn first and each call starts from the next until the last is reached and then restart from the first, to minimize ghosting and keep all the digits brightness even, and uses pre-built **`shiftOut()`** kind of methods. This working criteria has two consequences: +Refreshes the display, **all available digits per call**, the method takes care of registering which digit was redrawn first and each call starts from the next until the last is reached and then restart from the first, to minimize ghosting and keep all the digits brightness even, and uses pre-built **`shiftOut()`** kind of methods. This working criteria has two consequences: * The method works slower than the **`fastRefresh()`**, so it will take more time to execute. * When used by the developer to refresh the display from the code it will avoid ghosting or blinking effects being called less frequently to keep the display's cinematic effect. ### Parameters: @@ -417,9 +443,8 @@ None Changes the blinking mask that indicates which digits will be involved after a **`blink()`** method is invoked. Indicating true for a digit makes it blink when the method is called, indicating false makes it display steady independently of the others. The parameter is positional referenced to the display, and for ease of use the index numbers of the array indicate their position relative to the rightmost digit (blnkPort0). The mask might be reset to its original value (all digits set to blink) by using this method with all parameters set to **true** or by using the **`.resetBlinkMask()`** method. ### Parameters: -**blnkPort[]**: array of booleans of length **dspDigits**, indexes are positional referenced to the display, indicating each one which digits must blink after a **`blink()`** method is invoked (true) or stay steady (false). The indexes valid range is 0 <= index <= (dspDigits-1), corresponding the [0] position withe the rightmost display port, the [1] position the second from the right and so on . - -### Return value: +**blnkPort[]**: array of booleans of length **dspDigits**, indexes are positional referenced to the display, indicating each one which digits must blink after a **`blink()`** method is invoked (true) or stay steady (false). The indexes valid range is 0 <= index <= (dspDigits-1), corresponding the [0] position withe the rightmost display port, the [1] position the second from the right and so on. + ### Return value: None. ### Use example: **`bool tstMask[4]{true, true, true, true};`** @@ -435,7 +460,6 @@ None. **`myLedDisp.setBlinkMask(tstMask);`** //Sets the two central digits to blink in a 4 digits display --- - ### **setBlinkRate**(unsigned long **onRate**(,unsigned long **offRate**)); ### Description: Changes the time parameters to use for the display blinking the contents it shows. The parameters change will take immediate effect, either if the display is already blinking or not, in the latter case the parameters will be the ones used when a **`blink()`** method is called without parameters. The blinking will be **symmetrical** if only one parameter is passed, **asymmetrical** if two different parameters are passed, meaning that the time the display shows the contents and the time the display is blank will be equal (symmetrical) or not (asymmetrical), depending of those two parameters. The blink rate set will be kept after a **`.noBlink()`** or new **`.blink()`** without parameters call is done, until it is modified with a new **`.setBlinkRate()`** call, or it is restarted by a **`.blink()`** with parameters. Note that to restart the blinking with a **`.blink()`** the service must first be stopped, as the method makes no changes if the blinking service was already running. @@ -452,7 +476,6 @@ false: One or more of the parameters passed were out of range. The rate change w **`myLedDisp.setBlinkRate(600, 3500);`** //Returns false and the display blinking rate stays without change. --- - ### **setDigitsOrder**(uint8_t* **newOrderPtr**); ### Description: As different 7 segments dynamic displays based on two 74HC595 are differently wired, some implement the leftmost display port as the LSb of the shift register driving the port selection, some implement it as the MSb. When more than one display modules are used it adds a new level of hardware implementation that differs from one supplier to the other. The library implements a mechanism to provide the instantiated object to relate the positions of the display ports to the bits of the selection byte through an array. The array has the size of the display instantiated, and each array elment is meant to hold the number of the bit that selects the corresponding port, being the first element of the array (array[0]) the corresponding to the leftmost display digit, array[1], the next to it's right and so on. The array is default defined in the constructor as (0, 1, 2,...) that is the most usual implementation found. If the order needs to be changed the `.setDigitsOrder()` method is the way to set a new mapping. @@ -580,27 +603,12 @@ Class constructor, creates an instance of the class for each display to use. The **zeroPad:** Boolean, optional parameter (if not specified the default value, false, will be assumed), indicates if the heading free spaces of the integer right aligned displayed must be filled with zeros (true) or spaces (false). In the case of a negative integer the spaces or zeros will fill the gap between the '-' sign kept in the leftmost position, and the first digit. **commAnode:** bool, indicates if the display uses common anode seven segment LED digits (**true** value, default to keep the implementation backwards compatible), or common cathode kind (**false** value). The use of one kind or the other makes a difference in the fact that one is complementary of the other, meaning a translation must be done on the information sent to the display. Each display instantiated by the class might be independently set up as one kind or the other. **dspDigits:** uint8_t (unsigned char), passes the number of digits in the instantiated display, the default value is 4, to keep the implementation backwards compatible. - - ### Return value: -The object created. - +The object created. ### Use example: **`ClickCounter myClickCounter(6, 7, 10, true, true);`** **`ClickCounter myClickCounter(6, 7, 10, true, true, true, 5);`** // 5 digits common anode counter ---- -### **countBegin**(); -### Description: -Refer to **SevenSeg74HC595::begin()** method. -### Parameters: -None -### Return value: -Refer to **SevenSeg74HC595::begin()** method. - -### Use example: -**`myClickCounter.countBegin();`** - --- ### **blink**(); ### Description: @@ -630,11 +638,11 @@ false: The display was already set to blink, and/or one or more of the parameter --- ### **countBegin**(int **startVal**); ### Description: -Attaches the display to a timer interrupt service, as described in the **SevenSeg74HC595::begin()** method. The display then is started with the current count value represented according to the selected options of alignement and padding. +Attaches the display to a timer interrupt service, as described in the **SevenSeg74HC595::begin()** method. The display then is started with the **startVal** count value, or **0** if no parameter is provided, represented according to the selected options of alignement and padding. ### Parameters: startVal: Optional integer value at wich the counter starts which must be in the range (-1)*(pow(10, (dspDigits - 1)) - 1) <= startValue <= (pow(10, dspDigits) - 1). ### Return value: -true: If the display could be attached to the ISR, or if the display was already attached to it, and the startValue was within the valid limits. +true: If the display could be attached to the ISR, or if the display was already attached to it, and the startValue was within the valid representable values range according to dspDigits. false: If the display couldn't be attached to the ISR, due to lack of free slots, or the startValue was out of range. ### Use example: **`myClickCounter.countBegin();`** @@ -674,8 +682,7 @@ Restarts the count from the value provided as parameter. The display is updated restartValue: Optional integer value, a value of 0 is set if no parameter is provided. The parameter must be in the range (-1)*(pow(10, (dspDigits - 1)) - 1) <= restartValue <= (pow(10, dspDigits) - 1). ### Return value: true: If the parameter value was within valid range. -false: If the parameter value was outside valid range. - +false: If the parameter value was outside valid range. ### Use example: **`myClickCounter.countRestart();`** //sets the counter to 0 **`myClickCounter.countRestart(-100);`** //Sets the counter to -100 if the display is more than 3 digits long, false otherwise @@ -688,8 +695,7 @@ Refer to **SevenSeg74HC595::stop()** method. ### Parameters: **None** ### Return value: -Refer to **SevenSeg74HC595::stop()** method. - +Refer to **SevenSeg74HC595::stop()** method. ### Use example: **`myClickCounter.countStop();`** @@ -717,9 +723,9 @@ qty: Optional integer value, its **absolute** value will be incremented in the c true: If the count could be incremented by the corresponding value without setting count out of range. The counter value will be updated false: If the count couldn't be incremented by the parameter value without getting out of range. The counter will keep its current value. ### Use example: -**`myClickCounter.countDown();`** //Decrements the current count by 1 -**`myClickCounter.countDown(2);`** //Decrements the current count by 2 -**`myClickCounter.countDown(-2);`** //Decrements the current count by 2 +**`myClickCounter.countUp();`** //Increments the current count by 1 +**`myClickCounter.countUp(2);`** //Increments the current count by 2 +**`myClickCounter.countUp(-2);`** //Increments the current count by 2 --- ## **getCount()**; @@ -730,7 +736,7 @@ None. ### Return value: The current value held by the counter, due to the 4 digits limitations, it will be in the range (-1)*(pow(10, (dspDigits - 1)) - 1) <= counter <= (pow(10, dspDigits) - 1) ### Use example: -int finalCount = **`myClickCounter.getCount();`** +**`long finalCount = myClickCounter.getCount();`** --- ## **getStartVal()** @@ -741,7 +747,7 @@ None. ### Return value: The value to wich the counter was originally started, it will be in the range (-1)*(pow(10, (dspDigits - 1)) - 1) <= counter <= (pow(10, dspDigits) - 1) ### Use example: -int countStarted = **`myClickCounter.getStartVal();`** +**`long countStarted = myClickCounter.getStartVal();`** --- ### **noBlink**(); @@ -766,7 +772,6 @@ Refer to **SevenSeg74HC595::setBlinkRate()** method. ### Use example: **`myClickCounter.setBlinkRate(400);`** //Returns true and sets the blinking rate to 400 millisecs on, 400 millisecs off (symmetrical blink). **`myClickCounter.setBlinkRate(800, 200);`** //Returns true and sets the blinking rate to 800 millisecs on, 200 millisecs off (asymmetrical blink) -**`myClickCounter.setBlinkRate(3000);`** //Returns false and the display blinking rate stays without change. **`myClickCounter.setBlinkRate(600, getMaxBlinkRate() + 500);`** //Returns false and the display blinking rate stays without change. --- diff --git a/keywords.txt b/keywords.txt index a10f599..eea87f4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -21,6 +21,9 @@ doubleGauge KEYWORD2 fastRefresh KEYWORD2 fastSend KEYWORD2 gauge KEYWORD2 +getDigitsQty KEYWORD2 +getDspValMax KEYWORD2 +getDspValMin KEYWORD2 getInstanceNbr KEYWORD2 getMaxBlinkRate KEYWORD2 getMinBlinkRate KEYWORD2 @@ -57,4 +60,5 @@ updDisplay KEYWORD2 ############################################### # Constants (LITERAL1) ############################################### - +_minBlinkRate LITERAL1 +_maxBlinkRate LITERAL1 diff --git a/library.json b/library.json index 210bcea..9df2949 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "SevenSegDisplays", - "version": "1.2.0", + "version": "1.3.0", "description": "7 segment 1 to 8 digits LED display easy to use and powerful library for modules based on 74HC595 (or similar) shift registers chips. Developed for the cheap and popular '4-bit Led Digital Tube Module' (**_and for all the custom made displays as: GIANTS COUNTERS, TIMERS, PRICING DISPLAYS, etc._**) based on two 74HC595 (or similar) shift registers, the main focus was set on: ease of use, flexibility and basic prevention of 'misrepresentation' errors.", "keywords": "7 Segment, 4 digits, 74HC595, LED, display, print, blink, gauge, floating point, negative, shift register, counter, tally counter, click counter", diff --git a/library.properties b/library.properties index cc788fe..6f92bc7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SevenSegDisplays -version=1.2.0 +version=1.3.0 author=Gabriel D. Goldman maintainer=Gabriel D. Goldman sentence=7 segment 4 digits (and extended to generic 1 to 8 digits) LED display easy to use and powerful library for modules based on two 74HC595 (or similar) shift registers chips diff --git a/src/SevenSeg-74HC595.cpp b/src/SevenSeg-74HC595.cpp index 3cce7b9..8511b7b 100644 --- a/src/SevenSeg-74HC595.cpp +++ b/src/SevenSeg-74HC595.cpp @@ -5,12 +5,16 @@ const uint8_t diyMore8Bits[8] {3, 2, 1, 0, 7, 6, 5, 4}; const uint8_t noName4Bits[4] {0, 1, 2, 3}; const int MAX_DIGITS_DISPLAYS{8}; -uint8_t SevenSeg74HC595::_displaysCount = 0; -uint8_t SevenSeg74HC595::_dspPtrArrLngth = 10; -SevenSeg74HC595** SevenSeg74HC595::_instancesLstPtr = nullptr; -TimerHandle_t SevenSeg74HC595::_dspRfrshTmrHndl = nullptr; +uint8_t SevenSegDisplays::_displaysCount = 0; +uint8_t SevenSegDisplays::_dspPtrArrLngth = 10; +SevenSegDisplays** SevenSegDisplays::_instancesLstPtr = nullptr; +TimerHandle_t SevenSegDisplays::_dspRfrshTmrHndl = nullptr; -SevenSeg74HC595::SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode, const uint8_t dspDigits) +SevenSegDisplays::SevenSegDisplays() +{ +} + +SevenSegDisplays::SevenSegDisplays(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode, const uint8_t dspDigits) :_sclk{sclk}, _rclk{rclk}, _dio{dio}, _commAnode{commAnode}, _dspDigits{dspDigits}, _digitPosPtr{new uint8_t[dspDigits]}, _digitPtr{new uint8_t [dspDigits]}, _blinkMaskPtr{new bool [dspDigits]} { // Configure display communications pins @@ -18,7 +22,12 @@ SevenSeg74HC595::SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool c pinMode(_rclk, OUTPUT); pinMode(_dio, OUTPUT); - if(_dspDigits > 1){ //Calculate the minimum integer value dispayable with this display's available digits + setAttrbts(); + clear(); +} + +void SevenSegDisplays::setAttrbts(){ + if(_dspDigits > 1){ //Calculate the minimum integer value displayable with this display's available digits _dspValMin = 1; for (uint8_t i{0}; i < (_dspDigits - 1); i++) _dspValMin *= 10; @@ -27,7 +36,7 @@ SevenSeg74HC595::SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool c else _dspValMin = 0; - _dspValMax = 1; //Calculate the maximum integer value dispayable with this display's available digits, create a Zero and a Space padding string for right alignement + _dspValMax = 1; //Calculate the maximum integer value displEayable with this display's available digits, create a Zero and a Space padding string for right alignement for (uint8_t i{0}; i < _dspDigits; i++){ _dspValMax *= 10; _zeroPadding += "0"; @@ -47,11 +56,11 @@ SevenSeg74HC595::SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool c for(int i {0}; i < (int)_charSet.length(); i++) _charLeds[i] = ~_charLeds[i]; } - - clear(); + + return; } -SevenSeg74HC595::~SevenSeg74HC595(){ +SevenSegDisplays::~SevenSegDisplays(){ stop(); //Frees the slot in the pointers array for the refresh timer, and stops the timer if there are no valid pointers left delete [] _digitPtr; //Free the resources of the digits buffer delete [] _digitPosPtr; @@ -60,7 +69,7 @@ SevenSeg74HC595::~SevenSeg74HC595(){ --_displaysCount; } -bool SevenSeg74HC595::begin(){ +bool SevenSegDisplays::begin(){ bool result {false}; int frstFreeSlot{-1}; BaseType_t tmrModResult {pdFAIL}; @@ -73,7 +82,7 @@ bool SevenSeg74HC595::begin(){ pdMS_TO_TICKS((int)(1000/(30 * MAX_DIGITS_DISPLAYS))), pdTRUE, //Autoreload NULL, //TimerID, data to be passed to the callback function - SevenSeg74HC595::tmrCbRefresh //Callback function + SevenSegDisplays::tmrCbRefresh //Callback function ); } @@ -81,7 +90,7 @@ bool SevenSeg74HC595::begin(){ // Include the object's pointer to the array of pointers to be serviced by the timer Callback, // If this is the first instance created, create the array of instances in Heap if(_instancesLstPtr == nullptr){ - _instancesLstPtr = new SevenSeg74HC595* [_dspPtrArrLngth]; + _instancesLstPtr = new SevenSegDisplays* [_dspPtrArrLngth]; for(int i{0}; i < _dspPtrArrLngth; i++) *(_instancesLstPtr + i) = nullptr; } @@ -113,7 +122,7 @@ bool SevenSeg74HC595::begin(){ return result; } -bool SevenSeg74HC595::blink(){ +bool SevenSegDisplays::blink(){ bool result {false}; if (!_blinking){ @@ -126,7 +135,7 @@ bool SevenSeg74HC595::blink(){ return result; } -bool SevenSeg74HC595::blink(const unsigned long &onRate, const unsigned long &offRate){ +bool SevenSegDisplays::blink(const unsigned long &onRate, const unsigned long &offRate){ bool result {false}; if (!_blinking){ @@ -141,7 +150,7 @@ bool SevenSeg74HC595::blink(const unsigned long &onRate, const unsigned long &of return result; } -void SevenSeg74HC595::clear(){ +void SevenSegDisplays::clear(){ //Cleans the contents of the internal display buffer (All leds off for all digits) for (int i{0}; i < _dspDigits; i++){ *(_digitPtr + i) = _space; @@ -151,7 +160,7 @@ void SevenSeg74HC595::clear(){ return; } -bool SevenSeg74HC595::doubleGauge(const int &levelLeft, const int &levelRight, char labelLeft, char labelRight){ +bool SevenSegDisplays::doubleGauge(const int &levelLeft, const int &levelRight, char labelLeft, char labelRight){ bool displayable{true}; String readOut{""}; @@ -204,7 +213,7 @@ bool SevenSeg74HC595::doubleGauge(const int &levelLeft, const int &levelRight, c return displayable; } -void SevenSeg74HC595::fastRefresh(){ +void SevenSegDisplays::fastRefresh(){ bool tmpLogic {true}; updBlinkState(); @@ -227,7 +236,7 @@ void SevenSeg74HC595::fastRefresh(){ return; } -void SevenSeg74HC595::fastSend(uint8_t content){ +void SevenSegDisplays::fastSend(uint8_t content){ //Sends the byte value (char <=> unsigned short int) to the 4 7-segment display bit by bit //by direct manipulation of the microcontroller pins. There is no time added, so the total time //consumed to shift an entire byte is supposed to be the lowest achievable in this level of abstraction. @@ -246,7 +255,7 @@ void SevenSeg74HC595::fastSend(uint8_t content){ return; } -void SevenSeg74HC595::fastSend(const uint8_t &segments, const uint8_t &port){ +void SevenSegDisplays::fastSend(const uint8_t &segments, const uint8_t &port){ // Sends the character 'segments' to the digit 'port' of the display // Content and Port must be sent in two sequencial parts, character first, port second // so this overloaded two char fastSend() method uses the one char fastSend() method twice and then moves @@ -261,7 +270,7 @@ void SevenSeg74HC595::fastSend(const uint8_t &segments, const uint8_t &port){ return; } -bool SevenSeg74HC595::gauge(const int &level, char label){ +bool SevenSegDisplays::gauge(const int &level, char label){ bool displayable{true}; String readOut{""}; @@ -293,7 +302,7 @@ bool SevenSeg74HC595::gauge(const int &level, char label){ return displayable; } -bool SevenSeg74HC595::gauge(const double &level, char label) { +bool SevenSegDisplays::gauge(const double &level, char label) { bool displayable{true}; int intLevel{0}; @@ -316,37 +325,47 @@ bool SevenSeg74HC595::gauge(const double &level, char label) { return displayable; } -uint8_t SevenSeg74HC595::getDigitsQty(){ +uint8_t SevenSegDisplays::getDigitsQty(){ return _dspDigits; } -uint8_t SevenSeg74HC595::getInstanceNbr(){ +uint32_t SevenSegDisplays::getDspValMax(){ + + return _dspValMax; +} + +uint32_t SevenSegDisplays::getDspValMin(){ + + return _dspValMin; +} + +uint8_t SevenSegDisplays::getInstanceNbr(){ return _dispInstNbr; } -unsigned long SevenSeg74HC595::getMaxBlinkRate(){ +unsigned long SevenSegDisplays::getMaxBlinkRate(){ return _maxBlinkRate; } -unsigned long SevenSeg74HC595::getMinBlinkRate(){ +unsigned long SevenSegDisplays::getMinBlinkRate(){ return _minBlinkRate; } -bool SevenSeg74HC595::isBlinking(){ +bool SevenSegDisplays::isBlinking(){ return _blinking; } -bool SevenSeg74HC595::isWaiting(){ +bool SevenSegDisplays::isWaiting(){ return _waiting; } -bool SevenSeg74HC595::noBlink(){ +bool SevenSegDisplays::noBlink(){ bool result {false}; if(_blinking){ @@ -359,7 +378,7 @@ bool SevenSeg74HC595::noBlink(){ return result; } -bool SevenSeg74HC595::noWait(){ +bool SevenSegDisplays::noWait(){ bool result {false}; if (_waiting){ @@ -372,7 +391,7 @@ bool SevenSeg74HC595::noWait(){ return result; } -bool SevenSeg74HC595::print(String text){ +bool SevenSegDisplays::print(String text){ bool displayable{true}; int position{-1}; String tempText{""}; @@ -420,7 +439,7 @@ bool SevenSeg74HC595::print(String text){ return displayable; } -bool SevenSeg74HC595::print(const int32_t &value, bool rgtAlgn, bool zeroPad){ +bool SevenSegDisplays::print(const int32_t &value, bool rgtAlgn, bool zeroPad){ bool displayable{true}; String readOut{""}; @@ -449,7 +468,7 @@ bool SevenSeg74HC595::print(const int32_t &value, bool rgtAlgn, bool zeroPad){ return displayable; } -bool SevenSeg74HC595::print(const double &value, const unsigned int &decPlaces, bool rgtAlgn, bool zeroPad){ +bool SevenSegDisplays::print(const double &value, const unsigned int &decPlaces, bool rgtAlgn, bool zeroPad){ bool displayable{true}; String readOut{""}; String pad{""}; @@ -492,7 +511,7 @@ bool SevenSeg74HC595::print(const double &value, const unsigned int &decPlaces, return displayable; } -void SevenSeg74HC595::refresh(){ +void SevenSegDisplays::refresh(){ bool tmpLogic {true}; uint8_t tmpDigToSend{0}; @@ -524,22 +543,24 @@ void SevenSeg74HC595::refresh(){ return; } -void SevenSeg74HC595::resetBlinkMask(){ +void SevenSegDisplays::resetBlinkMask(){ for (uint8_t i{0}; i < _dspDigits; i++) *(_blinkMaskPtr + i) = true; return; } -void SevenSeg74HC595::send(const uint8_t &content){ +void SevenSegDisplays::send(const uint8_t &content){ //Sends the byte value (char <=> unsigned short int) to the 4 7-segment display bit by bit //by using the shiftOut() function. The time added (or not) to send it bit is unknown, so the total time //consumed to shift an entire byte is unknown, issue that must be considered when the method is invoked //from an ISR and multiple times depending on the qty of displays being used shiftOut(_dio, _sclk, MSBFIRST, content); + + return; } -void SevenSeg74HC595::send(const uint8_t &segments, const uint8_t &port){ +void SevenSegDisplays::send(const uint8_t &segments, const uint8_t &port){ // Sends the character 'segments' to the digit 'port' of the display // Content and Port must be sent in two sequencial parts, character first, port second // so this overloaded two char send method uses the one char send method twice and then moves @@ -549,16 +570,19 @@ void SevenSeg74HC595::send(const uint8_t &segments, const uint8_t &port){ send(segments); send(port); digitalWrite(_rclk, HIGH); + + return; } -void SevenSeg74HC595::setBlinkMask(const bool blnkPort[]){ + +void SevenSegDisplays::setBlinkMask(const bool blnkPort[]){ for (int i{0}; i < _dspDigits; i++) *(_blinkMaskPtr + i) = blnkPort[i]; return; } -bool SevenSeg74HC595::setBlinkRate(const unsigned long &newOnRate, const unsigned long &newOffRate){ +bool SevenSegDisplays::setBlinkRate(const unsigned long &newOnRate, const unsigned long &newOffRate){ bool result {false}; if ((newOnRate >= _minBlinkRate) && newOnRate <= _maxBlinkRate) { @@ -578,7 +602,7 @@ bool SevenSeg74HC595::setBlinkRate(const unsigned long &newOnRate, const unsigne return result; } -bool SevenSeg74HC595::setDigitsOrder(uint8_t* newOrderPtr){ +bool SevenSegDisplays::setDigitsOrder(uint8_t* newOrderPtr){ bool result{true}; for(int i {0}; i < _dspDigits; i++){ @@ -596,7 +620,7 @@ bool SevenSeg74HC595::setDigitsOrder(uint8_t* newOrderPtr){ return result; } -bool SevenSeg74HC595::setWaitChar (const char &newChar){ +bool SevenSegDisplays::setWaitChar (const char &newChar){ bool result {false}; int position {-1}; @@ -614,7 +638,7 @@ bool SevenSeg74HC595::setWaitChar (const char &newChar){ return result; } -bool SevenSeg74HC595::setWaitRate(const unsigned long &newWaitRate){ +bool SevenSegDisplays::setWaitRate(const unsigned long &newWaitRate){ bool result {false}; if ((newWaitRate >= _minBlinkRate) && newWaitRate <= _maxBlinkRate) { @@ -628,7 +652,7 @@ bool SevenSeg74HC595::setWaitRate(const unsigned long &newWaitRate){ return result; } -bool SevenSeg74HC595::stop() { +bool SevenSegDisplays::stop() { //This object's pointer will be deleted from the arrays of pointers. If the array has no more valid pointers the timer will be stopped to avoid loosing processing time. bool pointersFound(false); bool result {false}; @@ -661,8 +685,8 @@ bool SevenSeg74HC595::stop() { return result; } -void SevenSeg74HC595::tmrCbRefresh(TimerHandle_t dspTmrCbArg){ - SevenSeg74HC595 **argObj = (SevenSeg74HC595**)pvTimerGetTimerID(dspTmrCbArg); +void SevenSegDisplays::tmrCbRefresh(TimerHandle_t dspTmrCbArg){ + SevenSegDisplays **argObj = (SevenSegDisplays**)pvTimerGetTimerID(dspTmrCbArg); //Timer Callback to keep the display lit by calling each display's fastRefresh() method for(uint8_t i {0}; i < _dspPtrArrLngth; i++){ @@ -673,7 +697,7 @@ void SevenSeg74HC595::tmrCbRefresh(TimerHandle_t dspTmrCbArg){ return; } -void SevenSeg74HC595::updBlinkState(){ +void SevenSegDisplays::updBlinkState(){ //The use of a xTimer that keeps flip-floping the _blinkShowOn value is better suited for symmetrical blinking, but not for assymetrical cases. if (_blinking == true){ if (_blinkShowOn == false) { @@ -702,7 +726,7 @@ void SevenSeg74HC595::updBlinkState(){ return; } -void SevenSeg74HC595::updWaitState(){ +void SevenSegDisplays::updWaitState(){ if (_waiting == true){ if (_waitTimer == 0){ for (int i{0}; i < _dspDigits; i++) @@ -727,7 +751,7 @@ void SevenSeg74HC595::updWaitState(){ return; } -bool SevenSeg74HC595::wait(const unsigned long &newWaitRate){ +bool SevenSegDisplays::wait(const unsigned long &newWaitRate){ bool result {true}; if (_waiting == false){ @@ -753,7 +777,7 @@ bool SevenSeg74HC595::wait(const unsigned long &newWaitRate){ return result; } -bool SevenSeg74HC595::write(const uint8_t &segments, const uint8_t &port){ +bool SevenSegDisplays::write(const uint8_t &segments, const uint8_t &port){ bool result {false}; if (port < _dspDigits){ @@ -764,7 +788,7 @@ bool SevenSeg74HC595::write(const uint8_t &segments, const uint8_t &port){ return result; } -bool SevenSeg74HC595::write(const String &character, const uint8_t &port){ +bool SevenSegDisplays::write(const String &character, const uint8_t &port){ bool result {false}; int position {-1}; @@ -782,8 +806,86 @@ bool SevenSeg74HC595::write(const String &character, const uint8_t &port){ //============================================================> Class methods separator +// SevenSeg74HC595::SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode, const uint8_t dspDigits) +// :SevenSegDisplays(sclk, rclk, dio, commAnode, dspDigits) +// { +// } + +// SevenSeg74HC595::~SevenSeg74HC595(){ +// } + +// void SevenSeg74HC595::fastSend(uint8_t content){ +// //Sends the byte value (char <=> unsigned short int) to the 4 7-segment display bit by bit +// //by direct manipulation of the microcontroller pins. There is no time added, so the total time +// //consumed to shift an entire byte is supposed to be the lowest achievable in this level of abstraction. +// //So this is the method suggested to be called from an ISR to keep the ISR time consumed to the lowest + +// for (int i {7}; i >= 0; i--){ //Send each of the 8 bits representing the character +// if (content & 0x80) +// digitalWrite(_dio, HIGH); +// else +// digitalWrite(_dio, LOW); +// content <<= 1; +// digitalWrite(_sclk, LOW); +// digitalWrite(_sclk, HIGH); +// } + +// return; +// } + +// void SevenSeg74HC595::fastSend(const uint8_t &segments, const uint8_t &port){ +// // Sends the character 'segments' to the digit 'port' of the display +// // Content and Port must be sent in two sequencial parts, character first, port second +// // so this overloaded two char fastSend() method uses the one char fastSend() method twice and then moves +// // up the RCLK pin to present the content in the shift register. This method doesn't add time delays, +// //So this is the method suggested to be called from an ISR to keep the ISR time consumed to the lowest + +// digitalWrite(_rclk, LOW); +// fastSend(segments); +// fastSend(port); +// digitalWrite(_rclk, HIGH); + +// return; +// } + +// void SevenSeg74HC595::send(const uint8_t &content){ +// //Sends the byte value (char <=> unsigned short int) to the 4 7-segment display bit by bit +// //by using the shiftOut() function. The time added (or not) to send it bit is unknown, so the total time +// //consumed to shift an entire byte is unknown, issue that must be considered when the method is invoked +// //from an ISR and multiple times depending on the qty of displays being used +// shiftOut(_dio, _sclk, MSBFIRST, content); + +// return; +// } + +// void SevenSeg74HC595::send(const uint8_t &segments, const uint8_t &port){ +// // Sends the character 'segments' to the digit 'port' of the display +// // Content and Port must be sent in two sequencial parts, character first, port second +// // so this overloaded two char send method uses the one char send method twice and then moves +// // up the RCLK pin to present the content in the shift register. This method depends on the shiftOut() function +// // so consumed time must be considered +// digitalWrite(_rclk, LOW); +// send(segments); +// send(port); +// digitalWrite(_rclk, HIGH); + +// return; +// } + + +//============================================================> Class methods separator + +// SevenSegTM1637::SevenSegTM1637(uint8_t clk, uint8_t dio, bool commAnode, const uint8_t dspDigits) +// { +// } + +// SevenSegTM1637::~SevenSegTM1637(){ +// } + +//============================================================> Class methods separator + ClickCounter::ClickCounter(uint8_t ccSclk, uint8_t ccRclk, uint8_t ccDio, bool rgthAlgn, bool zeroPad, bool commAnode, const uint8_t dspDigits) -:SevenSeg74HC595(ccSclk, ccRclk, ccDio, commAnode, dspDigits), _countRgthAlgn {rgthAlgn}, _countZeroPad {zeroPad} +:_display(ccSclk, ccRclk, ccDio, commAnode, dspDigits), _countRgthAlgn {rgthAlgn}, _countZeroPad {zeroPad} { //Class constructor } @@ -793,24 +895,32 @@ ClickCounter::~ClickCounter(){ } bool ClickCounter::blink(){ - - return SevenSeg74HC595::blink(); + + return _display.blink(); } bool ClickCounter::blink(const unsigned long &onRate, const unsigned long &offRate){ - return SevenSeg74HC595::blink(onRate, offRate); + return _display.blink(onRate, offRate); } +void ClickCounter::clear(){ + _display.clear(); + + return; +} + + bool ClickCounter::countBegin(int32_t startVal){ bool result{false}; - if (SevenSeg74HC595::begin() == true){ - result = countRestart(startVal); - if (result) - _beginStartVal = startVal; + if ((startVal >= _display.getDspValMin()) && (startVal <= _display.getDspValMax())){ + if (_display.begin() == true){ + result = countRestart(startVal); + if (result) + _beginStartVal = startVal; + } } - return result; } @@ -818,7 +928,7 @@ bool ClickCounter::countDown(int32_t qty){ bool result {false}; qty = abs(qty); - if((_count - qty) >= _dspValMin){ + if((_count - qty) >= _display.getDspValMin()){ _count -= qty; result = updDisplay(); } @@ -834,7 +944,7 @@ bool ClickCounter::countReset(){ bool ClickCounter::countRestart(int32_t restartValue){ bool result{false}; - if ((restartValue >= _dspValMin) && (restartValue <= _dspValMax)){ + if ((restartValue >= _display.getDspValMin()) && (restartValue <= _display.getDspValMax())){ _count = restartValue; result = updDisplay(); } @@ -844,7 +954,7 @@ bool ClickCounter::countRestart(int32_t restartValue){ bool ClickCounter::countStop(){ - return SevenSeg74HC595::stop(); + return _display.stop(); } bool ClickCounter::countToZero(int32_t qty){ @@ -862,7 +972,7 @@ bool ClickCounter::countUp(int32_t qty){ bool result {false}; qty = abs(qty); - if((_count + qty) <= _dspValMax){ + if((_count + qty) <= _display.getDspValMax()){ _count += qty; result = updDisplay(); } @@ -882,15 +992,15 @@ int ClickCounter::getStartVal(){ bool ClickCounter::noBlink(){ - return SevenSeg74HC595::noBlink(); + return _display.noBlink(); } bool ClickCounter::setBlinkRate(const unsigned long &newOnRate, const unsigned long &newOffRate){ - return SevenSeg74HC595::setBlinkRate(newOnRate, newOffRate); + return _display.setBlinkRate(newOnRate, newOffRate); } bool ClickCounter::updDisplay(){ - return print(_count, _countRgthAlgn, _countZeroPad); + return _display.print(_count, _countRgthAlgn, _countZeroPad); } diff --git a/src/SevenSeg-74HC595.h b/src/SevenSeg-74HC595.h index 3697144..0c3579f 100644 --- a/src/SevenSeg-74HC595.h +++ b/src/SevenSeg-74HC595.h @@ -2,10 +2,10 @@ #define SEVENSEG_74HC595_H #include -class SevenSeg74HC595 { +class SevenSegDisplays { static uint8_t _displaysCount; static uint8_t _dspPtrArrLngth; - static SevenSeg74HC595** _instancesLstPtr; + static SevenSegDisplays** _instancesLstPtr; static void tmrCbRefresh(TimerHandle_t dspTmrCbArg); static TimerHandle_t _dspRfrshTmrHndl; @@ -31,7 +31,7 @@ class SevenSeg74HC595 { const unsigned long _minBlinkRate{100}; const unsigned long _maxBlinkRate{2000}; - SevenSeg74HC595* _dispInstance; + SevenSegDisplays* _dispInstance; uint8_t _dispInstNbr{0}; uint8_t _firstRefreshed{0}; bool _blinking{false}; @@ -94,14 +94,16 @@ class SevenSeg74HC595 { String _zeroPadding{""}; String _spacePadding{""}; + void setAttrbts(); void fastSend(uint8_t content); void send(const uint8_t &content); void updBlinkState(); void updWaitState(); public: - SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode = true, const uint8_t dspDigits = 4); - ~SevenSeg74HC595(); + SevenSegDisplays(); + SevenSegDisplays(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode = true, const uint8_t dspDigits = 4); + ~SevenSegDisplays(); bool begin(); bool blink(); bool blink(const unsigned long &onRate, const unsigned long &offRate = 0); @@ -112,6 +114,8 @@ class SevenSeg74HC595 { bool gauge(const int &level, char label = ' '); bool gauge(const double &level, char label = ' '); uint8_t getDigitsQty(); + uint32_t getDspValMax(); + uint32_t getDspValMin(); uint8_t getInstanceNbr(); unsigned long getMaxBlinkRate(); unsigned long getMinBlinkRate(); @@ -139,8 +143,30 @@ class SevenSeg74HC595 { //============================================================> Class declarations separator -class ClickCounter: protected SevenSeg74HC595{ +// class SevenSeg74HC595: public SevenSegDisplays{ +// protected: +// // void fastSend(uint8_t content); +// void send(const uint8_t &content); + +// public: +// SevenSeg74HC595(uint8_t sclk, uint8_t rclk, uint8_t dio, bool commAnode = true, const uint8_t dspDigits = 4); +// ~SevenSeg74HC595(); + +// }; + +//============================================================> Class declarations separator + +// class SevenSegTM1637: public SevenSegDisplays{ +// public: +// SevenSegTM1637(uint8_t clk, uint8_t dio, bool commAnode = true, const uint8_t dspDigits = 4); +// ~SevenSegTM1637(); +// }; + +//============================================================> Class declarations separator + +class ClickCounter{ private: + SevenSegDisplays _display; int _count{0}; int _beginStartVal{0}; bool _countRgthAlgn{true}; @@ -151,6 +177,7 @@ class ClickCounter: protected SevenSeg74HC595{ ~ClickCounter(); bool blink(); bool blink(const unsigned long &onRate, const unsigned long &offRate = 0); + void clear(); bool countBegin(int32_t startVal = 0); bool countDown(int32_t qty = 1); bool countReset();