Commit 2fb78caa authored by trilader's avatar trilader
Browse files

feat(epicardium): Add (wristband) GPIO module

parent 132874f7
......@@ -90,6 +90,11 @@ typedef _Bool bool;
#define API_LIGHT_SENSOR_STOP 0x82
#define API_BUTTONS_READ 0x90
#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
/* clang-format on */
typedef uint32_t api_int_id_t;
......@@ -338,6 +343,132 @@ enum epic_button {
*/
API(API_BUTTONS_READ, uint8_t epic_buttons_read(uint8_t mask));
/**
* Wristband GPIO
* ==============
*/
/** GPIO pins IDs */
enum gpio_pin {
/** ``1``, Wristband connector 1 */
GPIO_WRISTBAND_1 = 1,
/** ``2``, Wristband connector 2 */
GPIO_WRISTBAND_2 = 2,
/** ``3``, Wristband connector 3 */
GPIO_WRISTBAND_3 = 3,
/** ``4``, Wristband connector 4 */
GPIO_WRISTBAND_4 = 4,
};
/** GPIO pin modes */
enum gpio_mode {
/** Configure the pin as input */
GPIO_MODE_IN = (1<<0),
/** Configure the pin as output */
GPIO_MODE_OUT = (1<<1),
/** Enable the internal pull-up resistor */
GPIO_PULL_UP = (1<<6),
/** Enable the internal pull-down resistor */
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));
/**
* 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, uint32_t epic_gpio_read_pin(uint8_t pin));
/**
* LEDs
* ====
......
#include "epicardium.h"
#include "gpio.h"
#include "max32665.h"
#include "mxc_errors.h"
/*
* 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_WRISTBAND_1] = { PORT_0, PIN_21, GPIO_FUNC_OUT, GPIO_PAD_NONE },
[GPIO_WRISTBAND_2] = { PORT_0, PIN_22, GPIO_FUNC_OUT, GPIO_PAD_NONE },
[GPIO_WRISTBAND_3] = { PORT_0, PIN_29, GPIO_FUNC_OUT, GPIO_PAD_NONE },
[GPIO_WRISTBAND_4] = { PORT_0, PIN_20, GPIO_FUNC_OUT, GPIO_PAD_NONE },
};
int epic_gpio_set_pin_mode(uint8_t pin, uint8_t mode)
{
if (pin < GPIO_WRISTBAND_1 || pin > GPIO_WRISTBAND_4)
return -EINVAL;
gpio_cfg_t *cfg = &gpio_configs[pin];
bool is_input = (mode & GPIO_MODE_IN) == GPIO_MODE_IN;
bool is_output = (mode & GPIO_MODE_OUT) == GPIO_MODE_OUT;
// Pins can't be input and output at the same time.
if (is_input && is_output)
return -EINVAL;
uint32_t func_value = 0;
if (is_input)
func_value |= GPIO_FUNC_IN;
if (is_output)
func_value |= GPIO_FUNC_OUT;
uint32_t pad_value = 0;
if (mode & GPIO_PULL_UP)
pad_value |= GPIO_PAD_PULL_UP;
if (mode & GPIO_PULL_DOWN)
pad_value |= GPIO_PAD_PULL_DOWN;
cfg->func = func_value;
cfg->pad = pad_value;
if (GPIO_Config(cfg) != E_NO_ERROR)
return -EINVAL;
return 0;
}
int epic_gpio_get_pin_mode(uint8_t pin)
{
if (pin < GPIO_WRISTBAND_1 || pin > GPIO_WRISTBAND_4)
return -EINVAL;
gpio_cfg_t *cfg = &gpio_configs[pin];
int res = 0;
if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN)
res |= GPIO_MODE_IN;
if ((cfg->func & GPIO_FUNC_OUT) == GPIO_FUNC_OUT)
res |= GPIO_MODE_OUT;
if ((cfg->pad & GPIO_PAD_PULL_UP) == GPIO_PAD_PULL_UP)
res |= GPIO_PULL_UP;
if ((cfg->pad & GPIO_PAD_PULL_DOWN) == GPIO_PAD_PULL_DOWN)
res |= GPIO_PULL_DOWN;
return res;
}
int epic_gpio_write_pin(uint8_t pin, bool on)
{
if (pin < GPIO_WRISTBAND_1 || pin > GPIO_WRISTBAND_4)
return -EINVAL;
gpio_cfg_t *cfg = &gpio_configs[pin];
if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN)
return -EINVAL;
if (on)
GPIO_OutSet(cfg);
else
GPIO_OutClr(cfg);
return 0;
}
uint32_t epic_gpio_read_pin(uint8_t pin)
{
if (pin < GPIO_WRISTBAND_1 || pin > GPIO_WRISTBAND_4)
return -EINVAL;
gpio_cfg_t *cfg = &gpio_configs[pin];
if ((cfg->func & GPIO_FUNC_OUT) == GPIO_FUNC_OUT) {
return GPIO_OutGet(cfg);
} else if ((cfg->func & GPIO_FUNC_IN) == GPIO_FUNC_IN) {
return GPIO_InGet(cfg);
} else {
return -EINVAL;
}
}
......@@ -3,6 +3,7 @@ module_sources = files(
'dispatcher.c',
'display.c',
'fileops.c',
'gpio.c',
'hardware.c',
'leds.c',
'lifecycle.c',
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment