| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | #include "mbed.h"#include "main.h"#include "SWO.h"#include "pca9685.h"#include "tusb322.h"#include "ds3231.h"#include "ioc.h"#include "animation.h"I2C i2c(PA_10, PA_9);// SWO_Channel swo("swo");bool RtcTick, RefreshTick;bool StartupFlag, RuntimeFlag;typedef struct {    char PrevDigit;     // Previous digit to fade out    ushort PrevValue;   // Brightness of previous digit    char NextDigit;     // Next digit to fade in    ushort NextValue;   // Brightness of next digit} Digit;Digit Digits[NUM_DIGITS] = {0};  // Active per-tube digit settingint DotNextValue, DotPrevValue;bool DotIncrement = false;Ticker StartupTicker, RuntimeTicker;int StartupTickerIter, RuntimeTickerIter;void RtcCallback(void) {    RtcTick = true;}void RefreshCallback(void) {    RefreshTick = true;}void StartupTickerCallback(void) {    for (int i = 0; i < NUM_DIGITS; i++) {        Digits[i].NextValue = (i == 0 && Digits[i].NextDigit == 0) ? 0 : Digits[i].NextValue + FADE_TICK_STEP;    }    DotNextValue += FADE_TICK_STEP;    if (--StartupTickerIter == 0) {        StartupTicker.detach();        for (int i = 0; i < NUM_DIGITS; i++) {            Digits[i].PrevDigit = Digits[i].NextDigit;        }        // Switch to runtime mode once startup sequence has completed        RuntimeFlag = true;    }}void RuntimeTickerCallback(void) {    for (int i = 0; i < NUM_DIGITS; i++) {        if(Digits[i].PrevDigit != Digits[i].NextDigit) {            Digits[i].PrevValue -= FADE_TICK_STEP;            Digits[i].NextValue = (i == 0 && Digits[i].NextDigit == 0) ? 0 : Digits[i].NextValue + FADE_TICK_STEP;        }    }    DotNextValue = DotIncrement ? DotNextValue + FADE_TICK_STEP: DotNextValue - FADE_TICK_STEP;    if (--RuntimeTickerIter == 0) {        RuntimeTicker.detach();        for (int i = 0; i < NUM_DIGITS; i++) {            Digits[i].PrevDigit = Digits[i].NextDigit;        }        DotIncrement = !DotIncrement;    }}int main() {        RtcTick = false;    RefreshTick = false;    StartupFlag = true;    RuntimeFlag = false;    // Start I2C at 400kHz for DS3231     i2c.frequency(400000);        // Start with HV PSU disabled    HV_EnableOutput(false);        TUSB322_Init();    PCA9685_Init();    DS3231_Init(RtcCallback);        // Enable HV PSU    HV_EnableOutput(true);        // Set PCA9685 input voltage to highest possible    PCA9685_SetVoltage(1.0);        // swo.printf("CPU SystemCoreClock is %d Hz\r\n", SystemCoreClock);        // 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);    while(1) {        // Animate_Cycle_Basic();        // Animate_Cycle_Analog();        // Animate_Cycle_Low_Pwm();        // Animate_Cycle_Pwm();        // Animate_Cycle_Fade();        // Animate_Cycle_Fade_Random();        // Animate_Cycle_Fast();        // Animate_Cycle_Fast_Random();        if (RefreshTick) {            RefreshTick = false;            // On refresh, update the display with new values            // If brightness has changed, update both prevous and next digits with new values            for (int i = 0; i < NUM_DIGITS; i++) {                if (Digits[i].NextValue != Digits[i].PrevValue) {                    PCA9685_SetDigit(i, Digits[i].PrevDigit, Digits[i].PrevValue);                    PCA9685_SetDigit(i, Digits[i].NextDigit, Digits[i].NextValue);                }            }            if (DotNextValue != DotPrevValue) {                PCA9685_SetDot(DotNextValue);            }            // Update previous values to what was just set            for (int i = 0; i < NUM_DIGITS; i++) {                Digits[i].PrevValue = Digits[i].NextValue;            }            DotPrevValue = DotNextValue;        }        if (RtcTick) {                        RtcTick = false;            // On RTC 1Hz ticks, get the time and begin update            int nextSecond, nextMinute, nextHour;            DS3231_GetTime(&nextSecond, &nextMinute, &nextHour);            Digits[3].NextDigit = nextMinute % 10;            Digits[2].NextDigit = nextMinute / 10;            Digits[1].NextDigit = nextHour % 10;            Digits[0].NextDigit = nextHour / 10;            if (StartupFlag) {                // Fade in the current time                StartupTickerIter = FADE_TICKS;                StartupTicker.attach(StartupTickerCallback, 1/FADE_TICKS);                StartupFlag = false;            }             if (RuntimeFlag) {                // Fade in the new time                RuntimeTickerIter = FADE_TICKS;                RuntimeTicker.attach(RuntimeTickerCallback, 1/FADE_TICKS);            }        }    }}void I2C_Write(int DeviceAddress, char RegAddress, char *Data, int Length) {    char buffer[I2C_MAX_BUFFER+1] = {0};    if (Length > I2C_MAX_BUFFER) LED_Fault(1);    buffer[0] = RegAddress;    memcpy(&buffer[1], Data, Length);    i2c.write(DeviceAddress << 1, buffer, Length + 1);}void I2C_Read(int DeviceAddress, char RegAddress, char *Data, int Length) {        i2c.write(DeviceAddress << 1, &RegAddress, 1);    i2c.read(DeviceAddress << 1, Data, Length);}
 |