diff --git a/Documentation/index.rst b/Documentation/index.rst index a34b597553401994ed47fe20d9a20bb69a5ae06e..06aa3b7e95c0a64495ffc5b42d9659e44031f7cd 100644 --- a/Documentation/index.rst +++ b/Documentation/index.rst @@ -29,6 +29,7 @@ Last but not least, if you want to start hacking the lower-level firmware, the pycardium/leds pycardium/light-sensor pycardium/os + pycardium/personal_state pycardium/utime pycardium/vibra diff --git a/Documentation/pycardium/personal_state.rst b/Documentation/pycardium/personal_state.rst new file mode 100644 index 0000000000000000000000000000000000000000..7bf03681840a8b407fa00cf815bdbd7127d93334 --- /dev/null +++ b/Documentation/pycardium/personal_state.rst @@ -0,0 +1,63 @@ +.. py:module:: personal_state + +``personal_state`` - Personal State +=================================== +The :py:mod:`personal_state` module allows you to set and get the card10 users personal state from your script. The personal state is displayed on the top-left LED on the bottom of the harmonics board. While the personal state is set the LED can't be controlled by the :py:mod:`leds` module. + +**Example**: + +.. code-block:: python + + import personal_state + + # Enable the "camp" state only while the app is running. + personal_state.set(personal_state.CAMP, False) + + # Enable the "chaos" state and keep it after the app exits. + personal_state.set(personal_state.CHAOS, True) + + # Query the currently configured state and if it's persistent. + state, persistent = personal_state.get() + + # Clear the currently configured state + personal_state.clear() + +.. py:function:: personal_state.set(state, persistent) + + Set the users personal state. + + :param int state: ID of the personal state to set. Must be one of :py:data:`personal_state.NO_CONTACT`, :py:data:`personal_state.CHAOS`, :py:data:`personal_state.COMMUNICATION`, :py:data:`personal_state.CAMP`. + :param int persistent: Controls whether the personal state is persistent. A persistent state is not reset when the pycardium application is changed or restarted. In persistent mode the personal state LED is not controllable by the pycardium application. + +.. py:function:: personal_state.clear() + + Clears a previously set personal state. + + If no personal state was set this function does nothing. It does not matter + if a set state is marked as persistent or not. + +.. py:function:: personal_state.get() + + Get the users personal state. + + :returns: A tuple containing the currently set state and a boolean indicating if it's persistent or not. + +.. py:data:: personal_state.NO_STATE + + State ID reported when no personal state is set. + +.. py:data:: personal_state.NO_CONTACT + + State ID for the "No Contact" personal state. + +.. py:data:: personal_state.CHAOS + + State ID for the "Chaos" personal state. + +.. py:data:: personal_state.COMMUNICATION + + State ID for the "Communicatoin" personal state. + +.. py:data:: personal_state.CAMP + + State ID for the "Camp" personal state. diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 7ecf9b5711adbb8ca8f5e8195fb6b1d8ff6a636b..87b24e8975dff763119aa4ffe6ce336e1cb75212 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -84,6 +84,7 @@ typedef _Bool bool; #define API_LEDS_SET_ALL 0x6a #define API_LEDS_SET_ALL_HSV 0x6b #define API_LEDS_SET_GAMMA_TABLE 0x6c +#define API_LEDS_CLEAR_ALL 0x6d #define API_VIBRA_SET 0x70 #define API_VIBRA_VIBRATE 0x71 @@ -101,6 +102,10 @@ typedef _Bool bool; #define API_TRNG_READ 0xB0 +#define API_PERSONAL_STATE_SET 0xc0 +#define API_PERSONAL_STATE_GET 0xc1 +#define API_PERSONAL_STATE_IS_PERSISTENT 0xc2 + /* clang-format on */ typedef uint32_t api_int_id_t; @@ -648,6 +653,75 @@ API(API_LEDS_SET_GAMMA_TABLE, void epic_leds_set_gamma_table( uint8_t *gamma_table )); +/** + * Set all LEDs to a certain RGB color. + * + * :param uint8_t r: Value for the red color channel. + * :param uint8_t g: Value for the green color channel. + * :param uint8_t b: Value for the blue color channel. + */ +API(API_LEDS_CLEAR_ALL, void epic_leds_clear_all(uint8_t r, uint8_t g, uint8_t b)); + +/** + * Personal State + * ============== + * Card10 can display your personal state. + * + * If a personal state is set the top-left LED on the bottom side of the + * harmonics board is directly controlled by epicardium and it can't be + * controlled by pycardium. + * + * To re-enable pycardium control the personal state has to be cleared. To do + * that simply set it to ``STATE_NONE``. + * + * The personal state can be set to be persistent which means it won't get reset + * on pycardium application change/restart. + */ + +/** Possible personal states. */ +enum personal_state { + /** ``0``, No personal state - LED is under regular application control. */ + STATE_NONE = 0, + /** ``1``, "no contact, please!" - I am overloaded. Please leave me be - red led, continuously on. */ + STATE_NO_CONTACT = 1, + /** ``2``, "chaos" - Adventure time - blue led, short blink, long blink. */ + STATE_CHAOS = 2, + /** ``3``, "communication" - want to learn something or have a nice conversation - green led, long blinks. */ + STATE_COMMUNICATION = 3, + /** ``4``, "camp" - I am focussed on self-, camp-, or community maintenance - yellow led, fade on and off. */ + STATE_CAMP = 4, +}; + +/** + * Set the users personal state. + * + * Using :c:func:`epic_personal_state_set` an application can set the users personal state. + * + * :param uint8_t state: The users personal state. Must be one of :c:type:`personal_state`. + * :param bool persistent: Indicates whether the configured personal state will remain set and active on pycardium application restart/change. + * :returns: ``0`` on success, ``-EINVAL`` if an invalid state was requested. + */ +API(API_PERSONAL_STATE_SET, int epic_personal_state_set(uint8_t state, + bool persistent)); + +/** + * Get the users personal state. + * + * Using :c:func:`epic_personal_state_get` an application can get the currently set personal state of the user. + * + * :returns: A value with exactly one value of :c:type:`personal_state` set. + */ +API(API_PERSONAL_STATE_GET, int epic_personal_state_get()); + +/** + * Get whether the users personal state is persistent. + * + * Using :c:func:`epic_personal_state_is_persistent` an app can find out whether the users personal state is persistent or transient. + * + * :returns: ``1`` if the state is persistent, ``0`` otherwise. + */ +API(API_PERSONAL_STATE_IS_PERSISTENT, int epic_personal_state_is_persistent()); + /** * Sensor Data Streams * =================== diff --git a/epicardium/main.c b/epicardium/main.c index 57b07ca4e054f41bb3ba995d1046871540249914..7074d4df20eb94450ea14c63373dd70b8a96b926 100644 --- a/epicardium/main.c +++ b/epicardium/main.c @@ -73,6 +73,18 @@ int main(void) } } + /* LEDs */ + if (xTaskCreate( + vLedTask, + (const char *)"LED", + configMINIMAL_STACK_SIZE, + NULL, + tskIDLE_PRIORITY + 1, + NULL) != pdPASS) { + LOG_CRIT("startup", "Failed to create %s task!", "LED"); + abort(); + } + /* Lifecycle */ if (xTaskCreate( vLifecycleTask, diff --git a/epicardium/modules/hardware.c b/epicardium/modules/hardware.c index 75a995e9703456ea7ceaaa57922fc2ff4ee2c14e..cb6b70b51302234ca6d2c796afb51c09de74e581 100644 --- a/epicardium/modules/hardware.c +++ b/epicardium/modules/hardware.c @@ -190,10 +190,22 @@ int hardware_reset(void) api_interrupt_init(); api_dispatcher_init(); + /* Personal State */ + const int personal_state_is_persistent = + epic_personal_state_is_persistent(); + + if (personal_state_is_persistent == 0) { + epic_personal_state_set(STATE_NONE, 0); + } + /* * LEDs */ - leds_init(); + if (personal_state_is_persistent) { + epic_leds_clear_all(0, 0, 0); + } else { + leds_init(); + } epic_leds_set_rocket(0, 0); epic_leds_set_rocket(1, 0); epic_leds_set_rocket(2, 0); diff --git a/epicardium/modules/leds.c b/epicardium/modules/leds.c index 0faca35e33fc51b755c6b5e6a920ecfa23697dfc..93b80a993717adaa0d058da554e3d7f6433e2dc5 100644 --- a/epicardium/modules/leds.c +++ b/epicardium/modules/leds.c @@ -1,31 +1,59 @@ #include "leds.h" #include "pmic.h" -//#include "FreeRTOS.h" -//#include "task.h" +#include "FreeRTOS.h" +#include "task.h" +#include "epicardium.h" +#include "modules.h" + +#include <stdbool.h> //TODO: create smth like vTaskDelay(pdMS_TO_TICKS(//put ms here)) for us, remove blocking delay from /lib/leds.c to avoid process blocking -void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b) +#define NUM_LEDS 15 /* Take from lib/card10/leds.c */ + +static void do_update() { - leds_prep(led, r, g, b); + while (hwlock_acquire(HWLOCK_LED, pdMS_TO_TICKS(1)) < 0) { + vTaskDelay(pdMS_TO_TICKS(1)); + } + leds_update_power(); leds_update(); + + hwlock_release(HWLOCK_LED); +} + +void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b) +{ + if (led == PERSONAL_STATE_LED && personal_state_enabled()) + return; + + leds_prep(led, r, g, b); + do_update(); } void epic_leds_set_hsv(int led, float h, float s, float v) { + if (led == PERSONAL_STATE_LED && personal_state_enabled()) + return; + leds_prep_hsv(led, h, s, v); - leds_update_power(); - leds_update(); + do_update(); } void epic_leds_prep(int led, uint8_t r, uint8_t g, uint8_t b) { + if (led == PERSONAL_STATE_LED && personal_state_enabled()) + return; + leds_prep(led, r, g, b); } void epic_leds_prep_hsv(int led, float h, float s, float v) { + if (led == PERSONAL_STATE_LED && personal_state_enabled()) + return; + leds_prep_hsv(led, h, s, v); } @@ -33,32 +61,38 @@ void epic_leds_set_all(uint8_t *pattern_ptr, uint8_t len) { uint8_t(*pattern)[3] = (uint8_t(*)[3])pattern_ptr; for (int i = 0; i < len; i++) { + if (i == PERSONAL_STATE_LED && personal_state_enabled()) + continue; + leds_prep(i, pattern[i][0], pattern[i][1], pattern[i][2]); } - leds_update_power(); - leds_update(); + do_update(); } void epic_leds_set_all_hsv(float *pattern_ptr, uint8_t len) { float(*pattern)[3] = (float(*)[3])pattern_ptr; for (int i = 0; i < len; i++) { + if (i == PERSONAL_STATE_LED && personal_state_enabled()) + continue; + leds_prep_hsv(i, pattern[i][0], pattern[i][1], pattern[i][2]); } - leds_update_power(); - leds_update(); + do_update(); } void epic_leds_dim_top(uint8_t value) { leds_set_dim_top(value); - leds_update(); + if (personal_state_enabled() == 0) + leds_update(); } void epic_leds_dim_bottom(uint8_t value) { leds_set_dim_bottom(value); - leds_update(); + if (personal_state_enabled() == 0) + leds_update(); } void epic_leds_set_rocket(int led, uint8_t value) @@ -74,8 +108,7 @@ void epic_set_flashlight(bool power) void epic_leds_update(void) { - leds_update_power(); - leds_update(); + do_update(); } void epic_leds_set_powersave(bool eco) @@ -87,3 +120,15 @@ void epic_leds_set_gamma_table(uint8_t rgb_channel, uint8_t gamma_table[256]) { leds_set_gamma_table(rgb_channel, gamma_table); } + +void epic_leds_clear_all(uint8_t r, uint8_t g, uint8_t b) +{ + for (int i = 0; i < NUM_LEDS; i++) { + if (i == PERSONAL_STATE_LED && personal_state_enabled()) + continue; + + leds_prep(i, r, g, b); + } + + do_update(); +} diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build index 4966be6c9122ed2333ca6a5ecf1b6fc5e5ceb988..5b4199b1739de26ef4a633397e0aa80dabd42c5d 100644 --- a/epicardium/modules/meson.build +++ b/epicardium/modules/meson.build @@ -10,6 +10,7 @@ module_sources = files( 'lifecycle.c', 'light_sensor.c', 'log.c', + 'personal_state.c', 'pmic.c', 'rtc.c', 'serial.c', diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h index ccd8a900d6f0aa58fa157536ad6c3eb4c62b6fa9..3555ab52e7c8ed66707459f2b0b4c90bf123dadd 100644 --- a/epicardium/modules/modules.h +++ b/epicardium/modules/modules.h @@ -26,6 +26,11 @@ void return_to_menu(void); void vSerialTask(void *pvParameters); void serial_enqueue_char(char chr); +/* ---------- LED Animation / Personal States ------------------------------ */ +#define PERSONAL_STATE_LED 14 +void vLedTask(void *pvParameters); +int personal_state_enabled(); + /* ---------- PMIC --------------------------------------------------------- */ /* In 1/10s */ #define PMIC_PRESS_SLEEP 20 @@ -43,6 +48,7 @@ void hwlock_init(void); enum hwlock_periph { HWLOCK_I2C = 0, HWLOCK_ADC, + HWLOCK_LED, _HWLOCK_MAX, }; diff --git a/epicardium/modules/personal_state.c b/epicardium/modules/personal_state.c new file mode 100644 index 0000000000000000000000000000000000000000..cd6c52c7471af09a37560ef4b94644fc0549179c --- /dev/null +++ b/epicardium/modules/personal_state.c @@ -0,0 +1,141 @@ +#include "epicardium.h" +#include "leds.h" +#include "modules.h" + +#include <math.h> + +uint8_t _personal_state_enabled = 0; +uint8_t personal_state = STATE_NONE; +uint8_t personal_state_persistent = 0; + +int led_animation_ticks = 0; +int led_animation_state = 0; + +int personal_state_enabled() +{ + return _personal_state_enabled; +} + +int epic_personal_state_set(uint8_t state, bool persistent) +{ + if (state < STATE_NONE || state > STATE_CAMP) + return -EINVAL; + + led_animation_state = 0; + led_animation_ticks = 0; + personal_state = state; + + uint8_t was_enabled = _personal_state_enabled; + + _personal_state_enabled = (state != STATE_NONE); + personal_state_persistent = persistent; + + if (was_enabled && !_personal_state_enabled) { + while (hwlock_acquire(HWLOCK_LED, pdMS_TO_TICKS(1)) < 0) { + vTaskDelay(pdMS_TO_TICKS(1)); + } + + leds_prep(PERSONAL_STATE_LED, 0, 0, 0); + leds_update_power(); + leds_update(); + + hwlock_release(HWLOCK_LED); + } + + return 0; +} + +int epic_personal_state_get() +{ + return personal_state; +} + +int epic_personal_state_is_persistent() +{ + return personal_state_persistent; +} + +void vLedTask(void *pvParameters) +{ + const int led_animation_rate = 1000 / 25; /* 25Hz -> 40ms*/ + while (1) { + if (_personal_state_enabled) { + while (hwlock_acquire(HWLOCK_LED, pdMS_TO_TICKS(1)) < + 0) { + vTaskDelay(pdMS_TO_TICKS(1)); + } + + led_animation_ticks++; + if (personal_state == STATE_NO_CONTACT) { + leds_prep(PERSONAL_STATE_LED, 255, 0, 0); + } else if (personal_state == STATE_CHAOS) { + if (led_animation_state == 0) { + leds_prep( + PERSONAL_STATE_LED, 0, 0, 255 + ); + if (led_animation_ticks > + (200 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 1; + } + } else if (led_animation_state == 1) { + leds_prep(PERSONAL_STATE_LED, 0, 0, 0); + if (led_animation_ticks > + (300 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 2; + } + } else if (led_animation_state == 2) { + leds_prep( + PERSONAL_STATE_LED, 0, 0, 255 + ); + if (led_animation_ticks > + (1000 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 3; + } + } else if (led_animation_state == 3) { + leds_prep(PERSONAL_STATE_LED, 0, 0, 0); + if (led_animation_ticks > + (300 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 0; + } + } + } else if (personal_state == STATE_COMMUNICATION) { + if (led_animation_state == 0) { + leds_prep( + PERSONAL_STATE_LED, 255, 255, 0 + ); + if (led_animation_ticks > + (1000 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 1; + } + } else if (led_animation_state == 1) { + leds_prep(PERSONAL_STATE_LED, 0, 0, 0); + if (led_animation_ticks > + (300 / led_animation_rate)) { + led_animation_ticks = 0; + led_animation_state = 0; + } + } + } else if (personal_state == STATE_CAMP) { + leds_prep_hsv( + PERSONAL_STATE_LED, + 120.0f, + 1.0f, + fabs(sin( + led_animation_ticks / + (float)(1000 / + led_animation_rate)))); + } + leds_update_power(); + leds_update(); + + hwlock_release(HWLOCK_LED); + } + + vTaskDelay(led_animation_rate / portTICK_PERIOD_MS); + } +} diff --git a/preload/personal_state.py b/preload/personal_state.py new file mode 100644 index 0000000000000000000000000000000000000000..7605652c95070dba46cb8e572e48e2ebd2f6c641 --- /dev/null +++ b/preload/personal_state.py @@ -0,0 +1,92 @@ +""" +Personal State Script +=========== +With this script you can +""" +import buttons +import color +import display +import os +import personal_state + +states = [ + ("No State", personal_state.NO_STATE), + ("No Contact", personal_state.NO_CONTACT), + ("Chaos", personal_state.CHAOS), + ("Communication", personal_state.COMMUNICATION), + ("Camp", personal_state.CAMP), +] + + +def button_events(): + """Iterate over button presses (event-loop).""" + yield 0 + button_pressed = False + while True: + v = buttons.read(buttons.BOTTOM_LEFT | buttons.BOTTOM_RIGHT | buttons.TOP_RIGHT) + + if v == 0: + button_pressed = False + + if not button_pressed and v & buttons.BOTTOM_LEFT != 0: + button_pressed = True + yield buttons.BOTTOM_LEFT + + if not button_pressed and v & buttons.BOTTOM_RIGHT != 0: + button_pressed = True + yield buttons.BOTTOM_RIGHT + + if not button_pressed and v & buttons.TOP_RIGHT != 0: + button_pressed = True + yield buttons.TOP_RIGHT + + +COLOR1, COLOR2 = (color.CHAOSBLUE_DARK, color.CHAOSBLUE) + + +def draw_menu(disp, idx, offset): + disp.clear() + + for y, i in enumerate(range(len(states) + idx - 3, len(states) + idx + 4)): + selected = states[i % len(states)] + disp.print( + " " + selected[0] + " " * (11 - len(selected[0])), + posy=offset + y * 20 - 40, + bg=COLOR1 if i % 2 == 0 else COLOR2, + ) + + disp.print(">", posy=20, fg=color.COMMYELLOW, bg=COLOR2 if idx % 2 == 0 else COLOR1) + disp.update() + + +def main(): + disp = display.open() + numstates = len(states) + + current, _ = personal_state.get() + for ev in button_events(): + if ev == buttons.BOTTOM_RIGHT: + # Scroll down + draw_menu(disp, current, -8) + current = (current + 1) % numstates + state = states[current] + personal_state.set(state[1], False) + elif ev == buttons.BOTTOM_LEFT: + # Scroll up + draw_menu(disp, current, 8) + current = (current + numstates - 1) % numstates + state = states[current] + personal_state.set(state[1], False) + elif ev == buttons.TOP_RIGHT: + state = states[current] + personal_state.set(state[1], True) + # Select & start + disp.clear().update() + disp.close() + os.exit(0) + + draw_menu(disp, current, 0) + + +if __name__ == "__main__": + main() diff --git a/pycardium/meson.build b/pycardium/meson.build index 8d3b447a1750f369ff595d17271e43fc8e3d5707..40fabde700ce03eff4d117b7e5e87c024b5f35f5 100644 --- a/pycardium/meson.build +++ b/pycardium/meson.build @@ -9,6 +9,7 @@ modsrc = files( 'modules/sys_leds.c', 'modules/light_sensor.c', 'modules/os.c', + 'modules/personal_state.c', 'modules/sys_display.c', 'modules/utime.c', 'modules/vibra.c', diff --git a/pycardium/modules/personal_state.c b/pycardium/modules/personal_state.c new file mode 100644 index 0000000000000000000000000000000000000000..36353534b667a3c4a48bdee9af202d5e5f05f37a --- /dev/null +++ b/pycardium/modules/personal_state.c @@ -0,0 +1,67 @@ +#include "epicardium.h" + +#include "py/builtin.h" +#include "py/obj.h" +#include "py/runtime.h" + +static mp_obj_t +mp_personal_state_set(mp_obj_t state_obj, mp_obj_t persistent_obj) +{ + int state = mp_obj_get_int(state_obj); + int rc = epic_personal_state_set(state, mp_obj_is_true(persistent_obj)); + if (rc < 0) + mp_raise_OSError(-rc); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(personal_state_set, mp_personal_state_set); + +static mp_obj_t mp_personal_state_clear() +{ + int rc = epic_personal_state_set(STATE_NONE, 0); + if (rc < 0) + mp_raise_OSError(-rc); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(personal_state_clear, mp_personal_state_clear); + +static mp_obj_t mp_personal_state_get() +{ + int state = epic_personal_state_get(); + int persistent = epic_personal_state_is_persistent(); + mp_obj_t persistent_obj = mp_const_false; + if (persistent > 0) + persistent_obj = mp_const_true; + mp_obj_t tup[] = { + mp_obj_new_int(state & 0xff), + persistent_obj, + }; + return mp_obj_new_tuple(2, tup); +} +static MP_DEFINE_CONST_FUN_OBJ_0(personal_state_get, mp_personal_state_get); + +static const mp_rom_map_elem_t personal_state_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_personal_state) }, + { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&personal_state_set) }, + { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&personal_state_get) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&personal_state_clear) }, + { MP_ROM_QSTR(MP_QSTR_NO_STATE), MP_OBJ_NEW_SMALL_INT(STATE_NONE) }, + { MP_ROM_QSTR(MP_QSTR_NO_CONTACT), + MP_OBJ_NEW_SMALL_INT(STATE_NO_CONTACT) }, + { MP_ROM_QSTR(MP_QSTR_CHAOS), MP_OBJ_NEW_SMALL_INT(STATE_CHAOS) }, + { MP_ROM_QSTR(MP_QSTR_COMMUNICATION), + MP_OBJ_NEW_SMALL_INT(STATE_COMMUNICATION) }, + { MP_ROM_QSTR(MP_QSTR_CAMP), MP_OBJ_NEW_SMALL_INT(STATE_CAMP) }, +}; +static MP_DEFINE_CONST_DICT( + personal_state_module_globals, personal_state_module_globals_table +); + +// Define module object. +const mp_obj_module_t personal_state_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&personal_state_module_globals, +}; + +/* Register the module to make it available in Python */ +/* clang-format off */ +MP_REGISTER_MODULE(MP_QSTR_personal_state, personal_state_module, MODULE_PERSONAL_STATE_ENABLED); diff --git a/pycardium/modules/qstrdefs.h b/pycardium/modules/qstrdefs.h index 3300907012a50e3df7d3815458832a0c8ba0ddea..9e3f3979af79ebbfb16f821b7127424cadb563ff 100644 --- a/pycardium/modules/qstrdefs.h +++ b/pycardium/modules/qstrdefs.h @@ -118,3 +118,12 @@ Q(INPUT) Q(OUTPUT) Q(PULL_UP) Q(PULL_DOWN) + +/* personal_state */ +Q(personal_state) +Q(get) +Q(NO_STATE) +Q(NO_CONTACT) +Q(CHAOS) +Q(COMMUNICATION) +Q(CAMP) diff --git a/pycardium/mpconfigport.h b/pycardium/mpconfigport.h index 0708ebe52ad745d888ac5fa0cbace2b7fc655558..309b8f7f76ba776b791288f5f9aa69d9825e4fdd 100644 --- a/pycardium/mpconfigport.h +++ b/pycardium/mpconfigport.h @@ -46,6 +46,7 @@ #define MODULE_LEDS_ENABLED (1) #define MODULE_LIGHT_SENSOR_ENABLED (1) #define MODULE_OS_ENABLED (1) +#define MODULE_PERSONAL_STATE_ENABLED (1) #define MODULE_UTIME_ENABLED (1) #define MODULE_VIBRA_ENABLED (1)