Merge branch 'main' into movement-timer-stuff
This commit is contained in:
commit
e4f9737e21
@ -45,7 +45,7 @@ These tiny “sensor boards” have a set outline, and the available area for yo
|
|||||||
|
|
||||||
Getting code on the watch
|
Getting code on the watch
|
||||||
-------------------------
|
-------------------------
|
||||||
The watch library in this repository is very work-in-progress, but it should allow you to get started. To create a new project, copy the “Sensor Watch Starter Project” and write your code in the app.c file.
|
The watch library in this repository is very work-in-progress, but it should allow you to get started. To create a new project, copy the “starter-project” folder in the apps folder, and write your code in the app.c file.
|
||||||
|
|
||||||
You will need to install [the GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads/) to build projects for the watch. The watch library has been tested with the `9-2019-q4-major` version and the `10.3-2021.07` versions.
|
You will need to install [the GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads/) to build projects for the watch. The watch library has been tested with the `9-2019-q4-major` version and the `10.3-2021.07` versions.
|
||||||
|
|
||||||
|
@ -1,380 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <math.h>
|
|
||||||
#include "watch.h"
|
|
||||||
#include "bme280.h"
|
|
||||||
|
|
||||||
#include "app.h"
|
|
||||||
|
|
||||||
ApplicationState application_state;
|
|
||||||
char buf[16] = {0};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Zeroes out the application state struct.
|
|
||||||
*/
|
|
||||||
void app_init() {
|
|
||||||
memset(&application_state, 0, sizeof(application_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
|
||||||
// This app does not support BACKUP mode.
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_setup() {
|
|
||||||
watch_enable_external_interrupts();
|
|
||||||
watch_register_interrupt_callback(BTN_MODE, cb_mode_pressed, INTERRUPT_TRIGGER_RISING);
|
|
||||||
watch_register_interrupt_callback(BTN_LIGHT, cb_light_pressed, INTERRUPT_TRIGGER_RISING);
|
|
||||||
watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true);
|
|
||||||
|
|
||||||
watch_enable_buzzer();
|
|
||||||
watch_enable_leds();
|
|
||||||
|
|
||||||
// pin A0 powers the sensor on this board.
|
|
||||||
watch_enable_digital_output(A0);
|
|
||||||
watch_set_pin_level(A0, true);
|
|
||||||
delay_ms(10);
|
|
||||||
|
|
||||||
watch_enable_i2c();
|
|
||||||
|
|
||||||
watch_i2c_write8(BME280_ADDRESS, BME280_REGISTER_SOFTRESET, BME280_SOFT_RESET_CODE);
|
|
||||||
delay_ms(10);
|
|
||||||
application_state.dig_T1 = watch_i2c_read16(BME280_ADDRESS, BME280_REGISTER_DIG_T1);
|
|
||||||
application_state.dig_T2 = (int16_t)watch_i2c_read16(BME280_ADDRESS, BME280_REGISTER_DIG_T2);
|
|
||||||
application_state.dig_T3 = (int16_t)watch_i2c_read16(BME280_ADDRESS, BME280_REGISTER_DIG_T3);
|
|
||||||
application_state.dig_H1 = watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H1);
|
|
||||||
application_state.dig_H2 = (int16_t)watch_i2c_read16(BME280_ADDRESS, BME280_REGISTER_DIG_H2);
|
|
||||||
application_state.dig_H3 = watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H3);
|
|
||||||
application_state.dig_H4 = ((int8_t)watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H4) << 4) |
|
|
||||||
(watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H4 + 1) & 0xF);
|
|
||||||
application_state.dig_H5 = ((int8_t)watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H5 + 1) << 4) |
|
|
||||||
(watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H5) >> 4);
|
|
||||||
application_state.dig_H6 = (int8_t)watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_DIG_H6);
|
|
||||||
|
|
||||||
watch_i2c_write8(BME280_ADDRESS, BME280_REGISTER_CONTROL_HUMID, BME280_CONTROL_HUMID_SAMPLING_NONE);
|
|
||||||
watch_i2c_write8(BME280_ADDRESS, BME280_REGISTER_CONTROL, BME280_CONTROL_TEMPERATURE_SAMPLING_X16 |
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_NONE |
|
|
||||||
BME280_CONTROL_MODE_FORCED);
|
|
||||||
|
|
||||||
watch_enable_display();
|
|
||||||
|
|
||||||
watch_rtc_register_tick_callback(cb_tick);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Nothing to do here.
|
|
||||||
*/
|
|
||||||
void app_prepare_for_standby() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo restore the BME280's calibration values from backup memory
|
|
||||||
*/
|
|
||||||
void app_wake_from_standby() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays the temperature and humidity on screen, or a string indicating no measurements are being taken.
|
|
||||||
*/
|
|
||||||
bool app_loop() {
|
|
||||||
// play a beep if the mode has changed in response to a user's press of the MODE button
|
|
||||||
if (application_state.mode_changed) {
|
|
||||||
// low note for nonzero case, high note for return to clock
|
|
||||||
watch_buzzer_play_note(application_state.mode ? BUZZER_NOTE_C7 : BUZZER_NOTE_C8, 100);
|
|
||||||
application_state.mode_changed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user is not in clock mode and the mode timeout has expired, return them to clock mode
|
|
||||||
if (application_state.mode != MODE_CLOCK && application_state.mode_ticks == 0) {
|
|
||||||
application_state.mode = MODE_CLOCK;
|
|
||||||
application_state.mode_changed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the LED is off and should be on, turn it on
|
|
||||||
if (application_state.light_ticks > 0 && !application_state.led_on) {
|
|
||||||
watch_set_led_green();
|
|
||||||
application_state.led_on = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the LED is on and should be off, turn it off
|
|
||||||
if (application_state.led_on && application_state.light_ticks == 0) {
|
|
||||||
// unless the user is holding down the LIGHT button, in which case, give them more time.
|
|
||||||
if (watch_get_pin_level(BTN_LIGHT)) {
|
|
||||||
application_state.light_ticks = 3;
|
|
||||||
} else {
|
|
||||||
watch_set_led_off();
|
|
||||||
application_state.led_on = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (application_state.mode) {
|
|
||||||
case MODE_CLOCK:
|
|
||||||
do_clock_mode();
|
|
||||||
break;
|
|
||||||
case MODE_TEMP:
|
|
||||||
do_temp_mode();
|
|
||||||
break;
|
|
||||||
case MODE_LOG:
|
|
||||||
do_log_mode();
|
|
||||||
break;
|
|
||||||
case MODE_PREFS:
|
|
||||||
do_prefs_mode();
|
|
||||||
break;
|
|
||||||
case MODE_SET:
|
|
||||||
do_set_time_mode();
|
|
||||||
break;
|
|
||||||
case NUM_MODES:
|
|
||||||
// dummy case, just silences a warning
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
application_state.mode_changed = false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the temperature from the BME280
|
|
||||||
* @param p_t_fine - an optional pointer to an int32_t; if provided, the t_fine measurement
|
|
||||||
* (required for humidity calculation) will be returned by reference.
|
|
||||||
* Pass in NULL if you do not care about this value.
|
|
||||||
* @return a float indicating the temperature in degrees celsius.
|
|
||||||
*/
|
|
||||||
float read_temperature(int32_t *p_t_fine) {
|
|
||||||
// read24 reads the bytes into a uint32 which works for little-endian values (MSB is 0)
|
|
||||||
uint32_t raw_data = watch_i2c_read24(BME280_ADDRESS, BME280_REGISTER_TEMP_DATA) >> 8;
|
|
||||||
// alas the sensor's register layout is big-endian-ish, with a nibble of zeroes at the end of the LSB.
|
|
||||||
// this line shuffles everything back into place (swaps LSB and MSB and shifts the zeroes off the end)
|
|
||||||
int32_t adc_value = (((raw_data >> 16) | (raw_data & 0xFF00) | (raw_data << 16)) & 0xFFFFFF) >> 4;
|
|
||||||
|
|
||||||
// this bit is cribbed from Adafruit's BME280 driver. support their open source efforts by buying some stuff!
|
|
||||||
int32_t var1 = ((((adc_value >> 3) - ((int32_t)application_state.dig_T1 << 1))) * ((int32_t)application_state.dig_T2)) >> 11;
|
|
||||||
int32_t var2 = (((((adc_value >> 4) - ((int32_t)application_state.dig_T1)) * ((adc_value >> 4) - ((int32_t)application_state.dig_T1))) >> 12) * ((int32_t)application_state.dig_T3)) >> 14;
|
|
||||||
int32_t t_fine = var1 + var2;
|
|
||||||
|
|
||||||
// if we got a pointer to a t_fine, return it by reference (for humidity calculation).
|
|
||||||
if (p_t_fine != NULL) *p_t_fine = t_fine;
|
|
||||||
|
|
||||||
if (application_state.is_fahrenheit) {
|
|
||||||
return (((t_fine * 5 + 128) >> 8) / 100.0) * 1.8 + 32;
|
|
||||||
} else {
|
|
||||||
return ((t_fine * 5 + 128) >> 8) / 100.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the humidity from the BME280
|
|
||||||
* @param t_fine - the t_fine measurement from a call to read_temperature
|
|
||||||
* @return a float indicating the relative humidity as a percentage from 0-100.
|
|
||||||
* @todo the returned value is glitchy, need to fix.
|
|
||||||
*/
|
|
||||||
float read_humidity(int32_t t_fine) {
|
|
||||||
int32_t adc_value = watch_i2c_read16(BME280_ADDRESS, BME280_REGISTER_HUMID_DATA);
|
|
||||||
|
|
||||||
// again, cribbed from Adafruit's BME280 driver. they sell a great breakout board for this sensor!
|
|
||||||
int32_t v_x1_u32r = (t_fine - ((int32_t)76800));
|
|
||||||
v_x1_u32r = (((((adc_value << 14) - (((int32_t)application_state.dig_H4) << 20) - (((int32_t)application_state.dig_H5) * v_x1_u32r)) +
|
|
||||||
((int32_t)16384)) >> 15) * (((((((v_x1_u32r * ((int32_t)application_state.dig_H6)) >> 10) * (((v_x1_u32r * ((int32_t)application_state.dig_H3)) >> 11) +
|
|
||||||
((int32_t)32768))) >> 10) + ((int32_t)2097152)) * ((int32_t)application_state.dig_H2) + 8192) >> 14));
|
|
||||||
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * ((int32_t)application_state.dig_H1)) >> 4));
|
|
||||||
v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
|
|
||||||
v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
|
|
||||||
float h = (v_x1_u32r >> 12);
|
|
||||||
|
|
||||||
return h / 1024.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_data() {
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
|
||||||
uint8_t hour = date_time.unit.hour;
|
|
||||||
int8_t temperature = read_temperature(NULL);
|
|
||||||
|
|
||||||
for(int i = 0; i < MAX_DATA_POINTS - 1; i++) {
|
|
||||||
application_state.logged_data[i] = application_state.logged_data[i + 1];
|
|
||||||
}
|
|
||||||
application_state.logged_data[MAX_DATA_POINTS - 1].is_valid = true;
|
|
||||||
application_state.logged_data[MAX_DATA_POINTS - 1].hour = hour;
|
|
||||||
application_state.logged_data[MAX_DATA_POINTS - 1].temperature = temperature;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_clock_mode() {
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
|
||||||
const char months[12][3] = {"JA", "FE", "MR", "AR", "MA", "JN", "JL", "AU", "SE", "OC", "NO", "dE"};
|
|
||||||
|
|
||||||
watch_display_string((char *)months[date_time.unit.month - 1], 0);
|
|
||||||
sprintf(buf, "%2d%2d%02d%02d", date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second);
|
|
||||||
watch_display_string(buf, 2);
|
|
||||||
watch_set_colon();
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_temp_mode() {
|
|
||||||
int32_t t_fine;
|
|
||||||
float temperature;
|
|
||||||
float humidity;
|
|
||||||
|
|
||||||
// take one reading
|
|
||||||
watch_i2c_write8(BME280_ADDRESS, BME280_REGISTER_CONTROL, BME280_CONTROL_TEMPERATURE_SAMPLING_X16 |
|
|
||||||
BME280_CONTROL_MODE_FORCED);
|
|
||||||
// wait for reading to finish
|
|
||||||
while(watch_i2c_read8(BME280_ADDRESS, BME280_REGISTER_STATUS) & BME280_STATUS_UPDATING_MASK);
|
|
||||||
temperature = read_temperature(&t_fine);
|
|
||||||
humidity = read_humidity(t_fine);
|
|
||||||
if (application_state.show_humidity) {
|
|
||||||
sprintf(buf, "TE%2d%4.1f#%c", (int)(humidity / 10), temperature, application_state.is_fahrenheit ? 'F' : 'C');
|
|
||||||
} else {
|
|
||||||
sprintf(buf, "TE %4.1f#%c", temperature, application_state.is_fahrenheit ? 'F' : 'C');
|
|
||||||
}
|
|
||||||
watch_display_string(buf, 0);
|
|
||||||
watch_clear_colon();
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_log_mode() {
|
|
||||||
bool is_valid = (uint8_t)(application_state.logged_data[MAX_DATA_POINTS - 1 - application_state.page].is_valid);
|
|
||||||
uint8_t hour = (uint8_t)(application_state.logged_data[MAX_DATA_POINTS - 1 - application_state.page].hour);
|
|
||||||
int8_t temperature = (int8_t)(application_state.logged_data[MAX_DATA_POINTS - 1 - application_state.page].temperature);
|
|
||||||
if (!is_valid) {
|
|
||||||
sprintf(buf, "LO%2d------", application_state.page);
|
|
||||||
watch_clear_colon();
|
|
||||||
} else {
|
|
||||||
sprintf(buf, "LO%2d%2d%4d", application_state.page, hour, temperature);
|
|
||||||
watch_set_colon();
|
|
||||||
}
|
|
||||||
watch_display_string(buf, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_mode_handle_primary_button() {
|
|
||||||
application_state.page++;
|
|
||||||
if (application_state.page == MAX_DATA_POINTS) application_state.page = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_prefs_mode() {
|
|
||||||
sprintf(buf, "PR CorF %c", application_state.is_fahrenheit ? 'F' : 'C');
|
|
||||||
watch_display_string(buf, 0);
|
|
||||||
watch_clear_colon();
|
|
||||||
}
|
|
||||||
|
|
||||||
void prefs_mode_handle_primary_button() {
|
|
||||||
// TODO: add rest of preferences (12/24, humidity, LED color, etc.)
|
|
||||||
// for now only one, C or F
|
|
||||||
}
|
|
||||||
|
|
||||||
void prefs_mode_handle_secondary_button() {
|
|
||||||
application_state.is_fahrenheit = !application_state.is_fahrenheit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void do_set_time_mode() {
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
|
||||||
|
|
||||||
watch_display_string(" ", 0);
|
|
||||||
switch (application_state.page) {
|
|
||||||
case 0: // hour
|
|
||||||
sprintf(buf, "ST t%2d", date_time.unit.hour);
|
|
||||||
break;
|
|
||||||
case 1: // minute
|
|
||||||
sprintf(buf, "ST t %02d", date_time.unit.minute);
|
|
||||||
break;
|
|
||||||
case 2: // second
|
|
||||||
sprintf(buf, "ST t %02d", date_time.unit.second);
|
|
||||||
break;
|
|
||||||
case 3: // year
|
|
||||||
sprintf(buf, "ST d%2d", date_time.unit.year + 20);
|
|
||||||
break;
|
|
||||||
case 4: // month
|
|
||||||
sprintf(buf, "ST d %02d", date_time.unit.month);
|
|
||||||
break;
|
|
||||||
case 5: // day
|
|
||||||
sprintf(buf, "ST d %02d", date_time.unit.day);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
watch_display_string(buf, 0);
|
|
||||||
watch_set_pixel(1, 12); // required for T in position 1
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_time_mode_handle_primary_button() {
|
|
||||||
application_state.page++;
|
|
||||||
if (application_state.page == 6) application_state.page = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_time_mode_handle_secondary_button() {
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
|
||||||
const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31};
|
|
||||||
|
|
||||||
switch (application_state.page) {
|
|
||||||
case 0: // hour
|
|
||||||
date_time.unit.hour = (date_time.unit.hour + 1) % 24;
|
|
||||||
break;
|
|
||||||
case 1: // minute
|
|
||||||
date_time.unit.minute = (date_time.unit.minute + 1) % 60;
|
|
||||||
break;
|
|
||||||
case 2: // second
|
|
||||||
date_time.unit.second = 0;
|
|
||||||
break;
|
|
||||||
case 3: // year
|
|
||||||
// only allow 2021-2030. fix this sometime next decade
|
|
||||||
date_time.unit.year = ((date_time.unit.year % 10) + 1);
|
|
||||||
break;
|
|
||||||
case 4: // month
|
|
||||||
date_time.unit.month = ((date_time.unit.month + 1) % 12);
|
|
||||||
break;
|
|
||||||
case 5: // day
|
|
||||||
date_time.unit.day = date_time.unit.day + 1;
|
|
||||||
// can't set to the 29th on a leap year. if it's february 29, set to 11:59 on the 28th.
|
|
||||||
// and it should roll over.
|
|
||||||
if (date_time.unit.day > days_in_month[date_time.unit.month - 1]) {
|
|
||||||
date_time.unit.day = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
watch_rtc_set_date_time(date_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cb_mode_pressed() {
|
|
||||||
application_state.mode = (application_state.mode + 1) % NUM_MODES;
|
|
||||||
application_state.mode_changed = true;
|
|
||||||
application_state.mode_ticks = 300;
|
|
||||||
application_state.page = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cb_light_pressed() {
|
|
||||||
switch (application_state.mode) {
|
|
||||||
case MODE_PREFS:
|
|
||||||
prefs_mode_handle_secondary_button();
|
|
||||||
break;
|
|
||||||
case MODE_SET:
|
|
||||||
set_time_mode_handle_secondary_button();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
application_state.light_ticks = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cb_alarm_pressed() {
|
|
||||||
switch (application_state.mode) {
|
|
||||||
case MODE_LOG:
|
|
||||||
log_mode_handle_primary_button();
|
|
||||||
break;
|
|
||||||
case MODE_PREFS:
|
|
||||||
prefs_mode_handle_primary_button();
|
|
||||||
break;
|
|
||||||
case MODE_SET:
|
|
||||||
set_time_mode_handle_primary_button();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cb_tick() {
|
|
||||||
// TODO: use alarm interrupt to trigger data acquisition.
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
|
||||||
if (date_time.unit.minute == 0 && date_time.unit.second == 0) {
|
|
||||||
log_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (application_state.light_ticks > 0) {
|
|
||||||
application_state.light_ticks--;
|
|
||||||
}
|
|
||||||
if (application_state.mode_ticks > 0) {
|
|
||||||
application_state.mode_ticks--;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
// Sensor Watch: Hiking Log Demo App
|
|
||||||
// This app displays a clock and temperature data from a BME280 temperature and humidiity sensor.
|
|
||||||
// It also logs up to 36 hours of temperature data for playback.
|
|
||||||
// You can use this app on backcountry treks: take the watch off at night and place it outside your tent.
|
|
||||||
// It will log overnight low temperatures for review in the morning and optional transfer to your notepad.
|
|
||||||
|
|
||||||
#define MAX_DATA_POINTS 36
|
|
||||||
|
|
||||||
typedef enum ApplicationMode {
|
|
||||||
MODE_CLOCK = 0, // Displays month, day and current time.
|
|
||||||
MODE_TEMP, // (TE) Displays temperature and an optional humidity reading (0-10 representing 0-100%)
|
|
||||||
MODE_LOG, // (LO) Plays back temperature data (temperature in seconds slot)
|
|
||||||
MODE_PREFS, // (PR) Allows setting options for the application
|
|
||||||
MODE_SET, // (ST) Set time and date
|
|
||||||
NUM_MODES // Last item in the enum, it's the number of cases.
|
|
||||||
} ApplicationMode;
|
|
||||||
|
|
||||||
typedef struct SensorReading {
|
|
||||||
bool is_valid;
|
|
||||||
uint8_t hour;
|
|
||||||
int8_t temperature;
|
|
||||||
} SensorReading;
|
|
||||||
|
|
||||||
typedef struct ApplicationState {
|
|
||||||
// Internal application state
|
|
||||||
ApplicationMode mode; // Current mode
|
|
||||||
bool mode_changed; // Lets us perform one-time setup for a given mode
|
|
||||||
uint16_t mode_ticks; // Timeout for the mode (returns to clock after timeout expires)
|
|
||||||
uint8_t light_ticks; // Timeout for the light
|
|
||||||
bool led_on; // Indicates that the LED is on
|
|
||||||
uint8_t page; // Tracks the current page in log, prefs or settings.
|
|
||||||
bool is_fahrenheit; // User preference, C or F
|
|
||||||
|
|
||||||
// Data logging
|
|
||||||
SensorReading logged_data[MAX_DATA_POINTS];
|
|
||||||
|
|
||||||
// User preference
|
|
||||||
bool show_humidity; // Indicates that the LED is on
|
|
||||||
|
|
||||||
// BME280 calibration values
|
|
||||||
uint16_t dig_T1;
|
|
||||||
int16_t dig_T2;
|
|
||||||
int16_t dig_T3;
|
|
||||||
uint8_t dig_H1;
|
|
||||||
int16_t dig_H2;
|
|
||||||
uint8_t dig_H3;
|
|
||||||
int16_t dig_H4;
|
|
||||||
int16_t dig_H5;
|
|
||||||
int8_t dig_H6;
|
|
||||||
} ApplicationState;
|
|
||||||
|
|
||||||
float read_temperature(int32_t *p_t_fine);
|
|
||||||
float read_humidity(int32_t t_fine);
|
|
||||||
|
|
||||||
void log_data();
|
|
||||||
|
|
||||||
void do_clock_mode();
|
|
||||||
|
|
||||||
void do_temp_mode();
|
|
||||||
void temp_mode_handle_primary_button();
|
|
||||||
|
|
||||||
void do_log_mode();
|
|
||||||
void log_mode_handle_primary_button();
|
|
||||||
|
|
||||||
void do_prefs_mode();
|
|
||||||
void prefs_mode_handle_primary_button();
|
|
||||||
void prefs_mode_handle_secondary_button();
|
|
||||||
|
|
||||||
void do_set_time_mode();
|
|
||||||
void set_time_mode_handle_primary_button();
|
|
||||||
void set_time_mode_handle_secondary_button();
|
|
||||||
|
|
||||||
void cb_light_pressed();
|
|
||||||
void cb_mode_pressed();
|
|
||||||
void cb_alarm_pressed();
|
|
||||||
void cb_tick();
|
|
@ -1,85 +0,0 @@
|
|||||||
#define BME280_ADDRESS (0x77)
|
|
||||||
#define BME280_SOFT_RESET_CODE (0xB6)
|
|
||||||
#define BME280_STATUS_UPDATING_MASK (1 << 3)
|
|
||||||
|
|
||||||
typedef enum BME280Register {
|
|
||||||
BME280_REGISTER_DIG_T1 = 0x88,
|
|
||||||
BME280_REGISTER_DIG_T2 = 0x8A,
|
|
||||||
BME280_REGISTER_DIG_T3 = 0x8C,
|
|
||||||
|
|
||||||
BME280_REGISTER_DIG_P1 = 0x8E,
|
|
||||||
BME280_REGISTER_DIG_P2 = 0x90,
|
|
||||||
BME280_REGISTER_DIG_P3 = 0x92,
|
|
||||||
BME280_REGISTER_DIG_P4 = 0x94,
|
|
||||||
BME280_REGISTER_DIG_P5 = 0x96,
|
|
||||||
BME280_REGISTER_DIG_P6 = 0x98,
|
|
||||||
BME280_REGISTER_DIG_P7 = 0x9A,
|
|
||||||
BME280_REGISTER_DIG_P8 = 0x9C,
|
|
||||||
BME280_REGISTER_DIG_P9 = 0x9E,
|
|
||||||
|
|
||||||
BME280_REGISTER_DIG_H1 = 0xA1,
|
|
||||||
BME280_REGISTER_DIG_H2 = 0xE1,
|
|
||||||
BME280_REGISTER_DIG_H3 = 0xE3,
|
|
||||||
BME280_REGISTER_DIG_H4 = 0xE4,
|
|
||||||
BME280_REGISTER_DIG_H5 = 0xE5,
|
|
||||||
BME280_REGISTER_DIG_H6 = 0xE7,
|
|
||||||
|
|
||||||
BME280_REGISTER_CHIPID = 0xD0,
|
|
||||||
BME280_REGISTER_VERSION = 0xD1,
|
|
||||||
BME280_REGISTER_SOFTRESET = 0xE0,
|
|
||||||
|
|
||||||
BME280_REGISTER_CAL26 = 0xE1,
|
|
||||||
|
|
||||||
BME280_REGISTER_CONTROL_HUMID = 0xF2,
|
|
||||||
BME280_REGISTER_STATUS = 0XF3,
|
|
||||||
BME280_REGISTER_CONTROL = 0xF4,
|
|
||||||
BME280_REGISTER_CONFIG = 0xF5,
|
|
||||||
BME280_REGISTER_PRESSURE_DATA = 0xF7,
|
|
||||||
BME280_REGISTER_TEMP_DATA = 0xFA,
|
|
||||||
BME280_REGISTER_HUMID_DATA = 0xFD
|
|
||||||
} BME280Register;
|
|
||||||
|
|
||||||
typedef enum BME280Control {
|
|
||||||
BME280_CONTROL_MODE_SLEEP = 0b00,
|
|
||||||
BME280_CONTROL_MODE_FORCED = 0b01,
|
|
||||||
BME280_CONTROL_MODE_NORMAL = 0b11,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_NONE = 0b000 << 2,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_X1 = 0b001 << 2,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_X2 = 0b010 << 2,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_X4 = 0b011 << 2,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_X8 = 0b100 << 2,
|
|
||||||
BME280_CONTROL_PRESSURE_SAMPLING_X16 = 0b101 << 2,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_NONE = 0b000 << 5,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_X1 = 0b001 << 5,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_X2 = 0b010 << 5,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_X4 = 0b011 << 5,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_X8 = 0b100 << 5,
|
|
||||||
BME280_CONTROL_TEMPERATURE_SAMPLING_X16 = 0b101 << 5
|
|
||||||
} BME280Control;
|
|
||||||
|
|
||||||
typedef enum BME280ControlHumidity {
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_NONE = 0b000,
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_X1 = 0b001,
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_X2 = 0b010,
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_X4 = 0b011,
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_X8 = 0b100,
|
|
||||||
BME280_CONTROL_HUMID_SAMPLING_X16 = 0b101
|
|
||||||
} BME280ControlHumidity;
|
|
||||||
|
|
||||||
typedef enum BME280Filter {
|
|
||||||
BME280_CONFIG_FILTER_OFF = 0b000 << 2,
|
|
||||||
BME280_CONFIG_FILTER_X2 = 0b001 << 2,
|
|
||||||
BME280_CONFIG_FILTER_X4 = 0b010 << 2,
|
|
||||||
BME280_CONFIG_FILTER_X8 = 0b011 << 2,
|
|
||||||
BME280_CONFIG_FILTER_X16 = 0b10 << 2,
|
|
||||||
BME280_CONFIG_STANDBY_MS_0_5 = 0b000 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_10 = 0b110 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_20 = 0b111 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_62_5 = 0b001 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_125 = 0b010 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_250 = 0b011 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_500 = 0b100 << 5,
|
|
||||||
BME280_CONFIG_STANDBY_MS_1000 = 0b101 << 5
|
|
||||||
} BME280Filter;
|
|
||||||
|
|
||||||
inline uint16_t make_le_16(uint16_t val) { return (val >> 8) | (val << 8); }
|
|
@ -1,10 +0,0 @@
|
|||||||
TOP = ../../..
|
|
||||||
include $(TOP)/make.mk
|
|
||||||
|
|
||||||
INCLUDES += \
|
|
||||||
-I../
|
|
||||||
|
|
||||||
SRCS += \
|
|
||||||
../app.c
|
|
||||||
|
|
||||||
include $(TOP)/rules.mk
|
|
@ -11,13 +11,13 @@
|
|||||||
// Also note that this board has its INT1 pin wired to A1, which is not an external
|
// Also note that this board has its INT1 pin wired to A1, which is not an external
|
||||||
// wake pin. Future accelerometer boards will wire interrupt pins to A2 and A4.
|
// wake pin. Future accelerometer boards will wire interrupt pins to A2 and A4.
|
||||||
|
|
||||||
void cb_light_pressed() {
|
void cb_light_pressed(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_mode_pressed() {
|
void cb_mode_pressed(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_pressed() {
|
void cb_alarm_pressed(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t interrupts = 0;
|
uint8_t interrupts = 0;
|
||||||
@ -25,11 +25,11 @@ uint8_t last_interrupts = 0;
|
|||||||
uint8_t ticks = 0;
|
uint8_t ticks = 0;
|
||||||
char buf[13] = {0};
|
char buf[13] = {0};
|
||||||
|
|
||||||
void cb_interrupt_1() {
|
void cb_interrupt_1(void) {
|
||||||
interrupts++;
|
interrupts++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_tick() {
|
void cb_tick(void) {
|
||||||
if (++ticks == 30) {
|
if (++ticks == 30) {
|
||||||
last_interrupts = interrupts;
|
last_interrupts = interrupts;
|
||||||
interrupts = 0;
|
interrupts = 0;
|
||||||
@ -37,7 +37,7 @@ void cb_tick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
gpio_set_pin_direction(A0, GPIO_DIRECTION_OUT);
|
gpio_set_pin_direction(A0, GPIO_DIRECTION_OUT);
|
||||||
gpio_set_pin_function(A0, GPIO_PIN_FUNCTION_OFF);
|
gpio_set_pin_function(A0, GPIO_PIN_FUNCTION_OFF);
|
||||||
gpio_set_pin_level(A0, true);
|
gpio_set_pin_level(A0, true);
|
||||||
@ -64,19 +64,19 @@ void app_init() {
|
|||||||
watch_rtc_register_tick_callback(cb_tick);
|
watch_rtc_register_tick_callback(cb_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_prepare_for_standby() {
|
void app_prepare_for_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
sprintf(buf, "IN%2d%3d%3d", ticks, interrupts, last_interrupts);
|
sprintf(buf, "IN%2d%3d%3d", ticks, interrupts, last_interrupts);
|
||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
|
|
@ -26,19 +26,19 @@ typedef struct ApplicationState {
|
|||||||
uint8_t subsecond; // a value from 0 to (BEAT_REFRESH_FREQUENCY - 1) indicating the fractional second
|
uint8_t subsecond; // a value from 0 to (BEAT_REFRESH_FREQUENCY - 1) indicating the fractional second
|
||||||
} ApplicationState;
|
} ApplicationState;
|
||||||
|
|
||||||
void do_clock_mode();
|
void do_clock_mode(void);
|
||||||
void do_beats_mode();
|
void do_beats_mode(void);
|
||||||
void do_set_time_mode();
|
void do_set_time_mode(void);
|
||||||
void set_time_mode_handle_primary_button();
|
void set_time_mode_handle_primary_button(void);
|
||||||
void set_time_mode_handle_secondary_button();
|
void set_time_mode_handle_secondary_button(void);
|
||||||
|
|
||||||
float clock2beats(uint16_t, uint16_t, uint16_t, int16_t);
|
float clock2beats(uint16_t, uint16_t, uint16_t, int16_t);
|
||||||
|
|
||||||
void cb_light_pressed();
|
void cb_light_pressed(void);
|
||||||
void cb_mode_pressed();
|
void cb_mode_pressed(void);
|
||||||
void cb_alarm_pressed();
|
void cb_alarm_pressed(void);
|
||||||
void cb_tick();
|
void cb_tick(void);
|
||||||
void cb_fast_tick();
|
void cb_fast_tick(void);
|
||||||
|
|
||||||
ApplicationState application_state;
|
ApplicationState application_state;
|
||||||
char buf[16] = {0};
|
char buf[16] = {0};
|
||||||
@ -46,15 +46,15 @@ char buf[16] = {0};
|
|||||||
/**
|
/**
|
||||||
* @brief Zeroes out the application state struct.
|
* @brief Zeroes out the application state struct.
|
||||||
*/
|
*/
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
memset(&application_state, 0, sizeof(application_state));
|
memset(&application_state, 0, sizeof(application_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
// This app does not support BACKUP mode.
|
// This app does not support BACKUP mode.
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
watch_enable_external_interrupts();
|
watch_enable_external_interrupts();
|
||||||
watch_register_interrupt_callback(BTN_MODE, cb_mode_pressed, INTERRUPT_TRIGGER_RISING);
|
watch_register_interrupt_callback(BTN_MODE, cb_mode_pressed, INTERRUPT_TRIGGER_RISING);
|
||||||
watch_register_interrupt_callback(BTN_LIGHT, cb_light_pressed, INTERRUPT_TRIGGER_RISING);
|
watch_register_interrupt_callback(BTN_LIGHT, cb_light_pressed, INTERRUPT_TRIGGER_RISING);
|
||||||
@ -67,13 +67,13 @@ void app_setup() {
|
|||||||
watch_rtc_register_tick_callback(cb_tick);
|
watch_rtc_register_tick_callback(cb_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_prepare_for_standby() {
|
void app_prepare_for_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_tick_frequency() {
|
static void update_tick_frequency(void) {
|
||||||
watch_rtc_disable_all_periodic_callbacks();
|
watch_rtc_disable_all_periodic_callbacks();
|
||||||
if (application_state.mode == MODE_BEATS) {
|
if (application_state.mode == MODE_BEATS) {
|
||||||
watch_rtc_register_periodic_callback(cb_fast_tick, BEAT_REFRESH_FREQUENCY);
|
watch_rtc_register_periodic_callback(cb_fast_tick, BEAT_REFRESH_FREQUENCY);
|
||||||
@ -82,7 +82,7 @@ void update_tick_frequency() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
// play a beep if the mode has changed in response to a user's press of the MODE button
|
// play a beep if the mode has changed in response to a user's press of the MODE button
|
||||||
if (application_state.mode_changed) {
|
if (application_state.mode_changed) {
|
||||||
// low note for nonzero case, high note for return to clock
|
// low note for nonzero case, high note for return to clock
|
||||||
@ -135,7 +135,7 @@ bool app_loop() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_clock_mode() {
|
void do_clock_mode(void) {
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
const char months[12][3] = {"JA", "FE", "MR", "AR", "MA", "JN", "JL", "AU", "SE", "OC", "NO", "dE"};
|
const char months[12][3] = {"JA", "FE", "MR", "AR", "MA", "JN", "JL", "AU", "SE", "OC", "NO", "dE"};
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ void do_clock_mode() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_beats_mode() {
|
void do_beats_mode(void) {
|
||||||
watch_clear_colon();
|
watch_clear_colon();
|
||||||
|
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
@ -168,7 +168,7 @@ float clock2beats(uint16_t hours, uint16_t minutes, uint16_t seconds, int16_t ut
|
|||||||
return beats;
|
return beats;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_set_time_mode() {
|
void do_set_time_mode(void) {
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
|
|
||||||
watch_display_string(" ", 0);
|
watch_display_string(" ", 0);
|
||||||
@ -196,12 +196,12 @@ void do_set_time_mode() {
|
|||||||
watch_set_pixel(1, 12); // required for T in position 1
|
watch_set_pixel(1, 12); // required for T in position 1
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_time_mode_handle_primary_button() {
|
void set_time_mode_handle_primary_button(void) {
|
||||||
application_state.page++;
|
application_state.page++;
|
||||||
if (application_state.page == 6) application_state.page = 0;
|
if (application_state.page == 6) application_state.page = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_time_mode_handle_secondary_button() {
|
void set_time_mode_handle_secondary_button(void) {
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31};
|
const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31};
|
||||||
|
|
||||||
@ -234,14 +234,14 @@ void set_time_mode_handle_secondary_button() {
|
|||||||
watch_rtc_set_date_time(date_time);
|
watch_rtc_set_date_time(date_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_mode_pressed() {
|
void cb_mode_pressed(void) {
|
||||||
application_state.mode = (application_state.mode + 1) % NUM_MODES;
|
application_state.mode = (application_state.mode + 1) % NUM_MODES;
|
||||||
application_state.mode_changed = true;
|
application_state.mode_changed = true;
|
||||||
application_state.mode_ticks = 300;
|
application_state.mode_ticks = 300;
|
||||||
application_state.page = 0;
|
application_state.page = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_light_pressed() {
|
void cb_light_pressed(void) {
|
||||||
switch (application_state.mode) {
|
switch (application_state.mode) {
|
||||||
case MODE_SET:
|
case MODE_SET:
|
||||||
set_time_mode_handle_secondary_button();
|
set_time_mode_handle_secondary_button();
|
||||||
@ -252,7 +252,7 @@ void cb_light_pressed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_pressed() {
|
void cb_alarm_pressed(void) {
|
||||||
switch (application_state.mode) {
|
switch (application_state.mode) {
|
||||||
case MODE_SET:
|
case MODE_SET:
|
||||||
set_time_mode_handle_primary_button();
|
set_time_mode_handle_primary_button();
|
||||||
@ -262,7 +262,7 @@ void cb_alarm_pressed() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_tick() {
|
void cb_tick(void) {
|
||||||
if (application_state.light_ticks > 0) {
|
if (application_state.light_ticks > 0) {
|
||||||
application_state.light_ticks--;
|
application_state.light_ticks--;
|
||||||
}
|
}
|
||||||
@ -271,7 +271,7 @@ void cb_tick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_fast_tick() {
|
void cb_fast_tick(void) {
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
if (date_time.unit.second != application_state.last_second) {
|
if (date_time.unit.second != application_state.last_second) {
|
||||||
application_state.last_second = date_time.unit.second;
|
application_state.last_second = date_time.unit.second;
|
||||||
|
@ -9,18 +9,18 @@ typedef struct ApplicationState {
|
|||||||
ApplicationState application_state;
|
ApplicationState application_state;
|
||||||
|
|
||||||
|
|
||||||
void cb_alarm_pressed() {
|
void cb_alarm_pressed(void) {
|
||||||
application_state.play = true;
|
application_state.play = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
memset(&application_state, 0, sizeof(application_state));
|
memset(&application_state, 0, sizeof(application_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true);
|
watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true);
|
||||||
|
|
||||||
watch_enable_display();
|
watch_enable_display();
|
||||||
@ -28,14 +28,14 @@ void app_setup() {
|
|||||||
watch_enable_buzzer();
|
watch_enable_buzzer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_prepare_for_standby() {
|
void app_prepare_for_standby(void) {
|
||||||
watch_display_string(" rains ", 2);
|
watch_display_string(" rains ", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
if (application_state.play) {
|
if (application_state.play) {
|
||||||
printf("Playing song...\n");
|
printf("Playing song...\n");
|
||||||
const BuzzerNote rains[] = {
|
const BuzzerNote rains[] = {
|
@ -10,7 +10,7 @@
|
|||||||
struct io_descriptor *io;
|
struct io_descriptor *io;
|
||||||
struct spi_m_sync_descriptor SPI_0;
|
struct spi_m_sync_descriptor SPI_0;
|
||||||
|
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
// SPI_0_CLOCK_init
|
// SPI_0_CLOCK_init
|
||||||
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||||
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||||
@ -39,21 +39,21 @@ void app_init() {
|
|||||||
spi_m_sync_enable(&SPI_0);
|
spi_m_sync_enable(&SPI_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_prepare_for_standby() {
|
void app_prepare_for_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_id_command[4] = {0x9F};
|
static uint8_t get_id_command[4] = {0x9F};
|
||||||
|
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
watch_set_pin_level(A3, false);
|
watch_set_pin_level(A3, false);
|
||||||
io_write(io, get_id_command, 1);
|
io_write(io, get_id_command, 1);
|
||||||
uint8_t buf[3] = {0};
|
uint8_t buf[3] = {0};
|
@ -31,9 +31,9 @@ ApplicationState application_state;
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// This section defines the callbacks for our button press events (implemented at bottom).
|
// This section defines the callbacks for our button press events (implemented at bottom).
|
||||||
// Add any other callbacks you may need either here or in another file.
|
// Add any other callbacks you may need either here or in another file.
|
||||||
void cb_light_pressed();
|
void cb_light_pressed(void);
|
||||||
void cb_mode_pressed();
|
void cb_mode_pressed(void);
|
||||||
void cb_alarm_pressed();
|
void cb_alarm_pressed(void);
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -46,7 +46,7 @@ void cb_alarm_pressed();
|
|||||||
* @brief the app_init function is called before anything else. Use it to set up any
|
* @brief the app_init function is called before anything else. Use it to set up any
|
||||||
* internal data structures or application state required by your app.
|
* internal data structures or application state required by your app.
|
||||||
*/
|
*/
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
memset(&application_state, 0, sizeof(application_state));
|
memset(&application_state, 0, sizeof(application_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ void app_init() {
|
|||||||
*
|
*
|
||||||
* @see watch_enter_deep_sleep()
|
* @see watch_enter_deep_sleep()
|
||||||
*/
|
*/
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
// This app does not support BACKUP mode.
|
// This app does not support BACKUP mode.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ void app_wake_from_backup() {
|
|||||||
* also wiped out the system RAM. Note that when this is called after waking from sleep,
|
* also wiped out the system RAM. Note that when this is called after waking from sleep,
|
||||||
* the RTC will still be configured with the correct date and time.
|
* the RTC will still be configured with the correct date and time.
|
||||||
*/
|
*/
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
watch_enable_leds();
|
watch_enable_leds();
|
||||||
watch_enable_buzzer();
|
watch_enable_buzzer();
|
||||||
|
|
||||||
@ -101,14 +101,14 @@ void app_setup() {
|
|||||||
* In STANDBY mode, most peripherals are shut down, and no code will run until the watch receives
|
* In STANDBY mode, most peripherals are shut down, and no code will run until the watch receives
|
||||||
* an interrupt (generally either the 1Hz tick or a press on one of the buttons).
|
* an interrupt (generally either the 1Hz tick or a press on one of the buttons).
|
||||||
*/
|
*/
|
||||||
void app_prepare_for_standby() {
|
void app_prepare_for_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief the app_wake_from_standby function is called after the watch wakes from STANDBY mode,
|
* @brief the app_wake_from_standby function is called after the watch wakes from STANDBY mode,
|
||||||
* but before your main app_loop.
|
* but before your main app_loop.
|
||||||
*/
|
*/
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
application_state.wake_count++;
|
application_state.wake_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ void app_wake_from_standby() {
|
|||||||
* @brief the app_loop function is called once on app startup and then again each time the
|
* @brief the app_loop function is called once on app startup and then again each time the
|
||||||
* watch exits STANDBY mode.
|
* watch exits STANDBY mode.
|
||||||
*/
|
*/
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
if (application_state.beep) {
|
if (application_state.beep) {
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_C7, 50);
|
watch_buzzer_play_note(BUZZER_NOTE_C7, 50);
|
||||||
application_state.beep = false;
|
application_state.beep = false;
|
||||||
@ -178,7 +178,7 @@ bool app_loop() {
|
|||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Implementations for our callback functions. Replace these with whatever functionality
|
// Implementations for our callback functions. Replace these with whatever functionality
|
||||||
// your app requires.
|
// your app requires.
|
||||||
void cb_light_pressed() {
|
void cb_light_pressed(void) {
|
||||||
// always turn the light off when the pin goes low
|
// always turn the light off when the pin goes low
|
||||||
if (watch_get_pin_level(BTN_LIGHT) == 0) {
|
if (watch_get_pin_level(BTN_LIGHT) == 0) {
|
||||||
application_state.light_on = false;
|
application_state.light_on = false;
|
||||||
@ -188,11 +188,11 @@ void cb_light_pressed() {
|
|||||||
application_state.light_on = true;
|
application_state.light_on = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_mode_pressed() {
|
void cb_mode_pressed(void) {
|
||||||
application_state.mode = (application_state.mode + 1) % 2;
|
application_state.mode = (application_state.mode + 1) % 2;
|
||||||
application_state.beep = true;
|
application_state.beep = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_pressed() {
|
void cb_alarm_pressed(void) {
|
||||||
application_state.enter_sleep_mode = true;
|
application_state.enter_sleep_mode = true;
|
||||||
}
|
}
|
@ -38,7 +38,7 @@ uint32_t rol32(uint32_t number, uint8_t bits) {
|
|||||||
return ((number << bits) | (uint32_t)(number >> (32-bits)));
|
return ((number << bits) | (uint32_t)(number >> (32-bits)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void hashBlock() {
|
void hashBlock(void) {
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint32_t a,b,c,d,e,t;
|
uint32_t a,b,c,d,e,t;
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ void writeArray(uint8_t *buffer, uint8_t size){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pad() {
|
void pad(void) {
|
||||||
// Implement SHA-1 padding (fips180-2 <20><>5.1.1)
|
// Implement SHA-1 padding (fips180-2 <20><>5.1.1)
|
||||||
|
|
||||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||||
|
@ -39,6 +39,7 @@ SRCS += \
|
|||||||
../watch_faces/demos/character_set_face.c \
|
../watch_faces/demos/character_set_face.c \
|
||||||
../watch_faces/demos/voltage_face.c \
|
../watch_faces/demos/voltage_face.c \
|
||||||
../watch_faces/demos/lis2dh_logging_face.c \
|
../watch_faces/demos/lis2dh_logging_face.c \
|
||||||
|
../watch_faces/demos/demo_face.c \
|
||||||
../watch_faces/complications/beats_face.c \
|
../watch_faces/complications/beats_face.c \
|
||||||
../watch_faces/complications/day_one_face.c \
|
../watch_faces/complications/day_one_face.c \
|
||||||
../watch_faces/complications/stopwatch_face.c \
|
../watch_faces/complications/stopwatch_face.c \
|
||||||
|
@ -58,27 +58,27 @@ const int16_t movement_timezone_offsets[] = {
|
|||||||
const char movement_valid_position_0_chars[] = " AaBbCcDdEeFGgHhIiJKLMNnOoPQrSTtUuWXYZ-='+\\/0123456789";
|
const char movement_valid_position_0_chars[] = " AaBbCcDdEeFGgHhIiJKLMNnOoPQrSTtUuWXYZ-='+\\/0123456789";
|
||||||
const char movement_valid_position_1_chars[] = " ABCDEFHlJLNORTtUX-='01378";
|
const char movement_valid_position_1_chars[] = " ABCDEFHlJLNORTtUX-='01378";
|
||||||
|
|
||||||
void cb_mode_btn_interrupt();
|
void cb_mode_btn_interrupt(void);
|
||||||
void cb_light_btn_interrupt();
|
void cb_light_btn_interrupt(void);
|
||||||
void cb_alarm_btn_interrupt();
|
void cb_alarm_btn_interrupt(void);
|
||||||
void cb_alarm_btn_extwake();
|
void cb_alarm_btn_extwake(void);
|
||||||
void cb_alarm_fired();
|
void cb_alarm_fired(void);
|
||||||
void cb_fast_tick();
|
void cb_fast_tick(void);
|
||||||
void cb_tick();
|
void cb_tick(void);
|
||||||
|
|
||||||
static inline void _movement_reset_inactivity_countdown() {
|
static inline void _movement_reset_inactivity_countdown(void) {
|
||||||
movement_state.le_mode_ticks = movement_le_inactivity_deadlines[movement_state.settings.bit.le_interval];
|
movement_state.le_mode_ticks = movement_le_inactivity_deadlines[movement_state.settings.bit.le_interval];
|
||||||
movement_state.timeout_ticks = movement_timeout_inactivity_deadlines[movement_state.settings.bit.to_interval];
|
movement_state.timeout_ticks = movement_timeout_inactivity_deadlines[movement_state.settings.bit.to_interval];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _movement_enable_fast_tick_if_needed() {
|
static inline void _movement_enable_fast_tick_if_needed(void) {
|
||||||
if (!movement_state.fast_tick_enabled) {
|
if (!movement_state.fast_tick_enabled) {
|
||||||
movement_state.fast_ticks = 0;
|
movement_state.fast_ticks = 0;
|
||||||
watch_rtc_register_periodic_callback(cb_fast_tick, 128);
|
watch_rtc_register_periodic_callback(cb_fast_tick, 128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void _movement_disable_fast_tick_if_possible() {
|
static inline void _movement_disable_fast_tick_if_possible(void) {
|
||||||
if ((movement_state.light_ticks == -1) &&
|
if ((movement_state.light_ticks == -1) &&
|
||||||
(movement_state.alarm_ticks == -1) &&
|
(movement_state.alarm_ticks == -1) &&
|
||||||
((movement_state.light_down_timestamp + movement_state.mode_down_timestamp + movement_state.alarm_down_timestamp) == 0)) {
|
((movement_state.light_down_timestamp + movement_state.mode_down_timestamp + movement_state.alarm_down_timestamp) == 0)) {
|
||||||
@ -87,7 +87,7 @@ static inline void _movement_disable_fast_tick_if_possible() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _movement_handle_background_tasks() {
|
static void _movement_handle_background_tasks(void) {
|
||||||
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
for(uint8_t i = 0; i < MOVEMENT_NUM_FACES; i++) {
|
||||||
// For each face, if the watch face wants a background task...
|
// For each face, if the watch face wants a background task...
|
||||||
if (watch_faces[i].wants_background_task != NULL && watch_faces[i].wants_background_task(&movement_state.settings, watch_face_contexts[i])) {
|
if (watch_faces[i].wants_background_task != NULL && watch_faces[i].wants_background_task(&movement_state.settings, watch_face_contexts[i])) {
|
||||||
@ -107,7 +107,7 @@ void movement_request_tick_frequency(uint8_t freq) {
|
|||||||
if (freq) watch_rtc_register_periodic_callback(cb_tick, freq);
|
if (freq) watch_rtc_register_periodic_callback(cb_tick, freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movement_illuminate_led() {
|
void movement_illuminate_led(void) {
|
||||||
if (movement_state.settings.bit.led_duration) {
|
if (movement_state.settings.bit.led_duration) {
|
||||||
watch_set_led_color(movement_state.settings.bit.led_red_color ? (0xF | movement_state.settings.bit.led_red_color << 4) : 0,
|
watch_set_led_color(movement_state.settings.bit.led_red_color ? (0xF | movement_state.settings.bit.led_red_color << 4) : 0,
|
||||||
movement_state.settings.bit.led_green_color ? (0xF | movement_state.settings.bit.led_green_color << 4) : 0);
|
movement_state.settings.bit.led_green_color ? (0xF | movement_state.settings.bit.led_green_color << 4) : 0);
|
||||||
@ -121,22 +121,22 @@ void movement_move_to_face(uint8_t watch_face_index) {
|
|||||||
movement_state.next_watch_face = watch_face_index;
|
movement_state.next_watch_face = watch_face_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void movement_move_to_next_face() {
|
void movement_move_to_next_face(void) {
|
||||||
movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES);
|
movement_move_to_face((movement_state.current_watch_face + 1) % MOVEMENT_NUM_FACES);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movement_play_signal() {
|
void movement_play_signal(void) {
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_C8, 75);
|
watch_buzzer_play_note(BUZZER_NOTE_C8, 75);
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_REST, 100);
|
watch_buzzer_play_note(BUZZER_NOTE_REST, 100);
|
||||||
watch_buzzer_play_note(BUZZER_NOTE_C8, 100);
|
watch_buzzer_play_note(BUZZER_NOTE_C8, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movement_play_alarm() {
|
void movement_play_alarm(void) {
|
||||||
movement_state.alarm_ticks = 128 * 5 - 80; // 80 ticks short of 5 seconds, or 4.375 seconds (our beep is 0.375 seconds)
|
movement_state.alarm_ticks = 128 * 5 - 80; // 80 ticks short of 5 seconds, or 4.375 seconds (our beep is 0.375 seconds)
|
||||||
_movement_enable_fast_tick_if_needed();
|
_movement_enable_fast_tick_if_needed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_init() {
|
void app_init(void) {
|
||||||
memset(&movement_state, 0, sizeof(movement_state));
|
memset(&movement_state, 0, sizeof(movement_state));
|
||||||
|
|
||||||
movement_state.settings.bit.led_green_color = 0xF;
|
movement_state.settings.bit.led_green_color = 0xF;
|
||||||
@ -149,11 +149,11 @@ void app_init() {
|
|||||||
_movement_reset_inactivity_countdown();
|
_movement_reset_inactivity_countdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_backup() {
|
void app_wake_from_backup(void) {
|
||||||
movement_state.settings.reg = watch_get_backup_data(0);
|
movement_state.settings.reg = watch_get_backup_data(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_setup() {
|
void app_setup(void) {
|
||||||
watch_store_backup_data(movement_state.settings.reg, 0);
|
watch_store_backup_data(movement_state.settings.reg, 0);
|
||||||
|
|
||||||
static bool is_first_launch = true;
|
static bool is_first_launch = true;
|
||||||
@ -218,13 +218,14 @@ void TC2_Handler(void) {
|
|||||||
printf("TICK!\n");
|
printf("TICK!\n");
|
||||||
TC2->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF;
|
TC2->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF;
|
||||||
}
|
}
|
||||||
void app_prepare_for_standby() {
|
|
||||||
|
void app_prepare_for_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_wake_from_standby() {
|
void app_wake_from_standby(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool app_loop() {
|
bool app_loop(void) {
|
||||||
if (movement_state.watch_face_changed) {
|
if (movement_state.watch_face_changed) {
|
||||||
if (movement_state.settings.bit.button_should_sound) {
|
if (movement_state.settings.bit.button_should_sound) {
|
||||||
// low note for nonzero case, high note for return to watch_face 0
|
// low note for nonzero case, high note for return to watch_face 0
|
||||||
@ -324,7 +325,7 @@ bool app_loop() {
|
|||||||
return can_sleep && (movement_state.light_ticks == -1) && !movement_state.is_buzzing;
|
return can_sleep && (movement_state.light_ticks == -1) && !movement_state.is_buzzing;
|
||||||
}
|
}
|
||||||
|
|
||||||
movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint8_t *down_timestamp) {
|
static movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_type_t button_down_event_type, uint8_t *down_timestamp) {
|
||||||
// force alarm off if the user pressed a button.
|
// force alarm off if the user pressed a button.
|
||||||
if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0;
|
if (movement_state.alarm_ticks) movement_state.alarm_ticks = 0;
|
||||||
|
|
||||||
@ -347,34 +348,34 @@ movement_event_type_t _figure_out_button_event(bool pin_level, movement_event_ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_light_btn_interrupt() {
|
void cb_light_btn_interrupt(void) {
|
||||||
bool pin_level = watch_get_pin_level(BTN_LIGHT);
|
bool pin_level = watch_get_pin_level(BTN_LIGHT);
|
||||||
_movement_reset_inactivity_countdown();
|
_movement_reset_inactivity_countdown();
|
||||||
event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp);
|
event.event_type = _figure_out_button_event(pin_level, EVENT_LIGHT_BUTTON_DOWN, &movement_state.light_down_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_mode_btn_interrupt() {
|
void cb_mode_btn_interrupt(void) {
|
||||||
bool pin_level = watch_get_pin_level(BTN_MODE);
|
bool pin_level = watch_get_pin_level(BTN_MODE);
|
||||||
_movement_reset_inactivity_countdown();
|
_movement_reset_inactivity_countdown();
|
||||||
event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp);
|
event.event_type = _figure_out_button_event(pin_level, EVENT_MODE_BUTTON_DOWN, &movement_state.mode_down_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_btn_interrupt() {
|
void cb_alarm_btn_interrupt(void) {
|
||||||
bool pin_level = watch_get_pin_level(BTN_ALARM);
|
bool pin_level = watch_get_pin_level(BTN_ALARM);
|
||||||
_movement_reset_inactivity_countdown();
|
_movement_reset_inactivity_countdown();
|
||||||
event.event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp);
|
event.event_type = _figure_out_button_event(pin_level, EVENT_ALARM_BUTTON_DOWN, &movement_state.alarm_down_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_btn_extwake() {
|
void cb_alarm_btn_extwake(void) {
|
||||||
// wake up!
|
// wake up!
|
||||||
_movement_reset_inactivity_countdown();
|
_movement_reset_inactivity_countdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_alarm_fired() {
|
void cb_alarm_fired(void) {
|
||||||
movement_state.needs_background_tasks_handled = true;
|
movement_state.needs_background_tasks_handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_fast_tick() {
|
void cb_fast_tick(void) {
|
||||||
movement_state.fast_ticks++;
|
movement_state.fast_ticks++;
|
||||||
if (movement_state.light_ticks > 0) movement_state.light_ticks--;
|
if (movement_state.light_ticks > 0) movement_state.light_ticks--;
|
||||||
if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--;
|
if (movement_state.alarm_ticks > 0) movement_state.alarm_ticks--;
|
||||||
@ -383,7 +384,7 @@ void cb_fast_tick() {
|
|||||||
if (movement_state.fast_ticks >= 1280) watch_rtc_disable_periodic_callback(128);
|
if (movement_state.fast_ticks >= 1280) watch_rtc_disable_periodic_callback(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cb_tick() {
|
void cb_tick(void) {
|
||||||
event.event_type = EVENT_TICK;
|
event.event_type = EVENT_TICK;
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
if (date_time.unit.second != movement_state.last_second) {
|
if (date_time.unit.second != movement_state.last_second) {
|
||||||
|
@ -242,11 +242,11 @@ typedef struct {
|
|||||||
} movement_state_t;
|
} movement_state_t;
|
||||||
|
|
||||||
void movement_move_to_face(uint8_t watch_face_index);
|
void movement_move_to_face(uint8_t watch_face_index);
|
||||||
void movement_move_to_next_face();
|
void movement_move_to_next_face(void);
|
||||||
void movement_illuminate_led();
|
void movement_illuminate_led(void);
|
||||||
void movement_request_tick_frequency(uint8_t freq);
|
void movement_request_tick_frequency(uint8_t freq);
|
||||||
|
|
||||||
void movement_play_signal();
|
void movement_play_signal(void);
|
||||||
void movement_play_alarm();
|
void movement_play_alarm(void);
|
||||||
|
|
||||||
#endif // MOVEMENT_H_
|
#endif // MOVEMENT_H_
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "stopwatch_face.h"
|
#include "stopwatch_face.h"
|
||||||
#include "totp_face.h"
|
#include "totp_face.h"
|
||||||
#include "lis2dh_logging_face.h"
|
#include "lis2dh_logging_face.h"
|
||||||
|
#include "demo_face.h"
|
||||||
|
|
||||||
const watch_face_t watch_faces[] = {
|
const watch_face_t watch_faces[] = {
|
||||||
simple_clock_face,
|
simple_clock_face,
|
||||||
|
@ -26,7 +26,7 @@ void world_clock_face_activate(movement_settings_t *settings, void *context) {
|
|||||||
watch_set_colon();
|
watch_set_colon();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool world_clock_face_do_display_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) {
|
static bool world_clock_face_do_display_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) {
|
||||||
char buf[11];
|
char buf[11];
|
||||||
uint8_t pos;
|
uint8_t pos;
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ bool world_clock_face_do_display_mode(movement_event_t event, movement_settings_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool world_clock_face_do_settings_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) {
|
static bool _world_clock_face_do_settings_mode(movement_event_t event, movement_settings_t *settings, world_clock_state_t *state) {
|
||||||
switch (event.event_type) {
|
switch (event.event_type) {
|
||||||
case EVENT_MODE_BUTTON_UP:
|
case EVENT_MODE_BUTTON_UP:
|
||||||
movement_move_to_next_face();
|
movement_move_to_next_face();
|
||||||
@ -176,7 +176,7 @@ bool world_clock_face_loop(movement_event_t event, movement_settings_t *settings
|
|||||||
if (state->current_screen == 0) {
|
if (state->current_screen == 0) {
|
||||||
return world_clock_face_do_display_mode(event, settings, state);
|
return world_clock_face_do_display_mode(event, settings, state);
|
||||||
} else {
|
} else {
|
||||||
return world_clock_face_do_settings_mode(event, settings, state);
|
return _world_clock_face_do_settings_mode(event, settings, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
#include "day_one_face.h"
|
#include "day_one_face.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16_t day) {
|
static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16_t day) {
|
||||||
// from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation
|
// from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation
|
||||||
return (1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100))/4 + day - 32075;
|
return (1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100))/4 + day - 32075;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _day_one_face_update(day_one_state_t state) {
|
static void _day_one_face_update(day_one_state_t state) {
|
||||||
char buf[14];
|
char buf[14];
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
uint32_t julian_date = _day_one_face_juliandaynum(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day);
|
uint32_t julian_date = _day_one_face_juliandaynum(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day);
|
||||||
|
91
movement/watch_faces/demos/demo_face.c
Normal file
91
movement/watch_faces/demos/demo_face.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "demo_face.h"
|
||||||
|
#include "watch.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEMO_FACE_HELLO = 0,
|
||||||
|
DEMO_FACE_TIME,
|
||||||
|
DEMO_FACE_WORLD_TIME,
|
||||||
|
DEMO_FACE_BEATS,
|
||||||
|
DEMO_FACE_TEMP_F,
|
||||||
|
DEMO_FACE_TEMP_C,
|
||||||
|
DEMO_FACE_BATTERY_VOLTAGE,
|
||||||
|
DEMO_FACE_NUM_FACES
|
||||||
|
} demo_face_index_t;
|
||||||
|
|
||||||
|
void demo_face_setup(movement_settings_t *settings, void ** context_ptr) {
|
||||||
|
(void) settings;
|
||||||
|
if (*context_ptr == NULL) {
|
||||||
|
*context_ptr = malloc(sizeof(demo_face_index_t));
|
||||||
|
memset(*context_ptr, 0, sizeof(demo_face_index_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void demo_face_activate(movement_settings_t *settings, void *context) {
|
||||||
|
(void) settings;
|
||||||
|
(void) context;
|
||||||
|
movement_request_tick_frequency(0);
|
||||||
|
// ensure the watch never enters low energy mode
|
||||||
|
settings->bit.le_interval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||||
|
(void) settings;
|
||||||
|
demo_face_index_t *screen = (demo_face_index_t *)context;
|
||||||
|
switch (event.event_type) {
|
||||||
|
case EVENT_MODE_BUTTON_UP:
|
||||||
|
movement_move_to_next_face();
|
||||||
|
break;
|
||||||
|
case EVENT_LIGHT_BUTTON_DOWN:
|
||||||
|
movement_illuminate_led();
|
||||||
|
break;
|
||||||
|
case EVENT_ALARM_BUTTON_UP:
|
||||||
|
*screen = ((*screen) + 1) % DEMO_FACE_NUM_FACES;
|
||||||
|
// fall through
|
||||||
|
case EVENT_ACTIVATE:
|
||||||
|
switch (*screen) {
|
||||||
|
case DEMO_FACE_HELLO:
|
||||||
|
watch_display_string(" Hello ", 0);
|
||||||
|
watch_clear_colon();
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_TIME:
|
||||||
|
watch_display_string("TH 6101036", 0);
|
||||||
|
watch_set_colon();
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_WORLD_TIME:
|
||||||
|
watch_display_string("MT 6 81036", 0);
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_BEATS:
|
||||||
|
watch_display_string("bt 64125", 0);
|
||||||
|
watch_clear_colon();
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_TEMP_F:
|
||||||
|
watch_display_string("TE 72.1#F", 0);
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_TEMP_C:
|
||||||
|
watch_display_string("TE 22.3#C", 0);
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_BATTERY_VOLTAGE:
|
||||||
|
watch_display_string("BA 2.97 V", 0);
|
||||||
|
break;
|
||||||
|
case DEMO_FACE_NUM_FACES:
|
||||||
|
// we won't get here, but silence the warning
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EVENT_TIMEOUT:
|
||||||
|
// ignore timeout
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void demo_face_resign(movement_settings_t *settings, void *context) {
|
||||||
|
(void) settings;
|
||||||
|
(void) context;
|
||||||
|
movement_request_tick_frequency(1);
|
||||||
|
}
|
19
movement/watch_faces/demos/demo_face.h
Normal file
19
movement/watch_faces/demos/demo_face.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef DEMO_FACE_H_
|
||||||
|
#define DEMO_FACE_H_
|
||||||
|
|
||||||
|
#include "movement.h"
|
||||||
|
|
||||||
|
void demo_face_setup(movement_settings_t *settings, void ** context_ptr);
|
||||||
|
void demo_face_activate(movement_settings_t *settings, void *context);
|
||||||
|
bool demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||||
|
void demo_face_resign(movement_settings_t *settings, void *context);
|
||||||
|
|
||||||
|
static const watch_face_t demo_face = {
|
||||||
|
demo_face_setup,
|
||||||
|
demo_face_activate,
|
||||||
|
demo_face_loop,
|
||||||
|
demo_face_resign,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEMO_FACE_H_
|
@ -12,7 +12,7 @@
|
|||||||
// Pressing the alarm button enters the log mode, where the main display shows the number of interrupts detected in each of the last
|
// Pressing the alarm button enters the log mode, where the main display shows the number of interrupts detected in each of the last
|
||||||
// 24 hours (the hour is shown in the top right digit and AM/PM indicator, if the clock is set to 12 hour mode)
|
// 24 hours (the hour is shown in the top right digit and AM/PM indicator, if the clock is set to 12 hour mode)
|
||||||
|
|
||||||
void _lis2dh_logging_face_update_display(movement_settings_t *settings, lis2dh_logger_state_t *logger_state, lis2dh_interrupt_state interrupt_state, watch_date_time date_time) {
|
static void _lis2dh_logging_face_update_display(movement_settings_t *settings, lis2dh_logger_state_t *logger_state, lis2dh_interrupt_state interrupt_state, watch_date_time date_time) {
|
||||||
char buf[14];
|
char buf[14];
|
||||||
char time_indication_character;
|
char time_indication_character;
|
||||||
int8_t pos;
|
int8_t pos;
|
||||||
@ -66,7 +66,7 @@ void _lis2dh_logging_face_update_display(movement_settings_t *settings, lis2dh_l
|
|||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _lis2dh_logging_face_log_data(lis2dh_logger_state_t *logger_state) {
|
static void _lis2dh_logging_face_log_data(lis2dh_logger_state_t *logger_state) {
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
// we get this call 15 minutes late; i.e. at 6:15 we're logging events for 6:00.
|
// we get this call 15 minutes late; i.e. at 6:15 we're logging events for 6:00.
|
||||||
// so: if we're at the top of the hour, roll the hour back too (7:00 task logs data for 6:45)
|
// so: if we're at the top of the hour, roll the hour back too (7:00 task logs data for 6:45)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "voltage_face.h"
|
#include "voltage_face.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
void _voltage_face_update_display() {
|
static void _voltage_face_update_display(void) {
|
||||||
char buf[14];
|
char buf[14];
|
||||||
float voltage = (float)watch_get_vcc_voltage() / 1000.0;
|
float voltage = (float)watch_get_vcc_voltage() / 1000.0;
|
||||||
sprintf(buf, "BA %4.2f V", voltage);
|
sprintf(buf, "BA %4.2f V", voltage);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
#include "watch_utility.h"
|
#include "watch_utility.h"
|
||||||
|
|
||||||
void thermistor_driver_enable() {
|
void thermistor_driver_enable(void) {
|
||||||
// Enable the ADC peripheral, which we'll use to read the thermistor value.
|
// Enable the ADC peripheral, which we'll use to read the thermistor value.
|
||||||
watch_enable_adc();
|
watch_enable_adc();
|
||||||
// Enable analog circuitry on the sense pin, which is tied to the thermistor resistor divider.
|
// Enable analog circuitry on the sense pin, which is tied to the thermistor resistor divider.
|
||||||
@ -13,7 +13,7 @@ void thermistor_driver_enable() {
|
|||||||
watch_set_pin_level(THERMISTOR_ENABLE_PIN, !THERMISTOR_ENABLE_VALUE);
|
watch_set_pin_level(THERMISTOR_ENABLE_PIN, !THERMISTOR_ENABLE_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thermistor_driver_disable() {
|
void thermistor_driver_disable(void) {
|
||||||
// Disable the ADC peripheral.
|
// Disable the ADC peripheral.
|
||||||
watch_disable_adc();
|
watch_disable_adc();
|
||||||
// Disable analog circuitry on the sense pin to save power.
|
// Disable analog circuitry on the sense pin to save power.
|
||||||
@ -22,7 +22,7 @@ void thermistor_driver_disable() {
|
|||||||
watch_disable_digital_output(THERMISTOR_ENABLE_PIN);
|
watch_disable_digital_output(THERMISTOR_ENABLE_PIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
float thermistor_driver_get_temperature() {
|
float thermistor_driver_get_temperature(void) {
|
||||||
// set the enable pin to the level that powers the thermistor circuit.
|
// set the enable pin to the level that powers the thermistor circuit.
|
||||||
watch_set_pin_level(THERMISTOR_ENABLE_PIN, THERMISTOR_ENABLE_VALUE);
|
watch_set_pin_level(THERMISTOR_ENABLE_PIN, THERMISTOR_ENABLE_VALUE);
|
||||||
// get the sense pin level
|
// get the sense pin level
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#define THERMISTOR_NOMINAL_RESISTANCE (10000.0)
|
#define THERMISTOR_NOMINAL_RESISTANCE (10000.0)
|
||||||
#define THERMISTOR_SERIES_RESISTANCE (10000.0)
|
#define THERMISTOR_SERIES_RESISTANCE (10000.0)
|
||||||
|
|
||||||
void thermistor_driver_enable();
|
void thermistor_driver_enable(void);
|
||||||
void thermistor_driver_disable();
|
void thermistor_driver_disable(void);
|
||||||
float thermistor_driver_get_temperature();
|
float thermistor_driver_get_temperature(void);
|
||||||
|
|
||||||
#endif // THERMISTOR_DRIVER_H_
|
#endif // THERMISTOR_DRIVER_H_
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "thermistor_driver.h"
|
#include "thermistor_driver.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
void _thermistor_logging_face_log_data(thermistor_logger_state_t *logger_state) {
|
static void _thermistor_logging_face_log_data(thermistor_logger_state_t *logger_state) {
|
||||||
thermistor_driver_enable();
|
thermistor_driver_enable();
|
||||||
watch_date_time date_time = watch_rtc_get_date_time();
|
watch_date_time date_time = watch_rtc_get_date_time();
|
||||||
size_t pos = logger_state->data_points % THERMISTOR_LOGGING_NUM_DATA_POINTS;
|
size_t pos = logger_state->data_points % THERMISTOR_LOGGING_NUM_DATA_POINTS;
|
||||||
@ -16,7 +16,7 @@ void _thermistor_logging_face_log_data(thermistor_logger_state_t *logger_state)
|
|||||||
thermistor_driver_disable();
|
thermistor_driver_disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _thermistor_logging_face_update_display(thermistor_logger_state_t *logger_state, bool in_fahrenheit, bool clock_mode_24h) {
|
static void _thermistor_logging_face_update_display(thermistor_logger_state_t *logger_state, bool in_fahrenheit, bool clock_mode_24h) {
|
||||||
int8_t pos = (logger_state->data_points - 1 - logger_state->display_index) % THERMISTOR_LOGGING_NUM_DATA_POINTS;
|
int8_t pos = (logger_state->data_points - 1 - logger_state->display_index) % THERMISTOR_LOGGING_NUM_DATA_POINTS;
|
||||||
char buf[14];
|
char buf[14];
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "thermistor_driver.h"
|
#include "thermistor_driver.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
void _thermistor_readout_face_update_display(bool in_fahrenheit) {
|
static void _thermistor_readout_face_update_display(bool in_fahrenheit) {
|
||||||
thermistor_driver_enable();
|
thermistor_driver_enable();
|
||||||
float temperature_c = thermistor_driver_get_temperature();
|
float temperature_c = thermistor_driver_get_temperature();
|
||||||
char buf[14];
|
char buf[14];
|
||||||
|
@ -29,7 +29,7 @@ void error(const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setup() {
|
void setup(void) {
|
||||||
pinMode(13, OUTPUT);
|
pinMode(13, OUTPUT);
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
// while(!Serial) {
|
// while(!Serial) {
|
||||||
@ -102,7 +102,7 @@ void setup() {
|
|||||||
dap.dap_disconnect();
|
dap.dap_disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop(void) {
|
||||||
//blink led on the host to show we're done
|
//blink led on the host to show we're done
|
||||||
digitalWrite(13, HIGH);
|
digitalWrite(13, HIGH);
|
||||||
delay(500);
|
delay(500);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "lis2dh.h"
|
#include "lis2dh.h"
|
||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
bool lis2dh_begin() {
|
bool lis2dh_begin(void) {
|
||||||
if (lis2dh_get_device_id() != LIS2DH_WHO_AM_I_VAL) {
|
if (lis2dh_get_device_id() != LIS2DH_WHO_AM_I_VAL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -40,16 +40,16 @@ bool lis2dh_begin() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t lis2dh_get_device_id() {
|
uint8_t lis2dh_get_device_id(void) {
|
||||||
return watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_WHO_AM_I);
|
return watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_WHO_AM_I);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lis2dh_have_new_data() {
|
bool lis2dh_have_new_data(void) {
|
||||||
uint8_t retval = watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_STATUS);
|
uint8_t retval = watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_STATUS);
|
||||||
return !!retval; // return true if any bit is set
|
return !!retval; // return true if any bit is set
|
||||||
}
|
}
|
||||||
|
|
||||||
lis2dh_reading lis2dh_get_raw_reading() {
|
lis2dh_reading lis2dh_get_raw_reading(void) {
|
||||||
uint8_t buffer[6];
|
uint8_t buffer[6];
|
||||||
uint8_t reg = LIS2DH_REG_OUT_X_L | 0x80; // set high bit for consecutive reads
|
uint8_t reg = LIS2DH_REG_OUT_X_L | 0x80; // set high bit for consecutive reads
|
||||||
lis2dh_reading retval;
|
lis2dh_reading retval;
|
||||||
@ -97,7 +97,7 @@ void lis2dh_set_range(lis2dh_range_t range) {
|
|||||||
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL4, val | bits);
|
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL4, val | bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
lis2dh_range_t lis2dh_get_range() {
|
lis2dh_range_t lis2dh_get_range(void) {
|
||||||
uint8_t retval = watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL4) & 0x30;
|
uint8_t retval = watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL4) & 0x30;
|
||||||
retval >>= 4;
|
retval >>= 4;
|
||||||
return (lis2dh_range_t)retval;
|
return (lis2dh_range_t)retval;
|
||||||
@ -111,7 +111,7 @@ void lis2dh_set_data_rate(lis2dh_data_rate_t dataRate) {
|
|||||||
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL1, val | bits);
|
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL1, val | bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
lis2dh_data_rate_t lis2dh_get_data_rate() {
|
lis2dh_data_rate_t lis2dh_get_data_rate(void) {
|
||||||
return watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL1) >> 4;
|
return watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL1) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ void lis2dh_configure_aoi_int1(lis2dh_interrupt_configuration configuration, uin
|
|||||||
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL5, val | latch ? LIS2DH_CTRL5_VAL_LIR_INT1 : 0);
|
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL5, val | latch ? LIS2DH_CTRL5_VAL_LIR_INT1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
lis2dh_interrupt_state lis2dh_get_int1_state() {
|
lis2dh_interrupt_state lis2dh_get_int1_state(void) {
|
||||||
return (lis2dh_interrupt_state) watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_INT1_SRC);
|
return (lis2dh_interrupt_state) watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_INT1_SRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ void lis2dh_configure_aoi_int2(lis2dh_interrupt_configuration configuration, uin
|
|||||||
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL5, val | latch ? LIS2DH_CTRL5_VAL_LIR_INT2 : 0);
|
watch_i2c_write8(LIS2DH_ADDRESS, LIS2DH_REG_CTRL5, val | latch ? LIS2DH_CTRL5_VAL_LIR_INT2 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
lis2dh_interrupt_state lis2dh_get_int2_state() {
|
lis2dh_interrupt_state lis2dh_get_int2_state(void) {
|
||||||
return (lis2dh_interrupt_state) watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_INT2_SRC);
|
return (lis2dh_interrupt_state) watch_i2c_read8(LIS2DH_ADDRESS, LIS2DH_REG_INT2_SRC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,31 +84,31 @@ typedef enum {
|
|||||||
LIS2DH_INTERRUPT_STATE_X_LOW = 0b00000001, // X down
|
LIS2DH_INTERRUPT_STATE_X_LOW = 0b00000001, // X down
|
||||||
} lis2dh_interrupt_state;
|
} lis2dh_interrupt_state;
|
||||||
|
|
||||||
bool lis2dh_begin();
|
bool lis2dh_begin(void);
|
||||||
|
|
||||||
uint8_t lis2dh_get_device_id();
|
uint8_t lis2dh_get_device_id(void);
|
||||||
|
|
||||||
bool lis2dh_have_new_data();
|
bool lis2dh_have_new_data(void);
|
||||||
|
|
||||||
lis2dh_reading lis2dh_get_raw_reading();
|
lis2dh_reading lis2dh_get_raw_reading(void);
|
||||||
|
|
||||||
lis2dh_acceleration_measurement lis2dh_get_acceleration_measurement(lis2dh_reading *out_reading);
|
lis2dh_acceleration_measurement lis2dh_get_acceleration_measurement(lis2dh_reading *out_reading);
|
||||||
|
|
||||||
void lis2dh_set_range(lis2dh_range_t range);
|
void lis2dh_set_range(lis2dh_range_t range);
|
||||||
|
|
||||||
lis2dh_range_t lis2dh_get_range();
|
lis2dh_range_t lis2dh_get_range(void);
|
||||||
|
|
||||||
void lis2dh_set_data_rate(lis2dh_data_rate_t dataRate);
|
void lis2dh_set_data_rate(lis2dh_data_rate_t dataRate);
|
||||||
|
|
||||||
lis2dh_data_rate_t lis2dh_get_data_rate();
|
lis2dh_data_rate_t lis2dh_get_data_rate(void);
|
||||||
|
|
||||||
void lis2dh_configure_aoi_int1(lis2dh_interrupt_configuration configuration, uint8_t threshold, uint8_t duration, bool latch);
|
void lis2dh_configure_aoi_int1(lis2dh_interrupt_configuration configuration, uint8_t threshold, uint8_t duration, bool latch);
|
||||||
|
|
||||||
lis2dh_interrupt_state lis2dh_get_int1_state();
|
lis2dh_interrupt_state lis2dh_get_int1_state(void);
|
||||||
|
|
||||||
void lis2dh_configure_aoi_int2(lis2dh_interrupt_configuration configuration, uint8_t threshold, uint8_t duration, bool latch);
|
void lis2dh_configure_aoi_int2(lis2dh_interrupt_configuration configuration, uint8_t threshold, uint8_t duration, bool latch);
|
||||||
|
|
||||||
lis2dh_interrupt_state lis2dh_get_int2_state();
|
lis2dh_interrupt_state lis2dh_get_int2_state(void);
|
||||||
|
|
||||||
// Assumes SA0 is high; if low, its 0x18
|
// Assumes SA0 is high; if low, its 0x18
|
||||||
#define LIS2DH_ADDRESS (0x19)
|
#define LIS2DH_ADDRESS (0x19)
|
||||||
|
@ -39,11 +39,6 @@
|
|||||||
*/
|
*/
|
||||||
#define DRIVER_VERSION 0x00000001u
|
#define DRIVER_VERSION 0x00000001u
|
||||||
|
|
||||||
uint32_t io_get_version(void)
|
|
||||||
{
|
|
||||||
return DRIVER_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief I/O write interface
|
* \brief I/O write interface
|
||||||
*/
|
*/
|
||||||
|
@ -58,4 +58,6 @@ static inline bool _is_in_isr(void)
|
|||||||
|
|
||||||
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
#endif /* !(defined(__ASSEMBLY__) || defined(__IAR_SYSTEMS_ASM__)) */
|
||||||
|
|
||||||
|
void Default_Handler(void);
|
||||||
|
|
||||||
#endif /* _HPL_CORE_PORT_H_INCLUDED */
|
#endif /* _HPL_CORE_PORT_H_INCLUDED */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <hpl_gclk_config.h>
|
#include <hpl_gclk_config.h>
|
||||||
|
#include <hpl_gclk_base.h>
|
||||||
#include <hpl_init.h>
|
#include <hpl_init.h>
|
||||||
#include <utils_assert.h>
|
#include <utils_assert.h>
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <compiler.h>
|
#include <compiler.h>
|
||||||
#include <hpl_mclk_config.h>
|
#include <hpl_mclk_config.h>
|
||||||
|
#include <hpl_init.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initialize master clock generator
|
* \brief Initialize master clock generator
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include <hpl_time_measure.h>
|
#include <hpl_time_measure.h>
|
||||||
#include <hpl_systick_config.h>
|
#include <hpl_systick_config.h>
|
||||||
|
#include <hpl_delay.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initialize system time module
|
* \brief Initialize system time module
|
||||||
|
@ -50,6 +50,7 @@ void delay_driver_init(void);
|
|||||||
|
|
||||||
void EXTERNAL_IRQ_0_init(void);
|
void EXTERNAL_IRQ_0_init(void);
|
||||||
|
|
||||||
|
void SEGMENT_LCD_0_PORT_init(void);
|
||||||
void SEGMENT_LCD_0_init(void);
|
void SEGMENT_LCD_0_init(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -35,6 +35,6 @@ void SYSTEM_Handler(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool watch_is_battery_low() {
|
bool watch_is_battery_low(void) {
|
||||||
return battery_is_low;
|
return battery_is_low;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,6 @@
|
|||||||
* the battery voltage has fallen to 2.5 volts, it will have probably less than 10% of its capacity remaining, and
|
* the battery voltage has fallen to 2.5 volts, it will have probably less than 10% of its capacity remaining, and
|
||||||
* you can expect the voltage to drop relatively quickly as the battery dies.
|
* you can expect the voltage to drop relatively quickly as the battery dies.
|
||||||
*/
|
*/
|
||||||
bool watch_is_battery_low();
|
bool watch_is_battery_low(void);
|
||||||
|
|
||||||
#endif /* WATCH_H_ */
|
#endif /* WATCH_H_ */
|
@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
#include "watch_adc.h"
|
#include "watch_adc.h"
|
||||||
|
|
||||||
void _watch_sync_adc() {
|
static void _watch_sync_adc(void) {
|
||||||
while (ADC->SYNCBUSY.reg);
|
while (ADC->SYNCBUSY.reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t _watch_get_analog_value(uint16_t channel) {
|
static uint16_t _watch_get_analog_value(uint16_t channel) {
|
||||||
if (ADC->INPUTCTRL.bit.MUXPOS != channel) {
|
if (ADC->INPUTCTRL.bit.MUXPOS != channel) {
|
||||||
ADC->INPUTCTRL.bit.MUXPOS = channel;
|
ADC->INPUTCTRL.bit.MUXPOS = channel;
|
||||||
_watch_sync_adc();
|
_watch_sync_adc();
|
||||||
@ -40,7 +40,7 @@ uint16_t _watch_get_analog_value(uint16_t channel) {
|
|||||||
return ADC->RESULT.reg;
|
return ADC->RESULT.reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_enable_adc() {
|
void watch_enable_adc(void) {
|
||||||
MCLK->APBCMASK.reg |= MCLK_APBCMASK_ADC;
|
MCLK->APBCMASK.reg |= MCLK_APBCMASK_ADC;
|
||||||
GCLK->PCHCTRL[ADC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
|
GCLK->PCHCTRL[ADC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ void watch_set_analog_reference_voltage(watch_adc_reference_voltage reference) {
|
|||||||
_watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_SCALEDCOREVCC);
|
_watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_SCALEDCOREVCC);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t watch_get_vcc_voltage() {
|
uint16_t watch_get_vcc_voltage(void) {
|
||||||
// stash the previous reference so we can restore it when we're done.
|
// stash the previous reference so we can restore it when we're done.
|
||||||
uint8_t oldref = ADC->REFCTRL.bit.REFSEL;
|
uint8_t oldref = ADC->REFCTRL.bit.REFSEL;
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ inline void watch_disable_analog_input(const uint8_t pin) {
|
|||||||
gpio_set_pin_function(pin, GPIO_PIN_FUNCTION_OFF);
|
gpio_set_pin_function(pin, GPIO_PIN_FUNCTION_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_disable_adc() {
|
inline void watch_disable_adc(void) {
|
||||||
ADC->CTRLA.bit.ENABLE = 0;
|
ADC->CTRLA.bit.ENABLE = 0;
|
||||||
_watch_sync_adc();
|
_watch_sync_adc();
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
/** @brief Enables the ADC peripheral. You must call this before attempting to read a value
|
/** @brief Enables the ADC peripheral. You must call this before attempting to read a value
|
||||||
* from an analog pin.
|
* from an analog pin.
|
||||||
*/
|
*/
|
||||||
void watch_enable_adc();
|
void watch_enable_adc(void);
|
||||||
|
|
||||||
/** @brief Configures the selected pin for analog input.
|
/** @brief Configures the selected pin for analog input.
|
||||||
* @param pin One of pins A0-A4.
|
* @param pin One of pins A0-A4.
|
||||||
@ -139,7 +139,7 @@ void watch_set_analog_reference_voltage(watch_adc_reference_voltage reference);
|
|||||||
* @note This function depends on INTREF being 1.024V. If you have changed it by poking at the supply
|
* @note This function depends on INTREF being 1.024V. If you have changed it by poking at the supply
|
||||||
* controller's VREF.SEL bits, this function will return inaccurate values.
|
* controller's VREF.SEL bits, this function will return inaccurate values.
|
||||||
*/
|
*/
|
||||||
uint16_t watch_get_vcc_voltage();
|
uint16_t watch_get_vcc_voltage(void);
|
||||||
|
|
||||||
/** @brief Disables the analog circuitry on the selected pin.
|
/** @brief Disables the analog circuitry on the selected pin.
|
||||||
* @param pin One of pins A0-A4.
|
* @param pin One of pins A0-A4.
|
||||||
@ -151,7 +151,7 @@ void watch_disable_analog_input(const uint8_t pin);
|
|||||||
* have the default settings of 16 samples and 1 measurement cycle; if you customized these
|
* have the default settings of 16 samples and 1 measurement cycle; if you customized these
|
||||||
* parameters, you will need to set them up again.
|
* parameters, you will need to set them up again.
|
||||||
**/
|
**/
|
||||||
void watch_disable_adc();
|
void watch_disable_adc(void);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
@ -55,13 +55,13 @@
|
|||||||
* anything else. Use it to set up any internal data structures or application state required by your app,
|
* anything else. Use it to set up any internal data structures or application state required by your app,
|
||||||
* but don't configure any peripherals just yet.
|
* but don't configure any peripherals just yet.
|
||||||
*/
|
*/
|
||||||
void app_init();
|
void app_init(void);
|
||||||
|
|
||||||
/** @brief A function you will implement to wake from BACKUP mode, which wipes the system's RAM, and with it, your
|
/** @brief A function you will implement to wake from BACKUP mode, which wipes the system's RAM, and with it, your
|
||||||
* application's state. You may have chosen to store some important application state in the RTC's backup
|
* application's state. You may have chosen to store some important application state in the RTC's backup
|
||||||
* registers prior to entering this mode. You may restore that state here.
|
* registers prior to entering this mode. You may restore that state here.
|
||||||
*/
|
*/
|
||||||
void app_wake_from_backup();
|
void app_wake_from_backup(void);
|
||||||
|
|
||||||
/** @brief A function you will implement to set up your application. The app_setup function is like setup() in Arduino.
|
/** @brief A function you will implement to set up your application. The app_setup function is like setup() in Arduino.
|
||||||
* It is called once when the program begins. You should set pin modes and enable any peripherals you want to
|
* It is called once when the program begins. You should set pin modes and enable any peripherals you want to
|
||||||
@ -71,7 +71,7 @@ void app_wake_from_backup();
|
|||||||
* @note If your app enters the ultra-low power BACKUP sleep mode, this function will be called again when it wakes
|
* @note If your app enters the ultra-low power BACKUP sleep mode, this function will be called again when it wakes
|
||||||
* from that deep sleep state. In this state, the RTC will still be configured with the correct date and time.
|
* from that deep sleep state. In this state, the RTC will still be configured with the correct date and time.
|
||||||
*/
|
*/
|
||||||
void app_setup();
|
void app_setup(void);
|
||||||
|
|
||||||
/** @brief A function you will implement to serve as the app's main run loop. This method will be called repeatedly,
|
/** @brief A function you will implement to serve as the app's main run loop. This method will be called repeatedly,
|
||||||
or if you enter STANDBY mode, as soon as the device wakes from sleep.
|
or if you enter STANDBY mode, as soon as the device wakes from sleep.
|
||||||
@ -86,7 +86,7 @@ void app_setup();
|
|||||||
* so e.g. the I2C controller, if configured, will sleep in STANDBY. But you can use it again as soon as your
|
* so e.g. the I2C controller, if configured, will sleep in STANDBY. But you can use it again as soon as your
|
||||||
* app wakes up.
|
* app wakes up.
|
||||||
*/
|
*/
|
||||||
bool app_loop();
|
bool app_loop(void);
|
||||||
|
|
||||||
/** @brief A function you will implement to prepare to enter STANDBY mode. The app_prepare_for_standby function is
|
/** @brief A function you will implement to prepare to enter STANDBY mode. The app_prepare_for_standby function is
|
||||||
* called after your app_loop function returns true, and just before the watch enters STANDBY mode. In this
|
* called after your app_loop function returns true, and just before the watch enters STANDBY mode. In this
|
||||||
@ -98,11 +98,11 @@ bool app_loop();
|
|||||||
* buzzer that could damage it if left in this state. If your app_loop does not prevent sleep during these
|
* buzzer that could damage it if left in this state. If your app_loop does not prevent sleep during these
|
||||||
* activities, you should make sure to disable these outputs in app_prepare_for_standby.
|
* activities, you should make sure to disable these outputs in app_prepare_for_standby.
|
||||||
*/
|
*/
|
||||||
void app_prepare_for_standby();
|
void app_prepare_for_standby(void);
|
||||||
|
|
||||||
/** @brief A method you will implement to configure the app after waking from STANDBY mode.
|
/** @brief A method you will implement to configure the app after waking from STANDBY mode.
|
||||||
*/
|
*/
|
||||||
void app_wake_from_standby();
|
void app_wake_from_standby(void);
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "watch_buzzer.h"
|
#include "watch_buzzer.h"
|
||||||
|
|
||||||
inline void watch_enable_buzzer() {
|
inline void watch_enable_buzzer(void) {
|
||||||
if (!hri_tcc_get_CTRLA_reg(TCC0, TCC_CTRLA_ENABLE)) {
|
if (!hri_tcc_get_CTRLA_reg(TCC0, TCC_CTRLA_ENABLE)) {
|
||||||
_watch_enable_tcc();
|
_watch_enable_tcc();
|
||||||
}
|
}
|
||||||
@ -33,16 +33,16 @@ inline void watch_set_buzzer_period(uint32_t period) {
|
|||||||
hri_tcc_write_PERBUF_reg(TCC0, period);
|
hri_tcc_write_PERBUF_reg(TCC0, period);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_disable_buzzer() {
|
void watch_disable_buzzer(void) {
|
||||||
_watch_disable_tcc();
|
_watch_disable_tcc();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_set_buzzer_on() {
|
inline void watch_set_buzzer_on(void) {
|
||||||
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OUT);
|
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OUT);
|
||||||
gpio_set_pin_function(BUZZER, WATCH_BUZZER_TCC_PINMUX);
|
gpio_set_pin_function(BUZZER, WATCH_BUZZER_TCC_PINMUX);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_set_buzzer_off() {
|
inline void watch_set_buzzer_off(void) {
|
||||||
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OFF);
|
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OFF);
|
||||||
gpio_set_pin_function(BUZZER, GPIO_PIN_FUNCTION_OFF);
|
gpio_set_pin_function(BUZZER, GPIO_PIN_FUNCTION_OFF);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
/// @{
|
/// @{
|
||||||
/** @brief Enables the TCC peripheral, which drives the buzzer.
|
/** @brief Enables the TCC peripheral, which drives the buzzer.
|
||||||
*/
|
*/
|
||||||
void watch_enable_buzzer();
|
void watch_enable_buzzer(void);
|
||||||
|
|
||||||
/** @brief Sets the period of the buzzer.
|
/** @brief Sets the period of the buzzer.
|
||||||
* @param period The period of a single cycle for the TCC peripheral. You can determine the period for
|
* @param period The period of a single cycle for the TCC peripheral. You can determine the period for
|
||||||
@ -45,17 +45,17 @@ void watch_set_buzzer_period(uint32_t period);
|
|||||||
* @note If you are using PWM to set custom LED colors, this method will also disable the LED PWM driver,
|
* @note If you are using PWM to set custom LED colors, this method will also disable the LED PWM driver,
|
||||||
* since the buzzer and LED both make use of the same peripheral to drive their PWM behavior.
|
* since the buzzer and LED both make use of the same peripheral to drive their PWM behavior.
|
||||||
*/
|
*/
|
||||||
void watch_disable_buzzer();
|
void watch_disable_buzzer(void);
|
||||||
|
|
||||||
/** @brief Turns the buzzer output on. It will emit a continuous sound at the given frequency.
|
/** @brief Turns the buzzer output on. It will emit a continuous sound at the given frequency.
|
||||||
* @note The TCC peripheral that drives the buzzer does not run in standby mode; if you wish for buzzer
|
* @note The TCC peripheral that drives the buzzer does not run in standby mode; if you wish for buzzer
|
||||||
* output to continue, you should prevent your app from going to sleep.
|
* output to continue, you should prevent your app from going to sleep.
|
||||||
*/
|
*/
|
||||||
void watch_set_buzzer_on();
|
void watch_set_buzzer_on(void);
|
||||||
|
|
||||||
/** @brief Turns the buzzer output off.
|
/** @brief Turns the buzzer output off.
|
||||||
*/
|
*/
|
||||||
void watch_set_buzzer_off();
|
void watch_set_buzzer_off(void);
|
||||||
|
|
||||||
/// @brief 87 notes for use with watch_buzzer_play_note
|
/// @brief 87 notes for use with watch_buzzer_play_note
|
||||||
typedef enum BuzzerNote {
|
typedef enum BuzzerNote {
|
||||||
|
@ -126,7 +126,7 @@ uint32_t watch_get_backup_data(uint8_t reg) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_disable_all_pins_except_rtc() {
|
static void _watch_disable_all_pins_except_rtc(void) {
|
||||||
uint32_t config = RTC->MODE0.TAMPCTRL.reg;
|
uint32_t config = RTC->MODE0.TAMPCTRL.reg;
|
||||||
uint32_t portb_pins_to_disable = 0xFFFFFFFF;
|
uint32_t portb_pins_to_disable = 0xFFFFFFFF;
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ void _watch_disable_all_pins_except_rtc() {
|
|||||||
gpio_set_port_direction(1, portb_pins_to_disable, GPIO_DIRECTION_OFF);
|
gpio_set_port_direction(1, portb_pins_to_disable, GPIO_DIRECTION_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_disable_all_peripherals_except_slcd() {
|
static void _watch_disable_all_peripherals_except_slcd(void) {
|
||||||
_watch_disable_tcc();
|
_watch_disable_tcc();
|
||||||
watch_disable_adc();
|
watch_disable_adc();
|
||||||
watch_disable_external_interrupts();
|
watch_disable_external_interrupts();
|
||||||
@ -151,7 +151,7 @@ void _watch_disable_all_peripherals_except_slcd() {
|
|||||||
MCLK->APBCMASK.reg &= ~MCLK_APBCMASK_SERCOM3;
|
MCLK->APBCMASK.reg &= ~MCLK_APBCMASK_SERCOM3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_enter_sleep_mode() {
|
void watch_enter_sleep_mode(void) {
|
||||||
// disable all other peripherals
|
// disable all other peripherals
|
||||||
_watch_disable_all_peripherals_except_slcd();
|
_watch_disable_all_peripherals_except_slcd();
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ void watch_enter_sleep_mode() {
|
|||||||
app_wake_from_standby();
|
app_wake_from_standby();
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_enter_deep_sleep_mode() {
|
void watch_enter_deep_sleep_mode(void) {
|
||||||
// identical to sleep mode except we disable the LCD first.
|
// identical to sleep mode except we disable the LCD first.
|
||||||
slcd_sync_deinit(&SEGMENT_LCD_0);
|
slcd_sync_deinit(&SEGMENT_LCD_0);
|
||||||
hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
|
hri_mclk_clear_APBCMASK_SLCD_bit(SLCD);
|
||||||
@ -185,7 +185,7 @@ void watch_enter_deep_sleep_mode() {
|
|||||||
watch_enter_sleep_mode();
|
watch_enter_sleep_mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_enter_backup_mode() {
|
void watch_enter_backup_mode(void) {
|
||||||
watch_rtc_disable_all_periodic_callbacks();
|
watch_rtc_disable_all_periodic_callbacks();
|
||||||
_watch_disable_all_peripherals_except_slcd();
|
_watch_disable_all_peripherals_except_slcd();
|
||||||
slcd_sync_deinit(&SEGMENT_LCD_0);
|
slcd_sync_deinit(&SEGMENT_LCD_0);
|
||||||
@ -203,7 +203,7 @@ void watch_enter_shallow_sleep(bool display_on) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
void watch_enter_deep_sleep() {
|
void watch_enter_deep_sleep(void) {
|
||||||
watch_register_extwake_callback(BTN_ALARM, NULL, true);
|
watch_register_extwake_callback(BTN_ALARM, NULL, true);
|
||||||
watch_enter_backup_mode();
|
watch_enter_backup_mode();
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ uint32_t watch_get_backup_data(uint8_t reg);
|
|||||||
* You can estimate the power consumption of this mode to be on the order of 30 microwatts
|
* You can estimate the power consumption of this mode to be on the order of 30 microwatts
|
||||||
* (about 10 µA at 3 V).
|
* (about 10 µA at 3 V).
|
||||||
*/
|
*/
|
||||||
void watch_enter_sleep_mode();
|
void watch_enter_sleep_mode(void);
|
||||||
|
|
||||||
/** @brief enters Deep Sleep Mode by disabling all pins and peripherals except the RTC.
|
/** @brief enters Deep Sleep Mode by disabling all pins and peripherals except the RTC.
|
||||||
* @details Short of BACKUP mode, this is the lowest power mode you can enter while retaining your
|
* @details Short of BACKUP mode, this is the lowest power mode you can enter while retaining your
|
||||||
@ -131,7 +131,7 @@ void watch_enter_sleep_mode();
|
|||||||
* All notes from watch_enter_sleep_mode apply here, except for power consumption. You can estimate
|
* All notes from watch_enter_sleep_mode apply here, except for power consumption. You can estimate
|
||||||
* the power consumption of this mode to be on the order of 12 microwatts (about 4µA at 3 V).
|
* the power consumption of this mode to be on the order of 12 microwatts (about 4µA at 3 V).
|
||||||
*/
|
*/
|
||||||
void watch_enter_deep_sleep_mode();
|
void watch_enter_deep_sleep_mode(void);
|
||||||
|
|
||||||
/** @brief Enters the SAM L22's lowest-power mode, BACKUP.
|
/** @brief Enters the SAM L22's lowest-power mode, BACKUP.
|
||||||
* @details This function does some housekeeping before entering BACKUP mode. It first disables all pins
|
* @details This function does some housekeeping before entering BACKUP mode. It first disables all pins
|
||||||
@ -148,12 +148,12 @@ void watch_enter_deep_sleep_mode();
|
|||||||
* this function unless you have a device on the nine-pin connector with an external interrupt
|
* this function unless you have a device on the nine-pin connector with an external interrupt
|
||||||
* on pin A2 or A4 (i.e. an accelerometer with an interrupt pin).
|
* on pin A2 or A4 (i.e. an accelerometer with an interrupt pin).
|
||||||
*/
|
*/
|
||||||
void watch_enter_backup_mode();
|
void watch_enter_backup_mode(void);
|
||||||
|
|
||||||
__attribute__((deprecated("Use watch_enter_sleep_mode or watch_enter_deep_sleep_mode instead")))
|
__attribute__((deprecated("Use watch_enter_sleep_mode or watch_enter_deep_sleep_mode instead")))
|
||||||
void watch_enter_shallow_sleep(bool display_on);
|
void watch_enter_shallow_sleep(bool display_on);
|
||||||
|
|
||||||
__attribute__((deprecated("Use watch_enter_backup_mode instead")))
|
__attribute__((deprecated("Use watch_enter_backup_mode instead")))
|
||||||
void watch_enter_deep_sleep();
|
void watch_enter_deep_sleep(void);
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#include "watch_extint.h"
|
#include "watch_extint.h"
|
||||||
|
|
||||||
void watch_enable_external_interrupts() {
|
void watch_enable_external_interrupts(void) {
|
||||||
// Configure EIC to use GCLK3 (the 32.768 kHz crystal)
|
// Configure EIC to use GCLK3 (the 32.768 kHz crystal)
|
||||||
hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
hri_gclk_write_PCHCTRL_reg(GCLK, EIC_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos));
|
||||||
// Enable AHB clock for the EIC
|
// Enable AHB clock for the EIC
|
||||||
@ -33,7 +33,7 @@ void watch_enable_external_interrupts() {
|
|||||||
ext_irq_init();
|
ext_irq_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_disable_external_interrupts() {
|
void watch_disable_external_interrupts(void) {
|
||||||
ext_irq_deinit();
|
ext_irq_deinit();
|
||||||
hri_mclk_clear_APBAMASK_EIC_bit(MCLK);
|
hri_mclk_clear_APBAMASK_EIC_bit(MCLK);
|
||||||
}
|
}
|
||||||
@ -106,6 +106,6 @@ inline void watch_register_button_callback(const uint8_t pin, ext_irq_cb_t callb
|
|||||||
watch_register_interrupt_callback(pin, callback, INTERRUPT_TRIGGER_RISING);
|
watch_register_interrupt_callback(pin, callback, INTERRUPT_TRIGGER_RISING);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_enable_buttons() {
|
inline void watch_enable_buttons(void) {
|
||||||
watch_enable_external_interrupts();
|
watch_enable_external_interrupts();
|
||||||
}
|
}
|
||||||
|
@ -49,10 +49,10 @@ typedef enum watch_interrupt_trigger {
|
|||||||
} watch_interrupt_trigger;
|
} watch_interrupt_trigger;
|
||||||
|
|
||||||
/// @brief Enables the external interrupt controller.
|
/// @brief Enables the external interrupt controller.
|
||||||
void watch_enable_external_interrupts();
|
void watch_enable_external_interrupts(void);
|
||||||
|
|
||||||
/// @brief Disables the external interrupt controller.
|
/// @brief Disables the external interrupt controller.
|
||||||
void watch_disable_external_interrupts();
|
void watch_disable_external_interrupts(void);
|
||||||
|
|
||||||
/** @brief Configures an external interrupt callback on one of the external interrupt pins.
|
/** @brief Configures an external interrupt callback on one of the external interrupt pins.
|
||||||
* @details You can set one interrupt callback per pin, and you can monitor for a rising condition,
|
* @details You can set one interrupt callback per pin, and you can monitor for a rising condition,
|
||||||
@ -80,6 +80,6 @@ __attribute__((deprecated("Use watch_register_interrupt_callback or watch_regist
|
|||||||
void watch_register_button_callback(const uint8_t pin, ext_irq_cb_t callback);
|
void watch_register_button_callback(const uint8_t pin, ext_irq_cb_t callback);
|
||||||
|
|
||||||
__attribute__((deprecated("Use watch_enable_external_interrupts instead")))
|
__attribute__((deprecated("Use watch_enable_external_interrupts instead")))
|
||||||
void watch_enable_buttons();
|
void watch_enable_buttons(void);
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,13 +26,13 @@
|
|||||||
|
|
||||||
struct io_descriptor *I2C_0_io;
|
struct io_descriptor *I2C_0_io;
|
||||||
|
|
||||||
void watch_enable_i2c() {
|
void watch_enable_i2c(void) {
|
||||||
I2C_0_init();
|
I2C_0_init();
|
||||||
i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io);
|
i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io);
|
||||||
i2c_m_sync_enable(&I2C_0);
|
i2c_m_sync_enable(&I2C_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_disable_i2c() {
|
void watch_disable_i2c(void) {
|
||||||
i2c_m_sync_disable(&I2C_0);
|
i2c_m_sync_disable(&I2C_0);
|
||||||
hri_mclk_clear_APBCMASK_SERCOM1_bit(MCLK);
|
hri_mclk_clear_APBCMASK_SERCOM1_bit(MCLK);
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,11 @@
|
|||||||
/// @{
|
/// @{
|
||||||
/** @brief Enables the I2C peripheral. Call this before attempting to interface with I2C devices.
|
/** @brief Enables the I2C peripheral. Call this before attempting to interface with I2C devices.
|
||||||
*/
|
*/
|
||||||
void watch_enable_i2c();
|
void watch_enable_i2c(void);
|
||||||
|
|
||||||
/** @brief Disables the I2C peripheral.
|
/** @brief Disables the I2C peripheral.
|
||||||
*/
|
*/
|
||||||
void watch_disable_i2c();
|
void watch_disable_i2c(void);
|
||||||
|
|
||||||
/** @brief Sends a series of values to a device on the I2C bus.
|
/** @brief Sends a series of values to a device on the I2C bus.
|
||||||
* @param addr The address of the device you wish to talk to.
|
* @param addr The address of the device you wish to talk to.
|
||||||
|
@ -24,13 +24,13 @@
|
|||||||
|
|
||||||
#include "watch_led.h"
|
#include "watch_led.h"
|
||||||
|
|
||||||
void watch_enable_leds() {
|
void watch_enable_leds(void) {
|
||||||
if (!hri_tcc_get_CTRLA_reg(TCC0, TCC_CTRLA_ENABLE)) {
|
if (!hri_tcc_get_CTRLA_reg(TCC0, TCC_CTRLA_ENABLE)) {
|
||||||
_watch_enable_tcc();
|
_watch_enable_tcc();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_disable_leds() {
|
void watch_disable_leds(void) {
|
||||||
_watch_disable_tcc();
|
_watch_disable_tcc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,18 +52,18 @@ void watch_set_led_color(uint8_t red, uint8_t green) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_set_led_red() {
|
void watch_set_led_red(void) {
|
||||||
watch_set_led_color(255, 0);
|
watch_set_led_color(255, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_set_led_green() {
|
void watch_set_led_green(void) {
|
||||||
watch_set_led_color(0, 255);
|
watch_set_led_color(0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_set_led_yellow() {
|
void watch_set_led_yellow(void) {
|
||||||
watch_set_led_color(255, 255);
|
watch_set_led_color(255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_set_led_off() {
|
void watch_set_led_off(void) {
|
||||||
watch_set_led_color(0, 0);
|
watch_set_led_color(0, 0);
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@
|
|||||||
* your app is asleep. If, however, you set a custom color using watch_set_led_color, the color will
|
* your app is asleep. If, however, you set a custom color using watch_set_led_color, the color will
|
||||||
* not display correctly in STANDBY mode. You will need to keep your app running while the LED is on.
|
* not display correctly in STANDBY mode. You will need to keep your app running while the LED is on.
|
||||||
*/
|
*/
|
||||||
void watch_enable_leds();
|
void watch_enable_leds(void);
|
||||||
|
|
||||||
/** @brief Disables the LEDs.
|
/** @brief Disables the LEDs.
|
||||||
* @note This method will also disable the buzzer, since the buzzer and LED both make use of the same
|
* @note This method will also disable the buzzer, since the buzzer and LED both make use of the same
|
||||||
* peripheral to drive their PWM behavior.
|
* peripheral to drive their PWM behavior.
|
||||||
*/
|
*/
|
||||||
void watch_disable_leds();
|
void watch_disable_leds(void);
|
||||||
|
|
||||||
/** @brief Sets the LED to a custom color by modulating each output's duty cycle.
|
/** @brief Sets the LED to a custom color by modulating each output's duty cycle.
|
||||||
* @param red The red value from 0-255.
|
* @param red The red value from 0-255.
|
||||||
@ -66,23 +66,23 @@ void watch_set_led_color(uint8_t red, uint8_t green);
|
|||||||
/** @brief Sets the red LED to full brightness, and turns the green LED off.
|
/** @brief Sets the red LED to full brightness, and turns the green LED off.
|
||||||
* @details Of the two LED's in the RG bi-color LED, the red LED is the less power-efficient one (~4.5 mA).
|
* @details Of the two LED's in the RG bi-color LED, the red LED is the less power-efficient one (~4.5 mA).
|
||||||
*/
|
*/
|
||||||
void watch_set_led_red();
|
void watch_set_led_red(void);
|
||||||
|
|
||||||
/** @brief Sets the green LED to full brightness, and turns the red LED off.
|
/** @brief Sets the green LED to full brightness, and turns the red LED off.
|
||||||
* @details Of the two LED's in the RG bi-color LED, the green LED is the more power-efficient one (~0.44 mA).
|
* @details Of the two LED's in the RG bi-color LED, the green LED is the more power-efficient one (~0.44 mA).
|
||||||
* @note If your watch has a red/blue LED, this method will set the LED to blue.
|
* @note If your watch has a red/blue LED, this method will set the LED to blue.
|
||||||
*/
|
*/
|
||||||
void watch_set_led_green();
|
void watch_set_led_green(void);
|
||||||
|
|
||||||
/** @brief Sets both red and green LEDs to full brightness.
|
/** @brief Sets both red and green LEDs to full brightness.
|
||||||
* @details The total current draw between the two LED's in this mode will be ~5 mA, which is more than the
|
* @details The total current draw between the two LED's in this mode will be ~5 mA, which is more than the
|
||||||
* watch draws in any other mode. Take care not to drain the battery.
|
* watch draws in any other mode. Take care not to drain the battery.
|
||||||
* @note If your watch has a red/blue LED, this method will set the LED to pink.
|
* @note If your watch has a red/blue LED, this method will set the LED to pink.
|
||||||
*/
|
*/
|
||||||
void watch_set_led_yellow();
|
void watch_set_led_yellow(void);
|
||||||
|
|
||||||
/** @brief Turns both the red and the green LEDs off. */
|
/** @brief Turns both the red and the green LEDs off. */
|
||||||
void watch_set_led_off();
|
void watch_set_led_off(void);
|
||||||
|
|
||||||
__attribute__((deprecated("Use watch_enable_leds instead")))
|
__attribute__((deprecated("Use watch_enable_leds instead")))
|
||||||
void watch_enable_led(bool unused);
|
void watch_enable_led(bool unused);
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#include "watch_private.h"
|
#include "watch_private.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
void _watch_init() {
|
void _watch_init(void) {
|
||||||
// disable the LED pin (it may have been enabled by the bootloader)
|
// disable the LED pin (it may have been enabled by the bootloader)
|
||||||
watch_disable_digital_output(RED);
|
watch_disable_digital_output(RED);
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ int getentropy(void *buf, size_t buflen) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_enable_tcc() {
|
void _watch_enable_tcc(void) {
|
||||||
// clock TCC0 with the main clock (8 MHz) and enable the peripheral clock.
|
// clock TCC0 with the main clock (8 MHz) and enable the peripheral clock.
|
||||||
hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN);
|
hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK0_Val | GCLK_PCHCTRL_CHEN);
|
||||||
hri_mclk_set_APBCMASK_TCC0_bit(MCLK);
|
hri_mclk_set_APBCMASK_TCC0_bit(MCLK);
|
||||||
@ -143,7 +143,7 @@ void _watch_enable_tcc() {
|
|||||||
gpio_set_pin_function(GREEN, WATCH_GREEN_TCC_PINMUX);
|
gpio_set_pin_function(GREEN, WATCH_GREEN_TCC_PINMUX);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_disable_tcc() {
|
void _watch_disable_tcc(void) {
|
||||||
// disable all PWM pins
|
// disable all PWM pins
|
||||||
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OFF);
|
gpio_set_pin_direction(BUZZER, GPIO_DIRECTION_OFF);
|
||||||
gpio_set_pin_function(BUZZER, GPIO_PIN_FUNCTION_OFF);
|
gpio_set_pin_function(BUZZER, GPIO_PIN_FUNCTION_OFF);
|
||||||
@ -157,7 +157,7 @@ void _watch_disable_tcc() {
|
|||||||
hri_mclk_clear_APBCMASK_TCC0_bit(MCLK);
|
hri_mclk_clear_APBCMASK_TCC0_bit(MCLK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_enable_usb() {
|
void _watch_enable_usb(void) {
|
||||||
// disable USB, just in case.
|
// disable USB, just in case.
|
||||||
hri_usb_clear_CTRLA_ENABLE_bit(USB);
|
hri_usb_clear_CTRLA_ENABLE_bit(USB);
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ int _write(int file, char *ptr, int len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this method could be overridden to read stuff from the USB console? but no need rn.
|
// this method could be overridden to read stuff from the USB console? but no need rn.
|
||||||
int _read() {
|
int _read(void) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,17 +27,24 @@
|
|||||||
#include "watch.h"
|
#include "watch.h"
|
||||||
|
|
||||||
/// Called by main.c while setting up the app. You should not call this from your app.
|
/// Called by main.c while setting up the app. You should not call this from your app.
|
||||||
void _watch_init();
|
void _watch_init(void);
|
||||||
|
|
||||||
/// Initializes the real-time clock peripheral.
|
/// Initializes the real-time clock peripheral.
|
||||||
void _watch_rtc_init();
|
void _watch_rtc_init(void);
|
||||||
|
|
||||||
/// Called by buzzer and LED setup functions. You should not call this from your app.
|
/// Called by buzzer and LED setup functions. You should not call this from your app.
|
||||||
void _watch_enable_tcc();
|
void _watch_enable_tcc(void);
|
||||||
|
|
||||||
/// Called by buzzer and LED teardown functions. You should not call this from your app.
|
/// Called by buzzer and LED teardown functions. You should not call this from your app.
|
||||||
void _watch_disable_tcc();
|
void _watch_disable_tcc(void);
|
||||||
|
|
||||||
/// Called by main.c if plugged in to USB. You should not call this from your app.
|
/// Called by main.c if plugged in to USB. You should not call this from your app.
|
||||||
void _watch_enable_usb();
|
void _watch_enable_usb(void);
|
||||||
|
|
||||||
|
// this function ends up getting called by printf to log stuff to the USB console.
|
||||||
|
int _write(int file, char *ptr, int len);
|
||||||
|
|
||||||
|
// this method could be overridden to read stuff from the USB console? but no need rn.
|
||||||
|
int _read(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,15 +30,15 @@ ext_irq_cb_t btn_alarm_callback;
|
|||||||
ext_irq_cb_t a2_callback;
|
ext_irq_cb_t a2_callback;
|
||||||
ext_irq_cb_t a4_callback;
|
ext_irq_cb_t a4_callback;
|
||||||
|
|
||||||
bool _watch_rtc_is_enabled() {
|
bool _watch_rtc_is_enabled(void) {
|
||||||
return RTC->MODE2.CTRLA.bit.ENABLE;
|
return RTC->MODE2.CTRLA.bit.ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _sync_rtc() {
|
static void _sync_rtc(void) {
|
||||||
while (RTC->MODE2.SYNCBUSY.reg);
|
while (RTC->MODE2.SYNCBUSY.reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _watch_rtc_init() {
|
void _watch_rtc_init(void) {
|
||||||
MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC;
|
MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC;
|
||||||
|
|
||||||
if (_watch_rtc_is_enabled()) return; // don't reset the RTC if it's already set up.
|
if (_watch_rtc_is_enabled()) return; // don't reset the RTC if it's already set up.
|
||||||
@ -61,7 +61,7 @@ void watch_rtc_set_date_time(watch_date_time date_time) {
|
|||||||
_sync_rtc();
|
_sync_rtc();
|
||||||
}
|
}
|
||||||
|
|
||||||
watch_date_time watch_rtc_get_date_time() {
|
watch_date_time watch_rtc_get_date_time(void) {
|
||||||
watch_date_time retval;
|
watch_date_time retval;
|
||||||
|
|
||||||
_sync_rtc();
|
_sync_rtc();
|
||||||
@ -74,7 +74,7 @@ void watch_rtc_register_tick_callback(ext_irq_cb_t callback) {
|
|||||||
watch_rtc_register_periodic_callback(callback, 1);
|
watch_rtc_register_periodic_callback(callback, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_rtc_disable_tick_callback() {
|
void watch_rtc_disable_tick_callback(void) {
|
||||||
watch_rtc_disable_periodic_callback(1);
|
watch_rtc_disable_periodic_callback(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ void watch_rtc_disable_periodic_callback(uint8_t frequency) {
|
|||||||
RTC->MODE2.INTENCLR.reg = 1 << per_n;
|
RTC->MODE2.INTENCLR.reg = 1 << per_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_rtc_disable_all_periodic_callbacks() {
|
void watch_rtc_disable_all_periodic_callbacks(void) {
|
||||||
RTC->MODE2.INTENCLR.reg = 0xFF;
|
RTC->MODE2.INTENCLR.reg = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time al
|
|||||||
RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_ALARM0;
|
RTC->MODE2.INTENSET.reg = RTC_MODE2_INTENSET_ALARM0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_rtc_disable_alarm_callback() {
|
void watch_rtc_disable_alarm_callback(void) {
|
||||||
RTC->MODE2.INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM0;
|
RTC->MODE2.INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ typedef enum watch_rtc_alarm_match {
|
|||||||
/** @brief Called by main.c to check if the RTC is enabled.
|
/** @brief Called by main.c to check if the RTC is enabled.
|
||||||
* You may call this function, but outside of app_init, it should always return true.
|
* You may call this function, but outside of app_init, it should always return true.
|
||||||
*/
|
*/
|
||||||
bool _watch_rtc_is_enabled();
|
bool _watch_rtc_is_enabled(void);
|
||||||
|
|
||||||
/** @brief Sets the date and time.
|
/** @brief Sets the date and time.
|
||||||
* @param date_time The date and time you wish to set, with a year value from 0-63 representing 2020-2083.
|
* @param date_time The date and time you wish to set, with a year value from 0-63 representing 2020-2083.
|
||||||
@ -79,7 +79,7 @@ void watch_rtc_set_date_time(watch_date_time date_time);
|
|||||||
* @return A watch_date_time with the current date and time, with a year value from 0-63 representing 2020-2083.
|
* @return A watch_date_time with the current date and time, with a year value from 0-63 representing 2020-2083.
|
||||||
* @see watch_rtc_set_date_time for notes about how the year is stored.
|
* @see watch_rtc_set_date_time for notes about how the year is stored.
|
||||||
*/
|
*/
|
||||||
watch_date_time watch_rtc_get_date_time();
|
watch_date_time watch_rtc_get_date_time(void);
|
||||||
|
|
||||||
/** @brief Registers an alarm callback that will be called when the RTC time matches the target time, as masked
|
/** @brief Registers an alarm callback that will be called when the RTC time matches the target time, as masked
|
||||||
* by the provided mask.
|
* by the provided mask.
|
||||||
@ -100,7 +100,7 @@ void watch_rtc_register_alarm_callback(ext_irq_cb_t callback, watch_date_time al
|
|||||||
|
|
||||||
/** @brief Disables the alarm callback.
|
/** @brief Disables the alarm callback.
|
||||||
*/
|
*/
|
||||||
void watch_rtc_disable_alarm_callback();
|
void watch_rtc_disable_alarm_callback(void);
|
||||||
|
|
||||||
/** @brief Registers a "tick" callback that will be called once per second.
|
/** @brief Registers a "tick" callback that will be called once per second.
|
||||||
* @param callback The function you wish to have called when the clock ticks. If you pass in NULL, the tick
|
* @param callback The function you wish to have called when the clock ticks. If you pass in NULL, the tick
|
||||||
@ -113,7 +113,7 @@ void watch_rtc_register_tick_callback(ext_irq_cb_t callback);
|
|||||||
|
|
||||||
/** @brief Disables the tick callback for the given period.
|
/** @brief Disables the tick callback for the given period.
|
||||||
*/
|
*/
|
||||||
void watch_rtc_disable_tick_callback();
|
void watch_rtc_disable_tick_callback(void);
|
||||||
|
|
||||||
/** @brief Registers a callback that will be called at a configurable period.
|
/** @brief Registers a callback that will be called at a configurable period.
|
||||||
* @param callback The function you wish to have called at the specified period. If you pass in NULL, the periodic
|
* @param callback The function you wish to have called at the specified period. If you pass in NULL, the periodic
|
||||||
@ -139,7 +139,7 @@ void watch_rtc_disable_periodic_callback(uint8_t frequency);
|
|||||||
|
|
||||||
/** @brief Disables all periodic callbacks, including the once-per-second tick callback.
|
/** @brief Disables all periodic callbacks, including the once-per-second tick callback.
|
||||||
*/
|
*/
|
||||||
void watch_rtc_disable_all_periodic_callbacks();
|
void watch_rtc_disable_all_periodic_callbacks(void);
|
||||||
|
|
||||||
/** @brief Sets the system date and time.
|
/** @brief Sets the system date and time.
|
||||||
* @param date_time A struct representing the date and time you wish to set.
|
* @param date_time A struct representing the date and time you wish to set.
|
||||||
|
@ -150,11 +150,11 @@ static const uint32_t IndicatorSegments[6] = {
|
|||||||
SLCD_SEGID(1, 10), // WATCH_INDICATOR_LAP
|
SLCD_SEGID(1, 10), // WATCH_INDICATOR_LAP
|
||||||
};
|
};
|
||||||
|
|
||||||
void _sync_slcd() {
|
static void _sync_slcd(void) {
|
||||||
while (SLCD->SYNCBUSY.reg);
|
while (SLCD->SYNCBUSY.reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_enable_display() {
|
void watch_enable_display(void) {
|
||||||
SEGMENT_LCD_0_init();
|
SEGMENT_LCD_0_init();
|
||||||
slcd_sync_enable(&SEGMENT_LCD_0);
|
slcd_sync_enable(&SEGMENT_LCD_0);
|
||||||
}
|
}
|
||||||
@ -167,13 +167,13 @@ inline void watch_clear_pixel(uint8_t com, uint8_t seg) {
|
|||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(com, seg));
|
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(com, seg));
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_clear_display() {
|
void watch_clear_display(void) {
|
||||||
SLCD->SDATAL0.reg = 0;
|
SLCD->SDATAL0.reg = 0;
|
||||||
SLCD->SDATAL1.reg = 0;
|
SLCD->SDATAL1.reg = 0;
|
||||||
SLCD->SDATAL2.reg = 0;
|
SLCD->SDATAL2.reg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_display_character(uint8_t character, uint8_t position) {
|
static void watch_display_character(uint8_t character, uint8_t position) {
|
||||||
// special cases for positions 4 and 6
|
// special cases for positions 4 and 6
|
||||||
if (position == 4 || position == 6) {
|
if (position == 4 || position == 6) {
|
||||||
if (character == '7') character = '&'; // "lowercase" 7
|
if (character == '7') character = '&'; // "lowercase" 7
|
||||||
@ -245,11 +245,11 @@ void watch_display_string(char *string, uint8_t position) {
|
|||||||
// printf("________\n %c%c %c%c\n%c%c %c%c %c%c\n--------\n", (position > 0) ? ' ' : string[0], (position > 1) ? ' ' : string[1 - position], (position > 2) ? ' ' : string[2 - position], (position > 3) ? ' ' : string[3 - position], (position > 4) ? ' ' : string[4 - position], (position > 5) ? ' ' : string[5 - position], (position > 6) ? ' ' : string[6 - position], (position > 7) ? ' ' : string[7 - position], (position > 8) ? ' ' : string[8 - position], (position > 9) ? ' ' : string[9 - position]);
|
// printf("________\n %c%c %c%c\n%c%c %c%c %c%c\n--------\n", (position > 0) ? ' ' : string[0], (position > 1) ? ' ' : string[1 - position], (position > 2) ? ' ' : string[2 - position], (position > 3) ? ' ' : string[3 - position], (position > 4) ? ' ' : string[4 - position], (position > 5) ? ' ' : string[5 - position], (position > 6) ? ' ' : string[6 - position], (position > 7) ? ' ' : string[7 - position], (position > 8) ? ' ' : string[8 - position], (position > 9) ? ' ' : string[9 - position]);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_set_colon() {
|
inline void watch_set_colon(void) {
|
||||||
slcd_sync_seg_on(&SEGMENT_LCD_0, SLCD_SEGID(1, 16));
|
slcd_sync_seg_on(&SEGMENT_LCD_0, SLCD_SEGID(1, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void watch_clear_colon() {
|
inline void watch_clear_colon(void) {
|
||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(1, 16));
|
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(1, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ inline void watch_clear_indicator(WatchIndicatorSegment indicator) {
|
|||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, IndicatorSegments[indicator]);
|
slcd_sync_seg_off(&SEGMENT_LCD_0, IndicatorSegments[indicator]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_clear_all_indicators() {
|
void watch_clear_all_indicators(void) {
|
||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(2, 17));
|
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(2, 17));
|
||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(2, 16));
|
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(2, 16));
|
||||||
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(0, 17));
|
slcd_sync_seg_off(&SEGMENT_LCD_0, SLCD_SEGID(0, 17));
|
||||||
@ -296,7 +296,7 @@ void watch_start_character_blink(char character, uint32_t duration) {
|
|||||||
_sync_slcd();
|
_sync_slcd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_stop_blink() {
|
void watch_stop_blink(void) {
|
||||||
SLCD->CTRLD.bit.FC0EN = 0;
|
SLCD->CTRLD.bit.FC0EN = 0;
|
||||||
SLCD->CTRLD.bit.BLINK = 0;
|
SLCD->CTRLD.bit.BLINK = 0;
|
||||||
}
|
}
|
||||||
@ -307,11 +307,11 @@ void watch_start_tick_animation(uint32_t duration) {
|
|||||||
slcd_sync_start_animation(&SEGMENT_LCD_0, segs, 1, duration);
|
slcd_sync_start_animation(&SEGMENT_LCD_0, segs, 1, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool watch_tick_animation_is_running() {
|
bool watch_tick_animation_is_running(void) {
|
||||||
return hri_slcd_get_CTRLD_CSREN_bit(SLCD);
|
return hri_slcd_get_CTRLD_CSREN_bit(SLCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_stop_tick_animation() {
|
void watch_stop_tick_animation(void) {
|
||||||
const uint32_t segs[] = { SLCD_SEGID(0, 2)};
|
const uint32_t segs[] = { SLCD_SEGID(0, 2)};
|
||||||
slcd_sync_stop_animation(&SEGMENT_LCD_0, segs, 1);
|
slcd_sync_stop_animation(&SEGMENT_LCD_0, segs, 1);
|
||||||
watch_display_character(' ', 8);
|
watch_display_character(' ', 8);
|
||||||
|
@ -53,7 +53,7 @@ typedef enum WatchIndicatorSegment {
|
|||||||
/** @brief Enables the Segment LCD display.
|
/** @brief Enables the Segment LCD display.
|
||||||
* Call this before attempting to set pixels or display strings.
|
* Call this before attempting to set pixels or display strings.
|
||||||
*/
|
*/
|
||||||
void watch_enable_display();
|
void watch_enable_display(void);
|
||||||
|
|
||||||
/** @brief Sets a pixel. Use this to manually set a pixel with a given common and segment number.
|
/** @brief Sets a pixel. Use this to manually set a pixel with a given common and segment number.
|
||||||
* See <a href="segmap.html">segmap.html</a>.
|
* See <a href="segmap.html">segmap.html</a>.
|
||||||
@ -71,7 +71,7 @@ void watch_clear_pixel(uint8_t com, uint8_t seg);
|
|||||||
|
|
||||||
/** @brief Clears all segments of the display, including incicators and the colon.
|
/** @brief Clears all segments of the display, including incicators and the colon.
|
||||||
*/
|
*/
|
||||||
void watch_clear_display();
|
void watch_clear_display(void);
|
||||||
|
|
||||||
/** @brief Displays a string at the given position, starting from the top left. There are ten digits.
|
/** @brief Displays a string at the given position, starting from the top left. There are ten digits.
|
||||||
A space in any position will clear that digit.
|
A space in any position will clear that digit.
|
||||||
@ -86,11 +86,11 @@ void watch_display_string(char *string, uint8_t position);
|
|||||||
|
|
||||||
/** @brief Turns the colon segment on.
|
/** @brief Turns the colon segment on.
|
||||||
*/
|
*/
|
||||||
void watch_set_colon();
|
void watch_set_colon(void);
|
||||||
|
|
||||||
/** @brief Turns the colon segment off.
|
/** @brief Turns the colon segment off.
|
||||||
*/
|
*/
|
||||||
void watch_clear_colon();
|
void watch_clear_colon(void);
|
||||||
|
|
||||||
/** @brief Sets an indicator on the LCD. Use this to turn on one of the indicator segments.
|
/** @brief Sets an indicator on the LCD. Use this to turn on one of the indicator segments.
|
||||||
* @param indicator One of the indicator segments from the enum. @see WatchIndicatorSegment
|
* @param indicator One of the indicator segments from the enum. @see WatchIndicatorSegment
|
||||||
@ -105,7 +105,7 @@ void watch_clear_indicator(WatchIndicatorSegment indicator);
|
|||||||
/** @brief Clears all indicator segments.
|
/** @brief Clears all indicator segments.
|
||||||
* @see WatchIndicatorSegment
|
* @see WatchIndicatorSegment
|
||||||
*/
|
*/
|
||||||
void watch_clear_all_indicators();
|
void watch_clear_all_indicators(void);
|
||||||
|
|
||||||
/** @brief Blinks a single character in position 7. Does not affect other positions.
|
/** @brief Blinks a single character in position 7. Does not affect other positions.
|
||||||
* @details Six of the seven segments in position 7 (and only position 7) are capable of autonomous
|
* @details Six of the seven segments in position 7 (and only position 7) are capable of autonomous
|
||||||
@ -124,7 +124,7 @@ void watch_start_character_blink(char character, uint32_t duration);
|
|||||||
/** @brief Stops and clears all blinking segments.
|
/** @brief Stops and clears all blinking segments.
|
||||||
* @details This will stop all blinking in position 7, and clear all segments in that digit.
|
* @details This will stop all blinking in position 7, and clear all segments in that digit.
|
||||||
*/
|
*/
|
||||||
void watch_stop_blink();
|
void watch_stop_blink(void);
|
||||||
|
|
||||||
/** @brief Begins a two-segment "tick-tock" animation in position 8.
|
/** @brief Begins a two-segment "tick-tock" animation in position 8.
|
||||||
* @details Six of the seven segments in position 8 (and only position 8) are capable of autonomous
|
* @details Six of the seven segments in position 8 (and only position 8) are capable of autonomous
|
||||||
@ -141,11 +141,11 @@ void watch_start_tick_animation(uint32_t duration);
|
|||||||
/** @brief Checks if the tick animation is currently running.
|
/** @brief Checks if the tick animation is currently running.
|
||||||
* @return true if the animation is running; false otherwise.
|
* @return true if the animation is running; false otherwise.
|
||||||
*/
|
*/
|
||||||
bool watch_tick_animation_is_running();
|
bool watch_tick_animation_is_running(void);
|
||||||
|
|
||||||
/** @brief Stops the tick/tock animation and clears all animating segments.
|
/** @brief Stops the tick/tock animation and clears all animating segments.
|
||||||
* @details This will stop the animation and clear all segments in position 8.
|
* @details This will stop the animation and clear all segments in position 8.
|
||||||
*/
|
*/
|
||||||
void watch_stop_tick_animation();
|
void watch_stop_tick_animation(void);
|
||||||
/// @}
|
/// @}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user