epicardium.h 65.4 KB
Newer Older
Rahix's avatar
Rahix committed
1
2
#ifndef _EPICARDIUM_H
#define _EPICARDIUM_H
Rahix's avatar
Rahix committed
3

Rahix's avatar
Rahix committed
4
#include <stdint.h>
5
#include <errno.h>
Rahix's avatar
Rahix committed
6

Rahix's avatar
Rahix committed
7
#ifndef __SPHINX_DOC
fleur's avatar
fleur committed
8
/* Some headers are not recognized by hawkmoth for some odd reason */
Rahix's avatar
Rahix committed
9
#include <stddef.h>
fleur's avatar
fleur committed
10
#include <stdbool.h>
Rahix's avatar
Rahix committed
11
12
#else
typedef unsigned int size_t;
fleur's avatar
fleur committed
13
typedef _Bool bool;
Rahix's avatar
Rahix committed
14
15
16
17
18
#endif /* __SPHINX_DOC */

/*
 * These definitions are required for the code-generator.  Please don't touch!
 */
Rahix's avatar
Rahix committed
19
#ifndef API
Rahix's avatar
Rahix committed
20
#define API(id, def) def
Rahix's avatar
Rahix committed
21
#endif
22
23
24
#ifndef API_ISR
#define API_ISR(id, isr) void isr(void);
#endif
Rahix's avatar
Rahix committed
25

26
27
28
29
30
31
/*
 * IDs for all defined API calls.  These IDs should not be needed in application
 * code on any side.
 */

/* clang-format off */
Rahix's avatar
Rahix committed
32
33
#define API_SYSTEM_EXIT             0x1
#define API_SYSTEM_EXEC             0x2
Rahix's avatar
Rahix committed
34
#define API_SYSTEM_RESET            0x3
35
#define API_BATTERY_VOLTAGE         0x4
36
37
38

#define API_INTERRUPT_ENABLE        0xA
#define API_INTERRUPT_DISABLE       0xB
39
#define API_INTERRUPT_IS_ENABLED    0xC
40
41
42
43
44
45

#define API_UART_WRITE_STR         0x10
#define API_UART_READ_CHAR         0x11
#define API_UART_READ_STR          0x12

#define API_STREAM_READ            0x1F
Rahix's avatar
Rahix committed
46
47
48
49
50
51
52
53
54
55
56

#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
57
#define API_DISP_BACKLIGHT         0x2a
58
#define API_DISP_PRINT_ADV         0x2b
Rahix's avatar
Rahix committed
59

