diff --git a/samples/as6212_sample/Kconfig b/samples/as6212_sample/Kconfig index 746da25..2466f52 100644 --- a/samples/as6212_sample/Kconfig +++ b/samples/as6212_sample/Kconfig @@ -1,5 +1,4 @@ -# -# Copyright (c) 2021 Jimmy Johnson +# Copyright (c) 2022 T-Mobile USA, Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -20,8 +19,8 @@ config APP_ENABLE_ONE_SHOT config APP_TEMP_ALERT_HIGH_THRESH int "RH [%] high threshold for alert trigger in celsius" - range 0 50 - default 26 + range -40 125 + default 44 help Set this to enable alerts for high temperatures although this will work with one shot enabled, @@ -31,8 +30,8 @@ config APP_TEMP_ALERT_HIGH_THRESH config APP_TEMP_ALERT_LOW_THRESH int "RH [%] low threshold for alert trigger in celsius" - range 0 50 - default 18 + range -40 125 + default 38 help Set this to enable alerts for low temperatures although this will work with one shot enabled, diff --git a/samples/as6212_sample/README.rst b/samples/as6212_sample/README.rst index 381d03d..43391f8 100644 --- a/samples/as6212_sample/README.rst +++ b/samples/as6212_sample/README.rst @@ -67,8 +67,8 @@ This application aims to demonstrate the Gecko's Energy Mode 2 (EM2) (Deep Sleep Mode) and Wake capabilities in conjunction with the temperature interrupt of DevEdge's (tmo_dev_edge) AMS OSRAM AS6212 Digital Temperature Sensor. - Set SENSOR_ATTR_UPPER_THRESH (44) - Set SENSOR_ATTR_LOWER_THRESH (38) + Set SENSOR_ATTR_UPPER_THRESH (44C) + Set SENSOR_ATTR_LOWER_THRESH (38C) Set temperature_alert diff --git a/samples/as6212_sample/prj.conf b/samples/as6212_sample/prj.conf index c58a880..6ad5621 100644 --- a/samples/as6212_sample/prj.conf +++ b/samples/as6212_sample/prj.conf @@ -1,11 +1,24 @@ +# Copyright (c) 2022 T-Mobile USA, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +# Sensor CONFIG_SENSOR=y CONFIG_STDOUT_CONSOLE=y CONFIG_CBPRINTF_FP_SUPPORT=y CONFIG_I2C=y CONFIG_TMP108=y -CONFIG_ASSERT=y CONFIG_TMP108_ALERT_INTERRUPTS=y -#Power Managment + +# Power Managment CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_APP_REPORT_TEMP_ALERTS=y + +# GPIO +CONFIG_GPIO=y + +# Logging +CONFIG_LOG=y +# CONFIG_LOG_MODE_MINIMAL=y +CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/samples/as6212_sample/src/main.c b/samples/as6212_sample/src/main.c index 6bfa48c..ea79408 100644 --- a/samples/as6212_sample/src/main.c +++ b/samples/as6212_sample/src/main.c @@ -16,13 +16,12 @@ #include #include -LOG_MODULE_REGISTER(as6212_sample, LOG_LEVEL_INF); +// LOG_MODULE_REGISTER(as6212_sample, LOG_LEVEL_WRN); +LOG_MODULE_REGISTER(as6112_sample, CONFIG_LOG_DEFAULT_LEVEL); #define INTERRUPT_MODE 0x0200 -#define SLEEP_DURATION 2U -#define TEMPERATURE_THRESHOLD_LOW 38 -#define TEMPERATURE_THRESHOLD_HIGH 44 +#define SLEEP_DURATION 2U /* Thread properties */ #undef TASK_STACK_SIZE @@ -34,19 +33,47 @@ LOG_MODULE_REGISTER(as6212_sample, LOG_LEVEL_INF); K_THREAD_STACK_DEFINE(stack_a, TASK_STACK_SIZE); K_THREAD_STACK_DEFINE(stack_b, TASK_STACK_SIZE); +K_THREAD_STACK_DEFINE(pm_stack, TASK_STACK_SIZE); static struct k_thread as6212_a_id; static struct k_thread as6212_b_id; +static struct k_thread pm_thread_id; +const struct device *as6212; + +/* + * Pushbutton data + */ +#define SW0_NODE DT_ALIAS(sw0) +#if !DT_NODE_HAS_STATUS(SW0_NODE, okay) +#error "Unsupported board: sw0 device-tree alias is not defined" +#endif +static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0}); +static struct gpio_callback button_cb_data; +static int user_push_button_isr_count = 0; + +/* + * User Push Button (sw0) interrupt service routine + */ +static void user_push_button_intr_callback(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pin_mask) +{ + ARG_UNUSED(port); + ARG_UNUSED(cb); + ARG_UNUSED(pin_mask); + + user_push_button_isr_count++; + k_thread_resume(&pm_thread_id); +} /* AS6212 interrupt callback */ -int as6212_int1_int_isr_count = 0; -const struct device *as6212; +static int as6212_int1_int_isr_count = 0; -void as6212_intr_callback(const struct device *port, struct gpio_callback *cb, uint32_t pins) +static void as6212_intr_callback(const struct device *device, const struct sensor_trigger *trigger) { + ARG_UNUSED(device); + ARG_UNUSED(trigger); + as6212_int1_int_isr_count++; - printk("\n%s(): Received AS6212 Temperature Sensor ALERT Interrupt (%d)\n", __func__, - as6212_int1_int_isr_count); k_thread_resume(&as6212_a_id); k_thread_resume(&as6212_b_id); } @@ -90,9 +117,11 @@ static void enable_temp_alerts(const struct device *as6212) struct sensor_trigger sensor_trigger_type_temp_alert = {.chan = SENSOR_CHAN_AMBIENT_TEMP, .type = SENSOR_TRIG_THRESHOLD}; - struct sensor_value alert_upper_thresh = {TEMPERATURE_THRESHOLD_HIGH, 0}; + struct sensor_value alert_upper_thresh; + sensor_value_from_double(&alert_upper_thresh, CONFIG_APP_TEMP_ALERT_HIGH_THRESH); - struct sensor_value alert_lower_thresh = {TEMPERATURE_THRESHOLD_LOW, 0}; + struct sensor_value alert_lower_thresh; + sensor_value_from_double(&alert_lower_thresh, CONFIG_APP_TEMP_ALERT_LOW_THRESH); struct sensor_value thermostat_mode = {0, 0}; @@ -101,21 +130,20 @@ static void enable_temp_alerts(const struct device *as6212) sensor_attr_set(as6212, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_UPPER_THRESH, &alert_upper_thresh); - printf("\tSet SENSOR_ATTR_UPPER_THRESH (%d)\n", alert_upper_thresh.val1); + printf("\tSet SENSOR_ATTR_UPPER_THRESH (%gC)\n", + sensor_value_to_double(&alert_upper_thresh)); sensor_attr_set(as6212, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_LOWER_THRESH, &alert_lower_thresh); - printf("\tSet SENSOR_ATTR_LOWER_THRESH (%d)\n", alert_lower_thresh.val1); + printf("\tSet SENSOR_ATTR_LOWER_THRESH (%gC)\n", + sensor_value_to_double(&alert_lower_thresh)); sensor_trigger_set(as6212, &sensor_trigger_type_temp_alert, temperature_alert); puts("\n\tSet temperature_alert"); - struct sensor_value app_callback = {0, 0}; - app_callback.val1 = 1; - app_callback.val2 = (int32_t)as6212_intr_callback; - sensor_attr_set(as6212, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_USER_CALLBACK, &app_callback); + sensor_trigger_set(as6212, &sensor_trigger_type_temp_alert, as6212_intr_callback); } #endif @@ -134,49 +162,93 @@ static void enable_one_shot(const struct device *as6212) static void get_temperature(const struct device *as6212) { - - struct sensor_value temp_value; int result; +#if 1 + if ((result = sensor_sample_fetch(as6212))) { + LOG_ERR("error: sensor_sample_fetch failed: %d", result); + } else { +#endif + struct sensor_value temp_value; - result = sensor_channel_get(as6212, SENSOR_CHAN_AMBIENT_TEMP, &temp_value); + if ((result = sensor_channel_get(as6212, SENSOR_CHAN_AMBIENT_TEMP, &temp_value))) { + LOG_ERR("%s(): error: sensor_channel_get failed: %d", __func__, result); + } else { + LOG_INF("%s(): %gC", __func__, sensor_value_to_double(&temp_value)); + } +#if 1 + } +#endif +} - if (result) { - printf("%s(): error: sensor_channel_get failed: %d\n", __func__, result); - return; +static void pm_thread(void *this_thread, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + +#define STRUCT_INIT(enumerator) \ + { \ + .pm_state = enumerator, .name = #enumerator \ } + const struct { + enum pm_state pm_state; + const char *name; + } pm_state[] = { + STRUCT_INIT(PM_STATE_ACTIVE), // Doesn't go to sleep, as expected + STRUCT_INIT(PM_STATE_RUNTIME_IDLE), // Doesn't go to sleep + STRUCT_INIT(PM_STATE_SUSPEND_TO_IDLE), // Appears to work + STRUCT_INIT(PM_STATE_STANDBY), // Appears to work + STRUCT_INIT(PM_STATE_SUSPEND_TO_RAM), // Doesn't go to sleep + STRUCT_INIT(PM_STATE_SUSPEND_TO_DISK), // Doesn't go to sleep + // STRUCT_INIT(PM_STATE_SOFT_OFF), // Won't wake up + + }; +#undef STRUCT_INIT + const size_t pm_state_size = sizeof pm_state / sizeof *pm_state; + static int user_push_button_count = 0; - printf("\t%s(): temperature is %gC\n\n", __func__, sensor_value_to_double(&temp_value)); + + while (true) { + int next_state = user_push_button_count % pm_state_size; + + LOG_INF("pm_state_force(%d, %d): %s", next_state, pm_state[next_state].pm_state, pm_state[next_state].name); + pm_state_force(0u, &(struct pm_state_info){pm_state[next_state].pm_state, 0, 0}); + + k_thread_suspend((struct k_thread *)this_thread); + user_push_button_count++; + LOG_INF("%s(): running", __func__); + LOG_INF("%s(): Received user push button interrupt (%d/%d)", __func__, + user_push_button_count, + user_push_button_isr_count); + get_temperature(as6212); + // k_sleep(K_MSEC(50)); // Debounce + } } static void as6212_thread1(void *this_thread, void *p2, void *p3) { - int result; + ARG_UNUSED(p2); + ARG_UNUSED(p3); while (true) { - printf("\t%s(): running\n", __func__); - result = sensor_sample_fetch(as6212); - if (result) { - printf("error: as6212 thread 1 sensor sample fetch failed: %d\n", result); - return; - } - get_temperature(as6212); k_thread_suspend((struct k_thread *)this_thread); + LOG_INF("%s(): running", __func__); + LOG_INF("%s(): Received AS6212 Temperature Sensor ALERT Interrupt (%d)", __func__, + as6212_int1_int_isr_count); + get_temperature(as6212); } } static void as6212_thread2(void *this_thread, void *p2, void *p3) { - int result; + ARG_UNUSED(p2); + ARG_UNUSED(p3); while (true) { - printf("\t%s(): running\n", __func__); - result = sensor_sample_fetch(as6212); - if (result) { - printf("error: as6212 thread 2 sensor sample fetch failed: %d\n", result); - return; - } - get_temperature(as6212); k_thread_suspend((struct k_thread *)this_thread); + LOG_INF("%s(): running", __func__); + LOG_INF("%s(): Received AS6212 Temperature Sensor ALERT Interrupt (%d)", __func__, + as6212_int1_int_isr_count); + get_temperature(as6212); } } @@ -201,18 +273,40 @@ static void setup(void) as6212 = DEVICE_DT_GET_ANY(ams_as6212); - if (!as6212) { + if (NULL == as6212) { puts("error: no AMS OSRAM AS6212 (ams_as6212) device found"); return; + } else if (!device_is_ready(as6212)) { + puts("error: AMS OSRAM AS6212 (ams_as6212) device not ready"); + return; + } + if ((result = sensor_attr_set(as6212, SENSOR_CHAN_AMBIENT_TEMP, + SENSOR_ATTR_TMP108_CONTINUOUS_CONVERSION_MODE, NULL))) { + printf("error: sensor_attr_set(): %d\n", result); + return; } - if (!device_is_ready(as6212)) { - puts("error: AMS OSRAM AS6212 (ams_as6212) device not ready"); + if (!device_is_ready(button.port)) { + LOG_ERR("Error: button device %s is not ready", button.port->name); + return; + } + + result = gpio_pin_configure_dt(&button, GPIO_INPUT | GPIO_PULL_UP); + if (result != 0) { + LOG_ERR("Error %d: failed to configure %s pin %d", result, button.port->name, + button.pin); return; } - sensor_attr_set(as6212, SENSOR_CHAN_AMBIENT_TEMP, - SENSOR_ATTR_TMP108_CONTINUOUS_CONVERSION_MODE, NULL); + result = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_RISING); + if (result != 0) { + LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", result, + button.port->name, button.pin); + return; + } + gpio_init_callback(&button_cb_data, user_push_button_intr_callback, BIT(button.pin)); + gpio_add_callback(button.port, &button_cb_data); + LOG_INF("Set up button at %s pin %d\n", button.port->name, button.pin); #if CONFIG_APP_ENABLE_ONE_SHOT enable_one_shot(as6212); @@ -220,14 +314,11 @@ static void setup(void) #if CONFIG_APP_REPORT_TEMP_ALERTS enable_temp_alerts(as6212); - puts("\n\tCall enable_temp_alerts"); #endif - result = sensor_sample_fetch(as6212); - if (result) { - printf("error: sensor_sample_fetch failed: %d\n", result); - return; - } +#if !CONFIG_APP_ENABLE_ONE_SHOT + get_temperature(as6212); +#endif } void main(void) @@ -235,22 +326,12 @@ void main(void) greeting(); setup(); -#if !CONFIG_APP_ENABLE_ONE_SHOT - get_temperature(as6212); -#endif - k_thread_create(&as6212_a_id, stack_a, TASK_STACK_SIZE, as6212_thread1, &as6212_a_id, NULL, - NULL, PRIORITY, K_INHERIT_PERMS, K_FOREVER); + NULL, PRIORITY, K_INHERIT_PERMS, K_NO_WAIT); k_thread_create(&as6212_b_id, stack_b, TASK_STACK_SIZE, as6212_thread2, &as6212_b_id, NULL, - NULL, PRIORITY, K_INHERIT_PERMS, K_FOREVER); - - k_thread_start(&as6212_a_id); - k_thread_start(&as6212_b_id); - - k_sleep(K_MSEC(100)); - - k_thread_suspend(&as6212_a_id); - k_thread_suspend(&as6212_b_id); + NULL, PRIORITY, K_INHERIT_PERMS, K_NO_WAIT); + k_thread_create(&pm_thread_id, pm_stack, TASK_STACK_SIZE, pm_thread, &pm_thread_id, NULL, + NULL, PRIORITY, K_INHERIT_PERMS, K_NO_WAIT); puts("\nAwaiting the AS6212 temperature threshold-high/threshold-low (interrupt) " "alerts.\n\n" @@ -258,11 +339,10 @@ void main(void) "heat source) to momentarily raise the temperature of DevEdge board, triggering\n" "the AS6212 temperature-high alert. Remove the heat source and wait for the\n" "AS6212 temperature-low alert.\n"); - +#if 1 while (true) { - /* Try EM2 mode sleep */ - pm_state_force(0u, &(struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0}); + // pm_state_force(0u, &(struct pm_state_info){PM_STATE_SUSPEND_TO_IDLE, 0, 0}); /* * This will let the idle thread run and let the pm subsystem run in forced state. @@ -271,4 +351,5 @@ void main(void) k_sleep(K_SECONDS(SLEEP_DURATION)); puts("\nError: Wake from EM2 sleep: We shouldn't ever get here!"); } +#endif }