Browse Source

Rewrote refresh logic

Kevin Lee 5 years ago
parent
commit
36a7423ed4
3 changed files with 124 additions and 95 deletions
  1. 121 91
      Nixie_Firmware_Mbed/main.cpp
  2. 2 1
      Nixie_Firmware_Mbed/main.h
  3. 1 3
      Nixie_Firmware_Mbed/pca9685.cpp

+ 121 - 91
Nixie_Firmware_Mbed/main.cpp

@@ -11,23 +11,27 @@ I2C i2c(PA_10, PA_9);
 // SWO_Channel swo("swo");
 
 bool RtcTick, RefreshTick, RngTick;
-bool StartupFlag, RuntimeFlag;
 
 typedef struct {
-    char DigitA;
-    ushort DigitAValue;
-    char DigitB;
-    ushort DigitBValue;
-    bool DigitBActive;
+    char Value;
+    ushort Reg;
+    bool Active;
+    bool Increment;
+} DIGIT;
+
+typedef struct {
+    DIGIT Digits[MAX_FADE_DIGITS];
+    DIGIT *NextDigit;
+    DIGIT *PrevDigit;
     bool Updated;
     bool RefreshActive;
 } TUBE;
 
-TUBE Display[NUM_TUBES] = {0};  // Active per-tube digit setting
+TUBE Tube[NUM_TUBES] = {0};  // Active per-tube digit setting
 
-int DotValue;
-bool DotUpdated = false;;
-bool DotIncrement = false;
+ushort DotValue = PCA9685_Min_Brightness;
+bool DotUpdated = false;
+bool DotIncrement = true;
 
 Ticker StartupUpdateTicker, RuntimeUpdateTicker, RngUpdateTicker;
 int StartupTickerIter, RuntimeTickerIter, RngTickerIter;
@@ -45,57 +49,35 @@ void RngTickCallback(void) {
     RngTick = true;
 }
 
