Skip to content

Commit

Permalink
GPIO status & setting pins (#69)
Browse files Browse the repository at this point in the history
* add gpio status & set pin

* add documentation

* added strapping

* add necesarry includes in core.cpp

* code review

* tiny fix

---------

Co-authored-by: Johannes-Thiel <jojo.thadfun@gmail.com>
Co-authored-by: Falko Schindler <falko@zauberzeug.com>
  • Loading branch information
3 people authored Oct 14, 2024
1 parent 2ad1815 commit c59898d
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 10 deletions.
23 changes: 14 additions & 9 deletions docs/module_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@ It is automatically created right after the boot sequence.
| `core.millis` | Time since booting the microcontroller (ms) | `int` |
| `core.heap` | Free heap memory (bytes) | `int` |

| Methods | Description | Arguments |
| ------------------------------- | ------------------------------------------------- | --------- |
| `core.restart()` | Restart the microcontroller | |
| `core.version()` | Show lizard version | |
| `core.info()` | Show lizard version, compile time and IDF version | |
| `core.print(...)` | Print arbitrary arguments to the command line | arbitrary |
| `core.output(format)` | Define the output format | `str` |
| `core.startup_checksum()` | Show 16-bit checksum of the startup script | |
| `core.ota(ssid, password, url)` | Starts OTA update on a URL with given WiFi | 3x `str` |
| Methods | Description | Arguments |
| -------------------------------- | -------------------------------------------------- | ------------ |
| `core.restart()` | Restart the microcontroller | |
| `core.version()` | Show lizard version | |
| `core.info()` | Show lizard version, compile time and IDF version | |
| `core.print(...)` | Print arbitrary arguments to the command line | arbitrary |
| `core.output(format)` | Define the output format | `str` |
| `core.startup_checksum()` | Show 16-bit checksum of the startup script | |
| `core.ota(ssid, password, url)` | Starts OTA update on a URL with given WiFi | 3x `str` |
| `core.get_pin_status(pin)` | Print the status of the chosen pin | `int` |
| `core.set_pin_level(pin, value)` | Turns the pin into an output and sets its level | `int`, `int` |
| `core.get_pin_strapping(pin)` | Print value of the pin from the strapping register | `int` |

The output `format` is a string with multiple space-separated elements of the pattern `<module>.<property>[:<precision>]` or `<variable>[:<precision>]`.
The `precision` is an optional integer specifying the number of decimal places for a floating point number.
Expand All @@ -45,6 +48,8 @@ It will reconnect to the WiFi and try to access URL + `/verify` to receive a mes
The test is considered successful if an HTTP request is received, even if the version does not match or is empty.
If the newly updated Lizard cannot connect to URL + `/verify`, the OTA update will be rolled back.

`core.get_pin_status(pin)` reads the pin's voltage, not the output state directly.

## Bluetooth

Lizard can receive messages via Bluetooth Low Energy, and also send messages in return to a connected device.
Expand Down
78 changes: 77 additions & 1 deletion main/modules/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
#include "esp_ota_ops.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/gpio_reg.h"
#include "hal/gpio_hal.h"
#include "soc/io_mux_reg.h"
#include "soc/soc.h"
#include <memory>
#include <stdexcept>
#include <stdlib.h>
Expand Down Expand Up @@ -87,6 +88,81 @@ void Core::call(const std::string method_name, const std::vector<ConstExpression
arguments[2]->evaluate_string(),
};
xTaskCreate(ota::ota_task, "ota_task", 8192, params, 5, nullptr);
} else if (method_name == "get_pin_status") {
Module::expect(arguments, 1, integer);
const int gpio_num = arguments[0]->evaluate_integer();
if (gpio_num < 0 || gpio_num >= GPIO_NUM_MAX) {
throw std::runtime_error("invalid pin");
}

bool pullup, pulldown, input_enabled, output_enabled, open_drain, sleep_sel_enabled;
uint32_t drive_strength, func_sel, signal_output;
static gpio_hal_context_t _gpio_hal = {.dev = GPIO_HAL_GET_HW(GPIO_PORT_0)};
gpio_hal_get_io_config(&_gpio_hal, gpio_num, &pullup, &pulldown, &input_enabled, &output_enabled,
&open_drain, &drive_strength, &func_sel, &signal_output, &sleep_sel_enabled);

const int gpio_level = gpio_get_level(static_cast<gpio_num_t>(gpio_num));

echo("GPIO_Status[%d]| Level: %d| InputEn: %d| OutputEn: %d| OpenDrain: %d| Pullup: %d| Pulldown: %d| "
"DriveStrength: %d| SleepSel: %d",
gpio_num, gpio_level, input_enabled, output_enabled, open_drain, pullup, pulldown,
drive_strength, sleep_sel_enabled);
} else if (method_name == "set_pin_level") {
Module::expect(arguments, 2, integer, integer);
const int gpio_num = arguments[0]->evaluate_integer();
if (gpio_num < 0 || gpio_num >= GPIO_NUM_MAX) {
throw std::runtime_error("invalid pin");
}
const int value = arguments[1]->evaluate_integer();
if (value < 0 || value > 1) {
throw std::runtime_error("invalid value");
}

gpio_config_t io_conf;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << gpio_num);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
io_conf.intr_type = GPIO_INTR_DISABLE;
gpio_config(&io_conf);

const esp_err_t err = gpio_set_level(static_cast<gpio_num_t>(gpio_num), value);
if (err != ESP_OK) {
throw std::runtime_error("failed to set pin");
}
echo("GPIO_set[%d] set to %d", gpio_num, value);
} else if (method_name == "get_pin_strapping") {
Module::expect(arguments, 1, integer);
const gpio_num_t gpio_num = static_cast<gpio_num_t>(arguments[0]->evaluate_integer());
if (gpio_num < 0 || gpio_num >= GPIO_NUM_MAX) {
throw std::runtime_error("invalid pin");
}
const uint32_t strapping_reg = REG_READ(GPIO_STRAP_REG);
// Register 4.13. GPIO_STRAP_REG (0x0038)
// https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
switch (gpio_num) {
case GPIO_NUM_0:
echo("Strapping GPIO0: %d", (strapping_reg & BIT(0)) ? 1 : 0);
break;
case GPIO_NUM_2:
echo("Strapping GPIO2: %d", (strapping_reg & BIT(1)) ? 1 : 0);
break;
case GPIO_NUM_4:
echo("Strapping GPIO4: %d", (strapping_reg & BIT(5)) ? 1 : 0);
break;
case GPIO_NUM_5:
echo("Strapping GPIO5: %d", (strapping_reg & BIT(4)) ? 1 : 0);
break;
case GPIO_NUM_12:
echo("Strapping GPIO12 (MTDI): %d", (strapping_reg & BIT(3)) ? 1 : 0);
break;
case GPIO_NUM_15:
echo("Strapping GPIO15 (MTDO): %d", (strapping_reg & BIT(2)) ? 1 : 0);
break;
default:
echo("Not a strapping pin");
break;
}
} else {
Module::call(method_name, arguments);
}
Expand Down

0 comments on commit c59898d

Please sign in to comment.