fork Sensor-Watch to second-movement; remove non-Movement related files

This commit is contained in:
joeycastillo
2024-09-18 08:07:06 -04:00
parent e8f31beb70
commit 629e58d13b
143 changed files with 5 additions and 161095 deletions

View File

@@ -1,10 +0,0 @@
TOP = ../..
include $(TOP)/make.mk
INCLUDES += \
-I./
SRCS += \
./app.c
include $(TOP)/rules.mk

View File

@@ -1,72 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "watch.h"
#include "lis2dw.h"
static void cb_light_pressed(void) {
}
static void cb_mode_pressed(void) {
}
static void cb_alarm_pressed(void) {
}
uint8_t interrupts = 0;
uint8_t last_interrupts = 0;
bool tick = false;
char buf[13] = {0};
static void cb_tick(void) {
if (!lis2dw_have_new_data()) return;
tick = true;
}
void app_init(void) {
watch_enable_display();
watch_display_string("AC Strean", 0);
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_interrupt_callback(BTN_ALARM, cb_alarm_pressed, INTERRUPT_TRIGGER_RISING);
watch_enable_i2c();
lis2dw_begin();
lis2dw_set_data_rate(LIS2DW_DATA_RATE_25_HZ);
lis2dw_set_range(LIS2DW_RANGE_4_G);
lis2dw_set_low_noise_mode(true);
lis2dw_enable_fifo();
lis2dw_enable_fifo();
watch_rtc_register_periodic_callback(cb_tick, 1);
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
if (tick) {
tick = false;
lis2dw_fifo_t fifo;
lis2dw_read_fifo(&fifo);
for(int i = 0; i < fifo.count; i++) {
printf("%d, %d, %d, %d, %d\n", fifo.readings[i].x, fifo.readings[i].y, fifo.readings[i].z, i, fifo.count);
}
}
return true;
}

View File

