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>
102 const T_TMII& tmiInterface,
103 const uint8_t* remapArray =
nullptr
106 mTmiInterface(tmiInterface),
107 mRemapArray(remapArray)
124 memset(mPatterns, 0, T_DIGITS);
125 mBrightness = kBrightnessCmd | kBrightnessLevelOn | 0x7;
131 mIsDirty = internal::initialDirtyBits(T_DIGITS + 1);
147 mPatterns[pos] = pattern;
152 return mPatterns[pos];
156 mBrightness = (mBrightness & ~0x7) | (brightness & 0x7);
157 setDirtyBit(kBrightnessDirtyBit);
170 mBrightness |= kBrightnessLevelOn;
172 mBrightness &= ~kBrightnessLevelOn;
174 setDirtyBit(kBrightnessDirtyBit);
187 if (! mIsDirty)
return;
190 mTmiInterface.startCondition();
191 mTmiInterface.sendByte(mBrightness);
192 mTmiInterface.stopCondition();
195 mTmiInterface.startCondition();
196 mTmiInterface.sendByte(kDataCmdAutoAddress);
197 mTmiInterface.stopCondition();
199 mTmiInterface.startCondition();
200 mTmiInterface.sendByte(kAddressCmd);
201 for (uint8_t chipPos = 0; chipPos < T_DIGITS; ++chipPos) {
206 uint8_t physicalPos = remapLogicalToPhysical(chipPos);
207 uint8_t effectivePattern = mPatterns[physicalPos];
208 mTmiInterface.sendByte(effectivePattern);
210 mTmiInterface.stopCondition();
249 if (mFlushStage == T_DIGITS) {
251 if (isDirtyBit(T_DIGITS)) {
252 mTmiInterface.startCondition();
253 mTmiInterface.sendByte(mBrightness);
254 mTmiInterface.stopCondition();
255 clearDirtyBit(T_DIGITS);
262 const uint8_t chipPos = mFlushStage;
263 const uint8_t physicalPos = remapLogicalToPhysical(chipPos);
264 if (isDirtyBit(physicalPos)) {
266 mTmiInterface.startCondition();
267 mTmiInterface.sendByte(kDataCmdFixedAddress);
268 mTmiInterface.stopCondition();
270 mTmiInterface.startCondition();
271 mTmiInterface.sendByte(kAddressCmd | chipPos);
272 mTmiInterface.sendByte(mPatterns[physicalPos]);
273 mTmiInterface.stopCondition();
274 clearDirtyBit(physicalPos);
279 ace_common::incrementMod(mFlushStage, (uint8_t) (T_DIGITS + 1));
283 void setDirtyBit(uint8_t bit) {
284 mIsDirty |= (0x1 << bit);
287 void clearDirtyBit(uint8_t bit) {
288 mIsDirty &= ~(0x1 << bit);
291 bool isDirtyBit(uint8_t bit)
const {
292 return mIsDirty & (0x1 << bit);
296 uint8_t remapLogicalToPhysical(uint8_t pos)
const {
297 return mRemapArray ? mRemapArray[pos] : pos;
302 friend class ::Tm1637ModuleTest_flushIncremental;
303 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;
323 const T_TMII mTmiInterface;
325 const uint8_t*
const mRemapArray;
326 uint8_t mPatterns[T_DIGITS];