Skip to content

Commit

Permalink
Allow using Pico-W WL_GPIO pins with gpio nifs
Browse files Browse the repository at this point in the history
Modifies the Pico gpio dirver to accept atoms for the special wl_gpio pins
present in the Pico-W.
- Adds support for `wl0` and `wl1` as output pins in `gpio:digital_write/2`.
- Adds support for `wl2` as an input pin in `gpio:digital_read/1`.

Signed-off-by: Winford <[email protected]>
  • Loading branch information
UncleGrumpy committed Oct 28, 2023
1 parent 8c3e7d1 commit 7c71c5c
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added cmake configuration option `AVM_CONFIG_REBOOT_ON_NOT_OK` for STM32
- New gpio driver for STM32 with nif and port support for read and write functions.
- Added support for interrupts to STM32 GPIO port driver.
- Added suppoprt for PicoW extra gpio pins (led) to the gpio driver.

## [0.6.0-alpha.1] - 2023-10-09

Expand Down
2 changes: 1 addition & 1 deletion libs/eavmlib/src/gpio.erl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

-type gpio() :: pid().
%% This is the pid returned by `gpio:start/0'.
-type pin() :: non_neg_integer() | pin_tuple().
-type pin() :: non_neg_integer() | pin_tuple() | atom().
%% The pin definition for ESP32 and PR2040 is a non-negative integer, on the STM32 platform it is a tuple.
-type pin_tuple() :: {gpio_bank(), 0..15}.
%% A pin parameter on STM32 is a tuple consisting of a GPIO bank and pin number.
Expand Down
56 changes: 47 additions & 9 deletions src/platforms/rp2040/src/lib/gpiodriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ static const AtomStringIntPair pin_level_table[] = {
SELECT_INT_DEFAULT(AtomVMRP2040GPIOInvalid)
};

#ifdef LIB_PICO_CYW43_ARCH
static const AtomStringIntPair wl_pin_table[] = {
{ ATOM_STR("\x3", "wl0"), 0 },
{ ATOM_STR("\x3", "wl1"), 1 },
{ ATOM_STR("\x3", "wl2"), 2 },
SELECT_INT_DEFAULT(-1)
};
#endif

static term nif_gpio_init(Context *ctx, int argc, term argv[])
{
UNUSED(ctx);
Expand Down Expand Up @@ -96,7 +105,7 @@ static term nif_gpio_set_pin_mode(Context *ctx, int argc, term argv[])
int gpio_num = term_to_int(argv[0]);
int mode = interop_atom_term_select_int(pin_mode_table, argv[1], ctx->global);
if (UNLIKELY(mode < 0)) {
return ERROR_ATOM;
RAISE_ERROR(BADARG_ATOM);
}
gpio_set_dir(gpio_num, mode);
return OK_ATOM;
Expand All @@ -117,23 +126,37 @@ static term nif_gpio_digital_write(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

VALIDATE_VALUE(argv[0], term_is_integer);
int gpio_num = term_to_int(argv[0]);
term gpio_pin = argv[0];
term level_term = argv[1];

int level;
if (term_is_integer(level_term)) {
level = term_to_int32(level_term);
if (UNLIKELY((level != 0) && (level != 1))) {
return ERROR_ATOM;
RAISE_ERROR(BADARG_ATOM);
}
} else {
level = interop_atom_term_select_int(pin_level_table, level_term, ctx->global);
if (UNLIKELY(level < 0)) {
return ERROR_ATOM;
RAISE_ERROR(BADARG_ATOM);
}
}

int gpio_num;
if (term_is_integer(gpio_pin)) {
gpio_num = gpio_pin;
gpio_put(gpio_num, level);
#ifdef LIB_PICO_CYW43_ARCH
} else if (term_is_atom(gpio_pin)) {
gpio_num = interop_atom_term_select_int(wl_pin_table, gpio_pin, ctx->global);
if (UNLIKELY((gpio_num == -1) || (gpio_num > 1))) {
RAISE_ERROR(BADARG_ATOM);
}
cyw43_arch_gpio_put(gpio_num, level);
#endif
} else {
RAISE_ERROR(BADARG_ATOM);
}
gpio_put(gpio_num, level);

return OK_ATOM;
}
Expand All @@ -142,9 +165,24 @@ static term nif_gpio_digital_read(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

VALIDATE_VALUE(argv[0], term_is_integer);
int gpio_num = term_to_int(argv[0]);
bool level = gpio_get(gpio_num);
term gpio_pin = argv[0];
int gpio_num;
bool level;

if (term_is_integer(gpio_pin)) {
gpio_num = gpio_pin;
level = gpio_get(gpio_num);
#ifdef LIB_PICO_CYW43_ARCH
} else if (term_is_atom(gpio_pin)) {
gpio_num = interop_atom_term_select_int(wl_pin_table, gpio_pin, ctx->global);
if (UNLIKELY((gpio_num != 2))) {
RAISE_ERROR(BADARG_ATOM);
}
level = cyw43_arch_gpio_get(gpio_num);
#endif
} else {
RAISE_ERROR(BADARG_ATOM);
}

return level ? globalcontext_make_atom(ctx->global, ATOM_STR("\x4", "high")) : globalcontext_make_atom(ctx->global, ATOM_STR("\x3", "low"));
}
Expand Down

0 comments on commit 7c71c5c

Please sign in to comment.