Stefan Haun's avatar
Stefan Haun committed
60
61
62
63
64
65
66
/* 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

Rahix's avatar
Rahix committed
67
68
69
70
71
72
73
74
#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
75
76
77
#define API_FILE_OPENDIR           0x49
#define API_FILE_READDIR           0x4a
#define API_FILE_UNLINK            0x4b
swym's avatar
swym committed
78
79
#define API_FILE_RENAME            0x4c
#define API_FILE_MKDIR             0x4d
Rahix's avatar
Rahix committed
80
81
82

#define API_RTC_GET_SECONDS        0x50
#define API_RTC_SCHEDULE_ALARM     0x51
Hauke Mehrtens's avatar
Hauke Mehrtens committed
83
#define API_RTC_SET_MILLISECONDS   0x52
84
#define API_RTC_GET_MILLISECONDS   0x53
85
86
#define API_RTC_GET_MONOTONIC_SECONDS      0x54
#define API_RTC_GET_MONOTONIC_MILLISECONDS 0x55
Rahix's avatar
Rahix committed
87
88

#define API_LEDS_SET               0x60
fleur's avatar
fleur committed
89
90
91
92
93
94
95
96
97
98
99
100
#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
101
#define API_LEDS_CLEAR_ALL         0x6d
102
#define API_LEDS_GET_ROCKET        0x6e
103
#define API_LEDS_GET               0x6f
zenox's avatar
zenox committed
104
#define API_LEDS_FLASH_ROCKET      0x72
Rahix's avatar
Rahix committed
105
106
107
108
109
110
111

#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
112
#define API_LIGHT_SENSOR_READ	   0x83
Rahix's avatar
Rahix committed
113
114

#define API_BUTTONS_READ           0x90
115
116
117
118
119

#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
120
121
122

#define API_TRNG_READ              0xB0

123
124
125
126
#define API_PERSONAL_STATE_SET     0xc0
#define API_PERSONAL_STATE_GET     0xc1
#define API_PERSONAL_STATE_IS_PERSISTENT 0xc2

chris007's avatar
chris007 committed
127
128
129
130
#define API_BME680_INIT            0xD0
#define API_BME680_DEINIT          0xD1
#define API_BME680_GET_DATA        0xD2

131
132
#define API_BHI160_ENABLE          0xe0
#define API_BHI160_DISABLE         0xe1
133
#define API_BHI160_DISABLE_ALL     0xe2
134

schneider's avatar
schneider committed
135
136
137
#define API_MAX30001_ENABLE        0xf0
#define API_MAX30001_DISABLE       0xf1

138
139
#define API_MAX86150_ENABLE        0x0100
#define API_MAX86150_DISABLE       0x0101
140

swym's avatar
swym committed
141
142
143
144
#define API_USB_SHUTDOWN           0x110
#define API_USB_STORAGE            0x111
#define API_USB_CDCACM             0x112

145
146
#define API_WS2812_WRITE           0x0120

147
148
149
#define API_CONFIG_GET_STRING      0x130
#define API_CONFIG_GET_INTEGER     0x131
#define API_CONFIG_GET_BOOLEAN     0x132
150
#define API_CONFIG_SET_STRING      0x133
151

152
153
154
155
156
#define API_BLE_GET_COMPARE_VALUE     0x140
#define API_BLE_COMPARE_RESPONSE      0x141
#define API_BLE_SET_MODE              0x142
#define API_BLE_GET_EVENT             0x143
#define API_BLE_GET_SCAN_REPORT       0x144
157

158
159
160
161
162
163
164
165
166
167
168
/* 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`.
169
 *
170
171
172
173
 * 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*).
 *
174
175
176
177
178
179
 * .. 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.
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
 */

/**
 * 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));

196
197
198
199
200
201
202
203
204
205
206
207
208
/**
 * 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));

209
210
211
/**
 * The following interrupts are defined:
 */
212

213
/* clang-format off */
Rahix's avatar
Rahix committed
214
/** Reset Handler */
215
216
217
#define EPIC_INT_RESET                  0
/** ``^C`` interrupt. See :c:func:`epic_isr_ctrl_c` for details.  */
#define EPIC_INT_CTRL_C                 1
218
/** UART Receive interrupt.  See :c:func:`epic_isr_uart_rx`. */
Rahix's avatar
Rahix committed
219
#define EPIC_INT_UART_RX                2
220
/** RTC Alarm interrupt.  See :c:func:`epic_isr_rtc_alarm`. */
Rahix's avatar
Rahix committed
221
#define EPIC_INT_RTC_ALARM              3
222
/** BHI160 Accelerometer.  See :c:func:`epic_isr_bhi160_accelerometer`. */
223
#define EPIC_INT_BHI160_ACCELEROMETER	4
224
/** BHI160 Orientation Sensor.  See :c:func:`epic_isr_bhi160_orientation`. */
225
#define EPIC_INT_BHI160_ORIENTATION	5
226
/** BHI160 Gyroscope.  See :c:func:`epic_isr_bhi160_gyroscope`. */
227
#define EPIC_INT_BHI160_GYROSCOPE	6
228
/** MAX30001 ECG.  See :c:func:`epic_isr_max30001_ecg`. */
229
#define EPIC_INT_MAX30001_ECG		7
230
231
/** BHI160 Magnetometer.  See :c:func:`epic_isr_bhi160_magnetometer`. */
#define EPIC_INT_BHI160_MAGNETOMETER    8
232
233
/** MAX86150 ECG and PPG sensor.  See :c:func:`epic_isr_max86150`. */
#define EPIC_INT_MAX86150		9
234
235
/** Bluetooth Low Energy event.  See :c:func:`epic_isr_ble`. */
#define EPIC_INT_BLE                    10
236
/* Number of defined interrupts. */
237
#define EPIC_INT_NUM                    11
Rahix's avatar
Rahix committed
238
239
/* clang-format on */

Rahix's avatar
Rahix committed
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
266
267
/*
 * "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));
268

Rahix's avatar
Rahix committed
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/**
 * 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));
293

Rahix's avatar
Rahix committed
294
295
296
297
298
/**
 * Reset/Restart card10
 */