@@ -1,279 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "watch.h"
#include "watch_utility.h"
const int8_t UTC_OFFSET = 4; // set to your current UTC offset to see correct beats time
const uint8_t BEAT_REFRESH_FREQUENCY = 8;
typedef enum ApplicationMode {
MODE_CLOCK = 0, // Displays month, day and current time.
MODE_BEATS,
MODE_SET, // (ST) Set time and date
NUM_MODES // Last item in the enum, it's the number of cases.
} ApplicationMode;
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.
uint8_t last_second; // lets us see when the second changed, for subsecond timing
uint8_t subsecond; // a value from 0 to (BEAT_REFRESH_FREQUENCY - 1) indicating the fractional second
} ApplicationState;
void do_clock_mode(void);
void do_beats_mode(void);
void do_set_time_mode(void);
void set_time_mode_handle_primary_button(void);
void set_time_mode_handle_secondary_button(void);
float clock2beats(uint16_t, uint16_t, uint16_t, int16_t);
void cb_light_pressed(void);
void cb_mode_pressed(void);
void cb_alarm_pressed(void);
void cb_tick(void);
void cb_fast_tick(void);
ApplicationState application_state;
char buf[16] = {0};
/**
* @brief Zeroes out the application state struct.
*/
void app_init(void) {
memset(&application_state, 0, sizeof(application_state));
}
void app_wake_from_backup(void) {
// This app does not support BACKUP mode.
}
void app_setup(void) {
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();
watch_enable_display();
watch_rtc_register_tick_callback(cb_tick);
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
static void update_tick_frequency(void) {
watch_rtc_disable_all_periodic_callbacks();
if (application_state.mode == MODE_BEATS) {
watch_rtc_register_periodic_callback(cb_fast_tick, BEAT_REFRESH_FREQUENCY);
} else {
watch_rtc_register_tick_callback(cb_tick);
}
}
bool app_loop(void) {
// 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);
update_tick_frequency();
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;
update_tick_frequency();
}
// 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_BEATS:
do_beats_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;
}
void do_clock_mode(void) {
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_beats_mode(void) {
watch_clear_colon();
watch_date_time date_time = watch_rtc_get_date_time();
float beats = clock2beats(date_time.unit.hour, date_time.unit.minute, date_time.unit.second, UTC_OFFSET);
sprintf(buf, "bt %6.0f", beats * 100);
watch_display_string(buf, 0);
}
float clock2beats(uint16_t hours, uint16_t minutes, uint16_t seconds, int16_t utc_offset) {
float beats = seconds + ((float)application_state.subsecond / (float)BEAT_REFRESH_FREQUENCY);
beats += 60 * minutes;
beats += (float)hours * 60 * 60;
beats += (1 - utc_offset) * 60 * 60; // offset from utc + 1 since beats in in UTC+1
beats /= 86.4; // convert to beats
while(beats > 1000) beats -= 1000; // beats %= 1000 but for a float
return beats;
}
void do_set_time_mode(void) {
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(void) {
application_state.page++;
if (application_state.page == 6) application_state.page = 0;
}
void set_time_mode_handle_secondary_button(void) {
watch_date_time date_time = watch_rtc_get_date_time();
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;
break;
}
if (date_time.unit.day > days_in_month(date_time.unit.month, date_time.unit.year + WATCH_RTC_REFERENCE_YEAR))
date_time.unit.day = 1;
watch_rtc_set_date_time(date_time);
}
void cb_mode_pressed(void) {
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(void) {
switch (application_state.mode) {
case MODE_SET:
set_time_mode_handle_secondary_button();
break;
default:
application_state.light_ticks = 3;
break;
}
}
void cb_alarm_pressed(void) {
switch (application_state.mode) {
case MODE_SET:
set_time_mode_handle_primary_button();
break;
default:
break;
}
}
void cb_tick(void) {
if (application_state.light_ticks > 0) {
application_state.light_ticks--;
}
if (application_state.mode_ticks > 0) {
application_state.mode_ticks--;
}
}
void cb_fast_tick(void) {
watch_date_time date_time = watch_rtc_get_date_time();
if (date_time.unit.second != application_state.last_second) {
application_state.last_second = date_time.unit.second;
application_state.subsecond = 0;
} else {
application_state.subsecond++;
}
}

View File

@@ -1,24 +0,0 @@
# Leave this line at the top of the file; it has all the watch library sources and includes.
TOP = ../../..
include $(TOP)/make.mk
# If you add any other subdirectories with header files you wish to include, add them after ../
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
# INCLUDES += \
# -I../ \
# -I../drivers/ \
# -I../utils/
INCLUDES += \
-I../ \
# If you add any other source files you wish to compile, add them after ../app.c
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
# SRCS += \
# ../app.c \
# ../drivers/bmp280.c \
# ../utils/temperature.c
SRCS += \
../app.c \
# Leave this line at the bottom of the file; it has all the targets for making your project.
include $(TOP)/rules.mk

View File

@@ -1,134 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
typedef struct ApplicationState {
bool play;
} ApplicationState;
ApplicationState application_state;
void cb_alarm_pressed(void) {
application_state.play = true;
}
void app_init(void) {
memset(&application_state, 0, sizeof(application_state));
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true);
watch_enable_display();
watch_enable_buzzer();
}
void app_prepare_for_standby(void) {
watch_display_string(" rains ", 2);
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
if (application_state.play) {
printf("Playing song...\n");
const BuzzerNote rains[] = {
BUZZER_NOTE_A4,
BUZZER_NOTE_F5,
BUZZER_NOTE_REST,
BUZZER_NOTE_A4,
BUZZER_NOTE_E5,
BUZZER_NOTE_REST,
BUZZER_NOTE_A4,
BUZZER_NOTE_F5,
BUZZER_NOTE_G5,
BUZZER_NOTE_E5,
BUZZER_NOTE_REST,
BUZZER_NOTE_A4,
BUZZER_NOTE_G5,
BUZZER_NOTE_F5,
BUZZER_NOTE_E5,
BUZZER_NOTE_D5,
BUZZER_NOTE_E5,
BUZZER_NOTE_REST,
BUZZER_NOTE_A5,
BUZZER_NOTE_REST,
BUZZER_NOTE_A5,
BUZZER_NOTE_A5SHARP_B5FLAT,
BUZZER_NOTE_G5,
BUZZER_NOTE_REST,
BUZZER_NOTE_C5,
BUZZER_NOTE_A5,
BUZZER_NOTE_A5SHARP_B5FLAT,
BUZZER_NOTE_G5,
BUZZER_NOTE_REST,
BUZZER_NOTE_D5,
BUZZER_NOTE_A5SHARP_B5FLAT,
BUZZER_NOTE_A5,
BUZZER_NOTE_G5,
BUZZER_NOTE_F5,
BUZZER_NOTE_E5,
};
const uint16_t durations[] = {
200,
600,
100,
200,
600,
100,
200,
400,
400,
600,
100,
200,
400,
400,
400,
400,
800,
600,
200,
50,
400,
200,
400,
100,
200,
400,
400,
400,
200,
200,
400,
400,
400,
400,
900,
};
application_state.play = false;
for(size_t i = 0, count = sizeof(rains) / sizeof(rains[0]); i < count; i++) {
char buf[9] = {0};
if (rains[i] == BUZZER_NOTE_REST) {
printf("rest for %d ms\n", durations[i]);
sprintf(buf, "%2drESt ", i);
} else {
printf("playing note %2d: %3.0f Hz for %d ms\n", i, 1000000.0 / (float)NotePeriods[rains[i]], durations[i]);
sprintf(buf, "%2d%6d", i, NotePeriods[rains[i]]);
}
watch_display_string(buf, 2);
watch_buzzer_play_note(rains[i], durations[i]);
}
printf("done!\n\n");
}
return true;
}

View File

@@ -1,10 +0,0 @@
TOP = ../../..
include $(TOP)/make.mk
INCLUDES += \
-I../
SRCS += \
../app.c
include $(TOP)/rules.mk

View File

@@ -1,10 +0,0 @@
TOP = ../..
include $(TOP)/make.mk
INCLUDES += \
-I./
SRCS += \
./app.c
include $(TOP)/rules.mk

View File

@@ -1,62 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <peripheral_clk_config.h>
#include "watch.h"
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
delay_ms(5000);
while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY));
uint32_t user_row = (*((uint32_t *)NVMCTRL_AUX0_ADDRESS));
uint8_t eeprom = (user_row >> NVMCTRL_FUSES_EEPROM_SIZE_Pos) & 7;
printf("User row read successfully: 0x%lx\n", user_row);
if (eeprom != 1) {
user_row &= ~NVMCTRL_FUSES_EEPROM_SIZE_Msk;
user_row |= NVMCTRL_FUSES_EEPROM_SIZE(1);
if (NVMCTRL->STATUS.reg & NVMCTRL_STATUS_SB) {
printf("Secured bit was set; cannot perform upgrade.\n");
return;
}
printf("EEPROM configuration was %d.\nApplying change...\n", eeprom);
uint32_t temp = NVMCTRL->CTRLB.reg; // Backup settings
NVMCTRL->CTRLB.reg = temp | NVMCTRL_CTRLB_CACHEDIS; // Disable Cache
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags
NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_EAR | NVMCTRL_CTRLA_CMDEX_KEY; // Erase the user page
while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)); // Wait for NVM command to complete
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags
NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | NVMCTRL_CTRLA_CMDEX_KEY; // Erase the page buffer before buffering new data
while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)); // Wait for NVM command to complete
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear error flags
NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set address, command will be issued elsewhere
*((uint32_t *)NVMCTRL_AUX0_ADDRESS) = user_row; // write the new fuse values to the memory buffer
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_WAP | NVMCTRL_CTRLA_CMDEX_KEY; // Write the user page
NVMCTRL->CTRLB.reg = temp; // Restore settings
printf("Done! Resetting...\n");
delay_ms(1000);
NVIC_SystemReset();
} else {
printf("EEPROM configuration was %d (8192 bytes). Upgrade successful!\n", eeprom);
}
printf("%d %d\n", eeprom, NVMCTRL->PARAM.bit.RWWEEP);
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
return true;
}

