Let's build an alarm clock.
Building upon Adam Taylor's MiniZed motor control project, we are going to add an oled Pmod and convert the timer to a clock. To set the time and alarm time, we will use the serial port. The motor will be used to make the alarm sound.Vivado and the Hardware
Starting with the MiniZed Motor Control project, we need to add the oled Pmod and a clock for it.
Add the PmodOLEDrgb as shown below to the MiniZed motor control project:
Add the oled output to Pmod2. The constraints file is attached. The all of the interfaces pins to the display are inputs (outputs of the MiniZed). FCLK_CLK0 needs to be 50MHz for the Pmod IP to work correctly. By default it is 50MHz on the MiniZed.
Add the HB3 Pmod to the top row of the Pmod 1 connector exactly how Adam Taylor setup the original project. Then, add the oled Pmod to the Pmod 2 connector with the screen side up.Vitis (the software)
Using the MiniZed motor control code as a baseline and Digilent's IP as a guide, the software (in attachements) changes the timer to serve as a 1Hz update for the clock. When the time equals the alarm time, the motor runs and rings the bell(s).
What is going on in the code...
A vast majority of the code is setting up the timer and/or interrupts. With regards to the timer and interrupts, the only thing I changed from Adam's baseline was Line 15 from 100 Hz to 1Hz for the TICK_TIMER_FREQ_HZ and what the interrupt function does once triggered (more on that later). For more info on the timer interrupt code, see Adam Taylor's MicroZed Chronicles Part 15.
There are several variables for holding values of the time and alarm. Most of the variables are global. Not the ideal situation, but considering this is the first program I have made on an ARM processor, please excuse the mess.
The main function sets up the platform, outputs a welcome message over the serial port, and then sets up the oled via OLEDrgb_begin, which requires #include "PMODOLEDrgb.h"
The function display_menu() starting at line 91 is then called. In this program, it is only called once. This is where the clock and alarm times are set. I had an interesting time figuring out that the scanf function was needed for two digit/character serial port reads instead of the read function which is for one character inputs.
The update_oled() function starting at line 286 is then called. This outputs and formats the time and alarm time on the screen. It is called once in the main function after display_menu() gets the values and each minute (called inside the interrupt function).
Next in main, the timer interrupt is setup and enabled. Then the motor control pins are setup, but NOT commanded to run like Adam's program.
Then main waits in a while loop forever. Everything else happens in the TickHandler(void *CallBackRef) function.
The time updates and alarm check occur inside the TickHandler(void *CallBackRef) function starting at line 227. Each interrupt equals one second if a 1Hz TICK_TIMER_FREQ_HZ is set. After 60 seconds, the minute increases, just like a regular clock. Once a minute the update_oled() function is called to change the time. The alarm time is checked against the time and if it is equal, the motor turns on (line 287) for a minute to start your day.
Note: the clock function has a bug with a 12:59 to 1:00 roll-over...Let me know if you figure out what is wrong.Results
Here is a video of the final project:Conclusion
Thanks to Hackster and Adam Taylor for the build and motivating me to dig into FPGA SoCs. It was a very fun experience and hope to do more projects soon! Hope you learned something and create something even bigger.