-void StartupTickerUpdate(void) {
+void RuntimeTickerUpdate(void) {
 
     for (int i = 0; i < NUM_TUBES; i++) {
-        Display[i].DigitAValue = (i == 0 && Display[i].DigitA == 0) ? 0 : Display[i].DigitAValue + FADE_TICK_STEP;
-        Display[i].Updated = true;
-    }
 
-    DotValue += FADE_TICK_STEP;
-    DotUpdated = true;
+        if(!Tube[i].RefreshActive) {
 
-    if (--StartupTickerIter == 0) {
-        StartupUpdateTicker.detach();
-        for (int i = 0; i < NUM_TUBES; i++) {
-            Display[i].DigitBActive = !Display[i].DigitBActive;
-        }
+            for (int j = 0; j < MAX_FADE_DIGITS; j++) {
 
-        // Switch to runtime mode once startup sequence has completed
-        RuntimeFlag = true;
-    }
-}
+                DIGIT *digit = &Tube[i].Digits[j];
 
-void RuntimeTickerUpdate(void) {
+                if (digit->Active) {
 
-    for (int i = 0; i < NUM_TUBES; i++) {
-        if(!Display[i].RefreshActive) {
+                    if (digit->Increment && digit->Reg < PCA9685_Max_Brightness) {
+                        digit->Reg += FADE_TICK_STEP;
+                    } else if (digit->Reg > PCA9685_Min_Brightness) {
+                        digit->Reg -= FADE_TICK_STEP;
+                    }
 
-            if (Display[i].DigitA != Display[i].DigitB) {
-
-                if (Display[i].DigitBActive) {
-                    Display[i].DigitAValue -= FADE_TICK_STEP;
-                    Display[i].DigitBValue = (i == 0 && Display[i].DigitB == 0) ? 0 : Display[i].DigitBValue + FADE_TICK_STEP;
-                } else {
-                    Display[i].DigitBValue -= FADE_TICK_STEP;
-                    Display[i].DigitAValue = (i == 0 && Display[i].DigitA == 0) ? 0 : Display[i].DigitAValue + FADE_TICK_STEP;
+                    Tube[i].Updated = true;
                 }
-
-                Display[i].Updated = true;
-            } 
+            }
         }
     }
 
-    DotValue = DotIncrement ? DotValue + FADE_TICK_STEP: DotValue - FADE_TICK_STEP;
+    DotValue = DotIncrement ? DotValue + FADE_TICK_STEP : DotValue - FADE_TICK_STEP;
     DotUpdated = true;
 
     if (--RuntimeTickerIter == 0) {
         RuntimeUpdateTicker.detach();
-        for (int i = 0; i < NUM_TUBES; i++) {
-            if (Display[i].DigitA != Display[i].DigitB) {
-                Display[i].DigitBActive = !Display[i].DigitBActive;
-            }
-        }
         DotIncrement = !DotIncrement;
     }
 }
@@ -109,13 +91,20 @@ void RngTickerUpdate(void) {
 }
 
 int main() {
-    
+
+    // Initialize pointers in global data structure
+    for (int i = 0; i < NUM_TUBES; i++) {
+        Tube[i].NextDigit = &Tube[i].Digits[0];
+    }
+
     RtcTick = false;
     RefreshTick = false;
     RngTick = false;
-    StartupFlag = true;
-    RuntimeFlag = false;
 
+    int nextSecond, nextMinute, nextHour;
+    int prevMinute, prevHour;
+    bool startup = true;
+    
     // Start I2C at 400kHz for DS3231 
     i2c.frequency(400000);
     
@@ -125,7 +114,7 @@ int main() {
     TUSB322_Init();
     PCA9685_Init();
     DS3231_Init(RtcTickCallback);
-    
+
     // Enable HV PSU
     HV_EnableOutput(true);
     
@@ -135,7 +124,7 @@ int main() {
     // swo.printf("CPU SystemCoreClock is %d Hz\r\n", SystemCoreClock);
     
     // Bump I2C frequency to 1MHz
-    i2c.frequency(1000000);
+    // i2c.frequency(1000000);
 
     // Setup a ticker to refresh the display at 1kHz
     Ticker refreshTicker;
@@ -164,12 +153,19 @@ int main() {
 
             // On refresh, update the display with new values
 
-            // If values has changed, update both prevous and next digits with new values
             for (int i = 0; i < NUM_TUBES; i++) {
-                if (Display[i].Updated) {
-                    PCA9685_SetDigit(i, Display[i].DigitA, Display[i].DigitAValue);
-                    PCA9685_SetDigit(i, Display[i].DigitB, Display[i].DigitBValue);
-                    Display[i].Updated = false;
+                if (Tube[i].Updated) {
+                    Tube[i].Updated = false;
+
+                    for (int j = 0; j < MAX_FADE_DIGITS; j++) {
+                        DIGIT *digit = &Tube[i].Digits[j];
+                        if (digit->Active) {
+                            PCA9685_SetDigit(i, digit->Value, digit->Reg);
+                            if (digit->Reg == 0 && !digit->Increment) {
+                                digit->Active = false;
+                            }
+                        }
+                    }
                 }
             }
 
@@ -182,54 +178,88 @@ int main() {
         if (RtcTick) {
             RtcTick = false;
 
-            // On RTC 1Hz ticks, get the time and begin update
-            int nextSecond, nextMinute, nextHour;
-            DS3231_GetTime(&nextSecond, &nextMinute, &nextHour);
+            prevMinute = nextMinute;
+            prevHour = nextHour;
 
-            if (Display[3].DigitBActive) {
-                Display[3].DigitB = nextMinute % 10;
-            } else {
-                Display[3].DigitA = nextMinute % 10;
-            }
+            DS3231_GetTime(&nextSecond, &nextMinute, &nextHour);
 
-            if (Display[2].DigitBActive) {
-                Display[2].DigitB = nextMinute / 10;
-            } else {
-                Display[2].DigitA = nextMinute / 10;
-            }
+            if (startup) {
+                startup = false;
+
+                for (int i = 0; i < NUM_TUBES; i++) {
+
+                    bool Update = false;
+                    if (i == 0 && nextHour / 10 != 0) {
+                        Tube[i].NextDigit->Value = nextHour / 10;
+                        Update = true;
+                    } else if (i == 1) {
+                        Tube[i].NextDigit->Value = nextHour % 10;
+                        Update = true;
+                    } else if (i == 2) {
+                        Tube[i].NextDigit->Value = nextMinute / 10;
+                        Update = true;
+                    } else if (i == 3) {
+                        Tube[i].NextDigit->Value = nextMinute % 10;
+                        Update = true;
+                    }
+
+                    if (Update) {
+
+                        Tube[i].NextDigit->Increment = true;
+                        Tube[i].NextDigit->Active = true;
+                        Tube[i].PrevDigit = Tube[i].NextDigit;
+                        Tube[i].NextDigit = (Tube[i].NextDigit == &Tube[i].Digits[0]) ? 
+                            &Tube[i].Digits[1] : &Tube[i].Digits[0];
+                    }
+                }
 
-            if (Display[1].DigitBActive) {
-                Display[1].DigitB = nextHour % 10;
             } else {
-                Display[1].DigitA = nextHour % 10;
-            }
 
-            if (Display[0].DigitBActive) {
-                Display[0].DigitB = nextHour / 10;
-            } else {
-                Display[0].DigitA = nextHour / 10;
+                for (int i = 0; i < NUM_TUBES; i++) {
+
+                    bool Update = false;
+                    if (i == 0 && ((prevHour / 10) != (nextHour / 10))) {
+                        if (nextHour / 10 != 0) {
+                            Tube[i].NextDigit->Value = nextHour / 10;
+                            Tube[i].NextDigit->Increment = true;
+                            Tube[i].NextDigit->Active = true;
+                        }
+                        Update = true;
+                    } else if (i == 1 && ((prevHour % 10) != (nextHour % 10))) {
+                        Tube[i].NextDigit->Value = nextHour % 10;
+                        Tube[i].NextDigit->Increment = true;
+                        Tube[i].NextDigit->Active = true;
+                        Update = true;
+                    } else if (i == 2 && ((prevMinute / 10) != (nextMinute / 10))) {
+                        Tube[i].NextDigit->Value = nextMinute / 10;
+                        Tube[i].NextDigit->Increment = true;
+                        Tube[i].NextDigit->Active = true;
+                        Update = true;
+                    } else if (i == 3 && ((prevMinute % 10) != (nextMinute % 10))) {
+                        Tube[i].NextDigit->Value = nextMinute % 10;
+                        Tube[i].NextDigit->Increment = true;
+                        Tube[i].NextDigit->Active = true;
+                        Update = true;
+                    }
+
+                    if (Update) {
+                        Tube[i].PrevDigit->Increment = false;
+                        Tube[i].PrevDigit = Tube[i].NextDigit;
+                        Tube[i].NextDigit = (Tube[i].NextDigit == &Tube[i].Digits[0]) ? 
+                            &Tube[i].Digits[1] : &Tube[i].Digits[0];
+                    }
+                }
             }
 
-            if (StartupFlag) {
-
-                // Fade in the current time
-                StartupTickerIter = FADE_TICKS;
-                StartupUpdateTicker.attach(StartupTickerUpdate, (float)(DIGIT_REFRESH_RATE_US / 1000) / StartupTickerIter);
-                StartupFlag = false;
-            } 
-
-            if (RuntimeFlag) {
-
-                // Fade in the new time
-                RuntimeTickerIter = FADE_TICKS;
-                RuntimeUpdateTicker.attach(RuntimeTickerUpdate, (float)(DIGIT_REFRESH_RATE_US / 1000) / RuntimeTickerIter);
-            }
+            // Fade in the new time
+            RuntimeTickerIter = FADE_TICKS;
+            RuntimeUpdateTicker.attach(RuntimeTickerUpdate, (float)(DIGIT_REFRESH_RATE_US / 1000) / RuntimeTickerIter);
         }
 
         if (RngTick) {
 
             // Choose a random tube to refresh
-            Display[rand() % 4].RefreshActive = true;
+            Tube[rand() % 4].RefreshActive = true;
 
             RngTickerIter = DIGIT_RNG_REFRESH_ITER * FADE_TICKS;
             RngUpdateTicker.attach(RngTickerUpdate, (DIGIT_REFRESH_RATE_US/1000)/FADE_TICKS);

+ 2 - 1
Nixie_Firmware_Mbed/main.h

@@ -14,13 +14,14 @@
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
 #define NUM_TUBES 4
+#define MAX_FADE_DIGITS 2
 
 #define I2C_MAX_BUFFER 20
 
 #define FADE_TICKS 1024
 #define FADE_TICK_STEP (PCA9685_Max_Brightness / FADE_TICKS)
 
-#define DIGIT_REFRESH_RATE_US 1000
+#define DIGIT_REFRESH_RATE_US 1000  // 1KHz display refresh rate
 
 #define DIGIT_RNG_REFRESH_RATE_S 30
 #define DIGIT_RNG_REFRESH_ITER 20

+ 1 - 3
Nixie_Firmware_Mbed/pca9685.cpp

@@ -73,9 +73,7 @@ void PCA9685_SetDot(int Brightness) {
 
     Brightness /= 3;
     
-    if (Brightness >= PCA9685_Max_Brightness) {
-        reg.ON_FULL = 1;
-    } else if (Brightness == 0) {
+    if (Brightness == 0) {
         reg.OFF_FULL = 1;
     } else {
         reg.OFF = Brightness;