View File

@@ -1,13 +0,0 @@
TOP = ../..
include $(TOP)/make.mk
INCLUDES += \
-I$(TOP)/littlefs/ \
-I./
SRCS += \
$(TOP)/littlefs/lfs.c \
$(TOP)/littlefs/lfs_util.c \
./app.c
include $(TOP)/rules.mk

View File

@@ -1,131 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <peripheral_clk_config.h>
#include "watch.h"
#include "lfs.h"
#include "hpl_flash.h"
int lfs_storage_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size);
int lfs_storage_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size);
int lfs_storage_erase(const struct lfs_config *cfg, lfs_block_t block);
int lfs_storage_sync(const struct lfs_config *cfg);
int lfs_storage_read(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) {
(void) cfg;
return !watch_storage_read(block, off, (void *)buffer, size);
}
int lfs_storage_prog(const struct lfs_config *cfg, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) {
(void) cfg;
return !watch_storage_write(block, off, (void *)buffer, size);
}
int lfs_storage_erase(const struct lfs_config *cfg, lfs_block_t block) {
(void) cfg;
return !watch_storage_erase(block);
}
int lfs_storage_sync(const struct lfs_config *cfg) {
(void) cfg;
return !watch_storage_sync();
}
const struct lfs_config cfg = {
// block device operations
.read = lfs_storage_read,
.prog = lfs_storage_prog,
.erase = lfs_storage_erase,
.sync = lfs_storage_sync,
// block device configuration
.read_size = 16,
.prog_size = NVMCTRL_PAGE_SIZE,
.block_size = NVMCTRL_ROW_SIZE,
.block_count = NVMCTRL_RWWEE_PAGES / 4,
.cache_size = NVMCTRL_PAGE_SIZE,
.lookahead_size = 16,
.block_cycles = 100,
};
lfs_t lfs;
lfs_file_t file;
static int _traverse_df_cb(void *p, lfs_block_t block){
(void) block;
uint32_t *nb = p;
*nb += 1;
return 0;
}
static int get_free_space(void){
int err;
uint32_t free_blocks = 0;
err = lfs_fs_traverse(&lfs, _traverse_df_cb, &free_blocks);
if(err < 0){
return err;
}
uint32_t available = cfg.block_count * cfg.block_size - free_blocks * cfg.block_size;
return available;
}
static void cb_tick(void) {
watch_date_time date_time = watch_rtc_get_date_time();
if (date_time.unit.second == 0) {
int err = lfs_mount(&lfs, &cfg);
if (err) {
printf("Mount failed: %d\n", err);
}
// read current count
uint32_t loop_count = 0;
lfs_file_open(&lfs, &file, "loop_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &loop_count, sizeof(loop_count));
// update loop count
loop_count += 1;
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, &loop_count, sizeof(loop_count));
// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);
// release any resources we were using
lfs_unmount(&lfs);
// print the boot count
printf("loop_count: %ld\n", loop_count);
printf("free space: %d\n", get_free_space());
}
}
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
}
watch_rtc_register_tick_callback(cb_tick);
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
return true;
}

View File

@@ -1,73 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
watch_enable_display();
watch_enable_buzzer();
watch_enable_digital_output(RED);
watch_enable_digital_output(GREEN);
watch_enable_digital_input(BTN_ALARM);
watch_enable_digital_input(BTN_LIGHT);
watch_enable_digital_input(BTN_MODE);
watch_enable_pull_down(BTN_ALARM);
watch_enable_pull_down(BTN_LIGHT);
watch_enable_pull_down(BTN_MODE);
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
static int last_button = 0;
static int button = 0;
static int8_t loop = 0;
watch_set_pin_level(GREEN, false);
watch_set_pin_level(RED, false);
if (watch_get_pin_level(BTN_ALARM)) {
watch_set_pin_level(GREEN, true);
button = 1;
} else if (watch_get_pin_level(BTN_LIGHT)) {
watch_set_pin_level(RED, true);
button = 2;
} else if (watch_get_pin_level(BTN_MODE)) {
watch_set_pin_level(GREEN, true);
watch_set_pin_level(RED, true);
button = 3;
}
if (button != last_button) {
last_button = button;
watch_buzzer_play_note(BUZZER_NOTE_C8, 100);
}
static const bool segmap[3][24] = {
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1},
{1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1}
};
for(int com = 0; com < 3; com++) {
for(int seg = 0; seg < 24; seg++) {
if (segmap[com][seg]) (loop >= 0) ? watch_set_pixel(com, seg) : watch_clear_pixel(com, seg);
else (loop < 0) ? watch_set_pixel(com, seg) : watch_clear_pixel(com, seg);
}
}
loop++;
return false;
}

