|
@@ -10,10 +10,89 @@
|
|
|
I2C i2c(PA_10, PA_9);
|
|
|
// SWO_Channel swo("swo");
|
|
|
|
|
|
-bool Tick = false;
|
|
|
+bool RtcTick = false;
|
|
|
+bool RefreshTick = false;
|
|
|
|
|
|
void RtcCallback(void) {
|
|
|
- Tick = true;
|
|
|
+ RtcTick = true;
|
|
|
+}
|
|
|
+
|
|
|
+void RefreshCallback(void) {
|
|
|
+ RefreshTick = true;
|
|
|
+}
|
|
|
+
|
|
|
+typedef union {
|
|
|
+ struct {
|
|
|
+ char Hour10;
|
|
|
+ char Hour1;
|
|
|
+ char Minute10;
|
|
|
+ char Minute1;
|
|
|
+ };
|
|
|
+} DigitValue;
|
|
|
+
|
|
|
+DigitValue DigitPrev, DigitNext;
|
|
|
+int DigitNextValue[4][10] = {0};
|
|
|
+int DigitPrevValue[4][10] = {0};
|
|
|
+int DotNextValue, DotPrevValue;
|
|
|
+
|
|
|
+bool StartupFlag = true;
|
|
|
+bool RuntimeFlag = false;
|
|
|
+bool DotIncrement = false;
|
|
|
+
|
|
|
+Ticker StartupTicker;
|
|
|
+int StartupTickerIter = 1024;
|
|
|
+
|
|
|
+void StartupTickerCallback(void) {
|
|
|
+
|
|
|
+ DigitNextValue[3][DigitNext.Minute1] += 4;
|
|
|
+ DigitNextValue[2][DigitNext.Minute10] += 4;
|
|
|
+ DigitNextValue[1][DigitNext.Hour1] += 4;
|
|
|
+ if (DigitNext.Hour10 != 0) {
|
|
|
+ DigitNextValue[0][DigitNext.Hour10] += 4;
|
|
|
+ }
|
|
|
+ DotNextValue += 4;
|
|
|
+
|
|
|
+ if (--StartupTickerIter == 0) {
|
|
|
+ StartupTicker.detach();
|
|
|
+ memcpy(&DigitPrev, &DigitNext, sizeof(DigitValue));
|
|
|
+ RuntimeFlag = true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Ticker RuntimeTicker;
|
|
|
+int RuntimeTickerIter = 1024;
|
|
|
+
|
|
|
+void RuntimeTickerCallback(void) {
|
|
|
+
|
|
|
+ if (DigitPrev.Minute1 != DigitNext.Minute1) {
|
|
|
+ DigitNextValue[3][DigitPrev.Minute1] -= 4;
|
|
|
+ DigitNextValue[3][DigitNext.Minute1] += 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (DigitPrev.Minute10 != DigitNext.Minute10) {
|
|
|
+ DigitNextValue[2][DigitPrev.Minute10] -= 4;
|
|
|
+ DigitNextValue[2][DigitNext.Minute10] += 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (DigitPrev.Hour1 != DigitNext.Hour1) {
|
|
|
+ DigitNextValue[1][DigitPrev.Hour1] -= 4;
|
|
|
+ DigitNextValue[1][DigitNext.Hour1] += 4;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (DigitPrev.Hour10 != DigitNext.Hour10) {
|
|
|
+ DigitNextValue[0][DigitPrev.Hour10] -= 4;
|
|
|
+ if (DigitNext.Hour10 != 0) {
|
|
|
+ DigitNextValue[0][DigitNext.Hour10] += 4;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ DotNextValue = DotIncrement ? DotNextValue + 4 : DotNextValue - 4;
|
|
|
+
|
|
|
+ if (--RuntimeTickerIter == 0) {
|
|
|
+ RuntimeTicker.detach();
|
|
|
+ memcpy(&DigitPrev, &DigitNext, sizeof(DigitValue));
|
|
|
+ DotIncrement = !DotIncrement;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int main() {
|
|
@@ -39,13 +118,13 @@ int main() {
|
|
|
// Bump I2C frequency to 1MHz
|
|
|
i2c.frequency(1000000);
|
|
|
|
|
|
+ // Setup a ticker to refresh the display at 1kHz
|
|
|
+ Ticker refreshTicker;
|
|
|
+ refreshTicker.attach_us(RefreshCallback, 1000);
|
|
|
+
|
|
|
// DS3231_SetTime(0, 55, 6, true);
|
|
|
// DS3231_SetDate(0, 2, 12, 18, 0);
|
|
|
|
|
|
- int currMinute = 0, currHour = 0;
|
|
|
- int nextSecond, nextMinute, nextHour;
|
|
|
- int rngTick = 0;
|
|
|
-
|
|
|
while(1) {
|
|
|
|
|
|
// Animate_Cycle_Basic();
|
|
@@ -57,58 +136,55 @@ int main() {
|
|
|
// Animate_Cycle_Fast();
|
|
|
// Animate_Cycle_Fast_Random();
|
|
|
|
|
|
- rngTick = rand() % 60;
|
|
|
-
|
|
|
- if (Tick) {
|
|
|
-
|
|
|
- Tick = false;
|
|
|
-
|
|
|
- rngTick--;
|
|
|
- if (rngTick == 0) {
|
|
|
+ if (RefreshTick) {
|
|
|
|
|
|
+ RefreshTick = false;
|
|
|
|
|
|
+ // On refresh, update the display with new values
|
|
|
|
|
|
- rngTick = rand() % 60;
|
|
|
+ for (int i = 0; i < 4; i++) {
|
|
|
+ for (int j = 0; j < 10; j++) {
|
|
|
+ if (DigitNextValue[i][j] != DigitPrevValue[i][j]) {
|
|
|
+ PCA9685_SetDigit(i, j, DigitNextValue[i][j]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (DotNextValue != DotPrevValue) {
|
|
|
+ PCA9685_SetDot(DotNextValue);
|
|
|
}
|
|
|
|
|
|
- DS3231_GetTime(&nextSecond, &nextMinute, &nextHour);
|
|
|
+ memcpy(DigitPrevValue, DigitNextValue, sizeof(DigitPrevValue));
|
|
|
+ DotPrevValue = DotNextValue;
|
|
|
+ }
|
|
|
|
|
|
- // Fade dot/digits to show the updated time
|
|
|
- for (int i = 0; i < PCA9685_Max_Brightness; i += 4) {
|
|
|
+ if (RtcTick) {
|
|
|
+
|
|
|
+ RtcTick = false;
|
|
|
|
|
|
- if (nextMinute % 10 != currMinute % 10) {
|
|
|
- PCA9685_SetDigit(3, currMinute % 10, PCA9685_Max_Brightness - i);
|
|
|
- PCA9685_SetDigit(3, nextMinute % 10, PCA9685_Min_Brightness + i);
|
|
|
- }
|
|
|
+ // On RTC 1Hz ticks, get the time and begin update
|
|
|
|
|
|
- if (nextMinute / 10 != currMinute / 10) {
|
|
|
- PCA9685_SetDigit(2, currMinute / 10, PCA9685_Max_Brightness - i);
|
|
|
- PCA9685_SetDigit(2, nextMinute / 10, PCA9685_Min_Brightness + i);
|
|
|
- }
|
|
|
+ int nextSecond, nextMinute, nextHour;
|
|
|
+ DS3231_GetTime(&nextSecond, &nextMinute, &nextHour);
|
|
|
|
|
|
- if (nextHour % 10 != currHour % 10 ) {
|
|
|
- PCA9685_SetDigit(1, currHour % 10, PCA9685_Max_Brightness - i);
|
|
|
- PCA9685_SetDigit(1, nextHour % 10, PCA9685_Min_Brightness + i);
|
|
|
- }
|
|
|
+ DigitNext.Minute1 = nextMinute % 10;
|
|
|
+ DigitNext.Minute10 = nextMinute / 10;
|
|
|
+ DigitNext.Hour1 = nextHour % 10;
|
|
|
+ DigitNext.Hour10 = nextHour / 10;
|
|
|
|
|
|
- if (nextHour / 10 != currHour / 10) {
|
|
|
- PCA9685_SetDigit(0, currHour / 10, PCA9685_Max_Brightness - i);
|
|
|
- if (nextHour / 10 != 0) {
|
|
|
- PCA9685_SetDigit(0, nextHour / 10, PCA9685_Min_Brightness + i);
|
|
|
- }
|
|
|
- }
|
|
|
+ if (StartupFlag) {
|
|
|
|
|
|
- PCA9685_SetDot(nextSecond % 2 ? i : PCA9685_Max_Brightness - i);
|
|
|
+ // Fade in the current time
|
|
|
+ StartupTicker.attach_us(StartupTickerCallback, 900);
|
|
|
+ StartupFlag = false;
|
|
|
+ }
|
|
|
|
|
|
- wait(0.0007);
|
|
|
- }
|
|
|
+ if (RuntimeFlag) {
|
|
|
|
|
|
- currMinute = nextMinute;
|
|
|
- currHour = nextHour;
|
|
|
+ // Fade in the new time
|
|
|
+ RuntimeTickerIter = 1024;
|
|
|
+ RuntimeTicker.attach_us(RuntimeTickerCallback, 900);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- // Delay a bit to avoid constant polling
|
|
|
- wait(0.001);
|
|
|
}
|
|
|
}
|
|
|
|