25 #ifndef ACE_SEGMENT_TM1637_MODULE_H
26 #define ACE_SEGMENT_TM1637_MODULE_H
29 #include <AceCommon.h>
30 #include "../LedModule.h"
32 class Tm1637ModuleTest_flushIncremental;
33 class Tm1637ModuleTest_flush;
35 namespace ace_segment {
47 static const uint16_t kDefaultTm1637DelayMicros = 100;
62 extern const uint8_t kDigitRemapArray6Tm1637[6];
74 constexpr uint8_t initialDirtyBits(uint8_t numBits) {
75 return ((uint16_t) 0x1 << numBits) - 1;
90 template <
typename T_TMII, u
int8_t T_DIGITS>
103 const T_TMII& tmiInterface,
104 const uint8_t* remapArray =
nullptr
107 mTmiInterface(tmiInterface),
108 mRemapArray(remapArray)
125 memset(mPatterns, 0, T_DIGITS);
126 mBrightness = kBrightnessCmd | kBrightnessLevelOn | 0x7;
132 mIsDirty = internal::initialDirtyBits(T_DIGITS + 1);
148 mPatterns[pos] = pattern;
153 return mPatterns[pos];
157 mBrightness = (mBrightness & ~0x7) | (brightness & 0x7);
158 setDirtyBit(kBrightnessDirtyBit);
171 mBrightness |= kBrightnessLevelOn;
173 mBrightness &= ~kBrightnessLevelOn;
175 setDirtyBit(kBrightnessDirtyBit);
188 if (! mIsDirty)
return;
191 mTmiInterface.startCondition();
192 mTmiInterface.sendByte(mBrightness);
193 mTmiInterface.stopCondition();
196 mTmiInterface.startCondition();
197 mTmiInterface.sendByte(kDataCmdAutoAddress);
198 mTmiInterface.stopCondition();
200 mTmiInterface.startCondition();
201 mTmiInterface.sendByte(kAddressCmd);
202 for (uint8_t chipPos = 0; chipPos < T_DIGITS; ++chipPos) {
207 uint8_t physicalPos = remapLogicalToPhysical(chipPos);
208 uint8_t effectivePattern = mPatterns[physicalPos];
209 mTmiInterface.sendByte(effectivePattern);
211 mTmiInterface.stopCondition();
250 if (mFlushStage == T_DIGITS) {
252 if (isDirtyBit(T_DIGITS)) {
253 mTmiInterface.startCondition();
254 mTmiInterface.sendByte(mBrightness);
255 mTmiInterface.stopCondition();
256 clearDirtyBit(T_DIGITS);
263 const uint8_t chipPos = mFlushStage;
264 const uint8_t physicalPos = remapLogicalToPhysical(chipPos);
265 if (isDirtyBit(physicalPos)) {
267 mTmiInterface.startCondition();
268 mTmiInterface.sendByte(kDataCmdFixedAddress);
269 mTmiInterface.stopCondition();
271 mTmiInterface.startCondition();
272 mTmiInterface.sendByte(kAddressCmd | chipPos);
273 mTmiInterface.sendByte(mPatterns[physicalPos]);
274 mTmiInterface.stopCondition();
275 clearDirtyBit(physicalPos);
280 ace_common::incrementMod(mFlushStage, (uint8_t) (T_DIGITS + 1));
284 void setDirtyBit(uint8_t bit) {
285 mIsDirty |= (0x1 << bit);
288 void clearDirtyBit(uint8_t bit) {
289 mIsDirty &= ~(0x1 << bit);
292 bool isDirtyBit(uint8_t bit)
const {
293 return mIsDirty & (0x1 << bit);
297 uint8_t remapLogicalToPhysical(uint8_t pos)
const {
298 return mRemapArray ? mRemapArray[pos] : pos;
303 friend class ::Tm1637ModuleTest_flushIncremental;
304 friend class ::Tm1637ModuleTest_flush;
306 static uint8_t
const kDataCmdWriteDisplay = 0b01000000;
307 static uint8_t
const kDataCmdReadKeys = 0b01000010;
308 static uint8_t
const kDataCmdAutoAddress = 0b01000000;
309 static uint8_t
const kDataCmdFixedAddress = 0b01000100;
310 static uint8_t
const kAddressCmd = 0b11000000;
311 static uint8_t
const kBrightnessCmd = 0b10000000;
312 static uint8_t
const kBrightnessLevelOn = 0b00001000;
316 static uint8_t
const kBrightnessDirtyBit = T_DIGITS;
320 const T_TMII& mTmiInterface;
321 const uint8_t*
const mRemapArray;
322 uint8_t mPatterns[T_DIGITS];