View File

@@ -1,10 +0,0 @@
TOP = ../../..
include $(TOP)/make.mk
INCLUDES += \
-I../
SRCS += \
../app.c
include $(TOP)/rules.mk

View File

@@ -1,64 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
watch_enable_leds();
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
static uint8_t red = 0;
static uint8_t green = 0;
static uint8_t blue = 255;
static uint8_t phase = 0;
switch (phase) {
case 0:
red++;
if (red == 255) phase = 1;
break;
case 1:
green++;
if (green == 255) phase = 2;
break;
case 2:
red--;
if (red == 0) phase = 3;
break;
case 3:
blue++;
if (blue == 255) phase = 4;
break;
case 4:
green--;
if (green == 0) phase = 5;
break;
case 5:
red++;
if (red == 255) phase = 6;
break;
case 6:
blue--;
if (blue == 0) {
phase = 1;
}
break;
}
watch_set_led_color_rgb(red, green, blue);
delay_ms(2);
return false;
}

View File

@@ -1,10 +0,0 @@
TOP = ../../..
include $(TOP)/make.mk
INCLUDES += \
-I../
SRCS += \
../app.c
include $(TOP)/rules.mk

View File

@@ -1,75 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
bool even = false;
static void cb_tick(void) {
even = !even;
}
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
watch_enable_digital_output(RED);
watch_enable_digital_output(GREEN);
watch_enable_digital_output(A0);
watch_enable_digital_output(SCL);
watch_enable_digital_output(SDA);
watch_enable_digital_output(A1);
watch_enable_digital_output(A2);
watch_enable_digital_output(A3);
watch_enable_digital_output(A4);
watch_set_pin_level(A0, false);
watch_set_pin_level(SCL, false);
watch_set_pin_level(SDA, false);
watch_set_pin_level(A1, false);
watch_set_pin_level(A2, false);
watch_set_pin_level(A3, false);
watch_set_pin_level(A4, false);
watch_rtc_register_periodic_callback(cb_tick, 2);
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
watch_date_time date_time = watch_rtc_get_date_time();
char buf[16];
sprintf(buf, "%2d:%02d:%02d: ", date_time.unit.hour, date_time.unit.minute, date_time.unit.second);
printf(buf);
if (even) {
printf("Even\n");
watch_set_pin_level(RED, false);
watch_set_pin_level(GREEN, true);
watch_set_pin_level(A0, true);
watch_set_pin_level(SCL, false);
watch_set_pin_level(SDA, true);
watch_set_pin_level(A1, false);
watch_set_pin_level(A2, true);
watch_set_pin_level(A3, false);
watch_set_pin_level(A4, true);
} else {
printf("Odd\n");
watch_set_pin_level(RED, true);
watch_set_pin_level(GREEN, false);
watch_set_pin_level(A0, false);
watch_set_pin_level(SCL, true);
watch_set_pin_level(SDA, false);
watch_set_pin_level(A1, true);
watch_set_pin_level(A2, false);
watch_set_pin_level(A3, true);
watch_set_pin_level(A4, false);
}
return true;
}

View File

@@ -1,10 +0,0 @@
TOP = ../../..
include $(TOP)/make.mk
INCLUDES += \
-I../
SRCS += \
../app.c
include $(TOP)/rules.mk

View File

