Fixes for grove and i2c changes (#31)
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
#include "GroveLookup.h"
|
||||||
|
#include <tactility/drivers/i2c_controller.h>
|
||||||
|
#include <tactility/drivers/uart_controller.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct GroveChildSearch {
|
||||||
|
const DeviceType* childType;
|
||||||
|
Device* result;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool onGroveDevice(Device* groveDevice, void* context) {
|
||||||
|
auto* search = static_cast<GroveChildSearch*>(context);
|
||||||
|
|
||||||
|
GroveMode mode;
|
||||||
|
if (grove_get_mode(groveDevice, &mode) != ERROR_NONE) return true;
|
||||||
|
if (mode != (search->childType == &I2C_CONTROLLER_TYPE ? GROVE_MODE_I2C : GROVE_MODE_UART)) return true;
|
||||||
|
|
||||||
|
device_for_each_child(groveDevice, search, [](Device* child, void* ctx) -> bool {
|
||||||
|
auto* s = static_cast<GroveChildSearch*>(ctx);
|
||||||
|
if (device_get_type(child) == s->childType && device_is_ready(child)) {
|
||||||
|
s->result = child;
|
||||||
|
return false; // stop - found it
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return search->result == nullptr; // stop outer iteration once found
|
||||||
|
}
|
||||||
|
|
||||||
|
Device* findGroveChild(const DeviceType* childType) {
|
||||||
|
GroveChildSearch search{childType, nullptr};
|
||||||
|
device_for_each_of_type(&GROVE_TYPE, &search, onGroveDevice);
|
||||||
|
return search.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Device* findGroveI2cDevice() {
|
||||||
|
return findGroveChild(&I2C_CONTROLLER_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Device* findGroveUartDevice() {
|
||||||
|
return findGroveChild(&UART_CONTROLLER_TYPE);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <tactility/device.h>
|
||||||
|
#include <tactility/drivers/grove.h>
|
||||||
|
|
||||||
|
// Finds the I2C controller device exposed by the first grove port currently
|
||||||
|
// in GROVE_MODE_I2C, by checking each grove port's child device type
|
||||||
|
// (not by name - grove port names are not guaranteed, e.g. "port_a").
|
||||||
|
Device* findGroveI2cDevice();
|
||||||
|
|
||||||
|
// Same as findGroveI2cDevice() but for UART mode.
|
||||||
|
Device* findGroveUartDevice();
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnit8Encoder.h"
|
#include "TestUnit8Encoder.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -93,9 +94,9 @@ void TestUnit8Encoder::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* a
|
|||||||
lv_obj_set_flex_grow(lblSwitch_, 1);
|
lv_obj_set_flex_grow(lblSwitch_, 1);
|
||||||
dotSwitch_ = makeDot(swCard);
|
dotSwitch_ = makeDot(swCard);
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
lv_label_set_text(lblStatus_, "i2c1 not found");
|
lv_label_set_text(lblStatus_, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitByteButton.h"
|
#include "TestUnitByteButton.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -56,10 +57,10 @@ void TestUnitByteButton::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest*
|
|||||||
lv_obj_set_style_text_font(hint, lvgl_get_text_font(FONT_SIZE_SMALL), 0);
|
lv_obj_set_style_text_font(hint, lvgl_get_text_font(FONT_SIZE_SMALL), 0);
|
||||||
lv_label_set_text(hint, "Press buttons - LEDs toggle");
|
lv_label_set_text(hint, "Press buttons - LEDs toggle");
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
for (int i = 0; i < BTN_COUNT; i++) lv_obj_set_style_bg_color(indicators_[i], lv_color_hex(COLOR_ERROR), 0);
|
for (int i = 0; i < BTN_COUNT; i++) lv_obj_set_style_bg_color(indicators_[i], lv_color_hex(COLOR_ERROR), 0);
|
||||||
lv_label_set_text(hint, "i2c1 not found");
|
lv_label_set_text(hint, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitCardKB2.h"
|
#include "TestUnitCardKB2.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/drivers/uart_controller.h>
|
#include <tactility/drivers/uart_controller.h>
|
||||||
@@ -116,10 +117,10 @@ void TestUnitCardKB2::connectI2C() {
|
|||||||
lv_obj_delete(connectOverlay_);
|
lv_obj_delete(connectOverlay_);
|
||||||
connectOverlay_ = nullptr;
|
connectOverlay_ = nullptr;
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
buildMainUI();
|
buildMainUI();
|
||||||
lv_label_set_text(lblHistory_, "i2c1 not found");
|
lv_label_set_text(lblHistory_, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,10 +146,10 @@ void TestUnitCardKB2::connectUart() {
|
|||||||
lv_obj_delete(connectOverlay_);
|
lv_obj_delete(connectOverlay_);
|
||||||
connectOverlay_ = nullptr;
|
connectOverlay_ = nullptr;
|
||||||
|
|
||||||
Device* uart = device_find_by_name("uart1");
|
Device* uart = findGroveUartDevice();
|
||||||
buildMainUI();
|
buildMainUI();
|
||||||
if (!uart) {
|
if (!uart) {
|
||||||
lv_label_set_text(lblHistory_, "uart1 not found");
|
lv_label_set_text(lblHistory_, "grove0_uart not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!unit_.beginUart(uart)) {
|
if (!unit_.beginUart(uart)) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitJoystick2.h"
|
#include "TestUnitJoystick2.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -56,9 +57,9 @@ void TestUnitJoystick2::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest*
|
|||||||
lv_obj_set_style_border_width(dot_, 0, 0);
|
lv_obj_set_style_border_width(dot_, 0, 0);
|
||||||
lv_obj_set_pos(dot_, (JOY_AREA - DOT_SIZE) / 2, (JOY_AREA - DOT_SIZE) / 2);
|
lv_obj_set_pos(dot_, (JOY_AREA - DOT_SIZE) / 2, (JOY_AREA - DOT_SIZE) / 2);
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
lv_label_set_text(lblXY_, "i2c1 not found");
|
lv_label_set_text(lblXY_, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitLcd.h"
|
#include "TestUnitLcd.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -87,9 +88,9 @@ void TestUnitLcd::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app) {
|
|||||||
lv_label_set_text(lText, "Write Text");
|
lv_label_set_text(lText, "Write Text");
|
||||||
lv_obj_set_style_text_font(lText, fnt, 0);
|
lv_obj_set_style_text_font(lText, fnt, 0);
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
lv_label_set_text(lblStatus_, "i2c1 not found");
|
lv_label_set_text(lblStatus_, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitLcdGfx.h"
|
#include "TestUnitLcdGfx.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -65,8 +66,8 @@ void TestUnitLcdGfx::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app
|
|||||||
lv_obj_set_width(lblLog_, LV_PCT(100));
|
lv_obj_set_width(lblLog_, LV_PCT(100));
|
||||||
lv_label_set_text(lblLog_, "");
|
lv_label_set_text(lblLog_, "");
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) { lv_label_set_text(lblPhase_, "i2c1 not found"); return; }
|
if (!i2c) { lv_label_set_text(lblPhase_, "grove0_i2c not found"); return; }
|
||||||
|
|
||||||
if (lcd_.begin(i2c)) {
|
if (lcd_.begin(i2c)) {
|
||||||
usingPaHub_ = false;
|
usingPaHub_ = false;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitMidi.h"
|
#include "TestUnitMidi.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -84,7 +85,7 @@ void TestUnitMidi::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app)
|
|||||||
lv_obj_t* lOff = lv_label_create(btnOff); lv_label_set_text(lOff, "Note Off");
|
lv_obj_t* lOff = lv_label_create(btnOff); lv_label_set_text(lOff, "Note Off");
|
||||||
lv_obj_set_style_text_font(lOff, fntS, 0);
|
lv_obj_set_style_text_font(lOff, fntS, 0);
|
||||||
|
|
||||||
Device* uart = device_find_by_name(UART_DEVICE);
|
Device* uart = findGroveUartDevice();
|
||||||
if (!uart || !device_is_ready(uart) || !unit_.begin(uart)) {
|
if (!uart || !device_is_ready(uart) || !unit_.begin(uart)) {
|
||||||
lv_label_set_text(lblStatus_, "MIDI UART not available");
|
lv_label_set_text(lblStatus_, "MIDI UART not available");
|
||||||
updateLabels();
|
updateLabels();
|
||||||
|
|||||||
@@ -17,9 +17,6 @@ private:
|
|||||||
uint8_t note_ = 60; // middle C
|
uint8_t note_ = 60; // middle C
|
||||||
bool notePlaying_= false;
|
bool notePlaying_= false;
|
||||||
|
|
||||||
// UART device name for MIDI unit (adjust to match your board wiring)
|
|
||||||
static constexpr const char* UART_DEVICE = "uart1";
|
|
||||||
|
|
||||||
static void onNoteOnClicked(lv_event_t* e);
|
static void onNoteOnClicked(lv_event_t* e);
|
||||||
static void onNoteOffClicked(lv_event_t* e);
|
static void onNoteOffClicked(lv_event_t* e);
|
||||||
static void onChUp(lv_event_t* e);
|
static void onChUp(lv_event_t* e);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitPaHub.h"
|
#include "TestUnitPaHub.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/drivers/i2c_controller.h>
|
#include <tactility/drivers/i2c_controller.h>
|
||||||
@@ -60,7 +61,7 @@ void TestUnitPaHub::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app)
|
|||||||
lv_label_set_text_fmt(lblCh_[i], "CH%d: -", i);
|
lv_label_set_text_fmt(lblCh_[i], "CH%d: -", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c || !hub_.begin(i2c)) {
|
if (!i2c || !hub_.begin(i2c)) {
|
||||||
lv_label_set_text(lblStatus_, "PaHub not found");
|
lv_label_set_text(lblStatus_, "PaHub not found");
|
||||||
return;
|
return;
|
||||||
@@ -95,16 +96,16 @@ void TestUnitPaHub::probeSelected() {
|
|||||||
|
|
||||||
hub_.select((uint8_t)selChannel_);
|
hub_.select((uint8_t)selChannel_);
|
||||||
|
|
||||||
// Scan I2C addresses 0x08-0x77 on this channel
|
// Probe known unit addresses only (full-range scan can wedge the ESP-IDF i2c_master bus FSM)
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
lv_label_set_text_fmt(lblCh_[selChannel_], "CH%d: i2c1 not found", selChannel_);
|
lv_label_set_text_fmt(lblCh_[selChannel_], "CH%d: grove0_i2c not found", selChannel_);
|
||||||
hub_.deselect();
|
hub_.deselect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
char found[256] = "Found: ";
|
char found[256] = "Found: ";
|
||||||
bool any = false;
|
bool any = false;
|
||||||
for (uint8_t addr = 0x08; addr < 0x78; addr++) {
|
for (uint8_t addr : KNOWN_UNIT_ADDRS) {
|
||||||
if (i2c_controller_has_device_at_address(i2c, addr,
|
if (i2c_controller_has_device_at_address(i2c, addr,
|
||||||
pdMS_TO_TICKS(10)) == ERROR_NONE) {
|
pdMS_TO_TICKS(10)) == ERROR_NONE) {
|
||||||
size_t remaining = sizeof(found) - strlen(found) - 1;
|
size_t remaining = sizeof(found) - strlen(found) - 1;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitRfid2.h"
|
#include "TestUnitRfid2.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -101,7 +102,7 @@ void TestUnitRfid2::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app)
|
|||||||
lv_label_set_text(btnLbl, "Clear");
|
lv_label_set_text(btnLbl, "Clear");
|
||||||
|
|
||||||
// ── Device discovery ─────────────────────────────────────────────────────
|
// ── Device discovery ─────────────────────────────────────────────────────
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) return;
|
if (!i2c) return;
|
||||||
|
|
||||||
if (unit_.begin(i2c)) {
|
if (unit_.begin(i2c)) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "TestUnitScroll.h"
|
#include "TestUnitScroll.h"
|
||||||
|
#include "GroveLookup.h"
|
||||||
#include "UiScale.h"
|
#include "UiScale.h"
|
||||||
#include <tactility/device.h>
|
#include <tactility/device.h>
|
||||||
#include <tactility/lvgl_fonts.h>
|
#include <tactility/lvgl_fonts.h>
|
||||||
@@ -57,9 +58,9 @@ void TestUnitScroll::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app
|
|||||||
sliderB_ = makeSlider("B");
|
sliderB_ = makeSlider("B");
|
||||||
lv_label_set_text(lblLed_, "LED: #000000");
|
lv_label_set_text(lblLed_, "LED: #000000");
|
||||||
|
|
||||||
Device* i2c = device_find_by_name("i2c1");
|
Device* i2c = findGroveI2cDevice();
|
||||||
if (!i2c) {
|
if (!i2c) {
|
||||||
lv_label_set_text(lblCounter_, "i2c1 not found");
|
lv_label_set_text(lblCounter_, "grove0_i2c not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,20 @@ static constexpr uint32_t UNIT_I2C_PROBE_TIMEOUT_MS = 10; // shorter timeout fo
|
|||||||
static constexpr uint32_t UNIT_STM32_READ_DELAY_MS = 2; // STM32 needs STOP + delay before read
|
static constexpr uint32_t UNIT_STM32_READ_DELAY_MS = 2; // STM32 needs STOP + delay before read
|
||||||
static constexpr uint16_t UNIT_MAX_WRITE_PAYLOAD = 32; // max bytes in a single I2C write
|
static constexpr uint16_t UNIT_MAX_WRITE_PAYLOAD = 32; // max bytes in a single I2C write
|
||||||
|
|
||||||
|
// I2C addresses of the unit modules this library can drive (excludes PaHub itself
|
||||||
|
// and UART-only units like MIDI). Used by PaHub channel probing instead of a full
|
||||||
|
// 0x08-0x77 bus scan: the ESP-IDF i2c_master driver's probe op can wedge the bus
|
||||||
|
// FSM after heavy NACK traffic, so scanning only known addresses avoids that.
|
||||||
|
static constexpr uint8_t KNOWN_UNIT_ADDRS[] = {
|
||||||
|
0x28, // UnitRfid2
|
||||||
|
0x3E, // UnitLcd
|
||||||
|
0x40, // UnitScroll
|
||||||
|
0x41, // Unit8Encoder
|
||||||
|
0x47, // UnitByteButton
|
||||||
|
0x5F, // UnitCardKB2
|
||||||
|
0x63, // UnitJoystick2
|
||||||
|
};
|
||||||
|
|
||||||
// Probe whether a device exists at the given address on the given I2C bus.
|
// Probe whether a device exists at the given address on the given I2C bus.
|
||||||
inline bool unitProbe(Device* dev, uint8_t addr) {
|
inline bool unitProbe(Device* dev, uint8_t addr) {
|
||||||
return i2c_controller_has_device_at_address(
|
return i2c_controller_has_device_at_address(
|
||||||
|
|||||||
Reference in New Issue
Block a user