Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FastLED/FastLED.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Garcia <danielgarcia@gmail.com>2014-12-14 22:32:07 +0300
committerDaniel Garcia <danielgarcia@gmail.com>2014-12-14 22:32:07 +0300
commit44303ce7ced238da22853abbc571ac61d3c94d92 (patch)
tree411f7c209ded6e48f0c905f7f153be6b503b2d7d
parent337120ada48b98e9cc1750eb2e869fedb01748bd (diff)
parentf873455c0f27d7bfacf744effc681f585dc52c19 (diff)
Merge branch 'FastLED3.1' of https://github.com/FastLED/FastLED into FastLED3.1
-rw-r--r--colorutils.cpp87
-rw-r--r--colorutils.h41
-rw-r--r--lib8tion.cpp3
-rw-r--r--lib8tion.h223
-rw-r--r--pixeltypes.h91
5 files changed, 431 insertions, 14 deletions
diff --git a/colorutils.cpp b/colorutils.cpp
index 16433f45..0c747ba4 100644
--- a/colorutils.cpp
+++ b/colorutils.cpp
@@ -530,6 +530,64 @@ CRGB ColorFromPalette( const CRGBPalette16& pal, uint8_t index, uint8_t brightne
return CRGB( red1, green1, blue1);
}
+CRGB ColorFromPalette( const TProgmemRGBPalette16& pal, uint8_t index, uint8_t brightness, TBlendType blendType)
+{
+ uint8_t hi4 = index >> 4;
+ uint8_t lo4 = index & 0x0F;
+
+ // CRGB rgb1 = pal[ hi4];
+ CRGB entry = pgm_read_dword_near( &(pal[0]) + hi4 );
+
+ uint8_t red1 = entry.red;
+ uint8_t green1 = entry.green;
+ uint8_t blue1 = entry.blue;
+
+ uint8_t blend = lo4 && (blendType != NOBLEND);
+
+ if( blend ) {
+
+ if( hi4 == 15 ) {
+ entry = pgm_read_dword_near( &(pal[0]) );
+ } else {
+ entry = pgm_read_dword_near( &(pal[1]) + hi4 );
+ }
+
+ uint8_t f2 = lo4 << 4;
+ uint8_t f1 = 256 - f2;
+
+ // rgb1.nscale8(f1);
+ red1 = scale8_LEAVING_R1_DIRTY( red1, f1);
+ green1 = scale8_LEAVING_R1_DIRTY( green1, f1);
+ blue1 = scale8_LEAVING_R1_DIRTY( blue1, f1);
+
+ // cleanup_R1();
+
+ // CRGB rgb2 = pal[ hi4];
+ // rgb2.nscale8(f2);
+ uint8_t red2 = entry.red;
+ uint8_t green2 = entry.green;
+ uint8_t blue2 = entry.blue;
+ red2 = scale8_LEAVING_R1_DIRTY( red2, f2);
+ green2 = scale8_LEAVING_R1_DIRTY( green2, f2);
+ blue2 = scale8_LEAVING_R1_DIRTY( blue2, f2);
+
+ cleanup_R1();
+
+ // These sums can't overflow, so no qadd8 needed.
+ red1 += red2;
+ green1 += green2;
+ blue1 += blue2;
+
+ }
+
+ if( brightness != 255) {
+ nscale8x3_video( red1, green1, blue1, brightness);
+ }
+
+ return CRGB( red1, green1, blue1);
+}
+
+
CRGB ColorFromPalette( const CRGBPalette256& pal, uint8_t index, uint8_t brightness, TBlendType)
{
@@ -665,3 +723,32 @@ void SetupPartyColors(CRGBPalette16& pal)
}
#endif
+
+void nblendPaletteTowardPalette( CRGBPalette16& current, CRGBPalette16& target, uint8_t maxChanges)
+{
+ uint8_t* p1;
+ uint8_t* p2;
+ uint8_t changes = 0;
+
+ p1 = (uint8_t*)current.entries;
+ p2 = (uint8_t*)target.entries;
+
+ const uint8_t totalChannels = sizeof(CRGBPalette16);
+ for( byte i = 0; i < totalChannels; i++) {
+ // if the values are equal, no changes are needed
+ if( p1[i] == p2[i] ) { continue; }
+
+ // if the current value is less than the target, increase it by one
+ if( p1[i] < p2[i] ) { p1[i]++; changes++; }
+
+ // if the current value is greater than the target,
+ // increase it by one (or two if it's still greater).
+ if( p1[i] > p2[i] ) {
+ p1[i]--; changes++;
+ if( p1[i] > p2[i] ) { p1[i]--; }
+ }
+
+ // if we've hit the maximum number of changes, exit
+ if( changes >= maxChanges) { break; }
+ }
+}
diff --git a/colorutils.h b/colorutils.h
index 76542acf..5750cad6 100644
--- a/colorutils.h
+++ b/colorutils.h
@@ -781,6 +781,11 @@ public:
typedef enum { NOBLEND=0, BLEND=1 } TBlendType;
CRGB ColorFromPalette( const CRGBPalette16& pal,
+ uint8_t index,
+ uint8_t brightness=255,
+ TBlendType blendType=BLEND);
+
+CRGB ColorFromPalette( const TProgmemRGBPalette16& pal,
uint8_t index,
uint8_t brightness=255,
TBlendType blendType=BLEND);
@@ -835,4 +840,40 @@ void map_data_into_colors_through_palette(
}
}
+// nblendPaletteTowardPalette:
+// Alter one palette by making it slightly more like
+// a 'target palette', used for palette cross-fades.
+//
+// It does this by comparing each of the R, G, and B channels
+// of each entry in the current palette to the corresponding
+// entry in the target palette and making small adjustments:
+// If the Red channel is too low, it will be increased.
+// If the Red channel is too high, it will be slightly reduced.
+// ... and likewise for Green and Blue channels.
+//
+// Additionally, there are two significant visual improvements
+// to this algorithm implemented here. First is this:
+// When increasing a channel, it is stepped up by ONE.
+// When decreasing a channel, it is stepped down by TWO.
+// Due to the way the eye perceives light, and the way colors
+// are represented in RGB, this produces a more uniform apparent
+// brightness when cross-fading between most palette colors.
+//
+// The second visual tweak is limiting the number of changes
+// that will be made to the palette at once. If all the palette
+// entries are changed at once, it can give a muddled appearance.
+// However, if only a few palette entries are changed at once,
+// you get a visually smoother transition: in the middle of the
+// cross-fade your current palette will actually contain some
+// colors from the old palette, a few blended colors, and some
+// colors from the new palette.
+// The maximum number of possible palette changes per call
+// is 48 (sixteen color entries time three channels each).
+// The default 'maximim number of changes' here is 12, meaning
+// that only approximately a quarter of the palette entries
+// will be changed per call.
+void nblendPaletteTowardPalette( CRGBPalette16& currentPalette,
+ CRGBPalette16& targetPalette,
+ uint8_t maxChanges=24);
+
#endif
diff --git a/lib8tion.cpp b/lib8tion.cpp
index 557fa005..84bcafdb 100644
--- a/lib8tion.cpp
+++ b/lib8tion.cpp
@@ -121,6 +121,9 @@ void * memmove8 ( void * dst, void* src, uint16_t num )
#endif /* AVR */
+
+
+
#if 0
// TEST / VERIFICATION CODE ONLY BELOW THIS POINT
#include <Arduino.h>
diff --git a/lib8tion.h b/lib8tion.h
index 3b913ecd..b6e03ed6 100644
--- a/lib8tion.h
+++ b/lib8tion.h
@@ -153,9 +153,15 @@
= (sine(beatphase) * (high8-low8)) + low8
beatsin16( BPM, low16, high16)
= (sine(beatphase) * (high16-low16)) + low16
+ beatsin88( BPM88, low16, high16)
+ = (sine(beatphase) * (high16-low16)) + low16
beat8( BPM) = 8-bit repeating sawtooth wave
beat16( BPM) = 16-bit repeating sawtooth wave
-
+ beat88( BPM88) = 16-bit repeating sawtooth wave
+ BPM is beats per minute in either simple form
+ e.g. 120, or Q8.8 fixed-point form.
+ BPM88 is beats per minute in ONLY Q8.8 fixed-point
+ form.
Lib8tion is pronounced like 'libation': lie-BAY-shun
@@ -1767,13 +1773,18 @@ typedef q<uint16_t, 12,4> q124;
// per minute, rising from 0 to 65535, resetting to zero,
// rising up again, etc. The output of this function is
// suitable for feeding directly into sin16 and cos16.
-//
+// beat88( BPM88) is the same as beat16, except that the BPM88 argument
+// MUST be in Q8.8 fixed point format, e.g. 120BPM must
+// be specified as 120*256 = 30720.
// beatsin8( BPM, uint8_t low, uint8_t high) returns an 8-bit value that
// rises and falls in a sine wave, 'BPM' times per minute,
// between the values of 'low' and 'high'.
// beatsin16( BPM, uint16_t low, uint16_t high) returns a 16-bit value
// that rises and falls in a sine wave, 'BPM' times per
// minute, between the values of 'low' and 'high'.
+// beatsin88( BPM88, ...) is the same as beatsin16, except that the
+// BPM88 argument MUST be in Q8.8 fixed point format,
+// e.g. 120BPM must be specified as 120*256 = 30720.
//
// BPM can be supplied two ways. The simpler way of specifying BPM is as
// a simple 8-bit integer from 1-255, (e.g., "120").
@@ -1782,6 +1793,7 @@ typedef q<uint16_t, 12,4> q124;
// an 8-bit fractional part. The easiest way to construct this is to multiply
// a floating point BPM value (e.g. 120.3) by 256, (e.g. resulting in 30796
// in this case), and pass that as the 16-bit BPM argument.
+// "BPM88" MUST always be specified in Q8.8 format.
//
// Originally designed to make an entire animation project pulse with brightness.
// For that effect, add this line just above your existing call to "FastLED.show()":
@@ -1803,18 +1815,19 @@ typedef q<uint16_t, 12,4> q124;
#if defined(ARDUINO) && !defined(USE_GET_MILLISECOND_TIMER)
// Forward declaration of Arduino function 'millis'.
uint32_t millis();
-#define GET_MILLIS (millis())
+#define GET_MILLIS millis
#else
uint32_t get_millisecond_timer();
-#define GET_MILLIS (get_millisecond_timer())
+#define GET_MILLIS get_millisecond_timer
#endif
-// beat16 generates a 16-bit 'sawtooth' wave at a given BPM
-LIB8STATIC uint16_t beat16( accum88 beats_per_minute, uint32_t timebase = 0)
+// beat16 generates a 16-bit 'sawtooth' wave at a given BPM,
+// with BPM specified in Q8.8 fixed-point format; e.g.
+// for this function, 120 BPM MUST BE specified as
+// 120*256 = 30720.
+// If you just want to specify "120", use beat16 or beat8.
+LIB8STATIC uint16_t beat88( accum88 beats_per_minute_88, uint32_t timebase = 0)
{
- // Convert simple 8-bit BPM's to full Q8.8 accum88's if needed
- if( beats_per_minute < 256) beats_per_minute <<= 8;
-
// BPM is 'beats per minute', or 'beats per 60000ms'.
// To avoid using the (slower) division operator, we
// want to convert 'beats per 60000ms' to 'beats per 65536ms',
@@ -1823,9 +1836,15 @@ LIB8STATIC uint16_t beat16( accum88 beats_per_minute, uint32_t timebase = 0)
// The ratio 65536:60000 is 279.620266667:256; we'll call it 280:256.
// The conversion is accurate to about 0.05%, more or less,
// e.g. if you ask for "120 BPM", you'll get about "119.93".
- // If you need more precision than that, you can specify a
- // sixteen-bit BPM value in Q8.8 fixed-point (an 'accum88').
- return (((GET_MILLIS) - timebase) * beats_per_minute * 280) >> 16;
+ return (((GET_MILLIS()) - timebase) * beats_per_minute_88 * 280) >> 16;
+}
+
+// beat16 generates a 16-bit 'sawtooth' wave at a given BPM
+LIB8STATIC uint16_t beat16( accum88 beats_per_minute, uint32_t timebase = 0)
+{
+ // Convert simple 8-bit BPM's to full Q8.8 accum88's if needed
+ if( beats_per_minute < 256) beats_per_minute <<= 8;
+ return beat88(beats_per_minute);
}
// beat8 generates an 8-bit 'sawtooth' wave at a given BPM
@@ -1834,6 +1853,23 @@ LIB8STATIC uint8_t beat8( accum88 beats_per_minute, uint32_t timebase = 0)
return beat16( beats_per_minute, timebase) >> 8;
}
+// beatsin88 generates a 16-bit sine wave at a given BPM,
+// that oscillates within a given range.
+// For this function, BPM MUST BE SPECIFIED as
+// a Q8.8 fixed-point value; e.g. 120BPM must be
+// specified as 120*256 = 30720.
+// If you just want to specify "120", use beatsin16 or beatsin8.
+LIB8STATIC uint16_t beatsin88( accum88 beats_per_minute_88, uint16_t lowest = 0, uint16_t highest = 65535,
+ uint32_t timebase = 0, uint16_t phase_offset = 0)
+{
+ uint16_t beat = beat88( beats_per_minute_88, timebase);
+ uint16_t beatsin = (sin16( beat + phase_offset) + 32768);
+ uint16_t rangewidth = highest - lowest;
+ uint16_t scaledbeat = scale16( beatsin, rangewidth);
+ uint16_t result = lowest + scaledbeat;
+ return result;
+}
+
// beatsin16 generates a 16-bit sine wave at a given BPM,
// that oscillates within a given range.
LIB8STATIC uint16_t beatsin16( accum88 beats_per_minute, uint16_t lowest = 0, uint16_t highest = 65535,
@@ -1861,4 +1897,167 @@ LIB8STATIC uint8_t beatsin8( accum88 beats_per_minute, uint8_t lowest = 0, uint8
}
+// seconds16, minutes16, hours8
+// functions to return the current seconds, minutes, or hours
+// since boot time, in the specified width. Used as part of
+// the "every N time-periods" mechanism.
+
+LIB8STATIC uint16_t seconds16()
+{
+ uint32_t ms = GET_MILLIS();
+ uint16_t s16;
+ s16 = ms / 1000;
+ return s16;
+}
+
+LIB8STATIC uint16_t minutes16()
+{
+ uint32_t ms = GET_MILLIS();
+ uint16_t m16;
+ m16 = (ms / (60000L)) & 0xFFFF;
+ return m16;
+}
+
+LIB8STATIC uint8_t hours8()
+{
+ uint32_t ms = GET_MILLIS();
+ uint8_t h8;
+ h8 = (ms / (3600000L)) & 0xFF;
+ return h8;
+}
+
+
+// Helper routine to divide a 32-bit value by 1024, returning
+// only the low 16 bits. You'd think this would be just
+// result = (in32 >> 10) & 0xFFFF;
+// and on ARM, that's what you want and all is well.
+// But on AVR that code turns into a loop that executes
+// a four-byte shift ten times: 40 shifts in all, plus loop
+// overhead. This routine gets exactly the same result with
+// just six shifts (vs 40), and no loop overhead.
+// Used to convert millis to 'binary seconds' aka bseconds:
+// one bsecond == 1024 millis.
+LIB8STATIC uint16_t div1024_32_16( uint32_t in32)
+{
+ uint16_t out16;
+#if defined(__AVR__)
+ asm volatile (
+ " lsr %D[in] \n\t"
+ " ror %C[in] \n\t"
+ " ror %B[in] \n\t"
+ " lsr %D[in] \n\t"
+ " ror %C[in] \n\t"
+ " ror %B[in] \n\t"
+ " mov %B[out],%C[in] \n\t"
+ " mov %A[out],%B[in] \n\t"
+ : [in] "+r" (in32),
+ [out] "=r" (out16)
+ );
+#else
+ out16 = (in32 >> 10) & 0xFFFF;
+#endif
+ return out16;
+}
+
+// bseconds16 returns the current time-since-boot in
+// "binary seconds", which are actually 1024/1000 of a
+// second long.
+LIB8STATIC uint16_t bseconds16()
+{
+ uint32_t ms = GET_MILLIS();
+ uint16_t s16;
+ s16 = div1024_32_16( ms);
+ return s16;
+}
+
+
+// Classes to implement "Every N Milliseconds", "Every N Seconds",
+// "Every N Minutes", "Every N Hours", and "Every N BSeconds".
+#if 1
+#define INSTANTIATE_EVERY_N_TIME_PERIODS(NAME,TIMETYPE,TIMEGETTER) \
+class NAME { \
+public: \
+ TIMETYPE mPrevTrigger; \
+ TIMETYPE mPeriod; \
+ \
+ NAME() { reset(); mPeriod = 1; }; \
+ NAME(TIMETYPE period) { reset(); setPeriod(period); }; \
+ void setPeriod( TIMETYPE period) { mPeriod = period; }; \
+ TIMETYPE getTime() { return (TIMETYPE)(TIMEGETTER()); }; \
+ TIMETYPE getPeriod() { return mPeriod; }; \
+ TIMETYPE getElapsed() { return getTime() - mPrevTrigger; } \
+ TIMETYPE getRemaining() { return mPeriod - getElapsed(); } \
+ TIMETYPE getLastTriggerTime() { return mPrevTrigger; } \
+ bool ready() { \
+ bool isReady = (getElapsed() >= mPeriod); \
+ if( isReady ) { reset(); } \
+ return isReady; \
+ } \
+ void reset() { mPrevTrigger = getTime(); }; \
+ void trigger() { mPrevTrigger = getTime() - mPeriod; }; \
+ \
+ operator bool() { return ready(); } \
+};
+INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNMillis,uint32_t,GET_MILLIS);
+INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNSeconds,uint16_t,seconds16);
+INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNBSeconds,uint16_t,bseconds16);
+INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNMinutes,uint16_t,minutes16);
+INSTANTIATE_EVERY_N_TIME_PERIODS(CEveryNHours,uint8_t,hours8);
+#else
+
+// Under C++11 rules, we would be allowed to use not-external
+// -linkage-type symbols as template arguments,
+// e.g., LIB8STATIC seconds16, and we'd be able to use these
+// templates as shown below.
+// However, under C++03 rules, we cannot do that, and thus we
+// have to resort to the preprocessor to 'instantiate' 'templates',
+// as handled above.
+template<typename timeType,timeType (*timeGetter)()>
+class CEveryNTimePeriods {
+public:
+ timeType mPrevTrigger;
+ timeType mPeriod;
+
+ CEveryNTimePeriods() { reset(); mPeriod = 1; };
+ CEveryNTimePeriods(timeType period) { reset(); setPeriod(period); };
+ void setPeriod( timeType period) { mPeriod = period; };
+ timeType getTime() { return (timeType)(timeGetter()); };
+ timeType getPeriod() { return mPeriod; };
+ timeType getElapsed() { return getTime() - mPrevTrigger; }
+ timeType getRemaining() { return mPeriod - getElapsed(); }
+ timeType getLastTriggerTime() { return mPrevTrigger; }
+ bool ready() {
+ bool isReady = (getElapsed() >= mPeriod);
+ if( isReady ) { reset(); }
+ return isReady;
+ }
+ void reset() { mPrevTrigger = getTime(); };
+ void trigger() { mPrevTrigger = getTime() - mPeriod; };
+
+ operator bool() { return ready(); }
+};
+typedef CEveryNTimePeriods<uint16_t,seconds16> CEveryNSeconds;
+typedef CEveryNTimePeriods<uint16_t,bseconds16> CEveryNBSeconds;
+typedef CEveryNTimePeriods<uint32_t,millis> CEveryNMillis;
+typedef CEveryNTimePeriods<uint16_t,minutes16> CEveryNMinutes;
+typedef CEveryNTimePeriods<uint8_t,hours8> CEveryNHours;
+#endif
+
+
+#define CONCAT_HELPER( x, y ) x##y
+#define CONCAT_MACRO( x, y ) CONCAT_HELPER( x, y )
+#define EVERY_N_MILLIS(N) EVERY_N_MILLIS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
+#define EVERY_N_MILLIS_I(NAME,N) static CEveryNMillis NAME(N); if( NAME )
+#define EVERY_N_SECONDS(N) EVERY_N_SECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
+#define EVERY_N_SECONDS_I(NAME,N) static CEveryNSeconds NAME(N); if( NAME )
+#define EVERY_N_BSECONDS(N) EVERY_N_BSECONDS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
+#define EVERY_N_BSECONDS_I(NAME,N) static CEveryNBSeconds NAME(N); if( NAME )
+#define EVERY_N_MINUTES(N) EVERY_N_MINUTES_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
+#define EVERY_N_MINUTES_I(NAME,N) static CEveryNMinutes NAME(N); if( NAME )
+#define EVERY_N_HOURS(N) EVERY_N_HOURS_I(CONCAT_MACRO(PER, __COUNTER__ ),N)
+#define EVERY_N_HOURS_I(NAME,N) static CEveryNHours NAME(N); if( NAME )
+
+#define CEveryNMilliseconds CEveryNMillis
+#define EVERY_N_MILLISECONDS(N) EVERY_N_MILLIS(N)
+
#endif
diff --git a/pixeltypes.h b/pixeltypes.h
index e112636b..3c583a42 100644
--- a/pixeltypes.h
+++ b/pixeltypes.h
@@ -460,6 +460,85 @@ struct CRGB {
return ret;
}
+ // getParity returns 0 or 1, depending on the
+ // lowest bit of the sum of the color components.
+ inline uint8_t getParity()
+ {
+ uint8_t sum = r + g + b;
+ return (sum & 0x01);
+ }
+
+ // setParity adjusts the color in the smallest
+ // way possible so that the parity of the color
+ // is now the desired value. This allows you to
+ // 'hide' one bit of information in the color.
+ //
+ // Ideally, we find one color channel which already
+ // has data in it, and modify just that channel by one.
+ // We don't want to light up a channel that's black
+ // if we can avoid it, and if the pixel is 'grayscale',
+ // (meaning that R==G==B), we modify all three channels
+ // at once, to preserve the neutral hue.
+ //
+ // There's no such thing as a free lunch; in many cases
+ // this 'hidden bit' may actually be visible, but this
+ // code makes reasonable efforts to hide it as much
+ // as is reasonably possible.
+ //
+ // Also, an effort is made to have make it such that
+ // repeatedly setting the parity to different values
+ // will not cause the color to 'drift'. Toggling
+ // the parity twice should generally result in the
+ // original color again.
+ //
+ inline void setParity( uint8_t parity)
+ {
+ uint8_t curparity = getParity();
+
+ if( parity == curparity) return;
+
+ if( parity ) {
+ // going 'up'
+ if( (b > 0) && (b < 255)) {
+ if( r == g && g == b) {
+ r++;
+ g++;
+ }
+ b++;
+ } else if( (r > 0) && (r < 255)) {
+ r++;
+ } else if( (g > 0) && (g < 255)) {
+ g++;
+ } else {
+ if( r == g && g == b) {
+ r ^= 0x01;
+ g ^= 0x01;
+ }
+ b ^= 0x01;
+ }
+ } else {
+ // going 'down'
+ if( b > 1) {
+ if( r == g && g == b) {
+ r--;
+ g--;
+ }
+ b--;
+ } else if( g > 1) {
+ g--;
+ } else if( r > 1) {
+ r--;
+ } else {
+ if( r == g && g == b) {
+ r ^= 0x01;
+ g ^= 0x01;
+ }
+ b ^= 0x01;
+ }
+ }
+ }
+
+
typedef enum {
AliceBlue=0xF0F8FF,
Amethyst=0x9966CC,
@@ -608,9 +687,17 @@ struct CRGB {
White=0xFFFFFF,
WhiteSmoke=0xF5F5F5,
Yellow=0xFFFF00,
- YellowGreen=0x9ACD32
+ YellowGreen=0x9ACD32,
+
+ // LED RGB color that roughly approximates
+ // the color of incandescent fairy lights,
+ // assuming that you're using FastLED
+ // color correction on your LEDs (recommended).
+ FairyLight=0xFFE42D,
+ // If you are using no color correction, use this
+ FairyLightNCC=0xFF9D2A
+
} HTMLColorCode;
- // static uint32_t Squant;
};