API(API_SYSTEM_RESET, void epic_system_reset(void));

299
/**
Stefan Haun's avatar
Stefan Haun committed
300
 * PMIC API
301
302
303
 * ===============
 */

Stefan Haun's avatar
Stefan Haun committed
304

305
306
307
308
309
/**
 * Read the current battery voltage.
 */
API(API_BATTERY_VOLTAGE, int epic_read_battery_voltage(float *result));

Stefan Haun's avatar
Stefan Haun committed
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/**
 * 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));


Rahix's avatar
Rahix committed
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/**
 * 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.
 */
351
API(API_UART_WRITE_STR, void epic_uart_write_str(
352
	const char *str, size_t length
353
));
Rahix's avatar
Rahix committed
354

Rahix's avatar
Rahix committed
355
/**
356
 * Try reading a single character from any connected serial device.
357
 *
358
 * If nothing is available, :c:func:`epic_uart_read_char` returns ``(-1)``.
359
 *
360
361
362
363
 * :return:  The byte or ``(-1)`` if no byte was available.
 */
API(API_UART_READ_CHAR, int epic_uart_read_char(void));

364
365
366
367
368
369
370
371
372
373
374
375
376
/**
 * 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));

377
/**
378
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_UART_RX`
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
 *
 * 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);
Rahix's avatar
Rahix committed
399
 *
400
401
402
403
 *            while (1) {
 *                    __WFI();
 *            }
 *    }
Rahix's avatar
Rahix committed
404
 */
405
API_ISR(EPIC_INT_UART_RX, epic_isr_uart_rx);
Rahix's avatar
Rahix committed
406

407
/**
408
 * **Interrupt Service Routine** for :c:data:`EPIC_INT_CTRL_C`
409
410
411
412
413
414
415
416
417
418
419
420
421
 *
 * 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);

Rahix's avatar
Rahix committed
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
482
483
/**
 * 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));

484
485
486
487
488
489
490
491
/**
 * Wristband GPIO
 * ==============
 */

/** GPIO pins IDs */
enum gpio_pin {
    /** ``1``, Wristband connector 1 */
492
    EPIC_GPIO_WRISTBAND_1 = 1,
493
    /** ``2``, Wristband connector 2 */
494
    EPIC_GPIO_WRISTBAND_2 = 2,
495
    /** ``3``, Wristband connector 3 */
496
    EPIC_GPIO_WRISTBAND_3 = 3,
497
    /** ``4``, Wristband connector 4 */
498
    EPIC_GPIO_WRISTBAND_4 = 4,
499
500
501
502
503
};

/** GPIO pin modes */
enum gpio_mode {
    /** Configure the pin as input */
504
    EPIC_GPIO_MODE_IN = (1<<0),
505
    /** Configure the pin as output */
506
    EPIC_GPIO_MODE_OUT = (1<<1),
507
    EPIC_GPIO_MODE_ADC = (1<<2),
508
509

    /** Enable the internal pull-up resistor */
510
    EPIC_GPIO_PULL_UP = (1<<6),
511
    /** Enable the internal pull-down resistor */
512
    EPIC_GPIO_PULL_DOWN = (1<<7),
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
};

/**
 * 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.
 */
536
537
538
API(API_GPIO_SET_PIN_MODE, int epic_gpio_set_pin_mode(
	uint8_t pin, uint8_t mode
));
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
609
610

/**
 * 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.
 */
611
API(API_GPIO_READ_PIN, int epic_gpio_read_pin(uint8_t pin));
612

Rahix's avatar
Rahix committed
613
614
615
616
617
618
/**
 * LEDs
 * ====
 */

/**
fleur's avatar
fleur committed
619
 * Set one of card10's RGB LEDs to a certain color in RGB format.
Rahix's avatar
Rahix committed
620
 *
fleur's avatar
fleur committed
621
622
623
 * 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.
624
 *
fleur's avatar
fleur committed
625
626
627
628
629
 * :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.
Rahix's avatar
Rahix committed
630
 */
631
632
API(API_LEDS_SET, void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b));

633
634
635
636
637
638
639
640
641
642

/**
 * 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.
Rahix's avatar
Rahix committed
643
644
 *
 * .. versionadded:: 1.10
645
646
647
 */
API(API_LEDS_GET, int epic_leds_get_rgb(int led, uint8_t * rgb));

