Newer
Older
#ifndef _EPICARDIUM_H
#define _EPICARDIUM_H
/* Some headers are not recognized by hawkmoth for some odd reason */
#endif /* __SPHINX_DOC */
/*
* These definitions are required for the code-generator. Please don't touch!
*/
#ifndef API_ISR
#define API_ISR(id, isr) void isr(void);
#endif
/*
* IDs for all defined API calls. These IDs should not be needed in application
* code on any side.
*/
/* clang-format off */
#define API_SYSTEM_EXIT 0x1
#define API_SYSTEM_EXEC 0x2
#define API_INTERRUPT_ENABLE 0xA
#define API_INTERRUPT_DISABLE 0xB
#define API_INTERRUPT_IS_ENABLED 0xC
#define API_UART_WRITE_STR 0x10
#define API_UART_READ_CHAR 0x11
#define API_UART_READ_STR 0x12
#define API_STREAM_READ 0x1F
#define API_DISP_OPEN 0x20
#define API_DISP_CLOSE 0x21
#define API_DISP_PRINT 0x22
#define API_DISP_CLEAR 0x23
#define API_DISP_UPDATE 0x24
#define API_DISP_LINE 0x25
#define API_DISP_RECT 0x26
#define API_DISP_CIRC 0x27
#define API_DISP_PIXEL 0x28
#define API_DISP_FRAMEBUFFER 0x29
#define API_DISP_BACKLIGHT 0x2a
#define API_DISP_PRINT_ADV 0x2b
/* API_BATTERY_VOLTAGE 0x30 */
#define API_BATTERY_CURRENT 0x31
#define API_CHARGEIN_VOLTAGE 0x32
#define API_CHARGEIN_CURRENT 0x33
#define API_SYSTEM_VOLTAGE 0x34
#define API_THERMISTOR_VOLTAGE 0x35
#define API_FILE_OPEN 0x40
#define API_FILE_CLOSE 0x41
#define API_FILE_READ 0x42
#define API_FILE_WRITE 0x44
#define API_FILE_FLUSH 0x45
#define API_FILE_SEEK 0x46
#define API_FILE_TELL 0x47
#define API_FILE_STAT 0x48
#define API_FILE_OPENDIR 0x49
#define API_FILE_READDIR 0x4a
#define API_FILE_UNLINK 0x4b
#define API_FILE_RENAME 0x4c
#define API_FILE_MKDIR 0x4d
#define API_RTC_GET_SECONDS 0x50
#define API_RTC_SCHEDULE_ALARM 0x51
#define API_RTC_GET_MILLISECONDS 0x53
#define API_RTC_GET_MONOTONIC_SECONDS 0x54
#define API_RTC_GET_MONOTONIC_MILLISECONDS 0x55
#define API_LEDS_SET_HSV 0x61
#define API_LEDS_PREP 0x62
#define API_LEDS_PREP_HSV 0x63
#define API_LEDS_UPDATE 0x64
#define API_LEDS_SET_POWERSAVE 0x65
#define API_LEDS_SET_ROCKET 0x66
#define API_LEDS_SET_FLASHLIGHT 0x67
#define API_LEDS_DIM_TOP 0x68
#define API_LEDS_DIM_BOTTOM 0x69
#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
#define API_LIGHT_SENSOR_RUN 0x80
#define API_LIGHT_SENSOR_GET 0x81
#define API_LIGHT_SENSOR_STOP 0x82
#define API_LIGHT_SENSOR_READ 0x83
#define API_GPIO_SET_PIN_MODE 0xA0
#define API_GPIO_GET_PIN_MODE 0xA1
#define API_GPIO_WRITE_PIN 0xA2
#define API_GPIO_READ_PIN 0xA3
#define API_TRNG_READ 0xB0
#define API_PERSONAL_STATE_SET 0xc0
#define API_PERSONAL_STATE_GET 0xc1
#define API_PERSONAL_STATE_IS_PERSISTENT 0xc2
#define API_BME680_INIT 0xD0
#define API_BME680_DEINIT 0xD1
#define API_BME680_GET_DATA 0xD2
#define API_BHI160_ENABLE 0xe0
#define API_BHI160_DISABLE 0xe1
#define API_BHI160_DISABLE_ALL 0xe2
#define API_MAX30001_ENABLE 0xf0
#define API_MAX30001_DISABLE 0xf1
#define API_MAX86150_ENABLE 0x0100
#define API_MAX86150_DISABLE 0x0101