@@ -1,283 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
bool has_ticked = false;
// array of lcd pins from pins.h
const uint8_t lcd_pins[] = {
SLCD26, // SEG23
SLCD25, // SEG22
SLCD24, // SEG21
SLCD23, // SEG20
SLCD22, // SEG19
SLCD21, // SEG18
SLCD20, // SEG17
SLCD19, // SEG16
SLCD18, // SEG15
SLCD17, // SEG14
SLCD16, // SEG13
SLCD15, // SEG12
SLCD14, // SEG11
SLCD13, // SEG10
SLCD12, // SEG9
SLCD11, // SEG8
SLCD10, // SEG7
SLCD9, // SEG6
SLCD8, // SEG5
SLCD7, // SEG4
SLCD6, // SEG3
SLCD5, // SEG2
SLCD4, // SEG1
SLCD3, // SEG0
SLCD2, // COM2
SLCD1, // COM1
SLCD0, // COM0
};
void cb_tick(void);
void cb_tick(void) {
has_ticked = true;
watch_rtc_disable_periodic_callback(8);
}
void pass_if(bool passed);
void pass_if(bool passed) {
if (passed) {
watch_uart_puts("P");
} else {
watch_uart_puts("F");
}
}
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
// Set up tick for RTC test
watch_rtc_register_periodic_callback(cb_tick, 8);
// Set up UART for communication with tester
watch_enable_uart(A4, A1, 19200);
// Set up LED pins
watch_enable_leds();
watch_enable_buzzer();
// Set up buttons with pull-down resistors
gpio_set_pin_direction(BTN_ALARM, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(BTN_ALARM, GPIO_PULL_DOWN);
gpio_set_pin_direction(BTN_LIGHT, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(BTN_LIGHT, GPIO_PULL_DOWN);
gpio_set_pin_direction(BTN_MODE, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(BTN_MODE, GPIO_PULL_DOWN);
// Set up ADC for thermistor test
watch_enable_adc();
watch_enable_analog_input(A2);
// Pin A0 is the thermistor enable pin
gpio_set_pin_direction(A0, GPIO_DIRECTION_OUT);
watch_set_led_yellow();
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
uint8_t buf[5] = {0};
watch_storage_read(0, 0, buf, 4);
printf("%s\n", (const char *)buf);
if (strcmp((const char *)buf, "PASS") == 0) {
watch_buzzer_play_note(BUZZER_NOTE_C5, 150);
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
watch_buzzer_play_note(BUZZER_NOTE_E5, 150);
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
watch_buzzer_play_note(BUZZER_NOTE_G5, 150);
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
watch_buzzer_play_note(BUZZER_NOTE_C6, 150);
watch_set_led_green();
return true;
}
char char_received = watch_uart_getc();
if (char_received) {
switch (char_received) {
// - [X] UART echo
case 'S':
// Automatically passes if received by tester
pass_if(true);
break;
// - [X] RTC
case 'R':
pass_if(has_ticked);
break;
// - [X] LCD pin continuity
case 'O':
// Set all LCD pins high
for (int i = 0; i < 27; i++) {
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_OUT);
gpio_set_pin_level(lcd_pins[i], true);
}
// It is the tester's responsibility to check that the pins are high
pass_if(true);
break;
case 'P':
// Set all LCD pins low
for (int i = 0; i < 27; i++) {
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_OUT);
gpio_set_pin_level(lcd_pins[i], false);
}
// It is the tester's responsibility to check that the pins are low
pass_if(true);
break;
// - [X] LCD pin bridging
case 'Q':
{
bool passed = true;
// Pull all LCD pins up
for (int i = 0; i < 27; i++) {
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(lcd_pins[i], GPIO_PULL_UP);
}
// SEG23 is adjacent to the red LED.
// setting the LED red drives RED low.
watch_set_led_red();
if (!gpio_get_pin_level(lcd_pins[0])) {
// If SEG23 is low, then it must be bridged to the red pin
pass_if(false);
}
watch_set_led_off();
// After this, all LCD pins are adjacent. Test if each pin is bridged to the previous one.
for (int i = 1; i < 27; i++) {
gpio_set_pin_direction(lcd_pins[i - 1], GPIO_DIRECTION_OUT);
gpio_set_pin_level(lcd_pins[i - 1], false);
if (!gpio_get_pin_level(lcd_pins[i])) {
passed = false;
break;
}
gpio_set_pin_direction(lcd_pins[i - 1], GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(lcd_pins[i - 1], GPIO_PULL_UP);
}
// Special cases:
// SLCD0 neighbors VCC
gpio_set_pin_direction(SLCD0, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(SLCD0, GPIO_PULL_DOWN);
if (gpio_get_pin_level(SLCD0)) {
passed = false;
}
// SLCD11 neighbors VCC
gpio_set_pin_direction(SLCD11, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(SLCD11, GPIO_PULL_DOWN);
if (gpio_get_pin_level(SLCD11)) {
passed = false;
}
// SLCD21 neighbors VCC
gpio_set_pin_direction(SLCD21, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(SLCD21, GPIO_PULL_DOWN);
if (gpio_get_pin_level(SLCD21)) {
passed = false;
}
watch_enable_display();
delay_ms(50);
// SLCD12 neighbors VLCD
gpio_set_pin_function(SLCD12, GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(SLCD12, GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(SLCD12, GPIO_PULL_DOWN);
if (gpio_get_pin_level(SLCD12)) {
passed = false;
}
for (int i = 0; i < 27; i++) {
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_IN);
gpio_set_pin_pull_mode(lcd_pins[i], GPIO_PULL_OFF);
}
pass_if(passed);
}
break;
// - [X] Thermistor high
case 'U':
// Set A0 high and read the value of A2 via the ADC.
// Pass if the value is near VCC.
gpio_set_pin_level(A0, true);
pass_if(watch_get_analog_pin_level(A2) > 65000);
break;
// - [X] Thermistor low
case 'T':
{
// Set A0 low and read the value of A2 via the ADC.
// Pass if the value is within the realm of reasonable temperatures.
// 15000 is a few minutes in the freezer, 45000 is holding it a few feet over
gpio_set_pin_level(A0, false);
uint16_t value = watch_get_analog_pin_level(A2);
pass_if(value < 45000 && value > 15000);
}
break;
// - [X] VLCD low
case 'V':
watch_enable_display();
SLCD->CTRLA.bit.ENABLE = 0;
while(SLCD->SYNCBUSY.bit.ENABLE);
SLCD->CTRLC.bit.CTST = 0x0;
SLCD->CTRLA.bit.ENABLE = 1;
while(SLCD->SYNCBUSY.bit.ENABLE);
break;
// - [X] VLCD high
case 'W':
watch_enable_display();
SLCD->CTRLA.bit.ENABLE = 0;
while(SLCD->SYNCBUSY.bit.ENABLE);
SLCD->CTRLC.bit.CTST = 0xD;
SLCD->CTRLA.bit.ENABLE = 1;
while(SLCD->SYNCBUSY.bit.ENABLE);
break;
// - [X] Buttons
case 'B':
// Pass if all three buttons are low
pass_if(!gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_MODE));
break;
case 'L':
// pass if BTN_LIGHT is high and the other two are low
pass_if(gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_MODE));
watch_uart_puts("P");
break;
case 'A':
// pass if BTN_ALARM is high and the other two are low
pass_if(gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_MODE));
break;
case 'M':
// pass if BTN_MODE is high and the other two are low
pass_if(gpio_get_pin_level(BTN_MODE) && !gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT));
break;
// - [X] File system
case 'F':
watch_storage_erase(0);
watch_storage_write(0, 0, (const char *)"PASS", 4);
watch_storage_sync();
watch_storage_read(0, 0, buf, 4);
delay_ms(10);
pass_if(strcmp((const char *)buf, (const char *)"PASS") == 0);
break;
// - [ ] Buzzer
case 'Z':
// reset the board
break;
}
}
return false;
}

View File

@@ -1,10 +0,0 @@
TOP = ../../..
include $(TOP)/make.mk
INCLUDES += \
-I../
SRCS += \
../app.c
include $(TOP)/rules.mk

View File

@@ -1,10 +0,0 @@
TOP = ../..
include $(TOP)/make.mk
INCLUDES += \
-I./
SRCS += \
./app.c
include $(TOP)/rules.mk

View File

@@ -1,224 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <peripheral_clk_config.h>
#include "watch.h"
#include "watch_utility.h"
#include "spiflash.h"
#include "lis2dw.h"
#define ACCELEROMETER_DATA_ACQUISITION_INVALID ((uint64_t)(0b11)) // all bits are 1 when the flash is erased
#define ACCELEROMETER_DATA_ACQUISITION_HEADER ((uint64_t)(0b10))
#define ACCELEROMETER_DATA_ACQUISITION_DATA ((uint64_t)(0b01))
#define ACCELEROMETER_DATA_ACQUISITION_DELETED ((uint64_t)(0b00)) // You can always write a 0 to any 1 bit
typedef union {
struct {
struct {
uint16_t record_type : 2; // see above, helps us identify record types when reading back
uint16_t range : 2; // accelerometer range (see lis2dw_range_t)
uint16_t temperature : 12; // raw value from the temperature sensor
} info;
uint8_t char1 : 8; // First character of the activity type
uint8_t char2 : 8; // Second character of the activity type
uint32_t timestamp : 32; // UNIX timestamp for the measurement
} header;
struct {
struct {
uint16_t record_type : 2; // duplicate; this is the same field as info above
uint16_t accel : 14; // X acceleration value, raw, offset by 8192
} x;
struct {
uint16_t lpmode : 2; // low power mode (see lis2dw_low_power_mode_t)
uint16_t accel : 14; // Y acceleration value, raw, offset by 8192
} y;
struct {
uint16_t filter : 2; // bandwidth filtering selection (see lis2dw_bandwidth_filtering_mode_t)
uint16_t accel : 14; // Z acceleration value, raw, offset by 8192
} z;
uint32_t counter : 16; // number of centiseconds since timestamp in header
} data;
uint64_t value;
} accelerometer_data_acquisition_record_t;
static bool wait_for_flash_ready(void) {
watch_set_pin_level(A3, false);
bool ok = true;
uint8_t read_status_response[1] = {0x00};
do {
ok = spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1);
} while ((read_status_response[0] & 0x3) != 0);
delay_ms(1); // why do i need this?
watch_set_pin_level(A3, true);
return ok;
}
static void write_buffer_to_page(uint8_t *buf, uint16_t page) {
uint32_t address = 256 * page;
wait_for_flash_ready();
watch_set_pin_level(A3, false);
spi_flash_command(CMD_ENABLE_WRITE);
wait_for_flash_ready();
watch_set_pin_level(A3, false);
spi_flash_write_data(address, buf, 256);
wait_for_flash_ready();
uint8_t buf2[256];
watch_set_pin_level(A3, false);
spi_flash_read_data(address, buf2, 256);
wait_for_flash_ready();
uint8_t used_pages[256] = {0xFF};
uint16_t address_to_mark_used = page / 8;
uint8_t header_page = address_to_mark_used / 256;
uint8_t used_byte = 0x7F >> (page % 8);
uint8_t offset_in_buf = address_to_mark_used % 256;
watch_set_pin_level(A3, false);
spi_flash_read_data(header_page * 256, used_pages, 256);
used_pages[offset_in_buf] = used_byte;
watch_set_pin_level(A3, false);
spi_flash_command(CMD_ENABLE_WRITE);
wait_for_flash_ready();
watch_set_pin_level(A3, false);
spi_flash_write_data(header_page * 256, used_pages, 256);
wait_for_flash_ready();
}
static void print_records_at_page(uint16_t page) {
accelerometer_data_acquisition_record_t records[32];
static uint64_t timestamp = 0;
// static uint16_t temperature = 0;
static lis2dw_range_t range = LIS2DW_RANGE_2_G;
static double lsb_value = 1;
static bool printing_header = false;
wait_for_flash_ready();
spi_flash_read_data(page * 256, (void *)records, 256);
for(int i = 0; i < 32; i++) {
switch (records[i].header.info.record_type) {
case ACCELEROMETER_DATA_ACQUISITION_HEADER:
printing_header = true;
timestamp = records[i].header.timestamp;
// temperature = records[i].header.info.temperature;
printf("%c%c.%lld.", records[i].header.char1, records[i].header.char2, timestamp);
range = records[i].header.info.range;
break;
case ACCELEROMETER_DATA_ACQUISITION_DATA:
if (printing_header) {
printing_header = false;
uint8_t filter = 0;
switch (records[i].data.z.filter) {
case LIS2DW_BANDWIDTH_FILTER_DIV2:
filter = 2;
break;
case LIS2DW_BANDWIDTH_FILTER_DIV4:
filter = 4;
break;
case LIS2DW_BANDWIDTH_FILTER_DIV10:
filter = 10;
break;
case LIS2DW_BANDWIDTH_FILTER_DIV20:
filter = 20;
break;
}
switch (range) {
case LIS2DW_RANGE_16_G:
lsb_value = (records[i].data.y.lpmode == LIS2DW_LP_MODE_1) ? 7.808 : 1.952;
range = 16;
break;
case LIS2DW_RANGE_8_G:
lsb_value = (records[i].data.y.lpmode == LIS2DW_LP_MODE_1) ? 3.904 : 0.976;
range = 8;
break;
case LIS2DW_RANGE_4_G:
lsb_value = (records[i].data.y.lpmode == LIS2DW_LP_MODE_1) ? 1.952 : 0.488;
range = 4;
break;
case LIS2DW_RANGE_2_G:
lsb_value = (records[i].data.y.lpmode == LIS2DW_LP_MODE_1) ? 0.976 : 0.244;
range = 2;
break;
}
printf("RANGE%d_LP%d_FILT%d.CSV\n", range, records[i].data.y.lpmode + 1, filter);
printf("timestamp,accX,accY,accZ\n");
}
printf("%lld,%f,%f,%f\n",
(timestamp * 100 + records[i].data.counter) * 10,
9.80665 * ((double)(records[i].data.x.accel - 8192)) * lsb_value / 1000,
9.80665 * ((double)(records[i].data.y.accel - 8192)) * lsb_value / 1000,
9.80665 * ((double)(records[i].data.z.accel - 8192)) * lsb_value / 1000);
break;
case ACCELEROMETER_DATA_ACQUISITION_INVALID:
case ACCELEROMETER_DATA_ACQUISITION_DELETED:
// don't print anything
break;
}
records[i].header.info.record_type = ACCELEROMETER_DATA_ACQUISITION_DELETED;
}
// uncomment this to mark all pages deleted
// write_buffer_to_page((uint8_t *)records, page);
}
static void print_records() {
uint8_t buf[256];
for(int16_t i = 0; i < 4; i++) {
wait_for_flash_ready();
spi_flash_read_data(i * 256, buf, 256);
for(int16_t j = 0; j < 256; j++) {
uint8_t pages_written = buf[j];
uint8_t start = 0;
if (i == 0 && j == 0) {
pages_written <<= 4;
start = 4;
}
for(int k = start; k < 8; k++) {
if ((pages_written & 0x80) == 0) {
print_records_at_page(i * 2048 + j * 8 + k);
}
pages_written <<= 1;
}
}
}
printf("=== END ===\n");
}
void app_init(void) {
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
spi_flash_init();
delay_ms(5000);
// bool erase = false;
// if (erase) {
// printf("Erasing...\n");
// wait_for_flash_ready();
// watch_set_pin_level(A3, false);
// spi_flash_command(CMD_ENABLE_WRITE);
// wait_for_flash_ready();
// watch_set_pin_level(A3, false);
// spi_flash_command(CMD_CHIP_ERASE);
// delay_ms(10000);
// }
print_records();
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
delay_ms(5000);
return true;
}

