Commits (57)
......@@ -6,6 +6,39 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased]
## [v1.10] - 2019-09-05 21:42 - [JerusalemArtichoke]
[JerusalemArtichoke]: https://card10.badge.events.ccc.de/release/card10-v1.10-JerusalemArtichoke.zip
### Added
- **ws2812**: Connect Neopixels to the wristband GPIOs and make your card10
even more colorful!
- DigiClk is now in the default prelude!
- High-pass filter and pulse detection in default ECG app.
- Actually added `uuid` module - it was not built into the firmware before,
by accident.
- `leds.get_rgb()`: Get the current color of an LED.
- `leds.get_rocket()`: Get the current brightness of one of the rockets.
- `micropython.mem_use()` function.
- The analog-clock can now also set the time using the buttons.
### Changed
- **Pycardium**: Switched from `long-long` to `mpz` integer representation.
This should resolve any issues with large numbers which had popped up so far.
- Refactored BME680 sensor interface.
- Made OpenOCD scripts work with more debuggers out of the box.
- Internal changes in preparation for button-interrupts.
### Fixed
- Backlight and Vibration motor were not reset when switching apps.
- Mismatch in default settings of the *Card10 Nickname* app.
- Fixed the PMIC ADC muxer not being properly reset to neutral after a
measurement.
- Fixed wrong timezone offset calculation in `utime.time_ms()`.
- Fixed bug where `\` characters were not parsed as path separators.
- Fixed the alignment request check in our ELF l0der.
- Fixed a buffer-overflow in the config-parser.
## [v1.9] - 2019-08-28 23:23 - [IcebergLettuce]
[IcebergLettuce]: https://card10.badge.events.ccc.de/release/card10-v1.9-IcebergLettuce.zip
......@@ -207,7 +240,8 @@ fbf7c8c0 fix(menu.py) Refactored menu.py based on !138
## [v1.0] - 2019-08-21 00:50
Initial release.
[Unreleased]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.9...master
[Unreleased]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.10...master
[v1.10]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.9...v1.10
[v1.9]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.8...v1.9
[v1.8]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.7...v1.8
[v1.7]: https://git.card10.badge.events.ccc.de/card10/firmware/compare/v1.6...v1.7
......
......@@ -28,27 +28,27 @@ The current draft uses following service specification:
- Rockets characteristic:
UUID: ``42230210-2342-2342-2342-234223422342``
write no response
read and write no response
- Background LED Bottom Left characteristic:
UUID: ``42230211-2342-2342-2342-234223422342``
write no response
read and write no response
- Background LED Bottom Right characteristic:
UUID: ``42230212-2342-2342-2342-234223422342``
write no response
read and write no response
- Background LED Top Right characteristic:
UUID: ``42230213-2342-2342-2342-234223422342``
write no response
read and write no response
- Background LED Top Left characteristic:
UUID: ``42230214-2342-2342-2342-234223422342``
write no reponse
read and write no reponse
- LEDS dim bottom characteristic:
......@@ -78,7 +78,7 @@ The current draft uses following service specification:
- LEDs above characteristic:
UUID: ``42230220-2342-2342-2342-234223422342``
write no reponse
read and write no reponse
- Light sensor characteristic:
......@@ -104,6 +104,9 @@ Rockets characteristic
The Rockets characteristic makes it possible to address every three rockets.
Just write there three byte array, one for evey rocket.
On read you get the current value of all three rockets.
Range is between 0 and 31 (``0x1f`) if send higher value it will set to max of 31.
Dataformat:
......@@ -113,14 +116,14 @@ Dataformat:
Rocket0 Rocket1 Rocket2
======= ======= =======
- Enable only Rocket0: ``0xff0000``
- Enable all rockets with 50% brightness: ``0x7f7f7f``
- Enable only Rocket0: ``0x1f0000``
- Enable all rockets with 50% brightness: ``0x0f0f0f``
Background LED <Position> characteristic
----------------------------------------
The Background LEDs <Position> characteristic makes it possible to address the bottom LEDs by position.
Just write there three ``uint8`` for the rgb color.
Just write there three ``uint8`` for the rgb color or read the current value.
Dataformat:
......@@ -170,7 +173,7 @@ It writes always as persistant and it gives feedback if the value is in range an
LEDs above characteristic
---------------------------------
This characteristic set every 11 leds on the top module at once.
This characteristic set or read the current value of every 11 leds on the top module at once.
By defining 11x rgb from left to right. You need also to set exchange a bigger MTU to use this feature.
- set a rainbow beginnig with red on the right edge: ``0xff0000ff8b00e8ff005dff0000ff2e00ffb900b9ff002eff5d00ffe800ffff008b``
......
......@@ -90,6 +90,7 @@ html_context = {
autodoc_mock_imports = [
"buttons",
"interrupt",
"sys_bme680",
"sys_display",
"sys_leds",
"sys_max30001",
......
......@@ -115,6 +115,12 @@ command to soft-reset card10.
...
(gdb)
.. note::
You will also find the following self-describing gdb files in the firmware
root directory, which do not require additional arguments:
``flash-all.gdb, flash-bootloader.gdb,
flash-both.gdb, flash-epicardium.gdb, flash-pycardium.gdb``
.. warning::
If you are used to use ``mon reset halt``, be aware that the card10 prototypes
do not connect the reset line to the debugger. OpenOCD is configured to only do
......
......@@ -38,6 +38,7 @@ Last but not least, if you want to start hacking the lower-level firmware, the
pycardium/simple_menu
pycardium/utime
pycardium/vibra
pycardium/ws2812
.. toctree::
:maxdepth: 1
......
......@@ -2,6 +2,7 @@
``bme680`` - Environmental Sensor
=================================
Allows access to environmental data of card10's surroundings.
**Example**:
......@@ -9,17 +10,28 @@
import bme680, utime
bme680.init()
with bme680.Bme680() as environment:
while True:
d = environment.get_data()
while True:
temperature, humidity, pressure, resistance = bme680.get_data()
print("Temperature: {:10.2f} °C".format(d.temperature))
print("Humidity: {:10.2f} % r.h.".format(d.humidity))
print("Pressure: {:10.2f} hPa".format(d.pressure))
print("Gas Resistance: {:10.2f} Ω".format(d.resistance))
print("Temperature: {:10.2f} °C".format(temperature))
print("Humidity: {:10.2f} % r.h.".format(humidity))
print("Pressure: {:10.2f} hPa".format(pressure))
print("Gas Resistance: {:10.2f} Ω".format(resistance))
utime.sleep(1)
utime.sleep(1)
Sensor Class
------------
.. autoclass:: bme680.Bme680
:members:
Deprecated Interface
--------------------
The following functions should no longer be used directly. The only exist for
compatibility as they were the old BME680 interface in previous firmware
versions.
.. py:function:: init()
......@@ -29,6 +41,8 @@
:py:func:`bme680.init`.
.. versionadded:: 1.4
.. deprecated:: 1.10
Use the :py:class:`bme680.Bme680` class instead.
.. py:function:: get_data()
......@@ -38,9 +52,13 @@
``pressure`` (hPa) and ``gas resistance`` (Ohm).
.. versionadded:: 1.4
.. deprecated:: 1.10
Use the :py:class:`bme680.Bme680` class instead.
.. py:function:: deinit()
Deinitialize the sensor.
.. versionadded:: 1.4
.. deprecated:: 1.10
Use the :py:class:`bme680.Bme680` class instead.
......@@ -201,6 +201,8 @@ Struct module.
UUID(bytes='\x12\x34\x56\x78' * 4)
UUID(int=0x12345678123456781234567812345678)
.. versionadded:: 1.10
.. py:attribute:: bytes
UUID as ``bytes()`` object
......@@ -221,7 +223,4 @@ Struct module.
Generate a new UUID version 4 (random UUID).
.. todo::
This function is not yet usable because we don't have
:py:func:`os.urandom` yet.
.. versionadded:: 1.10
.. py:module:: ws2812
``ws2812`` - Neopixel LEDs
==========================
The ``ws2812`` module controls LEDs of the WS2812 type. Just as the ``leds`` module, it exposes a function :py:func:`ws2812.set_all`, which works a similar fashion.
.. versionadded:: 1.10
.. py:function:: set_all(pin, colors)
Set multiple of the LEDs to RGB values.
Filling starts at the LED connected to the specified gpio pin.
:param int pin: ID of the pin to use for sending the data.
:param colors: List of RGB triplets.
**Example**
.. code-block:: python
import color, utime, ws2812, gpio
i = 0
while True:
col1 = color.from_hsv(i % 360, 1.0, 0.1)
col2 = color.from_hsv((i + 20) % 360, 1.0, 0.1)
col3 = color.from_hsv((i + 40) % 360, 1.0, 0.1)
ws2812.set_all(gpio.WRISTBAND_2, [col1, col2, col3])
i += 1
utime.sleep_ms(10)
.. versionadded:: 1.10
......@@ -114,7 +114,7 @@ static const uint8_t UUID_attChar_vibra[] = {
/* BLE UUID for card10 char rockets */
static const uint8_t UUID_char_rockets[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_ROCKETS_VAL_HDL),
CARD10_UUID_SUFFIX, 0x10, CARD10_UUID_PREFIX
};
......@@ -123,9 +123,12 @@ static const uint8_t UUID_attChar_rockets[] = {
CARD10_UUID_SUFFIX, 0x10, CARD10_UUID_PREFIX
};
static uint8_t rocketsValue[] = { 0, 0, 0 };
static uint16_t rocketsLen = sizeof(rocketsValue);
/* BLE UUID for card10 led background bottom left */
static const uint8_t UUID_char_led_bg_bottom_left[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL),
CARD10_UUID_SUFFIX, 0x11, CARD10_UUID_PREFIX
};
......@@ -134,9 +137,13 @@ static const uint8_t UUID_attChar_led_bg_bottom_left[] = {
CARD10_UUID_SUFFIX, 0x11, CARD10_UUID_PREFIX
};
static uint8_t ledBGBottomLeftValue[] = { 0,0,0 };
// works vor everyone?
static uint16_t rgbLen = sizeof(ledBGBottomLeftValue);
/* BLE UUID for card10 led background bottom right */
static const uint8_t UUID_char_led_bg_bottom_right[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL),
CARD10_UUID_SUFFIX, 0x12, CARD10_UUID_PREFIX
};
......@@ -145,9 +152,11 @@ static const uint8_t UUID_attChar_led_bg_bottom_right[] = {
CARD10_UUID_SUFFIX, 0x12, CARD10_UUID_PREFIX
};
static uint8_t ledBGBottomRightValue[] = { 0,0,0 };
/* BLE UUID for card10 led background top right */
static const uint8_t UUID_char_led_bg_top_right[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_LED_BG_TOP_RIGHT_VAL_HDL),
CARD10_UUID_SUFFIX, 0x13, CARD10_UUID_PREFIX
};
......@@ -156,9 +165,11 @@ static const uint8_t UUID_attChar_led_bg_top_right[] = {
CARD10_UUID_SUFFIX, 0x13, CARD10_UUID_PREFIX
};
static uint8_t ledBGTopRightValue[] = { 0,0,0 };
/* BLE UUID for card10 led background top left */
static const uint8_t UUID_char_led_bg_top_left[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_LED_BG_TOP_LEFT_VAL_HDL),
CARD10_UUID_SUFFIX, 0x14, CARD10_UUID_PREFIX
};
......@@ -167,6 +178,8 @@ static const uint8_t UUID_attChar_led_bg_top_left[] = {
CARD10_UUID_SUFFIX, 0x14, CARD10_UUID_PREFIX
};
static uint8_t ledBGTopLeftValue[] = { 0,0,0 };
/* BLE UUID for card10 dim leds on bottom */
static const uint8_t UUID_char_leds_bottom_dim[] = {
ATT_PROP_WRITE,
......@@ -227,7 +240,7 @@ static uint16_t personalStateLen = sizeof(personalStateValue);
/* BLE UUID for card10 above leds */
static const uint8_t UUID_char_leds_above[] = {
ATT_PROP_WRITE_NO_RSP,
ATT_PROP_READ | ATT_PROP_WRITE_NO_RSP,
UINT16_TO_BYTES(CARD10_LEDS_ABOVE_VAL_HDL),
CARD10_UUID_SUFFIX, 0x20, CARD10_UUID_PREFIX
};
......@@ -235,6 +248,21 @@ static const uint8_t UUID_char_leds_above[] = {
static const uint8_t UUID_attChar_leds_above[] = {
CARD10_UUID_SUFFIX, 0x20, CARD10_UUID_PREFIX
};
static uint8_t aboveLEDsValue[] = {
0,0,0, // 0
0,0,0, // 1
0,0,0, // 2
0,0,0, // 3
0,0,0, // 4
0,0,0, // 5
0,0,0, // 6
0,0,0, // 7
0,0,0, // 8
0,0,0, // 9
0,0,0, // 10
};
static uint16_t aboveLEDsLen = sizeof(aboveLEDsValue);
// starting at 0xf0 with read only characteristics
/* BLE UUID for card10 char light sensor */
......@@ -313,11 +341,13 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_rockets,
.pValue = NULL,
.pValue = rocketsValue,
.pLen = &rocketsLen,
.maxLen = 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// BG LED Bottom left
......@@ -331,11 +361,13 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_led_bg_bottom_left,
.pValue = NULL,
.pValue = ledBGBottomLeftValue,
.pLen = &rgbLen,
.maxLen = 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// BG LED Bottom right
......@@ -349,15 +381,16 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_led_bg_bottom_right,
.pValue = NULL,
.pValue = ledBGBottomRightValue,
.pLen = &rgbLen,
.maxLen = 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// BG LED top right
{
.pUuid = attChUuid,
.pValue = (uint8_t *)UUID_char_led_bg_top_right,
......@@ -368,11 +401,13 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_led_bg_top_right,
.pValue = NULL,
.pValue = ledBGTopRightValue,
.pLen = &rgbLen,
.maxLen = 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// BG LED top left
......@@ -386,11 +421,13 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_led_bg_top_left,
.pValue = NULL,
.pValue = ledBGTopLeftValue,
.pLen = &rgbLen,
.maxLen = 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// Dim bottom module
......@@ -497,11 +534,13 @@ static const attsAttr_t card10SvcAttrList[] = {
},
{
.pUuid = UUID_attChar_leds_above,
.pValue = NULL,
.pValue = aboveLEDsValue,
.pLen = &aboveLEDsLen,
.maxLen = 11 * 3 * sizeof(uint8_t),
.settings = ATTS_SET_WRITE_CBACK,
.settings = ATTS_SET_WRITE_CBACK | ATTS_SET_READ_CBACK,
.permissions = ATTS_PERMIT_WRITE | ATTS_PERMIT_WRITE_ENC |
ATTS_PERMIT_WRITE_AUTH,
ATTS_PERMIT_WRITE_AUTH | ATTS_PERMIT_READ |
ATTS_PERMIT_READ_ENC | ATTS_PERMIT_READ_AUTH,
},
// Light sensor
......@@ -544,6 +583,38 @@ static uint8_t setTime(uint8_t *pValue)
return ATT_SUCCESS;
}
/*
* Set a rgb led
*/
static uint8_t setRGBLed(uint8_t led, uint8_t *pValue)
{
epic_leds_set(led, pValue[0], pValue[1], pValue[2]);
APP_TRACE_INFO4(
"ble-card10: set rgb led %d: #%02x%02x%02x\n",
led,
pValue[0],
pValue[1],
pValue[2]
);
return ATT_SUCCESS;
}
/*
* Get value of a rgb led
*/
static uint8_t getRGBLed(uint8_t led, attsAttr_t *pAttr)
{
epic_leds_get_rgb(led, pAttr->pValue);
APP_TRACE_INFO4(
"ble-card10: set rgb led %d: #%02x%02x%02x\n",
led,
pAttr->pValue[0],
pAttr->pValue[1],
pAttr->pValue[2]
);
return ATT_SUCCESS;
}
/*
* BLE card10 write callback.
*/
......@@ -584,41 +655,13 @@ static uint8_t writeCard10CB(
return ATT_SUCCESS;
// bg leds
case CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL:
epic_leds_set(11, pValue[0], pValue[1], pValue[2]);
APP_TRACE_INFO3(
"ble-card10: set bg bottom left: #%02x%02x%02x\n",
pValue[0],
pValue[1],
pValue[2]
);
return ATT_SUCCESS;
return setRGBLed(11, pValue);
case CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL:
epic_leds_set(12, pValue[0], pValue[1], pValue[2]);
APP_TRACE_INFO3(
"ble-card10: set bg bottom right: #%02x%02x%02x\n",
pValue[0],
pValue[1],
pValue[2]
);
return ATT_SUCCESS;
return setRGBLed(12, pValue);
case CARD10_LED_BG_TOP_RIGHT_VAL_HDL:
epic_leds_set(13, pValue[0], pValue[1], pValue[2]);
APP_TRACE_INFO3(
"ble-card10: set bg top right: #%02x%02x%02x\n",
pValue[0],
pValue[1],
pValue[2]
);
return ATT_SUCCESS;
return setRGBLed(13, pValue);
case CARD10_LED_BG_TOP_LEFT_VAL_HDL:
epic_leds_set(14, pValue[0], pValue[1], pValue[2]);
APP_TRACE_INFO3(
"ble-card10: set bg top left: #%02x%02x%02x\n",
pValue[0],
pValue[1],
pValue[2]
);
return ATT_SUCCESS;
return setRGBLed(14, pValue);
// dim
case CARD10_LEDS_BOTTOM_DIM_VAL_HDL:
ui8 = pValue[0];
......@@ -769,8 +812,10 @@ static uint8_t readCard10CB(
) {
uint16_t ui16 = 0;
uint64_t ui64 = 0;
uint8_t rgb[] = { 0, 0, 0 };
switch (handle) {
// time
case CARD10_TIME_VAL_HDL:
ui64 = epic_rtc_get_milliseconds();
uint64_t time;
......@@ -780,11 +825,49 @@ static uint8_t readCard10CB(
APP_TRACE_INFO0("ble-card10: read time\n");
return ATT_SUCCESS;
case CARD10_ROCKETS_VAL_HDL:
pAttr->pValue[0] = epic_leds_get_rocket(0);
pAttr->pValue[1] = epic_leds_get_rocket(1);
pAttr->pValue[2] = epic_leds_get_rocket(2);
APP_TRACE_INFO3(
"ble-card10: get rockets 0:%d, 1:%d, 2:%d\n",
pAttr->pValue[0],
pAttr->pValue[1],
pAttr->pValue[2]
);
return ATT_SUCCESS;
// background leds
case CARD10_LED_BG_BOTTOM_LEFT_VAL_HDL:
return getRGBLed(11, pAttr);
case CARD10_LED_BG_BOTTOM_RIGHT_VAL_HDL:
return getRGBLed(12, pAttr);
case CARD10_LED_BG_TOP_RIGHT_VAL_HDL:
return getRGBLed(13, pAttr);
case CARD10_LED_BG_TOP_LEFT_VAL_HDL:
return getRGBLed(14, pAttr);
// personal state
case CARD10_PERSONAL_STATE_VAL_HDL:
ui16 = epic_personal_state_get();
*pAttr->pValue = ui16;
APP_TRACE_INFO1("ble-card10: read personal state: %d\n", ui16);
return ATT_SUCCESS;
// leds above
case CARD10_LEDS_ABOVE_VAL_HDL:
for (ui16 = 0; ui16 < 11; ui16++) {
epic_leds_get_rgb(ui16, rgb);
pAttr->pValue[ui16 * 3] = rgb[0];
pAttr->pValue[ui16 * 3 + 1] = rgb[1];
pAttr->pValue[ui16 * 3 + 2] = rgb[2];
APP_TRACE_INFO4(
"ble-card10: get led %ld above to #%02x%02x%02x\n",
ui16,
pAttr->pValue[ui16 * 3],
pAttr->pValue[ui16 * 3 + 1],
pAttr->pValue[ui16 * 3 + 2]
);
}
return ATT_SUCCESS;
// light sensor
case CARD10_LIGHT_SENSOR_VAL_HDL:
epic_light_sensor_get(&ui16);
*pAttr->pValue = ui16;
......
......@@ -96,6 +96,8 @@ typedef _Bool bool;
#define API_LEDS_SET_ALL_HSV 0x6b
#define API_LEDS_SET_GAMMA_TABLE 0x6c
#define API_LEDS_CLEAR_ALL 0x6d
#define API_LEDS_GET_ROCKET 0x6e
#define API_LEDS_GET 0x6f
#define API_VIBRA_SET 0x70
#define API_VIBRA_VIBRATE 0x71
......@@ -137,6 +139,8 @@ typedef _Bool bool;
#define API_USB_STORAGE 0x111
#define API_USB_CDCACM 0x112
#define API_WS2812_WRITE 0x0120
/* clang-format on */
typedef uint32_t api_int_id_t;
......@@ -148,6 +152,13 @@ typedef uint32_t api_int_id_t;
* the other direction. These interrupts can be enabled/disabled
* (masked/unmasked) using :c:func:`epic_interrupt_enable` and
* :c:func:`epic_interrupt_disable`.
*
* .. 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.
*/
/**
......@@ -175,17 +186,16 @@ API(API_INTERRUPT_DISABLE, int epic_interrupt_disable(api_int_id_t int_id));
#define EPIC_INT_CTRL_C 1
/** UART Receive interrupt. See :c:func:`epic_isr_uart_rx`. */
#define EPIC_INT_UART_RX 2
/** RTC Alarm interrupt. See :c:func:`epic_isr_rtc_alarm` */
/** RTC Alarm interrupt. See :c:func:`epic_isr_rtc_alarm`. */
#define EPIC_INT_RTC_ALARM 3
/** BHI */
/** BHI180 Accelerometer. See :c:func:`epic_isr_bhi160_accelerometer`. */
#define EPIC_INT_BHI160_ACCELEROMETER 4
API_ISR(EPIC_INT_BHI160_ACCELEROMETER, epic_isr_bhi160_accelerometer);
/** BHI180 Orientation Sensor. See :c:func:`epic_isr_bhi160_orientation`. */
#define EPIC_INT_BHI160_ORIENTATION 5
API_ISR(EPIC_INT_BHI160_ORIENTATION, epic_isr_bhi160_orientation);
/** BHI180 Gyroscope. See :c:func:`epic_isr_bhi160_gyroscope`. */
#define EPIC_INT_BHI160_GYROSCOPE 6
API_ISR(EPIC_INT_BHI160_GYROSCOPE, epic_isr_bhi160_gyroscope);
/** MAX30001 ECG. See :c:func:`epic_isr_max30001_ecg`. */
#define EPIC_INT_MAX30001_ECG 7
API_ISR(EPIC_INT_MAX30001_ECG, epic_isr_max30001_ecg);
/* Number of defined interrupts. */
#define EPIC_INT_NUM 8
......@@ -303,8 +313,7 @@ API(API_THERMISTOR_VOLTAGE, int epic_read_thermistor_voltage(float *result));
* :param length: Amount of bytes to print.
*/
API(API_UART_WRITE_STR, void epic_uart_write_str(
const char *str,
intptr_t length
const char *str, intptr_t length
));
/**
......@@ -330,7 +339,7 @@ API(API_UART_READ_CHAR, int epic_uart_read_char(void));
API(API_UART_READ_STR, int epic_uart_read_str(char *buf, size_t cnt));
/**
* **Interrupt Service Routine**
* **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
......@@ -360,7 +369,7 @@ API(API_UART_READ_STR, int epic_uart_read_str(char *buf, size_t cnt));
API_ISR(EPIC_INT_UART_RX, epic_isr_uart_rx);
/**
* **Interrupt Service Routine**
* **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
......@@ -488,7 +497,9 @@ enum gpio_mode {
* :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));
API(API_GPIO_SET_PIN_MODE, int epic_gpio_set_pin_mode(
uint8_t pin, uint8_t mode
));
/**
* Get the mode of a card10 GPIO pin.
......@@ -583,6 +594,21 @@ API(API_GPIO_READ_PIN, int epic_gpio_read_pin(uint8_t pin));
*/
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.
*
* .. versionadded:: 1.10
*/
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.
*
......@@ -595,7 +621,9 @@ API(API_LEDS_SET, void epic_leds_set(int led, uint8_t r, uint8_t g, uint8_t b));
* :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));
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.
......@@ -618,7 +646,9 @@ API(API_LEDS_SET_ALL, void epic_leds_set_all(uint8_t *pattern, uint8_t len));
* 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));
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.
......@@ -631,7 +661,9 @@ API(API_LEDS_SET_ALL_HSV, void epic_leds_set_all_hsv(float *pattern, uint8_t len
* :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));
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.
......@@ -644,7 +676,9 @@ API(API_LEDS_PREP, void epic_leds_prep(int led, uint8_t r, uint8_t g, uint8_t b)
* :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));
API(API_LEDS_PREP_HSV, void epic_leds_prep_hsv(
int led, float h, float s, float v
));
/**
* Set global brightness for top RGB LEDs.
......@@ -708,6 +742,26 @@ API(API_LEDS_UPDATE, void epic_leds_update(void));
*/
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.
*
* .. versionadded:: 1.10
*/
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.
*
......@@ -727,8 +781,7 @@ API(API_LEDS_SET_FLASHLIGHT, void epic_set_flashlight(bool power));
* :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
uint8_t rgb_channel, uint8_t *gamma_table
));
/**
......@@ -738,7 +791,9 @@ API(API_LEDS_SET_GAMMA_TABLE, void epic_leds_set_gamma_table(
* :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));
API(API_LEDS_CLEAR_ALL, void epic_leds_clear_all(
uint8_t r, uint8_t g, uint8_t b
));
/**
* BME680
......@@ -805,8 +860,9 @@ API(API_BME680_DEINIT, int epic_bme680_deinit());
* - ``-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));
API(API_BME680_GET_DATA, int epic_bme680_read_sensors(
struct bme680_sensor_data *data
));
/**
* Personal State
......@@ -849,8 +905,9 @@ enum 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));
API(API_PERSONAL_STATE_SET, int epic_personal_state_set(
uint8_t state, bool persistent
));
/**
* Get the users personal state.
......@@ -1107,6 +1164,36 @@ API(API_BHI160_DISABLE, int epic_bhi160_disable_sensor(
*/
API(API_BHI160_DISABLE_ALL, void epic_bhi160_disable_all_sensors());
/**
* BHI160 Interrupt Handlers
* -------------------------
*/
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_ACCELEROMETER`
*
* :c:func:`epic_isr_bhi160_accelerometer` is called whenever the BHI160
* accelerometer has new data available.
*/
API_ISR(EPIC_INT_BHI160_ACCELEROMETER, epic_isr_bhi160_accelerometer);
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_ORIENTATION`
*
* :c:func:`epic_isr_bhi160_orientation` is called whenever the BHI160
* orientation sensor has new data available.
*/
API_ISR(EPIC_INT_BHI160_ORIENTATION, epic_isr_bhi160_orientation);
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_BHI160_GYROSCOPE`
*
* :c:func:`epic_isr_bhi160_orientation` is called whenever the BHI160
* gyroscrope has new data available.
*/
API_ISR(EPIC_INT_BHI160_GYROSCOPE, epic_isr_bhi160_gyroscope);
/**
* Vibration Motor
* ===============
......@@ -1245,7 +1332,7 @@ API(API_DISP_PRINT,
* Font Selection
*/
enum disp_font_name {
DISP_FONT8 = 0,
DISP_FONT8 = 0,
DISP_FONT12 = 1,
DISP_FONT16 = 2,
DISP_FONT20 = 3,
......@@ -1265,15 +1352,14 @@ enum disp_font_name {
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_PRINT_ADV,
int epic_disp_print_adv(
uint8_t font,
uint16_t posx,
uint16_t posy,
const char *pString,
uint16_t fg,
uint16_t bg)
);
API(API_DISP_PRINT_ADV, int epic_disp_print_adv(
uint8_t font,
uint16_t posx,
uint16_t posy,
const char *pString,
uint16_t fg,
uint16_t bg
));
/**
* Fills the whole screen with one color
......@@ -1295,12 +1381,9 @@ API(API_DISP_CLEAR, int epic_disp_clear(uint16_t color));
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_PIXEL,
int epic_disp_pixel(
uint16_t x,
uint16_t y,
uint16_t color)
);
API(API_DISP_PIXEL, int epic_disp_pixel(
uint16_t x, uint16_t y, uint16_t color
));
/**
* Draws a line on the display
......@@ -1316,16 +1399,15 @@ API(API_DISP_PIXEL,
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_LINE,
int epic_disp_line(
uint16_t xstart,
uint16_t ystart,
uint16_t xend,
uint16_t yend,
uint16_t color,
enum disp_linestyle linestyle,
uint16_t pixelsize)
);
API(API_DISP_LINE, int epic_disp_line(
uint16_t xstart,
uint16_t ystart,
uint16_t xend,
uint16_t yend,
uint16_t color,
enum disp_linestyle linestyle,
uint16_t pixelsize
));
/**
* Draws a rectangle on the display
......@@ -1341,16 +1423,15 @@ API(API_DISP_LINE,
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_RECT,
int epic_disp_rect(
uint16_t xstart,
uint16_t ystart,
uint16_t xend,
uint16_t yend,
uint16_t color,
enum disp_fillstyle fillstyle,
uint16_t pixelsize)
);
API(API_DISP_RECT, int epic_disp_rect(
uint16_t xstart,
uint16_t ystart,
uint16_t xend,
uint16_t yend,
uint16_t color,
enum disp_fillstyle fillstyle,
uint16_t pixelsize
));
/**
* Draws a circle on the display
......@@ -1365,15 +1446,14 @@ API(API_DISP_RECT,
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_CIRC,
int epic_disp_circ(
uint16_t x,
uint16_t y,
uint16_t rad,
uint16_t color,
enum disp_fillstyle fillstyle,
uint16_t pixelsize)
);
API(API_DISP_CIRC, int epic_disp_circ(
uint16_t x,
uint16_t y,
uint16_t rad,
uint16_t color,
enum disp_fillstyle fillstyle,
uint16_t pixelsize
));
/**
* Immediately send the contents of a framebuffer to the display. This overrides
......@@ -1384,7 +1464,9 @@ API(API_DISP_CIRC,
*
* - ``-EBUSY``: Display was already locked from another task.
*/
API(API_DISP_FRAMEBUFFER, int epic_disp_framebuffer(union disp_framebuffer *fb));
API(API_DISP_FRAMEBUFFER, int epic_disp_framebuffer(
union disp_framebuffer *fb
));
/**
......@@ -1485,10 +1567,9 @@ API(API_FILE_READ, int epic_file_read(int fd, void* buf, size_t nbytes));
* :return: ``< 0`` on error, ``nbytes`` on success. (Partial writes don't occur on success!)
*
*/
API(
API_FILE_WRITE,
int epic_file_write(int fd, const void* buf, size_t nbytes)
);
API(API_FILE_WRITE, int epic_file_write(
int fd, const void* buf, size_t nbytes
));
/** */
API(API_FILE_FLUSH, int epic_file_flush(int fd));
......@@ -1654,7 +1735,9 @@ API(API_RTC_GET_MILLISECONDS, uint64_t epic_rtc_get_milliseconds(void));
/**
* Sets the current RTC time in milliseconds
*/
API(API_RTC_SET_MILLISECONDS, void epic_rtc_set_milliseconds(uint64_t milliseconds));
API(API_RTC_SET_MILLISECONDS, void epic_rtc_set_milliseconds(
uint64_t milliseconds
));
/**
* Schedule the RTC alarm for the given timestamp.
......@@ -1668,7 +1751,7 @@ API(API_RTC_SET_MILLISECONDS, void epic_rtc_set_milliseconds(uint64_t millisecon
API(API_RTC_SCHEDULE_ALARM, int epic_rtc_schedule_alarm(uint32_t timestamp));
/**
* **Interrupt Service Routine**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_RTC_ALARM`
*
* ``epic_isr_rtc_alarm()`` is called when the RTC alarm triggers. The RTC alarm
* can be scheduled using :c:func:`epic_rtc_schedule_alarm`.
......@@ -1720,8 +1803,8 @@ struct max30001_sensor_config {
bool usb;
/**
* Set to true if the interal lead bias of the MAX30001 is to be used.
*/
* Set to true if the interal lead bias of the MAX30001 is to be used.
*/
bool bias;
/** Always zero. Reserved for future parameters. */
......@@ -1729,9 +1812,10 @@ struct max30001_sensor_config {
};
/**
* Enable a MAX30001 ecg sensor. Calling this funciton will instruct the
* MAX30001 to collect data for this sensor. You can then
* retrieve the samples using :c:func:`epic_stream_read`.
* Enable a MAX30001 ecg sensor.
*
* Calling this funciton will instruct the MAX30001 to collect data for this
* sensor. You can then retrieve the samples using :c:func:`epic_stream_read`.
*
* :param max30001_sensor_config* config: Configuration for this sensor.
* :returns: A sensor descriptor which can be used with
......@@ -1751,24 +1835,55 @@ API(API_MAX30001_ENABLE, int epic_max30001_enable_sensor(
*
* .. versionadded:: 1.6
*/
API(API_MAX30001_DISABLE, int epic_max30001_disable_sensor(
void
));
API(API_MAX30001_DISABLE, int epic_max30001_disable_sensor());
/**
* **Interrupt Service Routine** for :c:data:`EPIC_INT_MAX30001_ECG`
*
* This interrupt handler is called whenever the MAX30001 ECG has new data
* available.
*/
API_ISR(EPIC_INT_MAX30001_ECG, epic_isr_max30001_ecg);
/**
* USB
* ===
*/
/**
* De-initialize the currently configured USB device (if any)
*
*/
API(API_USB_SHUTDOWN, int epic_usb_shutdown(void));
/**
* Configure the USB peripheral to export the internal FLASH
* as a Mass Storage device
* as a Mass Storage device.
*/
API(API_USB_STORAGE, int epic_usb_storage(void));
/**
* Configure the USB peripheral to provide card10's stdin/stdout
* on a USB CDC-ACM device
* on a USB CDC-ACM device.
*/
API(API_USB_CDCACM, int epic_usb_cdcacm(void));
/**
* WS2812
* ======
*/
/**
* Takes a gpio pin specified with the gpio module and transmits
* the led data. The format `GG:RR:BB` is expected.
*
* :param uint8_t pin: The gpio pin to be used for data.
* :param uint8_t * pixels: The buffer, in which the pixel data is stored.
* :param uint32_t n_bytes: The size of the buffer.
*
* .. versionadded:: 1.10
*/
API(API_WS2812_WRITE, void epic_ws2812_write(uint8_t pin, uint8_t *pixels, uint32_t n_bytes));
#endif /* _EPICARDIUM_H */
......@@ -545,7 +545,8 @@ _load_pie(int fd, int size, Elf32_Ehdr *hdr, struct l0dable_info *info)
if (phdr.p_type == PT_LOAD) {
// Check alignment request.
if ((phdr.p_vaddr % phdr.p_align) != 0) {
if ((phdr.p_offset % phdr.p_align) !=
(phdr.p_vaddr % phdr.p_align)) {
LOG_ERR("l0der",
"_load_pie: phdr %d alignment too strict",
i);
......
......@@ -4,6 +4,10 @@
#include "modules/config.h"
#include "card10-version.h"
#include "gfx.h"
#include "display.h"
#include "version-splash.h"
#include "FreeRTOS.h"
#include "task.h"
#include "mxc_delay.h"
......@@ -27,10 +31,19 @@ int main(void)
* Version Splash
*/
const char *version_buf = CARD10_VERSION;
const int off = (160 - (int)strlen(version_buf) * 14) / 2;
mxc_delay(500000);
epic_disp_clear(0x0000);
epic_disp_print(10, 20, "Epicardium", 0xfe20, 0x0000);
epic_disp_print(off > 0 ? off : 0, 40, version_buf, 0xfe20, 0x0000);
if (strcmp(CARD10_VERSION, "v1.10") == 0) {
gfx_copy_region_raw(
&display_screen, 0, 0, 160, 80, 2, version_splash
);
} else {
const int off = (160 - (int)strlen(version_buf) * 14) / 2;
epic_disp_print(10, 20, "Epicardium", 0xfe20, 0x0000);
epic_disp_print(
off > 0 ? off : 0, 40, version_buf, 0xfe20, 0x0000
);
}
epic_disp_update();
mxc_delay(2000000);
......
......@@ -26,7 +26,7 @@ uint8_t epic_buttons_read(uint8_t mask)
* Not using PB_Get() here as that performs one I2C transcation
* per button.
*/
uint8_t pin_status = ~portexpander_get();
uint8_t pin_status = ~portexpander_in_get(0xFF);
hwlock_release(HWLOCK_I2C);
......
......@@ -31,17 +31,17 @@ struct config_option {
static struct config_option s_options[_EpicOptionCount] = {
/* clang-format off */
#define INIT_Boolean(v) { .boolean = (v) }
#define INIT_Int(v) { .integer = (v) }
#define INIT_Float(v) { .floating_point = (v) }
#define INIT_String(v) { .string = (v) }
#define INIT_(tp, v) INIT_ ## tp (v)
#define INIT(tp, v) INIT_ (tp, v)
#define INIT_Boolean(v) { .boolean = (v) }
#define INIT_Int(v) { .integer = (v) }
#define INIT_Float(v) { .floating_point = (v) }
#define INIT_String(v) { .string = (v) }
#define INIT_(tp, v) INIT_ ## tp (v)
#define INIT(tp, v) INIT_ (tp, v)
#define CARD10_SETTING(identifier, spelling, tp, default_value) \
#define CARD10_SETTING(identifier, spelling, tp, default_value) \
[Option ## identifier] = { .name = (spelling), \
.type = OptionType_ ## tp, \
.value = INIT(tp, (default_value)) },
.type = OptionType_ ## tp, \
.value = INIT(tp, (default_value)) },
#include "modules/config.def"
/* clang-format on */
......@@ -175,7 +175,7 @@ static void configure(const char *key, const char *value, int lineNumber)
static void doline(char *line, char *eol, int lineNumber)
{
//skip leading whitespace
while (*line && isspace(*line))
while (*line && isspace((int)*line))
++line;
char *key = line;
......@@ -199,7 +199,7 @@ static void doline(char *line, char *eol, int lineNumber)
char *e_key = eq - 1;
//skip trailing whitespace in key
while (e_key > key && isspace(*e_key))
while (e_key > key && isspace((int)*e_key))
--e_key;
e_key[1] = '\0';
if (*key == '\0') {
......@@ -209,12 +209,12 @@ static void doline(char *line, char *eol, int lineNumber)
char *value = eq + 1;
//skip leading whitespace
while (*value && isspace(*value))
while (*value && isspace((int)*value))
++value;
char *e_val = eol - 1;
//skip trailing whitespace
while (e_val > value && isspace(*e_val))
while (e_val > value && isspace((int)*e_val))
--e_val;
if (*value == '\0') {
LOG_WARN(
......@@ -270,17 +270,17 @@ void load_config(void)
);
return;
}
char buf[CONFIG_MAX_LINE_LENGTH];
char buf[CONFIG_MAX_LINE_LENGTH + 1];
int lineNumber = 0;
int nread;
do {
//zero-terminate in case file is empty
buf[0] = '\0';
nread = epic_file_read(fd, buf, sizeof(buf));
if (nread < sizeof(buf)) {
nread = epic_file_read(fd, buf, CONFIG_MAX_LINE_LENGTH);
if (nread < CONFIG_MAX_LINE_LENGTH) {
//add fake EOL to ensure termination
buf[nread] = '\n';
buf[nread++] = '\n';
}
//zero-terminate buffer
buf[nread] = '\0';
char *line = buf;
char *eol = NULL;
int last_eol = 0;
......@@ -344,4 +344,5 @@ void load_config(void)
}
}
} while (nread == sizeof(buf));
epic_file_close(fd);
}
......@@ -11,7 +11,7 @@
* Despite what the schematic (currently, 2019-08-18) says these are the correct
* pins for wristband GPIO 1-4 (not 0-3 as the schematic states)
*/
static gpio_cfg_t gpio_configs[] = {
gpio_cfg_t gpio_configs[] = {
[EPIC_GPIO_WRISTBAND_1] = { PORT_0,
PIN_21,
GPIO_FUNC_OUT,
......