mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-18 17:35:05 +00:00
Pi4 expander improvements
This commit is contained in:
parent
24a38f7aaf
commit
dfb0db86c5
@ -7,6 +7,7 @@
|
|||||||
#include <Tactility/hal/Configuration.h>
|
#include <Tactility/hal/Configuration.h>
|
||||||
#include <Tactility/hal/i2c/I2c.h>
|
#include <Tactility/hal/i2c/I2c.h>
|
||||||
#include <drivers/pi4ioe5v6408.h>
|
#include <drivers/pi4ioe5v6408.h>
|
||||||
|
#include <tactility/drivers/gpio_controller.h>
|
||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
@ -19,10 +20,7 @@ static DeviceVector createDevices() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t initPower(::Device* io_expander0, ::Device* io_expander1) {
|
/*
|
||||||
constexpr TickType_t i2c_timeout = pdMS_TO_TICKS(10);
|
|
||||||
|
|
||||||
/*
|
|
||||||
PI4IOE5V6408-0 (0x43)
|
PI4IOE5V6408-0 (0x43)
|
||||||
- Bit 0: RF internal/external switch
|
- Bit 0: RF internal/external switch
|
||||||
- Bit 1: Speaker enable
|
- Bit 1: Speaker enable
|
||||||
@ -33,16 +31,15 @@ static error_t initPower(::Device* io_expander0, ::Device* io_expander1) {
|
|||||||
- Bit 6: Camera reset
|
- Bit 6: Camera reset
|
||||||
- Bit 7: Headphone detect
|
- Bit 7: Headphone detect
|
||||||
*/
|
*/
|
||||||
|
constexpr auto GPIO_EXP0_PIN_RF_INTERNAL_EXTERNAL = 0;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_SPEAKER_ENABLE = 1;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_EXTERNAL_5V_BUS_ENABLE = 2;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_LCD_RESET = 4;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_TOUCH_RESET = 5;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_CAMERA_RESET = 6;
|
||||||
|
constexpr auto GPIO_EXP0_PIN_HEADPHONE_DETECT = 7;
|
||||||
|
|
||||||
check(pi4ioe5v6408_set_direction(io_expander0, 0b01111111, i2c_timeout) == ERROR_NONE);
|
/*
|
||||||
check(pi4ioe5v6408_set_output_level(io_expander0, 0b01000110, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_output_high_impedance(io_expander0, 0b00000000, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_pull_select(io_expander0, 0b01111111, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_pull_enable(io_expander0, 0b01111111, i2c_timeout) == ERROR_NONE);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
check(pi4ioe5v6408_set_output_level(io_expander0, 0b01110110, i2c_timeout) == ERROR_NONE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
PI4IOE5V6408-1 (0x44)
|
PI4IOE5V6408-1 (0x44)
|
||||||
- Bit 0: C6 WLAN enable
|
- Bit 0: C6 WLAN enable
|
||||||
- Bit 1: /
|
- Bit 1: /
|
||||||
@ -52,17 +49,81 @@ static error_t initPower(::Device* io_expander0, ::Device* io_expander1) {
|
|||||||
- Bit 5: IP2326: nCHG_QC_EN
|
- Bit 5: IP2326: nCHG_QC_EN
|
||||||
- Bit 6: IP2326: CHG_STAT_LED
|
- Bit 6: IP2326: CHG_STAT_LED
|
||||||
- Bit 7: IP2326: CHG_EN
|
- Bit 7: IP2326: CHG_EN
|
||||||
*/
|
*/
|
||||||
|
constexpr auto GPIO_EXP1_PIN_C6_WLAN_ENABLE = 0;
|
||||||
|
constexpr auto GPIO_EXP1_PIN_USB_A_5V_ENABLE = 3;
|
||||||
|
constexpr auto GPIO_EXP1_PIN_DEVICE_POWER = 4;
|
||||||
|
constexpr auto GPIO_EXP1_PIN_IP2326_NCHG_QC_EN = 5;
|
||||||
|
constexpr auto GPIO_EXP1_PIN_IP2326_CHG_STAT_LED = 6;
|
||||||
|
constexpr auto GPIO_EXP1_PIN_IP2326_CHG_EN = 7;
|
||||||
|
|
||||||
check(pi4ioe5v6408_set_direction(io_expander1, 0b10111001, i2c_timeout) == ERROR_NONE);
|
static void initExpander0(::Device* io_expander0) {
|
||||||
check(pi4ioe5v6408_set_output_high_impedance(io_expander1, 0b00000110, i2c_timeout) == ERROR_NONE);
|
constexpr TickType_t i2c_timeout = pdMS_TO_TICKS(10);
|
||||||
check(pi4ioe5v6408_set_pull_select(io_expander1, 0b10111001, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_pull_enable(io_expander1, 0b11111001, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_input_default_level(io_expander1, 0b01000000, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_interrupt_mask(io_expander1, 0b10111111, i2c_timeout) == ERROR_NONE);
|
|
||||||
check(pi4ioe5v6408_set_output_level(io_expander1, 0b10001001, i2c_timeout) == ERROR_NONE);
|
|
||||||
|
|
||||||
return ERROR_NONE;
|
auto* rf_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_RF_INTERNAL_EXTERNAL, GPIO_OWNER_GPIO);
|
||||||
|
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
|
||||||
|
auto* external_5v_bus_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_EXTERNAL_5V_BUS_ENABLE, GPIO_OWNER_GPIO);
|
||||||
|
auto* lcd_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_LCD_RESET, GPIO_OWNER_GPIO);
|
||||||
|
auto* touch_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_TOUCH_RESET, GPIO_OWNER_GPIO);
|
||||||
|
auto* camera_reset_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_CAMERA_RESET, GPIO_OWNER_GPIO);
|
||||||
|
auto* headphone_detect_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_HEADPHONE_DETECT, GPIO_OWNER_GPIO);
|
||||||
|
|
||||||
|
gpio_descriptor_set_flags(rf_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(speaker_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(external_5v_bus_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(lcd_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(touch_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(camera_reset_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(headphone_detect_pin, GPIO_FLAG_DIRECTION_INPUT);
|
||||||
|
|
||||||
|
gpio_descriptor_set_level(rf_pin, false);
|
||||||
|
gpio_descriptor_set_level(speaker_enable_pin, false);
|
||||||
|
gpio_descriptor_set_level(external_5v_bus_enable_pin, true);
|
||||||
|
gpio_descriptor_set_level(lcd_reset_pin, false);
|
||||||
|
gpio_descriptor_set_level(touch_reset_pin, false);
|
||||||
|
gpio_descriptor_set_level(camera_reset_pin, true);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
// Enable touch and lcd, but not the camera
|
||||||
|
gpio_descriptor_set_level(lcd_reset_pin, true);
|
||||||
|
gpio_descriptor_set_level(touch_reset_pin, true);
|
||||||
|
|
||||||
|
gpio_descriptor_release(rf_pin);
|
||||||
|
gpio_descriptor_release(speaker_enable_pin);
|
||||||
|
gpio_descriptor_release(external_5v_bus_enable_pin);
|
||||||
|
gpio_descriptor_release(lcd_reset_pin);
|
||||||
|
gpio_descriptor_release(touch_reset_pin);
|
||||||
|
gpio_descriptor_release(camera_reset_pin);
|
||||||
|
gpio_descriptor_release(headphone_detect_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initExpander1(::Device* io_expander1) {
|
||||||
|
|
||||||
|
auto* c6_wlan_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_C6_WLAN_ENABLE, GPIO_OWNER_GPIO);
|
||||||
|
auto* usb_a_5v_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_USB_A_5V_ENABLE, GPIO_OWNER_GPIO);
|
||||||
|
auto* device_power_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_DEVICE_POWER, GPIO_OWNER_GPIO);
|
||||||
|
auto* ip2326_ncharge_qc_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_NCHG_QC_EN, GPIO_OWNER_GPIO);
|
||||||
|
auto* ip2326_charge_state_led_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_STAT_LED, GPIO_OWNER_GPIO);
|
||||||
|
auto* ip2326_charge_enable_pin = gpio_descriptor_acquire(io_expander1, GPIO_EXP1_PIN_IP2326_CHG_EN, GPIO_OWNER_GPIO);
|
||||||
|
|
||||||
|
gpio_descriptor_set_flags(c6_wlan_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(usb_a_5v_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(device_power_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(ip2326_ncharge_qc_enable_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(ip2326_charge_state_led_pin, GPIO_FLAG_DIRECTION_OUTPUT);
|
||||||
|
gpio_descriptor_set_flags(ip2326_charge_enable_pin, GPIO_FLAG_DIRECTION_INPUT | GPIO_FLAG_PULL_UP);
|
||||||
|
|
||||||
|
gpio_descriptor_set_level(c6_wlan_enable_pin, true);
|
||||||
|
gpio_descriptor_set_level(usb_a_5v_enable_pin, true);
|
||||||
|
gpio_descriptor_set_level(device_power_pin, false);
|
||||||
|
gpio_descriptor_set_level(ip2326_ncharge_qc_enable_pin, false);
|
||||||
|
gpio_descriptor_set_level(ip2326_charge_state_led_pin, false);
|
||||||
|
|
||||||
|
gpio_descriptor_release(c6_wlan_enable_pin);
|
||||||
|
gpio_descriptor_release(usb_a_5v_enable_pin);
|
||||||
|
gpio_descriptor_release(device_power_pin);
|
||||||
|
gpio_descriptor_release(ip2326_ncharge_qc_enable_pin);
|
||||||
|
gpio_descriptor_release(ip2326_charge_state_led_pin);
|
||||||
|
gpio_descriptor_release(ip2326_charge_enable_pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t initSound(::Device* i2c_controller, ::Device* io_expander0 = nullptr) {
|
static error_t initSound(::Device* i2c_controller, ::Device* io_expander0 = nullptr) {
|
||||||
@ -113,13 +174,11 @@ static error_t initSound(::Device* i2c_controller, ::Device* io_expander0 = null
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t output_level = 0;
|
auto* speaker_enable_pin = gpio_descriptor_acquire(io_expander0, GPIO_EXP0_PIN_SPEAKER_ENABLE, GPIO_OWNER_GPIO);
|
||||||
if (pi4ioe5v6408_get_output_level(io_expander0, &output_level, pdMS_TO_TICKS(100)) != ERROR_NONE) {
|
check(speaker_enable_pin, "Failed to acquire speaker enable pin");
|
||||||
LOG_E(TAG, "Failed to read power level: %s", error_to_string(error));
|
error = gpio_descriptor_set_level(speaker_enable_pin, true);
|
||||||
return ERROR_RESOURCE;
|
gpio_descriptor_release(speaker_enable_pin);
|
||||||
}
|
if (error != ERROR_NONE) {
|
||||||
|
|
||||||
if (pi4ioe5v6408_set_output_level(io_expander0, output_level | 0b00000010, pdMS_TO_TICKS(100)) != ERROR_NONE) {
|
|
||||||
LOG_E(TAG, "Failed to enable amplifier: %s", error_to_string(error));
|
LOG_E(TAG, "Failed to enable amplifier: %s", error_to_string(error));
|
||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
@ -132,10 +191,12 @@ static bool initBoot() {
|
|||||||
check(i2c0, "i2c0 not found");
|
check(i2c0, "i2c0 not found");
|
||||||
|
|
||||||
auto* io_expander0 = device_find_by_name("io_expander0");
|
auto* io_expander0 = device_find_by_name("io_expander0");
|
||||||
|
check(io_expander0, "io_expander0 not found");
|
||||||
auto* io_expander1 = device_find_by_name("io_expander1");
|
auto* io_expander1 = device_find_by_name("io_expander1");
|
||||||
check(i2c0, "i2c0 not found");
|
check(io_expander1, "io_expander1 not found");
|
||||||
|
|
||||||
initPower(io_expander0, io_expander1);
|
initExpander0(io_expander0);
|
||||||
|
initExpander1(io_expander1);
|
||||||
|
|
||||||
error_t error = initSound(i2c0, io_expander0);
|
error_t error = initSound(i2c0, io_expander0);
|
||||||
if (error != ERROR_NONE) {
|
if (error != ERROR_NONE) {
|
||||||
|
|||||||
@ -2,40 +2,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <tactility/error.h>
|
|
||||||
#include <tactility/freertos/freertos.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Device;
|
|
||||||
|
|
||||||
struct Pi4ioe5v6408Config {
|
struct Pi4ioe5v6408Config {
|
||||||
/** Address on bus */
|
/** Address on bus */
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
};
|
};
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_direction(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_output_level(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_output_level(struct Device* device, uint8_t* bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_output_high_impedance(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_input_default_level(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_pull_enable(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_pull_select(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_input_level(struct Device* device, uint8_t* bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_interrupt_mask(struct Device* device, uint8_t bits, TickType_t timeout);
|
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_interrupt_level(struct Device* device, uint8_t* bits, TickType_t timeout);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
extern Driver pi4ioe5v6408_driver;
|
extern Driver pi4ioe5v6408_driver;
|
||||||
extern const ModuleSymbol pi4ioe5v6408_module_symbols[];
|
|
||||||
|
|
||||||
static error_t start() {
|
static error_t start() {
|
||||||
/* We crash when construct fails, because if a single driver fails to construct,
|
/* We crash when construct fails, because if a single driver fails to construct,
|
||||||
@ -26,7 +25,7 @@ Module pi4ioe5v6408_module = {
|
|||||||
.name = "pi4ioe5v6408",
|
.name = "pi4ioe5v6408",
|
||||||
.start = start,
|
.start = start,
|
||||||
.stop = stop,
|
.stop = stop,
|
||||||
.symbols = pi4ioe5v6408_module_symbols,
|
.symbols = nullptr,
|
||||||
.internal = nullptr
|
.internal = nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include <pi4ioe5v6408_module.h>
|
#include <pi4ioe5v6408_module.h>
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/driver.h>
|
#include <tactility/driver.h>
|
||||||
|
#include <tactility/drivers/gpio_controller.h>
|
||||||
|
#include <tactility/drivers/gpio_descriptor.h>
|
||||||
#include <tactility/drivers/i2c_controller.h>
|
#include <tactility/drivers/i2c_controller.h>
|
||||||
#include <tactility/log.h>
|
#include <tactility/log.h>
|
||||||
|
|
||||||
@ -27,72 +29,181 @@ static error_t start(Device* device) {
|
|||||||
return ERROR_RESOURCE;
|
return ERROR_RESOURCE;
|
||||||
}
|
}
|
||||||
LOG_I(TAG, "Started PI4IOE5V6408 device %s", device->name);
|
LOG_I(TAG, "Started PI4IOE5V6408 device %s", device->name);
|
||||||
return ERROR_NONE;
|
|
||||||
|
return gpio_controller_init_descriptors(device, 8, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t stop(Device* device) {
|
static error_t stop(Device* device) {
|
||||||
|
check(gpio_controller_deinit_descriptors(device) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_direction(Device* device, uint8_t bits, TickType_t timeout) {
|
|
||||||
|
static error_t set_level(GpioDescriptor* descriptor, bool high) {
|
||||||
|
auto* device = descriptor->controller;
|
||||||
auto* parent = device_get_parent(device);
|
auto* parent = device_get_parent(device);
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_DIRECTION, bits, timeout);
|
auto address = GET_CONFIG(device)->address;
|
||||||
|
uint8_t bit = 1 << descriptor->pin;
|
||||||
|
|
||||||
|
if (high) {
|
||||||
|
return i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_OUTPUT_LEVEL, bit, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
return i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_OUTPUT_LEVEL, bit, portMAX_DELAY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_output_level(Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t get_level(GpioDescriptor* descriptor, bool* high) {
|
||||||
|
auto* device = descriptor->controller;
|
||||||
auto* parent = device_get_parent(device);
|
auto* parent = device_get_parent(device);
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_OUTPUT_LEVEL, bits, timeout);
|
auto address = GET_CONFIG(device)->address;
|
||||||
|
uint8_t bits;
|
||||||
|
|
||||||
|
error_t err = i2c_controller_register8_get(parent, address, PI4_REGISTER_INPUT_LEVEL, &bits, portMAX_DELAY);
|
||||||
|
if (err != ERROR_NONE) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*high = (bits & (1 << descriptor->pin)) != 0;
|
||||||
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_output_level(Device* device, uint8_t* bits, TickType_t timeout) {
|
static error_t set_flags(GpioDescriptor* descriptor, gpio_flags_t flags) {
|
||||||
|
auto* device = descriptor->controller;
|
||||||
auto* parent = device_get_parent(device);
|
auto* parent = device_get_parent(device);
|
||||||
return i2c_controller_register8_get(parent, GET_CONFIG(device)->address, PI4_REGISTER_OUTPUT_LEVEL, bits, timeout);
|
auto address = GET_CONFIG(device)->address;
|
||||||
|
uint8_t bit = 1 << descriptor->pin;
|
||||||
|
|
||||||
|
error_t err;
|
||||||
|
|
||||||
|
// Direction
|
||||||
|
if (flags & GPIO_FLAG_DIRECTION_OUTPUT) {
|
||||||
|
err = i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_DIRECTION, bit, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
err = i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_DIRECTION, bit, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ERROR_NONE) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// High Impedance
|
||||||
|
if (flags & GPIO_FLAG_HIGH_IMPEDANCE) {
|
||||||
|
err = i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_OUTPUT_HIGH_IMPEDANCE, bit, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
err = i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_OUTPUT_HIGH_IMPEDANCE, bit, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ERROR_NONE) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull-up/down
|
||||||
|
if (flags & (GPIO_FLAG_PULL_UP | GPIO_FLAG_PULL_DOWN)) {
|
||||||
|
// Set pull up or pull down
|
||||||
|
if (flags & GPIO_FLAG_PULL_UP) {
|
||||||
|
err = i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_PULL_SELECT, bit, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
err = i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_PULL_SELECT, bit, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != ERROR_NONE) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable pull-up/down
|
||||||
|
err = i2c_controller_register8_set_bits(parent, address, PI4_REGISTER_PULL_ENABLE, bit, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
// Disable pull-up/down
|
||||||
|
err = i2c_controller_register8_reset_bits(parent, address, PI4_REGISTER_PULL_ENABLE, bit, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_output_high_impedance(struct Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
||||||
|
auto* device = descriptor->controller;
|
||||||
auto* parent = device_get_parent(device);
|
auto* parent = device_get_parent(device);
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_OUTPUT_HIGH_IMPEDANCE, bits, timeout);
|
auto address = GET_CONFIG(device)->address;
|
||||||
|
uint8_t bit = 1 << descriptor->pin;
|
||||||
|
uint8_t val;
|
||||||
|
error_t err;
|
||||||
|
|
||||||
|
gpio_flags_t f = GPIO_FLAG_NONE;
|
||||||
|
|
||||||
|
// Direction
|
||||||
|
err = i2c_controller_register8_get(parent, address, PI4_REGISTER_DIRECTION, &val, portMAX_DELAY);
|
||||||
|
if (err != ERROR_NONE) return err;
|
||||||
|
if (val & bit) {
|
||||||
|
f |= GPIO_FLAG_DIRECTION_OUTPUT;
|
||||||
|
} else {
|
||||||
|
f |= GPIO_FLAG_DIRECTION_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pull-up/down
|
||||||
|
err = i2c_controller_register8_get(parent, address, PI4_REGISTER_PULL_ENABLE, &val, portMAX_DELAY);
|
||||||
|
if (err != ERROR_NONE) return err;
|
||||||
|
if (val & bit) {
|
||||||
|
err = i2c_controller_register8_get(parent, address, PI4_REGISTER_PULL_SELECT, &val, portMAX_DELAY);
|
||||||
|
if (err != ERROR_NONE) return err;
|
||||||
|
if (val & bit) {
|
||||||
|
f |= GPIO_FLAG_PULL_UP;
|
||||||
|
} else {
|
||||||
|
f |= GPIO_FLAG_PULL_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// High Impedance
|
||||||
|
err = i2c_controller_register8_get(parent, address, PI4_REGISTER_OUTPUT_HIGH_IMPEDANCE, &val, portMAX_DELAY);
|
||||||
|
if (err != ERROR_NONE) return err;
|
||||||
|
if (val & bit) {
|
||||||
|
f |= GPIO_FLAG_HIGH_IMPEDANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*flags = f;
|
||||||
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_input_default_level(struct Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t get_native_pin_number(GpioDescriptor* descriptor, void* pin_number) {
|
||||||
auto* parent = device_get_parent(device);
|
return ERROR_NOT_SUPPORTED;
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_INPUT_DEFAULT_LEVEL, bits, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_pull_enable(struct Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t add_callback(GpioDescriptor* descriptor, void (*callback)(void*), void* arg) {
|
||||||
auto* parent = device_get_parent(device);
|
return ERROR_NOT_SUPPORTED;
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_PULL_ENABLE, bits, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_pull_select(struct Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t remove_callback(GpioDescriptor* descriptor) {
|
||||||
auto* parent = device_get_parent(device);
|
return ERROR_NOT_SUPPORTED;
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_PULL_SELECT, bits, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_input_level(struct Device* device, uint8_t* bits, TickType_t timeout) {
|
static error_t enable_interrupt(GpioDescriptor* descriptor) {
|
||||||
auto* parent = device_get_parent(device);
|
return ERROR_NOT_SUPPORTED;
|
||||||
return i2c_controller_register8_get(parent, GET_CONFIG(device)->address, PI4_REGISTER_INPUT_LEVEL, bits, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_set_interrupt_mask(struct Device* device, uint8_t bits, TickType_t timeout) {
|
static error_t disable_interrupt(GpioDescriptor* descriptor) {
|
||||||
auto* parent = device_get_parent(device);
|
return ERROR_NOT_SUPPORTED;
|
||||||
return i2c_controller_register8_set(parent, GET_CONFIG(device)->address, PI4_REGISTER_INTERRUPT_MASK, bits, timeout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t pi4ioe5v6408_get_interrupt_level(struct Device* device, uint8_t* bits, TickType_t timeout) {
|
const static GpioControllerApi pi4_gpio_api = {
|
||||||
auto* parent = device_get_parent(device);
|
.set_level = set_level,
|
||||||
return i2c_controller_register8_get(parent, GET_CONFIG(device)->address, PI4_REGISTER_INTERRUPT_LEVEL, bits, timeout);
|
.get_level = get_level,
|
||||||
}
|
.set_flags = set_flags,
|
||||||
|
.get_flags = get_flags,
|
||||||
|
.get_native_pin_number = get_native_pin_number,
|
||||||
|
.add_callback = add_callback,
|
||||||
|
.remove_callback = remove_callback,
|
||||||
|
.enable_interrupt = enable_interrupt,
|
||||||
|
.disable_interrupt = disable_interrupt
|
||||||
|
};
|
||||||
|
|
||||||
Driver pi4ioe5v6408_driver = {
|
Driver pi4ioe5v6408_driver = {
|
||||||
.name = "pi4ioe5v6408",
|
.name = "pi4ioe5v6408",
|
||||||
.compatible = (const char*[]) { "diodes,pi4ioe5v6408", nullptr},
|
.compatible = (const char*[]) { "diodes,pi4ioe5v6408", nullptr},
|
||||||
.start_device = start,
|
.start_device = start,
|
||||||
.stop_device = stop,
|
.stop_device = stop,
|
||||||
.api = nullptr,
|
.api = static_cast<const void*>(&pi4_gpio_api),
|
||||||
.device_type = nullptr,
|
.device_type = &GPIO_CONTROLLER_TYPE,
|
||||||
.owner = &pi4ioe5v6408_module,
|
.owner = &pi4ioe5v6408_module,
|
||||||
.internal = nullptr
|
.internal = nullptr
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
#include <drivers/pi4ioe5v6408.h>
|
|
||||||
#include <tactility/module.h>
|
|
||||||
|
|
||||||
const struct ModuleSymbol pi4ioe5v6408_module_symbols[] = {
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_direction),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_output_level),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_output_high_impedance),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_input_default_level),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_pull_enable),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_pull_select),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_get_input_level),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_set_interrupt_mask),
|
|
||||||
DEFINE_MODULE_SYMBOL(pi4ioe5v6408_get_interrupt_level),
|
|
||||||
MODULE_SYMBOL_TERMINATOR
|
|
||||||
};
|
|
||||||
@ -17,7 +17,7 @@ struct Esp32GpioInternal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->config)
|
#define GET_CONFIG(device) ((struct Esp32GpioConfig*)device->config)
|
||||||
#define GET_INTERNAL(device) ((struct Esp32GpioInternal*)device->internal)
|
#define GET_INTERNAL_FROM_DESCRIPTOR(gpio_descriptor) ((struct Esp32GpioInternal*)gpio_descriptor->controller_context)
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
@ -102,18 +102,18 @@ static error_t get_native_pin_number(GpioDescriptor* descriptor, void* pin_numbe
|
|||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t add_callback(struct GpioDescriptor* descriptor, void (*callback)(void*), void* arg) {
|
static error_t add_callback(GpioDescriptor* descriptor, void (*callback)(void*), void* arg) {
|
||||||
auto esp_error = gpio_isr_handler_add(static_cast<gpio_num_t>(descriptor->pin), callback, arg);
|
auto esp_error = gpio_isr_handler_add(static_cast<gpio_num_t>(descriptor->pin), callback, arg);
|
||||||
return esp_err_to_error(esp_error);
|
return esp_err_to_error(esp_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t remove_callback(struct GpioDescriptor* descriptor) {
|
static error_t remove_callback(GpioDescriptor* descriptor) {
|
||||||
auto esp_error = gpio_isr_handler_remove(static_cast<gpio_num_t>(descriptor->pin));
|
auto esp_error = gpio_isr_handler_remove(static_cast<gpio_num_t>(descriptor->pin));
|
||||||
return esp_err_to_error(esp_error);
|
return esp_err_to_error(esp_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t enable_interrupt(struct GpioDescriptor* descriptor) {
|
static error_t enable_interrupt(GpioDescriptor* descriptor) {
|
||||||
auto* internal = GET_INTERNAL(descriptor->controller);
|
auto* internal = GET_INTERNAL_FROM_DESCRIPTOR(descriptor);
|
||||||
if (internal->isr_service_ref_count == 0) {
|
if (internal->isr_service_ref_count == 0) {
|
||||||
auto esp_error = gpio_install_isr_service(0);
|
auto esp_error = gpio_install_isr_service(0);
|
||||||
if (esp_error != ESP_OK && esp_error != ESP_ERR_INVALID_STATE) {
|
if (esp_error != ESP_OK && esp_error != ESP_ERR_INVALID_STATE) {
|
||||||
@ -127,8 +127,8 @@ static error_t enable_interrupt(struct GpioDescriptor* descriptor) {
|
|||||||
return esp_err_to_error(esp_error);
|
return esp_err_to_error(esp_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t disable_interrupt(struct GpioDescriptor* descriptor) {
|
static error_t disable_interrupt(GpioDescriptor* descriptor) {
|
||||||
auto* internal = GET_INTERNAL(descriptor->controller);
|
auto* internal = GET_INTERNAL_FROM_DESCRIPTOR(descriptor);
|
||||||
auto esp_error = gpio_intr_disable(static_cast<gpio_num_t>(descriptor->pin));
|
auto esp_error = gpio_intr_disable(static_cast<gpio_num_t>(descriptor->pin));
|
||||||
if (esp_error == ESP_OK && internal->isr_service_ref_count > 0) {
|
if (esp_error == ESP_OK && internal->isr_service_ref_count > 0) {
|
||||||
internal->isr_service_ref_count--;
|
internal->isr_service_ref_count--;
|
||||||
@ -142,18 +142,18 @@ static error_t disable_interrupt(struct GpioDescriptor* descriptor) {
|
|||||||
static error_t start(Device* device) {
|
static error_t start(Device* device) {
|
||||||
ESP_LOGI(TAG, "start %s", device->name);
|
ESP_LOGI(TAG, "start %s", device->name);
|
||||||
const Esp32GpioConfig* config = GET_CONFIG(device);
|
const Esp32GpioConfig* config = GET_CONFIG(device);
|
||||||
device_set_driver_data(device, new Esp32GpioInternal());
|
auto* internal = new Esp32GpioInternal();
|
||||||
return gpio_controller_init_descriptors(device, config->gpioCount, nullptr);
|
return gpio_controller_init_descriptors(device, config->gpioCount, internal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static error_t stop(Device* device) {
|
static error_t stop(Device* device) {
|
||||||
ESP_LOGI(TAG, "stop %s", device->name);
|
ESP_LOGI(TAG, "stop %s", device->name);
|
||||||
auto* internal = GET_INTERNAL(device);
|
auto* internal = static_cast<Esp32GpioInternal*>(gpio_controller_get_controller_context(device));
|
||||||
if (internal->isr_service_ref_count > 0) {
|
if (internal->isr_service_ref_count > 0) {
|
||||||
gpio_uninstall_isr_service();
|
gpio_uninstall_isr_service();
|
||||||
}
|
}
|
||||||
check(gpio_controller_deinit_descriptors(device) == ERROR_NONE);
|
|
||||||
delete internal;
|
delete internal;
|
||||||
|
check(gpio_controller_deinit_descriptors(device) == ERROR_NONE);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,14 +169,14 @@ const static GpioControllerApi esp32_gpio_api = {
|
|||||||
.disable_interrupt = disable_interrupt
|
.disable_interrupt = disable_interrupt
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct Module platform_esp32_module;
|
extern Module platform_esp32_module;
|
||||||
|
|
||||||
Driver esp32_gpio_driver = {
|
Driver esp32_gpio_driver = {
|
||||||
.name = "esp32_gpio",
|
.name = "esp32_gpio",
|
||||||
.compatible = (const char*[]) { "espressif,esp32-gpio", nullptr },
|
.compatible = (const char*[]) { "espressif,esp32-gpio", nullptr },
|
||||||
.start_device = start,
|
.start_device = start,
|
||||||
.stop_device = stop,
|
.stop_device = stop,
|
||||||
.api = (void*)&esp32_gpio_api,
|
.api = static_cast<const void*>(&esp32_gpio_api),
|
||||||
.device_type = &GPIO_CONTROLLER_TYPE,
|
.device_type = &GPIO_CONTROLLER_TYPE,
|
||||||
.owner = &platform_esp32_module,
|
.owner = &platform_esp32_module,
|
||||||
.internal = nullptr
|
.internal = nullptr
|
||||||
|
|||||||
@ -7,7 +7,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define GPIO_FLAGS_MASK 0x1f
|
#define GPIO_FLAGS_MASK 0x1f
|
||||||
@ -27,6 +26,7 @@ extern "C" {
|
|||||||
#define GPIO_FLAG_INTERRUPT_BITMASK (0b111 << 5) // 3 bits to hold the values [0, 5]
|
#define GPIO_FLAG_INTERRUPT_BITMASK (0b111 << 5) // 3 bits to hold the values [0, 5]
|
||||||
#define GPIO_FLAG_INTERRUPT_FROM_OPTIONS(options) (gpio_int_type_t)((options & GPIO_FLAG_INTERRUPT_BITMASK) >> 5)
|
#define GPIO_FLAG_INTERRUPT_FROM_OPTIONS(options) (gpio_int_type_t)((options & GPIO_FLAG_INTERRUPT_BITMASK) >> 5)
|
||||||
#define GPIO_FLAG_INTERRUPT_TO_OPTIONS(options, interrupt) (options | (interrupt << 5))
|
#define GPIO_FLAG_INTERRUPT_TO_OPTIONS(options, interrupt) (options | (interrupt << 5))
|
||||||
|
#define GPIO_FLAG_HIGH_IMPEDANCE (1 << 8)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GPIO_INTERRUPT_DISABLE = 0,
|
GPIO_INTERRUPT_DISABLE = 0,
|
||||||
|
|||||||
@ -201,6 +201,15 @@ error_t gpio_controller_init_descriptors(struct Device* device, uint32_t pin_cou
|
|||||||
*/
|
*/
|
||||||
error_t gpio_controller_deinit_descriptors(struct Device* device);
|
error_t gpio_controller_deinit_descriptors(struct Device* device);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlike other drivers, a GPIO controller's internal data is created and set by gpio_controller_init_descriptors()
|
||||||
|
* This means that the specific controller implementation cannot set the device's driver data, as it's already set by the GPIO controller base coded.
|
||||||
|
* When calling init descriptors, the caller can pass a controller_context, which is an optional pointer that holds the implementation's internal data.
|
||||||
|
* @param device the GPIO controller device
|
||||||
|
* @return ERROR_NONE if successful
|
||||||
|
*/
|
||||||
|
void* gpio_controller_get_controller_context(struct Device* device);
|
||||||
|
|
||||||
extern const struct DeviceType GPIO_CONTROLLER_TYPE;
|
extern const struct DeviceType GPIO_CONTROLLER_TYPE;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -11,6 +11,11 @@ struct GpioDescriptor {
|
|||||||
gpio_pin_t pin;
|
gpio_pin_t pin;
|
||||||
/** @brief Current owner */
|
/** @brief Current owner */
|
||||||
enum GpioOwnerType owner_type;
|
enum GpioOwnerType owner_type;
|
||||||
/** @brief Implementation-specific context (e.g. from esp32 controller internally) */
|
/**
|
||||||
|
* @brief Implementation-specific context (e.g. from esp32 controller internally)
|
||||||
|
* Unlike other drivers, a GPIO controller's internal data is created and set by gpio_controller_init_descriptors()
|
||||||
|
* This means that the specific controller implementation cannot set the device's driver data, as it's already set by the GPIO controller base coded.
|
||||||
|
* When calling init descriptors, the caller can pass a controller_context, which is an optional pointer that holds the implementation's internal data.
|
||||||
|
*/
|
||||||
void* controller_context;
|
void* controller_context;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -14,22 +14,25 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
struct GpioControllerData {
|
struct GpioControllerData {
|
||||||
struct Mutex mutex {};
|
Mutex mutex {};
|
||||||
uint32_t pin_count;
|
uint32_t pin_count;
|
||||||
struct GpioDescriptor* descriptors = nullptr;
|
GpioDescriptor* descriptors = nullptr;
|
||||||
|
void* controller_context;
|
||||||
|
|
||||||
explicit GpioControllerData(uint32_t pin_count) : pin_count(pin_count) {
|
explicit GpioControllerData(
|
||||||
|
uint32_t pin_count, void* controller_context
|
||||||
|
) : pin_count(pin_count), controller_context(controller_context) {
|
||||||
mutex_construct(&mutex);
|
mutex_construct(&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t init_descriptors(Device* device, void* controller_context) {
|
error_t init_descriptors(Device* device) {
|
||||||
descriptors = (struct GpioDescriptor*)calloc(pin_count, sizeof(struct GpioDescriptor));
|
descriptors = static_cast<GpioDescriptor*>(calloc(pin_count, sizeof(GpioDescriptor)));
|
||||||
if (!descriptors) return ERROR_OUT_OF_MEMORY;
|
if (!descriptors) return ERROR_OUT_OF_MEMORY;
|
||||||
for (uint32_t i = 0; i < pin_count; ++i) {
|
for (uint32_t i = 0; i < pin_count; ++i) {
|
||||||
descriptors[i].controller = device;
|
descriptors[i].controller = device;
|
||||||
descriptors[i].pin = (gpio_pin_t)i;
|
descriptors[i].pin = static_cast<gpio_pin_t>(i);
|
||||||
descriptors[i].owner_type = GPIO_OWNER_NONE;
|
descriptors[i].owner_type = GPIO_OWNER_NONE;
|
||||||
descriptors[i].controller_context = controller_context;
|
descriptors[i].controller_context = this->controller_context;
|
||||||
}
|
}
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
@ -42,14 +45,14 @@ struct GpioControllerData {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GpioDescriptor* gpio_descriptor_acquire(
|
GpioDescriptor* gpio_descriptor_acquire(
|
||||||
struct Device* controller,
|
Device* controller,
|
||||||
gpio_pin_t pin_number,
|
gpio_pin_t pin_number,
|
||||||
enum GpioOwnerType owner
|
GpioOwnerType owner
|
||||||
) {
|
) {
|
||||||
check(owner != GPIO_OWNER_NONE);
|
check(owner != GPIO_OWNER_NONE);
|
||||||
|
|
||||||
auto* data = (struct GpioControllerData*)device_get_driver_data(controller);
|
auto* data = static_cast<struct GpioControllerData*>(device_get_driver_data(controller));
|
||||||
|
|
||||||
mutex_lock(&data->mutex);
|
mutex_lock(&data->mutex);
|
||||||
if (pin_number >= data->pin_count) {
|
if (pin_number >= data->pin_count) {
|
||||||
@ -57,7 +60,7 @@ struct GpioDescriptor* gpio_descriptor_acquire(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GpioDescriptor* desc = &data->descriptors[pin_number];
|
GpioDescriptor* desc = &data->descriptors[pin_number];
|
||||||
if (desc->owner_type != GPIO_OWNER_NONE) {
|
if (desc->owner_type != GPIO_OWNER_NONE) {
|
||||||
mutex_unlock(&data->mutex);
|
mutex_unlock(&data->mutex);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -69,22 +72,22 @@ struct GpioDescriptor* gpio_descriptor_acquire(
|
|||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_release(struct GpioDescriptor* descriptor) {
|
error_t gpio_descriptor_release(GpioDescriptor* descriptor) {
|
||||||
descriptor->owner_type = GPIO_OWNER_NONE;
|
descriptor->owner_type = GPIO_OWNER_NONE;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_controller_get_pin_count(struct Device* device, uint32_t* count) {
|
error_t gpio_controller_get_pin_count(Device* device, uint32_t* count) {
|
||||||
auto* data = (struct GpioControllerData*)device_get_driver_data(device);
|
auto* data = static_cast<struct GpioControllerData*>(device_get_driver_data(device));
|
||||||
*count = data->pin_count;
|
*count = data->pin_count;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_controller_init_descriptors(struct Device* device, uint32_t pin_count, void* controller_context) {
|
error_t gpio_controller_init_descriptors(Device* device, uint32_t pin_count, void* controller_context) {
|
||||||
auto* data = new(std::nothrow) GpioControllerData(pin_count);
|
auto* data = new(std::nothrow) GpioControllerData(pin_count, controller_context);
|
||||||
if (!data) return ERROR_OUT_OF_MEMORY;
|
if (!data) return ERROR_OUT_OF_MEMORY;
|
||||||
|
|
||||||
if (data->init_descriptors(device, controller_context) != ERROR_NONE) {
|
if (data->init_descriptors(device) != ERROR_NONE) {
|
||||||
delete data;
|
delete data;
|
||||||
return ERROR_OUT_OF_MEMORY;
|
return ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
@ -93,77 +96,82 @@ error_t gpio_controller_init_descriptors(struct Device* device, uint32_t pin_cou
|
|||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_controller_deinit_descriptors(struct Device* device) {
|
error_t gpio_controller_deinit_descriptors(Device* device) {
|
||||||
auto* data = static_cast<struct GpioControllerData*>(device_get_driver_data(device));
|
auto* data = static_cast<struct GpioControllerData*>(device_get_driver_data(device));
|
||||||
delete data;
|
delete data;
|
||||||
device_set_driver_data(device, nullptr);
|
device_set_driver_data(device, nullptr);
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_set_level(struct GpioDescriptor* descriptor, bool high) {
|
void* gpio_controller_get_controller_context(Device* device) {
|
||||||
|
auto* data = static_cast<struct GpioControllerData*>(device_get_driver_data(device));
|
||||||
|
return data->controller_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_t gpio_descriptor_set_level(GpioDescriptor* descriptor, bool high) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
return GPIO_INTERNAL_API(driver)->set_level(descriptor, high);
|
return GPIO_INTERNAL_API(driver)->set_level(descriptor, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_get_level(struct GpioDescriptor* descriptor, bool* high) {
|
error_t gpio_descriptor_get_level(GpioDescriptor* descriptor, bool* high) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
return GPIO_INTERNAL_API(driver)->get_level(descriptor, high);
|
return GPIO_INTERNAL_API(driver)->get_level(descriptor, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_set_flags(struct GpioDescriptor* descriptor, gpio_flags_t flags) {
|
error_t gpio_descriptor_set_flags(GpioDescriptor* descriptor, gpio_flags_t flags) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
return GPIO_INTERNAL_API(driver)->set_flags(descriptor, flags);
|
return GPIO_INTERNAL_API(driver)->set_flags(descriptor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_get_flags(struct GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
error_t gpio_descriptor_get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
return GPIO_INTERNAL_API(driver)->get_flags(descriptor, flags);
|
return GPIO_INTERNAL_API(driver)->get_flags(descriptor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_get_pin_number(struct GpioDescriptor* descriptor, gpio_pin_t* pin) {
|
error_t gpio_descriptor_get_pin_number(GpioDescriptor* descriptor, gpio_pin_t* pin) {
|
||||||
*pin = descriptor->pin;
|
*pin = descriptor->pin;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_get_native_pin_number(struct GpioDescriptor* descriptor, void* pin_number) {
|
error_t gpio_descriptor_get_native_pin_number(GpioDescriptor* descriptor, void* pin_number) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
return GPIO_INTERNAL_API(driver)->get_native_pin_number(descriptor, pin_number);
|
return GPIO_INTERNAL_API(driver)->get_native_pin_number(descriptor, pin_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_add_callback(struct GpioDescriptor* descriptor, void (*callback)(void*), void* arg) {
|
error_t gpio_descriptor_add_callback(GpioDescriptor* descriptor, void (*callback)(void*), void* arg) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
auto* api = GPIO_INTERNAL_API(driver);
|
auto* api = GPIO_INTERNAL_API(driver);
|
||||||
if (!api->add_callback) return ERROR_NOT_SUPPORTED;
|
if (!api->add_callback) return ERROR_NOT_SUPPORTED;
|
||||||
return api->add_callback(descriptor, callback, arg);
|
return api->add_callback(descriptor, callback, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_remove_callback(struct GpioDescriptor* descriptor) {
|
error_t gpio_descriptor_remove_callback(GpioDescriptor* descriptor) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
auto* api = GPIO_INTERNAL_API(driver);
|
auto* api = GPIO_INTERNAL_API(driver);
|
||||||
if (!api->remove_callback) return ERROR_NOT_SUPPORTED;
|
if (!api->remove_callback) return ERROR_NOT_SUPPORTED;
|
||||||
return api->remove_callback(descriptor);
|
return api->remove_callback(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_enable_interrupt(struct GpioDescriptor* descriptor) {
|
error_t gpio_descriptor_enable_interrupt(GpioDescriptor* descriptor) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
auto* api = GPIO_INTERNAL_API(driver);
|
auto* api = GPIO_INTERNAL_API(driver);
|
||||||
if (!api->enable_interrupt) return ERROR_NOT_SUPPORTED;
|
if (!api->enable_interrupt) return ERROR_NOT_SUPPORTED;
|
||||||
return api->enable_interrupt(descriptor);
|
return api->enable_interrupt(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_disable_interrupt(struct GpioDescriptor* descriptor) {
|
error_t gpio_descriptor_disable_interrupt(GpioDescriptor* descriptor) {
|
||||||
const auto* driver = device_get_driver(descriptor->controller);
|
const auto* driver = device_get_driver(descriptor->controller);
|
||||||
auto* api = GPIO_INTERNAL_API(driver);
|
auto* api = GPIO_INTERNAL_API(driver);
|
||||||
if (!api->disable_interrupt) return ERROR_NOT_SUPPORTED;
|
if (!api->disable_interrupt) return ERROR_NOT_SUPPORTED;
|
||||||
return api->disable_interrupt(descriptor);
|
return api->disable_interrupt(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_t gpio_descriptor_get_owner_type(struct GpioDescriptor* descriptor, GpioOwnerType* owner_type) {
|
error_t gpio_descriptor_get_owner_type(GpioDescriptor* descriptor, GpioOwnerType* owner_type) {
|
||||||
*owner_type = descriptor->owner_type;
|
*owner_type = descriptor->owner_type;
|
||||||
return ERROR_NONE;
|
return ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct DeviceType GPIO_CONTROLLER_TYPE {
|
const DeviceType GPIO_CONTROLLER_TYPE {
|
||||||
.name = "gpio-controller"
|
.name = "gpio-controller"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user