Basic alarm using low power interrupts

Dependencies:   mbed

Committer:
kgilbert
Date:
Wed Oct 03 21:25:47 2018 +0000
Revision:
0:d31de7b879e3
Child:
1:aa3c38eaaeff
First pass at alarm example

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kgilbert 0:d31de7b879e3 1 #include "mbed.h"
kgilbert 0:d31de7b879e3 2
kgilbert 0:d31de7b879e3 3 // Use buttons to select alarm time. Cycle through hours in an incrementing
kgilbert 0:d31de7b879e3 4 // fashion using button1, hit select and increment through minutes. Hit
kgilbert 0:d31de7b879e3 5 // select one more time to begin the alarm timer.
kgilbert 0:d31de7b879e3 6 //
kgilbert 0:d31de7b879e3 7 // The Time LEDs will blink in time with the button inputs to show the
kgilbert 0:d31de7b879e3 8 // currently selected alarm time. Once select is hit a second time to begin
kgilbert 0:d31de7b879e3 9 // the timer, the LEDs will blink out the configured delay in hours and
kgilbert 0:d31de7b879e3 10 // minutes before going into a low power sleep mode.
kgilbert 0:d31de7b879e3 11 //
kgilbert 0:d31de7b879e3 12 // Once the alarm fires, hitting the select button will turn the alarm off
kgilbert 0:d31de7b879e3 13 // until the next time it fires.
kgilbert 0:d31de7b879e3 14 //__________________________________________________________________________
kgilbert 0:d31de7b879e3 15 // You may also use the RTC (hardware or software through the Time API) to
kgilbert 0:d31de7b879e3 16 // set a real world time and set an alarm for a specific timestamp rather
kgilbert 0:d31de7b879e3 17 // than on a delay. This would require manually setting the time on each
kgilbert 0:d31de7b879e3 18 // reset however, or an internet connection to automatically collect the
kgilbert 0:d31de7b879e3 19 // time. See Example <TODO>[HERE] for how to do that.
kgilbert 0:d31de7b879e3 20
kgilbert 0:d31de7b879e3 21 // Time constants in seconds
kgilbert 0:d31de7b879e3 22 #define HOUR 60 * 60
kgilbert 0:d31de7b879e3 23 #define MINUTE 60
kgilbert 0:d31de7b879e3 24
kgilbert 0:d31de7b879e3 25 // Globals
kgilbert 0:d31de7b879e3 26 DigitalOut alarm_out(D0);
kgilbert 0:d31de7b879e3 27 DigitalOut alarm_led(LED_RED, 1);
kgilbert 0:d31de7b879e3 28 DigitalOut hour_led(LED_GREEN, 1);
kgilbert 0:d31de7b879e3 29 DigitalOut min_led(LED_BLUE, 1);
kgilbert 0:d31de7b879e3 30
kgilbert 0:d31de7b879e3 31 InterruptIn inc_time(BUTTON1);
kgilbert 0:d31de7b879e3 32 InterruptIn select(BUTTON2);
kgilbert 0:d31de7b879e3 33
kgilbert 0:d31de7b879e3 34 LowPowerTicker alarm_event;
kgilbert 0:d31de7b879e3 35
kgilbert 0:d31de7b879e3 36 volatile uint64_t delay = 0;
kgilbert 0:d31de7b879e3 37 volatile uint8_t hour_count = 0;
kgilbert 0:d31de7b879e3 38 volatile uint8_t min_count = 0;
kgilbert 0:d31de7b879e3 39 volatile uint8_t select_state = 0;
kgilbert 0:d31de7b879e3 40
kgilbert 0:d31de7b879e3 41 // Timer Callbacks
kgilbert 0:d31de7b879e3 42 void inc_select(void) {
kgilbert 0:d31de7b879e3 43 if (select_state < 2) {
kgilbert 0:d31de7b879e3 44 select_state++;
kgilbert 0:d31de7b879e3 45 } else {
kgilbert 0:d31de7b879e3 46 // Use select button to disable alarm
kgilbert 0:d31de7b879e3 47 alarm_out = !alarm_out;
kgilbert 0:d31de7b879e3 48 alarm_led = !alarm_led;
kgilbert 0:d31de7b879e3 49 }
kgilbert 0:d31de7b879e3 50 }
kgilbert 0:d31de7b879e3 51
kgilbert 0:d31de7b879e3 52 void set_time_leds(void) {
kgilbert 0:d31de7b879e3 53 if (select_state == 0) {
kgilbert 0:d31de7b879e3 54 hour_led = !hour_led;
kgilbert 0:d31de7b879e3 55 } else {
kgilbert 0:d31de7b879e3 56 min_led = !min_led;
kgilbert 0:d31de7b879e3 57 }
kgilbert 0:d31de7b879e3 58 }
kgilbert 0:d31de7b879e3 59
kgilbert 0:d31de7b879e3 60 void inc_delay(void) {
kgilbert 0:d31de7b879e3 61 if (select_state == 0) {
kgilbert 0:d31de7b879e3 62 delay += HOUR;
kgilbert 0:d31de7b879e3 63 hour_count++;
kgilbert 0:d31de7b879e3 64 hour_led = !hour_led;
kgilbert 0:d31de7b879e3 65 } else {
kgilbert 0:d31de7b879e3 66 delay += MINUTE;
kgilbert 0:d31de7b879e3 67 min_count++;
kgilbert 0:d31de7b879e3 68 min_led = !min_led;
kgilbert 0:d31de7b879e3 69 }
kgilbert 0:d31de7b879e3 70 }
kgilbert 0:d31de7b879e3 71
kgilbert 0:d31de7b879e3 72 void trigger_alarm_out(void) {
kgilbert 0:d31de7b879e3 73 alarm_out = 0;
kgilbert 0:d31de7b879e3 74 alarm_led = 0;
kgilbert 0:d31de7b879e3 75 }
kgilbert 0:d31de7b879e3 76
kgilbert 0:d31de7b879e3 77 // Main thread
kgilbert 0:d31de7b879e3 78 int main() {
kgilbert 0:d31de7b879e3 79 // Configure interrupt-in pins (button controls)
kgilbert 0:d31de7b879e3 80 select.rise(inc_select);
kgilbert 0:d31de7b879e3 81 inc_time.fall(set_time_leds);
kgilbert 0:d31de7b879e3 82 inc_time.rise(inc_delay);
kgilbert 0:d31de7b879e3 83
kgilbert 0:d31de7b879e3 84 // Sleep while waiting for user input to set the desired delay
kgilbert 0:d31de7b879e3 85 while (select_state < 2) { __WFI(); }
kgilbert 0:d31de7b879e3 86
kgilbert 0:d31de7b879e3 87 // Once the delay has been input, blink back the configured hours and
kgilbert 0:d31de7b879e3 88 // minutes selected
kgilbert 0:d31de7b879e3 89 for (uint8_t i = 0; i < hour_count * 2; i++) {
kgilbert 0:d31de7b879e3 90 hour_led = !hour_led;
kgilbert 0:d31de7b879e3 91 wait(0.25f);
kgilbert 0:d31de7b879e3 92 }
kgilbert 0:d31de7b879e3 93
kgilbert 0:d31de7b879e3 94 for (uint8_t i = 0; i < min_count * 2; i++) {
kgilbert 0:d31de7b879e3 95 min_led = !min_led;
kgilbert 0:d31de7b879e3 96 wait(0.25f);
kgilbert 0:d31de7b879e3 97 }
kgilbert 0:d31de7b879e3 98
kgilbert 0:d31de7b879e3 99 // Attach the low power ticker with the configured alarm delay
kgilbert 0:d31de7b879e3 100 alarm_event.attach(&trigger_alarm_out, delay);
kgilbert 0:d31de7b879e3 101
kgilbert 0:d31de7b879e3 102 // Sleep while waiting for the lowpower ticker interrupt to fire the alarm
kgilbert 0:d31de7b879e3 103 while (true) { __WFI(); }
kgilbert 0:d31de7b879e3 104 }