1919#define LARGE_NUM_ALLOC_SIZE (LARGE_NUM_MAX_DIGITS / 2 )
2020
2121/* *
22- * A structure for very large integers that can be edited using the multipart editor.
23- * They are represented as binary coded decimal to 12 dp with as many fraction decimal
24- * places as needed. The whole can be either negative or positive, while the fraction is
25- * an unsigned number in 32 bit form. This provides numbers in the range of at least 9 digits before
26- * the dp, and 9 after.
22+ * A structure for very large numbers that can be edited using the multipart editor. They are represented as binary
23+ * coded decimal to 12 dp with between 0 and 9 fraction decimal places if needed. The whole can be either negative or
24+ * positive between 1 and 9 decimal places. Both fraction and whole can be extracted as either a floating point, a
25+ * per digit value, or as integers containing whole, fraction and negative flag.
2726 */
2827class LargeFixedNumber {
2928private:
3029 uint8_t bcdRepresentation[LARGE_NUM_ALLOC_SIZE];
3130 bool negative;
31+ uint8_t totalSize;
3232 uint8_t fractionDp;
3333public:
3434 /* *
35- * Create a default instance with decimal places set to 4
35+ * Create a default instance with decimal places set to 4 and total size 12.
3636 */
3737 LargeFixedNumber () {
38+ totalSize = 12 ;
3839 setPrecision (4 );
3940 }
4041
@@ -44,16 +45,20 @@ class LargeFixedNumber {
4445 void clear ();
4546
4647 /* *
47- * @return the number of decimal places needed .
48+ * @return the number of decimal places this represents .
4849 */
4950 int decimalPointIndex () const { return fractionDp; }
5051
5152 /* *
52- * Set the number of decimal places and zero out any currently held value.
53+ * Set the number of decimal places and optionally the total size then zero out any currently held value. When
54+ * setting this value you should ensure that: fractionDp is not larger than 9, the difference between fractionDp
55+ * and maxDigits is not greater than 9.
5356 * @param dp the new number of decimal places
57+ * @param maxDigits the total number of digits needed.
5458 */
55- void setPrecision (uint8_t dp) {
59+ void setPrecision (uint8_t dp, uint8_t maxDigits = 12 ) {
5660 fractionDp = dp;
61+ totalSize = maxDigits;
5762 clear ();
5863 }
5964
@@ -67,17 +72,10 @@ class LargeFixedNumber {
6772
6873 /* *
6974 * Takes a floating point value and converts it into the internal representation.
70- * This class can nearly always accurately represent a float value unless it exceeds
71- * 12 digits.
75+ * This will represent the float within the bounds of the current total digits and decimal precision.
7276 * @param value the float value to convert
7377 */
74- void setFromFloat (float value) {
75- bool neg = value < 0 .0f ;
76- value = abs (value);
77- uint32_t val = (uint32_t )value;
78- uint32_t frc = (value - (float )val) * dpToDivisor (fractionDp);
79- setValue (val, frc, neg);
80- }
78+ void setFromFloat (float value);
8179
8280 /* *
8381 * Converts from the BCD packed structure into an integer
@@ -88,7 +86,7 @@ class LargeFixedNumber {
8886 uint32_t fromBcdPacked (int start, int end);
8987
9088 /* *
91- * Converts from the BCD packed structure into an integer
89+ * Converts from an integer into BCD packed.
9290 * @param value the value to be encoded
9391 * @param start the index to start in the packed data
9492 * @param end will stop at one before this point
@@ -116,18 +114,12 @@ class LargeFixedNumber {
116114 *
117115 * @return the current represented value as a floating point number.
118116 */
119- float getAsFloat () {
120- float fraction = ((float )getFraction () / (float )dpToDivisor (fractionDp));
121- float asFlt = (float )getWhole () + fraction;
122- serdebugF3 (" fract, asFlt " , fraction, asFlt);
123- if (negative) asFlt = -asFlt;
124- return asFlt;
125- }
117+ float getAsFloat ();
126118
127119 /* *
128120 * @return true if negative otherwise false.
129121 */
130- bool isNegative () { return negative; }
122+ bool isNegative () const { return negative; }
131123
132124 /* *
133125 * Sets the negative flag, if true the number becomes a negative value.
@@ -141,7 +133,7 @@ class LargeFixedNumber {
141133 * @return the whole part of the value
142134 */
143135 uint32_t getWhole () {
144- return fromBcdPacked (fractionDp, LARGE_NUM_MAX_DIGITS );
136+ return fromBcdPacked (fractionDp, totalSize );
145137 }
146138
147139 /* *
@@ -167,20 +159,33 @@ int largeNumItemRenderFn(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode,
167159
168160/* *
169161 * A multipart editor for very large numbers, either integer or fixed point decimal that exceed the usable range
170- * of a rotary encoder or joystick to set their value. This class works by editing each digit in turn.
162+ * of a rotary encoder or joystick to set their value. This class works by editing each digit in turn. This is based
163+ * on LargeFixedNumber, see that for more details on the capabilities
164+ * @see LargeFixedNumber
171165 */
172166class EditableLargeNumberMenuItem : public EditableMultiPartMenuItem <LargeFixedNumber> {
167+ private:
168+ bool negativeAllowed;
173169public:
174- EditableLargeNumberMenuItem (RuntimeRenderingFn renderFn, uint16_t id, int maxDigits, int dps, MenuItem* next = NULL )
170+ EditableLargeNumberMenuItem (RuntimeRenderingFn renderFn, uint16_t id, int maxDigits, int dps, bool allowNeg, MenuItem* next = nullptr )
171+ : EditableMultiPartMenuItem(MENUTYPE_LARGENUM_VALUE, id, maxDigits + (allowNeg ? 1 : 0 ), renderFn, next) {
172+ data.setPrecision (dps, maxDigits);
173+ negativeAllowed = allowNeg;
174+ }
175+
176+ EditableLargeNumberMenuItem (RuntimeRenderingFn renderFn, uint16_t id, int maxDigits, int dps, MenuItem* next = nullptr )
175177 : EditableMultiPartMenuItem(MENUTYPE_LARGENUM_VALUE, id, maxDigits + 1 , renderFn, next) {
176- data.setPrecision (dps);
178+ data.setPrecision (dps, maxDigits);
179+ negativeAllowed = true ;
177180 }
178181
179182 /* * gets the large integer value that this class is using */
180183 LargeFixedNumber* getLargeNumber () { return &data; }
181184
182185 /* * sets a number from a string in the form whole.fraction */
183186 void setLargeNumberFromString (const char * largeNum);
187+
188+ bool isNegativeAllowed () { return negativeAllowed; }
184189};
185190
186191#endif // _EDITABLE_LARGE_NUMBER_MENU_ITEM_H_
0 commit comments