Jakob
committed
#define API_USB_SHUTDOWN 0x110
#define API_USB_STORAGE 0x111
#define API_USB_CDCACM 0x112
#define API_WS2812_WRITE 0x0120
#define API_CONFIG_GET_STRING 0x130
#define API_CONFIG_GET_INTEGER 0x131
#define API_CONFIG_GET_BOOLEAN 0x132
#define API_CONFIG_SET_STRING 0x133
#define API_BLE_GET_COMPARE_VALUE 0x140
#define API_BLE_COMPARE_RESPONSE 0x141
#define API_BLE_SET_BONDABLE 0x142
#define API_BLE_GET_EVENT 0x143
/* clang-format on */
typedef uint32_t api_int_id_t;
/**
* Interrupts
* ==========
* Next to API calls, Epicardium API also has an interrupt mechanism to serve
* the other direction. These interrupts can be enabled/disabled
* (masked/unmasked) using :c:func:`epic_interrupt_enable` and
* :c:func:`epic_interrupt_disable`.
* These interrupts work similar to hardware interrupts: You will only get a
* single interrupt, even if multiple events occured since the ISR last ran
* (*this behavior is new since version 1.16*).
*
* .. warning::
*
* Never attempt to call the API from inside an ISR. This might trigger an
* assertion if a call is already being made from thread context. We plan to
* lift this restriction at some point, but for the time being, this is how
* it is.
*/
/**
* Enable/unmask an API interrupt.
*
* :param int_id: The interrupt to be enabled
*/
API(API_INTERRUPT_ENABLE, int epic_interrupt_enable(api_int_id_t int_id));
/**
* Disable/mask an API interrupt.
*
* :param int_id: The interrupt to be disabled
*/
API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id));
/**
* Check if an API interrupt is enabled.
*
* :param int int_id: The interrupt to be checked
* :param bool* enabled: ``true`` will be stored here if the interrupt is enabled.
* ``false`` otherwise.
*
* :return: 0 on success, ``-EINVAL`` if the interrupt is unknown.
*
* .. versionadded:: 1.16
*/
API(API_INTERRUPT_IS_ENABLED, int epic_interrupt_is_enabled(api_int_id_t int_id, bool *enabled));
/**
* The following interrupts are defined:
*/
#define EPIC_INT_RESET 0
/** ``^C`` interrupt. See :c:func:`epic_isr_ctrl_c` for details. */
#define EPIC_INT_CTRL_C 1
/** UART Receive interrupt. See :c:func:`epic_isr_uart_rx`. */
/** RTC Alarm interrupt. See :c:func:`epic_isr_rtc_alarm`. */
/** BHI160 Accelerometer. See :c:func:`epic_isr_bhi160_accelerometer`. */
/** BHI160 Orientation Sensor. See :c:func:`epic_isr_bhi160_orientation`. */
/** BHI160 Gyroscope. See :c:func:`epic_isr_bhi160_gyroscope`. */
/** MAX30001 ECG. See :c:func:`epic_isr_max30001_ecg`. */
/** BHI160 Magnetometer. See :c:func:`epic_isr_bhi160_magnetometer`. */
#define EPIC_INT_BHI160_MAGNETOMETER 8
/** MAX86150 ECG and PPG sensor. See :c:func:`epic_isr_max86150`. */
#define EPIC_INT_MAX86150 9
/** Bluetooth Low Energy event. See :c:func:`epic_isr_ble`. */
#define EPIC_INT_BLE 10
/* Number of defined interrupts. */
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/*
* "Reset Handler*. This isr is implemented by the API caller and is used to
* reset the core for loading a new payload.
*
* Just listed here for completeness. You don't need to implement this yourself.
*/
API_ISR(EPIC_INT_RESET, __epic_isr_reset);
/**
* Core API
* ========
* The following functions control execution of code on core 1.
*/
/**
* Stop execution of the current payload and return to the menu.
*
* :param int ret: Return code.
* :return: :c:func:`epic_exit` will never return.
*/
void epic_exit(int ret) __attribute__((noreturn));
/*
* The actual epic_exit() function is not an API call because it needs special
* behavior. The underlying call is __epic_exit() which returns. After calling
* this API function, epic_exit() will enter the reset handler.
*/
API(API_SYSTEM_EXIT, void __epic_exit(int ret));
/**
* Stop execution of the current payload and immediately start another payload.
*
* :param char* name: Name (path) of the new payload to start. This can either
* be:
*
* - A path to an ``.elf`` file (l0dable).
* - A path to a ``.py`` file (will be loaded using Pycardium).
* - A path to a directory (assumed to be a Python module, execution starts
* with ``__init__.py`` in this folder).
*
* :return: :c:func:`epic_exec` will only return in case loading went wrong.
* The following error codes can be returned:
*
* - ``-ENOENT``: File not found.
* - ``-ENOEXEC``: File not a loadable format.
*/
int epic_exec(char *name);
/*
* Underlying API call for epic_exec(). The function is not an API call itself
* because it needs special behavior when loading a new payload.
*/
API(API_SYSTEM_EXEC, int __epic_exec(char *name));
/**
* Reset/Restart card10
*/
API(API_SYSTEM_RESET, void epic_system_reset(void));
/**
* Read the current battery voltage.
*/
API(API_BATTERY_VOLTAGE, int epic_read_battery_voltage(float *result));
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/**
* Read the current battery current.
*/
API(API_BATTERY_CURRENT, int epic_read_battery_current(float *result));
/**
* Read the current charge voltage.
*/
API(API_CHARGEIN_VOLTAGE, int epic_read_chargein_voltage(float *result));
/**
* Read the current charge current.
*/
API(API_CHARGEIN_CURRENT, int epic_read_chargein_current(float *result));
/**
* Read the current system voltage.
*/
API(API_SYSTEM_VOLTAGE, int epic_read_system_voltage(float *result));
/**
* Read the current thermistor voltage.
*/
API(API_THERMISTOR_VOLTAGE, int epic_read_thermistor_voltage(float *result));
/**
* UART/Serial Interface
* =====================
*/
/**
* Write a string to all connected serial devices. This includes:
*
* - Real UART, whose pins are mapped onto USB-C pins. Accessible via the HW-debugger.
* - A CDC-ACM device available via USB.
* - Maybe, in the future, bluetooth serial?
*
* :param str: String to write. Does not necessarily have to be NULL-terminated.
* :param length: Amount of bytes to print.
*/
API(API_UART_WRITE_STR, void epic_uart_write_str(
* Try reading a single character from any connected serial device.
* If nothing is available, :c:func:`epic_uart_read_char` returns ``(-1)``.
* :return: The byte or ``(-1)`` if no byte was available.
*/
API(API_UART_READ_CHAR, int epic_uart_read_char(void));
/**
* Read as many characters as possible from the UART queue.
*
* :c:func:`epic_uart_read_str` will not block if no new data is available. For
* an example, see :c:func:`epic_isr_uart_rx`.
*
* :param char* buf: Buffer to be filled with incoming data.
* :param size_t cnt: Size of ``buf``.
* :returns: Number of bytes read. Can be ``0`` if no data was available.
* Might be a negative value if an error occured.
*/
API(API_UART_READ_STR, int epic_uart_read_str(char *buf, size_t cnt));
* **Interrupt Service Routine** for :c:data:`EPIC_INT_UART_RX`
*
* UART receive interrupt. This interrupt is triggered whenever a new character
* becomes available on any connected UART device. This function is weakly
* aliased to :c:func:`epic_isr_default` by default.
*
* **Example**:
*
* .. code-block:: cpp
*
* void epic_isr_uart_rx(void)
* {
* char buffer[33];
* int n = epic_uart_read_str(&buffer, sizeof(buffer) - 1);
* buffer[n] = '\0';
* printf("Got: %s\n", buffer);
* }
*
* int main(void)
* {
* epic_interrupt_enable(EPIC_INT_UART_RX);
* while (1) {
* __WFI();
* }
* }
API_ISR(EPIC_INT_UART_RX, epic_isr_uart_rx);
* **Interrupt Service Routine** for :c:data:`EPIC_INT_CTRL_C`
*
* A user-defineable ISR which is triggered when a ``^C`` (``0x04``) is received
* on any serial input device. This function is weakly aliased to
* :c:func:`epic_isr_default` by default.
*
* To enable this interrupt, you need to enable :c:data:`EPIC_INT_CTRL_C`:
*
* .. code-block:: cpp
*
* epic_interrupt_enable(EPIC_INT_CTRL_C);
*/
API_ISR(EPIC_INT_CTRL_C, epic_isr_ctrl_c);
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
/**
* Buttons
* =======
*
*/
/** Button IDs */
enum epic_button {
/** ``1``, Bottom left button (bit 0). */
BUTTON_LEFT_BOTTOM = 1,
/** ``2``, Bottom right button (bit 1). */
BUTTON_RIGHT_BOTTOM = 2,
/** ``4``, Top right button (bit 2). */
BUTTON_RIGHT_TOP = 4,
/** ``8``, Top left (power) button (bit 3). */
BUTTON_LEFT_TOP = 8,
/** ``8``, Top left (power) button (bit 3). */
BUTTON_RESET = 8,
};
/**
* Read buttons.
*
* :c:func:`epic_buttons_read` will read all buttons specified in ``mask`` and
* return set bits for each button which was reported as pressed.
*
* .. note::
*
* The reset button cannot be unmapped from reset functionality. So, while
* you can read it, it cannot be used for app control.
*
* **Example**:
*
* .. code-block:: cpp
*
* #include "epicardium.h"
*
* uint8_t pressed = epic_buttons_read(BUTTON_LEFT_BOTTOM | BUTTON_RIGHT_BOTTOM);
*
* if (pressed & BUTTON_LEFT_BOTTOM) {
* // Bottom left button is pressed
* }
*
* if (pressed & BUTTON_RIGHT_BOTTOM) {
* // Bottom right button is pressed
* }
*
* :param uint8_t mask: Mask of buttons to read. The 4 LSBs correspond to the 4
* buttons:
*
* ===== ========= ============ ===========
* ``3`` ``2`` ``1`` ``0``
* ----- --------- ------------ -----------
* Reset Right Top Right Bottom Left Bottom
* ===== ========= ============ ===========
*
* Use the values defined in :c:type:`epic_button` for masking, as shown in
* the example above.
* :return: Returns nonzero value if unmasked buttons are pushed.
*/
API(API_BUTTONS_READ, uint8_t epic_buttons_read(uint8_t mask));
/**
* Wristband GPIO
* ==============
*/
/** GPIO pins IDs */
enum gpio_pin {
/** ``1``, Wristband connector 1 */
EPIC_GPIO_WRISTBAND_1 = 1,
/** ``2``, Wristband connector 2 */
EPIC_GPIO_WRISTBAND_2 = 2,
/** ``3``, Wristband connector 3 */
EPIC_GPIO_WRISTBAND_3 = 3,
/** ``4``, Wristband connector 4 */
EPIC_GPIO_WRISTBAND_4 = 4,
};
/** GPIO pin modes */
enum gpio_mode {
/** Configure the pin as input */
EPIC_GPIO_MODE_IN = (1<<0),
/** Configure the pin as output */
EPIC_GPIO_MODE_OUT = (1<<1),
/** Enable the internal pull-up resistor */
EPIC_GPIO_PULL_UP = (1<<6),
/** Enable the internal pull-down resistor */
EPIC_GPIO_PULL_DOWN = (1<<7),
};
/**
* Set the mode of a card10 GPIO pin.
*
* :c:func:`epic_gpio_set_pin_mode` will set the pin specified by ``pin`` to the mode ``mode``.
* If the specified pin ID is not valid this function will do nothing.
*
* **Example:**
*
* .. code-block:: cpp
*
* #include "epicardium.h"
*
* // Configure wristband pin 1 as output.
* if (epic_gpio_set_pin_mode(GPIO_WRISTBAND_1, GPIO_MODE_OUT)) {
* // Do your error handling here...
* }
*
* :param uint8_t pin: ID of the pin to configure. Use on of the IDs defined in :c:type:`gpio_pin`.
* :param uint8_t mode: Mode to be configured. Use a combination of the :c:type:`gpio_mode` flags.
* :returns: ``0`` if the mode was set, ``-EINVAL`` if ``pin`` is not valid or the mode could not be set.
*/
API(API_GPIO_SET_PIN_MODE, int epic_gpio_set_pin_mode(
uint8_t pin, uint8_t mode
));
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
/**
* Get the mode of a card10 GPIO pin.
*
* :c:func:`epic_gpio_get_pin_mode` will get the current mode of the GPIO pin specified by ``pin``.
*
* **Example:**
*
* .. code-block:: cpp
*
* #include "epicardium.h"
*
* // Get the mode of wristband pin 1.
* int mode = epic_gpio_get_pin_mode(GPIO_WRISTBAND_1);
* if (mode < 0) {
* // Do your error handling here...
* } else {
* // Do something with the queried mode information
* }
*
* :param uint8_t pin: ID of the pin to get the configuration of. Use on of the IDs defined in :c:type:`gpio_pin`.
* :returns: Configuration byte for the specified pin or ``-EINVAL`` if the pin is not valid.
*/
API(API_GPIO_GET_PIN_MODE, int epic_gpio_get_pin_mode(uint8_t pin));
/**
* Write value to a card10 GPIO pin,
*
* :c:func:`epic_gpio_write_pin` will set the value of the GPIO pin described by ``pin`` to either on or off depending on ``on``.
*
* **Example:**
*
* .. code-block:: cpp
*
* #include "epicardium.h"
*
* // Get the mode of wristband pin 1.
* int mode = epic_gpio_get_pin_mode(GPIO_WRISTBAND_1);
* if (mode < 0) {
* // Do your error handling here...
* } else {
* // Do something with the queried mode information
* }
*
* :param uint8_t pin: ID of the pin to get the configuration of. Use on of the IDs defined in :c:type:`gpio_pin`.
* :param bool on: Sets the pin to either true (on/high) or false (off/low).
* :returns: ``0`` on succcess, ``-EINVAL`` if ``pin`` is not valid or is not configured as an output.
*/
API(API_GPIO_WRITE_PIN, int epic_gpio_write_pin(uint8_t pin, bool on));
/**
* Read value of a card10 GPIO pin.
*
* :c:func:`epic_gpio_read_pin` will get the value of the GPIO pin described by ``pin``.
*
* **Example:**
*
* .. code-block:: cpp
*
* #include "epicardium.h"
*
* // Get the current value of wristband pin 1.
* uint32_t value = epic_gpio_read_pin(GPIO_WRISTBAND_1);
* if (mode == -EINVAL) {
* // Do your error handling here...
* } else {
* // Do something with the current value
* }
*
* :param uint8_t pin: ID of the pin to get the configuration of. Use on of the IDs defined in :c:type:`gpio_pin`.
* :returns: ``-EINVAL`` if ``pin`` is not valid, an integer value otherwise.
*/
API(API_GPIO_READ_PIN, int epic_gpio_read_pin(uint8_t pin));
/**
* LEDs
* ====
*/
/**
* Set one of card10's RGB LEDs to a certain color in RGB format.
* This function is rather slow when setting multiple LEDs, use
* :c:func:`leds_set_all` or :c:func:`leds_prep` + :c:func:`leds_update`
* instead.
* :param int led: Which LED to set. 0-10 are the LEDs on the top and 11-14
* are the 4 "ambient" LEDs.
* :param uint8_t r: Red component of the color.
* :param uint8_t g: Green component of the color.
* :param uint8_t b: Blue component of the color.
API(API_LEDS_SET, void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b));
/**
* Get one of card10's RGB LEDs in format of RGB.
*
* :c:func:`epic_leds_get_rgb` will get the value of a RGB LED described by ``led``.
*
* :param int led: Which LED to get. 0-10 are the LEDs on the top and 11-14
* are the 4 "ambient" LEDs.
* :param uint8_t * rgb: need tree byte array to get the value of red, green and blue.
* :returns: ``0`` on success or ``-EPERM`` if the LED is blocked by personal-state.
*/
API(API_LEDS_GET, int epic_leds_get_rgb(int led, uint8_t * rgb));
/**
* Set one of card10's RGB LEDs to a certain color in HSV format.
*
* This function is rather slow when setting multiple LEDs, use
* :c:func:`leds_set_all_hsv` or :c:func:`leds_prep_hsv` + :c:func:`leds_update`
* instead.
*
* :param int led: Which LED to set. 0-10 are the LEDs on the top and 11-14 are the 4 "ambient" LEDs.
* :param float h: Hue component of the color. (0 <= h < 360)
* :param float s: Saturation component of the color. (0 <= s <= 1)
* :param float v: Value/Brightness component of the color. (0 <= v <= 0)
*/
API(API_LEDS_SET_HSV, void epic_leds_set_hsv(
int led, float h, float s, float v
));
/**
* Set multiple of card10's RGB LEDs to a certain color in RGB format.
*
* The first ``len`` leds are set, the remaining ones are not modified.
*
* :param uint8_t[len][r,g,b] pattern: Array with RGB Values with 0 <= len <=
* 15. 0-10 are the LEDs on the top and 11-14 are the 4 "ambient" LEDs.
* :param uint8_t len: Length of 1st dimension of ``pattern``, see above.
*/
API(API_LEDS_SET_ALL, void epic_leds_set_all(uint8_t *pattern, uint8_t len));
/**
* Set multiple of card10's RGB LEDs to a certain color in HSV format.
*
* The first ``len`` led are set, the remaining ones are not modified.
*
* :param uint8_t[len][h,s,v] pattern: Array of format with HSV Values with 0
* <= len <= 15. 0-10 are the LEDs on the top and 11-14 are the 4 "ambient"
* LEDs. (0 <= h < 360, 0 <= s <= 1, 0 <= v <= 1)
* :param uint8_t len: Length of 1st dimension of ``pattern``, see above.
*/
API(API_LEDS_SET_ALL_HSV, void epic_leds_set_all_hsv(
float *pattern, uint8_t len
));
/**
* Prepare one of card10's RGB LEDs to be set to a certain color in RGB format.
*
* Use :c:func:`leds_update` to apply changes.
*
* :param int led: Which LED to set. 0-10 are the LEDs on the top and 11-14
* are the 4 "ambient" LEDs.
* :param uint8_t r: Red component of the color.
* :param uint8_t g: Green component of the color.
* :param uint8_t b: Blue component of the color.
*/
API(API_LEDS_PREP, void epic_leds_prep(
int led, uint8_t r, uint8_t g, uint8_t b
));
/**
* Prepare one of card10's RGB LEDs to be set to a certain color in HSV format.
*
* Use :c:func:`leds_update` to apply changes.
*
* :param int led: Which LED to set. 0-10 are the LEDs on the top and 11-14
* are the 4 "ambient" LEDs.
* :param uint8_t h: Hue component of the color. (float, 0 <= h < 360)
* :param uint8_t s: Saturation component of the color. (float, 0 <= s <= 1)
* :param uint8_t v: Value/Brightness component of the color. (float, 0 <= v <= 0)
*/
API(API_LEDS_PREP_HSV, void epic_leds_prep_hsv(
int led, float h, float s, float v
));
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
/**
* Set global brightness for top RGB LEDs.
*
* Aside from PWM, the RGB LEDs' overall brightness can be controlled with a
* current limiter independently to achieve a higher resolution at low
* brightness which can be set with this function.
*
* :param uint8_t value: Global brightness of top LEDs. (1 <= value <= 8, default = 1)
*/
API(API_LEDS_DIM_BOTTOM, void epic_leds_dim_bottom(uint8_t value));
/**
* Set global brightness for bottom RGB LEDs.
*
* Aside from PWM, the RGB LEDs' overall brightness can be controlled with a
* current limiter independently to achieve a higher resolution at low
* brightness which can be set with this function.
*
* :param uint8_t value: Global brightness of bottom LEDs. (1 <= value <= 8, default = 8)
*/
API(API_LEDS_DIM_TOP, void epic_leds_dim_top(uint8_t value));
/**
* Enables or disables powersave mode.
*
* Even when set to zero, the RGB LEDs still individually consume ~1mA.
* Powersave intelligently switches the supply power in groups. This introduces
* delays in the magnitude of ~10µs, so it can be disabled for high speed
* applications such as POV.
*
* :param bool eco: Activates powersave if true, disables it when false. (default = True)
*/
API(API_LEDS_SET_POWERSAVE, void epic_leds_set_powersave(bool eco));
/**
* Updates the RGB LEDs with changes that have been set with :c:func:`leds_prep`
* or :c:func:`leds_prep_hsv`.
*
* The LEDs can be only updated in bulk, so using this approach instead of
* :c:func:`leds_set` or :c:func:`leds_set_hsv` significantly reduces the load
* on the corresponding hardware bus.
*/
API(API_LEDS_UPDATE, void epic_leds_update(void));
/**
* Set the brightness of one of the rocket LEDs.
*
* :param int led: Which LED to set.
*
* +-------+--------+----------+
* | ID | Color | Location |
* +=======+========+==========+
* | ``0`` | Blue | Left |
* +-------+--------+----------+
* | ``1`` | Yellow | Top |
* +-------+--------+----------+
* | ``2`` | Green | Right |
* +-------+--------+----------+
* :param uint8_t value: Brightness of LED (value between 0 and 31).
*/
API(API_LEDS_SET_ROCKET, void epic_leds_set_rocket(int led, uint8_t value));
/**
* Get the brightness of one of the rocket LEDs.
*
* :param int led: Which LED to get.
*
* +-------+--------+----------+
* | ID | Color | Location |
* +=======+========+==========+
* | ``0`` | Blue | Left |
* +-------+--------+----------+
* | ``1`` | Yellow | Top |
* +-------+--------+----------+
* | ``2`` | Green | Right |
* +-------+--------+----------+
* :returns value: Brightness of LED (value between 0 and 31) or ``-EINVAL`` if the LED/rocket does not exists.
*/
API(API_LEDS_GET_ROCKET, int epic_leds_get_rocket(int led));
/**
* Turn on the bright side LED which can serve as a flashlight if worn on the left wrist or as a rad tattoo illuminator if worn on the right wrist.
*
*:param bool power: Side LED on if true.
*/
API(API_LEDS_SET_FLASHLIGHT, void epic_set_flashlight(bool power));
/**
* Set gamma lookup table for individual rgb channels.
*
* Since the RGB LEDs' subcolor LEDs have different peak brightness and the
* linear scaling introduced by PWM is not desireable for color accurate work,
* custom lookup tables for each individual color channel can be loaded into the
* Epicardium's memory with this function.
*
* :param uint8_t rgb_channel: Color whose gamma table is to be updated, 0->Red, 1->Green, 2->Blue.
* :param uint8_t[256] gamma_table: Gamma lookup table. (default = 4th order power function rounded up)
*/
API(API_LEDS_SET_GAMMA_TABLE, void epic_leds_set_gamma_table(
uint8_t rgb_channel, 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
));
*/
/**
* BME680 Sensor Data
*/
struct bme680_sensor_data {
/** Temperature in degree celsius */
float temperature;
/** Humidity in % relative humidity */
float humidity;
/** Pressure in hPa */
float pressure;
/** Gas resistance in Ohms */
float gas_resistance;
};
/**
* Initialize the BM680 sensor.
*
* :return: 0 on success or ``-Exxx`` on error. The following
* errors might occur:
*
* - ``-EFAULT``: On NULL-pointer.
* - ``-EINVAL``: Invalid configuration.
* - ``-EIO``: Communication with the device failed.
* - ``-ENODEV``: Device was not found.
*/
API(API_BME680_INIT, int epic_bme680_init());
/**
* De-Initialize the BM680 sensor.
*
* :return: 0 on success or ``-Exxx`` on error. The following
* errors might occur:
*
* - ``-EFAULT``: On NULL-pointer.
* - ``-EINVAL``: Invalid configuration.
* - ``-EIO``: Communication with the device failed.
* - ``-ENODEV``: Device was not found.
*/
API(API_BME680_DEINIT, int epic_bme680_deinit());
/**
* Get the current BME680 data.
*
* :param data: Where to store the environmental data.
* :return: 0 on success or ``-Exxx`` on error. The following
* errors might occur:
*
* - ``-EFAULT``: On NULL-pointer.
* - ``-EINVAL``: Sensor not initialized.
* - ``-EIO``: Communication with the device failed.
* - ``-ENODEV``: Device was not found.
*/
API(API_BME680_GET_DATA, int epic_bme680_read_sensors(
struct bme680_sensor_data *data
));
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
/**
* MAX86150
* ======
*/
/**
* Configuration for a MAX86150 sensor.
*
* This struct is used when enabling a sensor using
* :c:func:`epic_max86150_enable_sensor`.
*/
struct max86150_sensor_config {
/**
* Number of samples Epicardium should keep for this sensor. Do not set
* this number too high as the sample buffer will eat RAM.
*/
size_t sample_buffer_len;
/**
* Sample rate for PPG from the sensor in Hz. Maximum data rate is limited
* to 200 Hz for all sensors though some might be limited at a lower
* rate.
*
* Possible values are 10, 20, 50, 84, 100, 200.
*/
uint16_t ppg_sample_rate;
};
/**
* MAX86150 Sensor Data
*/
struct max86150_sensor_data {
/** Red LED data */
uint32_t red;
/** IR LED data */
uint32_t ir;
/** ECG data */
int32_t ecg;
};
/**
* Enable a MAX86150 PPG and ECG sensor.
*
* Calling this function will instruct the MAX86150 to collect a
* data from the sensor. You can then retrieve the samples using
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
* :c:func:`epic_stream_read`.
*
* :param max86150_sensor_config* config: Configuration for this sensor.
* :param size_t config_size: Size of ``config``.
* :returns: A sensor descriptor which can be used with
* :c:func:`epic_stream_read` or a negative error value:
*
* - ``-ENOMEM``: The MAX86150 driver failed to create a stream queue.
* - ``-ENODEV``: The MAX86150 driver failed due to physical connectivity problem
* (broken wire, unpowered, etc).
* - ``-EINVAL``: config->ppg_sample_rate is not one of 10, 20, 50, 84, 100, 200
* or config_size is not size of config.
*
* .. versionadded:: 1.13
*/
API(API_MAX86150_ENABLE, int epic_max86150_enable_sensor(struct max86150_sensor_config *config, size_t config_size));
/**
* Disable the MAX86150 sensor.
*
* :returns: 0 in case of success or forward negative error value from stream_deregister.
*
* .. versionadded:: 1.13
*/
API(API_MAX86150_DISABLE, int epic_max86150_disable_sensor());
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_MAX86150`
*
* :c:func:`epic_isr_max86150` is called whenever the MAX86150
* PPG sensor has new data available.
*/
API_ISR(EPIC_INT_MAX86150, epic_isr_max86150);
/**
* 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,