zenox's avatar
zenox committed
648
/**
zenox's avatar
zenox committed
649
 * Set one of the rockets to flash for a certain time.
zenox's avatar
zenox committed
650
 *
zenox's avatar
zenox committed
651
 * :c:func:`epic_leds_flash_rocket` will set a timer for the flash of a rocket.
zenox's avatar
zenox committed
652
 *
zenox's avatar
zenox committed
653
 * :param int led: Number of the rocket that sould flash 
zenox's avatar
zenox committed
654
 * :param uint8_t value:  brightness of the 'on'-state of this rocket ( 0 < value < 32)
zenox's avatar
zenox committed
655
 * :param int millis:  time in milliseconds defining the duration of the flash (i.e. how long is the rocket 'on')
zenox's avatar
zenox committed
656
 *
zenox's avatar
zenox committed
657
 * .. versionadded:: 1.16
zenox's avatar
zenox committed
658
 */
zenox's avatar
zenox committed
659
API(API_LEDS_FLASH_ROCKET, void epic_leds_flash_rocket(int led, uint8_t valiue, int millis));
zenox's avatar
zenox committed
660

fleur's avatar
fleur committed
661
662
663
664
665
666
667
668
669
670
671
672
/**
 * 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)
 */
673
674
675
API(API_LEDS_SET_HSV, void epic_leds_set_hsv(
	int led, float h, float s, float v
));
fleur's avatar
fleur committed
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697

/**
 * 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.
 */
698
699
700
API(API_LEDS_SET_ALL_HSV, void epic_leds_set_all_hsv(
	float *pattern, uint8_t len
));
fleur's avatar
fleur committed
701
702
703
704
705
706
707
708
709
710
711
712

/**
 * 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.
 */
713
714
715
API(API_LEDS_PREP, void epic_leds_prep(
	int led, uint8_t r, uint8_t g, uint8_t b
));
fleur's avatar
fleur committed
716
717
718
719
720
721
722
723
724
725
726
727

/**
 * 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)
 */
728
729
730
API(API_LEDS_PREP_HSV, void epic_leds_prep_hsv(
	int led, float h, float s, float v
));
fleur's avatar
fleur committed
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
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

/**
 * 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    |
 *    +-------+--------+----------+
Rahix's avatar
Rahix committed
790
 * :param uint8_t value:  Brightness of LED (value between 0 and 31).
fleur's avatar
fleur committed
791
792
793
 */
API(API_LEDS_SET_ROCKET, void epic_leds_set_rocket(int led, uint8_t value));

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
/**
 * 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.
Rahix's avatar
Rahix committed
809
810
 *
 * .. versionadded:: 1.10
811
812
813
 */
API(API_LEDS_GET_ROCKET, int epic_leds_get_rocket(int led));

fleur's avatar
fleur committed
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
/**
 * 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(
833
	uint8_t rgb_channel, uint8_t *gamma_table
fleur's avatar
fleur committed
834
835
));

836
837
838
839
840
841
842
/**
 * 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.
 */
843
844
845
API(API_LEDS_CLEAR_ALL, void epic_leds_clear_all(
	uint8_t r, uint8_t g, uint8_t b
));
846

chris007's avatar
chris007 committed
847
848
849
/**
 * BME680
 * ======
850
851
 *
 * .. versionadded:: 1.4
chris007's avatar
chris007 committed
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
 */

/**
 * 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.
 *
871
872
 * .. versionadded:: 1.4
 *
chris007's avatar
chris007 committed
873
874
875
876
877
878
879
880
881
882
883
884
885
 * :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.
 *
886
887
 * .. versionadded:: 1.4
 *
chris007's avatar
chris007 committed
888
889
890
891
892
893
894
895
896
897
898
899
900
 * :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.
 *
901
902
 * .. versionadded:: 1.4
 *
chris007's avatar
chris007 committed
903
904
905
906
907
908
909
910
911
 * :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.
 */
912
913
914
API(API_BME680_GET_DATA, int epic_bme680_read_sensors(
	struct bme680_sensor_data *data
));
chris007's avatar
chris007 committed
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
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
/**
 * 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.
Rahix's avatar
Rahix committed
957
958
959
 *
 * Calling this function will instruct the MAX86150 to collect a
 * data from the sensor.  You can then retrieve the samples using
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
 * :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);

994
995
996
997
998
999
1000
/**
 * 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
For faster browsing, not all history is shown. View entire blame