5 April 2025
Now to make the code display the time instead of just “8.8.8.8.” all the time.
6 April 2025
That was a little more difficult than I expected. There wasn’t really that much different when compared to the previous, almost identical project, but I had made a few changes along the way, mostly the naming of the various tables and maps. Dereferencing the segment map was particularly fun. But it works, as far as being a timepiece.
There are some drawbacks to this specific implementation, however. The display is quite dim, overall. I’m still using a 1/32 duty cycle, so it could be brought up a few percentage points in the brilliance category, but I’m not sure it’s worth it. There is also a visible flicker while the RTC interrupt is handled that stops the foreground task from updating the display properly. Maybe I could move that code to a timer interrupt handler instead.
I’m still going to add the time setting buttons and that code as well, as I think this clock is good enough to be used in a dimly lit room. These displays have a date code of “037W”, but I’m not sure which decade it refers. I know I’ve had them for several years, and I suspect some of the newer LED technologies could be more efficient and much brighter in the same application.
I will also add the two little green colon LEDs for completeness. I might even add the temperature display I pondered earlier, but I’m not certain about that, yet. The only other desired feature that I had wanted to implement was the daylight saving option switch.
Again, favoring GPIOB for no particular reason, I have attached the hours and minutes setting push buttons to PB13 and PB14, respectively. Now to add the required code to configure them as inputs with pull-up resistors enabled, then set them up to trigger an external interrupt when pressed.
That was just a bunch of copy/pasting. The only difference was that in this setting, PB13 and PB14 share a single EXTI interrupt, called EXTI15_10, which encompasses EXTI10 through EXTI15. So now I have only a single interrupt enabled and a single interrupt handler. This new handler must now differentiate which of the two, or possibly both, buttons have been pressed and set their corresponding flags for the foreground task to address.
So the buttons are buttoning as I had hoped, but the logic from the last project does not work in this setting. While the previous project had an assistant to handle all the LED scanning and updating tasks (the TM1637 chip), these duties have now been in-sourced. I can’t just have the code stop and wait while the user holds down a button, as the display goes decidedly dark. Also, no detectable “setting” is happening, either. More pondering is indicated.
One way to do this is to implement a state machine. The initial state is when the button (either button) has yet to be pressed. We’ll start out in this state. When the button is pressed, it sets the flag in the interrupt handler, just as we’re doing now. When the foreground task detects that the button has been pressed, the time-of-button-press gets captured and the state advances to the button-is-pressed state. While in this state, the press-elapsed-time is calculated, and if it exceeds the threshold, in this case ~1/2 second, the unit (hour or minute) is incremented. If the unit overflows, it is reset. The time-of-button-press is then re-captured. When the button is released, the state cycles back to yet-to-be-pressed. At no point does the code loop, except for the singular outer loop. Not all that complicated, really.
State
------------------------------
button is not pressed
button has just been pressed
button continues to be pressed
This is only just a little more specific than the previous boolean values of ‘pressed’ or ‘released’. We differentiate the press event to trigger a particular action from the continuously pressed state. Anyway, it works as expected.