View File

@@ -1,26 +0,0 @@
# Leave these lines at the top of the file.
# TOP should get us to the root of the project...
TOP = ../..
# ...and make.mk has all the watch library sources and includes.
include $(TOP)/make.mk
# If you add any other subdirectories with header files you wish to include, add them after ./
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
# INCLUDES += \
# -I./ \
# -I drivers/ \
# -I utils/
INCLUDES += \
-I./ \
# If you add any other source files you wish to compile, add them after app.c
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
# SRCS += \
# ./app.c \
# ./drivers/bmp280.c \
# ./utils/temperature.c
SRCS += \
./app.c \
# Leave this line at the bottom of the file; rules.mk has all the targets for making your project.
include $(TOP)/rules.mk

View File

@@ -1,198 +0,0 @@
#include <stdio.h>
#include <string.h>
#include "watch.h"
//////////////////////////////////////////////////////////////////////////////////////////
// This section sets up types and storage for our application state.
// You can tear this out and replace it with whatever you want.
typedef enum ApplicationMode {
MODE_HELLO = 0,
MODE_THERE
} ApplicationMode;
typedef enum LightColor {
COLOR_RED = 0,
COLOR_GREEN,
COLOR_YELLOW
} LightColor;
typedef struct ApplicationState {
ApplicationMode mode;
LightColor color;
bool light_on;
bool beep;
uint8_t wake_count;
bool enter_sleep_mode;
} ApplicationState;
ApplicationState application_state;
//////////////////////////////////////////////////////////////////////////////////////////
// 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.
void cb_light_pressed(void);
void cb_mode_pressed(void);
void cb_alarm_pressed(void);
//////////////////////////////////////////////////////////////////////////////////////////
// This section contains the required functions for any watch app. You should tear out
// all the code in these functions when writing your app, but you must implement all
// of the functions, even if they are empty stubs. You can also replace the documentation
// lines with documentation that describes what your functions do!
/**
* @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.
*/
void app_init(void) {
memset(&application_state, 0, sizeof(application_state));
}
/**
* @brief the app_wake_from_backup function is only called if your app is waking from
* the ultra-low power BACKUP sleep mode. You may have chosen to store some state in the
* RTC's backup registers prior to entering this mode. You may restore that state here.
*
* @see watch_enter_deep_sleep()
*/
void app_wake_from_backup(void) {
// This app does not support BACKUP mode.
}
/**
* @brief 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
* set up (real-time clock, I2C, etc.) Depending on your application, you may or may not
* want to configure sensors on your sensor board here. For example, a low-power
* accelerometer that will run at all times should be configured here, whereas you may
* want to enable a more power-hungry environmental sensor only when you need it.
*
* @note If your app enters the Sleep or Deep Sleep modes, this function will be called
* again on wake, since those modes will have disabled all pins and peripherals; you'll
* likely need to set them up again. This function will also be called again if your app
* entered the ultra-low power BACKUP mode, since BACKUP mode will have done all that and
* 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.
*/
void app_setup(void) {
watch_enable_leds();
watch_enable_buzzer();
watch_enable_external_interrupts();
// This starter app demonstrates three different ways of using the button interrupts.
// The BTN_MODE interrupt only triggers on a rising edge, so the mode changes once per press.
watch_register_interrupt_callback(BTN_MODE, cb_mode_pressed, INTERRUPT_TRIGGER_RISING);
// The BTN_LIGHT interrupt triggers on both rising and falling edges. The callback then checks
// the pin state when triggered: on a button down event, it increments the color and turns the
// LED on, whereas on a button up event, it turns the light off.
watch_register_interrupt_callback(BTN_LIGHT, cb_light_pressed, INTERRUPT_TRIGGER_BOTH);
// The BTN_ALARM callback is on an external wake pin; we can avoid using the EIC for this pin
// by using the extwake interrupt — but note that it can only trigger on either a rising or
// a falling edge, not both.
watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true);
watch_enable_display();
}
/**
* @brief the app_prepare_for_standby function is called before the watch goes into STANDBY mode.
* 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).
*/
void app_prepare_for_standby(void) {
}
/**
* @brief the app_wake_from_standby function is called after the watch wakes from STANDBY mode,
* but before your main app_loop.
*/
void app_wake_from_standby(void) {
application_state.wake_count++;
}
/**
* @brief the app_loop function is called once on app startup and then again each time the
* watch exits STANDBY mode.
*/
bool app_loop(void) {
if (application_state.beep) {
watch_buzzer_play_note(BUZZER_NOTE_C7, 50);
application_state.beep = false;
}
// set the LED to a color
if (application_state.light_on) {
switch (application_state.color) {
case COLOR_RED:
watch_set_led_red();
break;
case COLOR_GREEN:
watch_set_led_green();
break;
case COLOR_YELLOW:
watch_set_led_yellow();
break;
}
} else {
watch_set_led_off();
}
// Display the number of times we've woken up (modulo 32 to fit in 2 digits at top right)
char buf[3] = {0};
sprintf(buf, "%2d", application_state.wake_count % 32);
watch_display_string(buf, 2);
// display "Hello there" text
switch (application_state.mode) {
case MODE_HELLO:
watch_display_string("Hello", 5);
break;
case MODE_THERE:
watch_display_string("there", 5);
break;
}
if (application_state.enter_sleep_mode) {
// wait a moment for the user's finger to be off the button
delay_ms(250);
// nap time :)
watch_enter_deep_sleep_mode();
// we just woke up; wait a moment again for the user's finger to be off the button...
delay_ms(250);
// and prevent ourselves from going right back to sleep.
application_state.enter_sleep_mode = false;
// finally, after sleep, return false so that our app loop runs again and updates the display.
return false;
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Implementations for our callback functions. Replace these with whatever functionality
// your app requires.
void cb_light_pressed(void) {
// always turn the light off when the pin goes low
if (watch_get_pin_level(BTN_LIGHT) == 0) {
application_state.light_on = false;
return;
}
application_state.color = (application_state.color + 1) % 3;
application_state.light_on = true;
}
void cb_mode_pressed(void) {
application_state.mode = (application_state.mode + 1) % 2;
application_state.beep = true;
}
void cb_alarm_pressed(void) {
application_state.enter_sleep_mode = true;
}

View File

@@ -1,10 +0,0 @@
TOP = ../..
include $(TOP)/make.mk
INCLUDES += \
-I./
SRCS += \
./app.c
include $(TOP)/rules.mk

View File

@@ -1,104 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <peripheral_clk_config.h>
#include "watch.h"
/*
Beginnings of a program to take UART input and update the screen accordingly.
Use alongside a prpgram that communicates with the watch over the UART pins.
This CircuitPython script turns the LED red in response to pressing the LIGHT button,
and turns it off when the MODE button is pressed:
```
import board
import busio
uart = busio.UART(board.TX, board.RX, baudrate=19200)
while True:
uart.write(b"\x00")
data = uart.read(1)
if data is not None:
data_string = ''.join([chr(b) for b in data])
print(data_string, end="")
if data_string[0] == 'L':
uart.write(b"R")
elif data_string[0] == 'M':
uart.write(b"O")
```
*/
char button_pressed = 0;
static void cb_light_pressed(void) {
button_pressed = 'L';
}
static void cb_mode_pressed(void) {
button_pressed = 'M';
}
static void cb_alarm_pressed(void) {
button_pressed = 'A';
}
void app_init(void) {
watch_enable_leds();
watch_enable_buzzer();
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_interrupt_callback(BTN_ALARM, cb_alarm_pressed, INTERRUPT_TRIGGER_RISING);
watch_enable_display();
watch_enable_uart(A2, A1, 19200);
}
void app_wake_from_backup(void) {
}
void app_setup(void) {
}
void app_prepare_for_standby(void) {
}
void app_wake_from_standby(void) {
}
bool app_loop(void) {
char buf[3];
if (button_pressed) {
sprintf(buf, "%c", button_pressed);
printf("%s\n", buf);
watch_uart_puts(buf);
button_pressed = 0;
}
char char_received = watch_uart_getc();
if (char_received) {
switch (char_received) {
case 'R':
watch_set_led_red();
break;
case 'G':
watch_set_led_green();
break;
case 'Y':
watch_set_led_yellow();
break;
case 'O':
watch_set_led_off();
break;
case 'U':
// receive a display update?
break;
}
}
return false;
}