129 lines
4.6 KiB
C++
129 lines
4.6 KiB
C++
#include "TestUnitPaHub.h"
|
|
#include "GroveLookup.h"
|
|
#include "UiScale.h"
|
|
#include <tactility/device.h>
|
|
#include <tactility/drivers/i2c_controller.h>
|
|
#include <tactility/lvgl_fonts.h>
|
|
|
|
void TestUnitPaHub::onStart(lv_obj_t* parent, AppHandle handle, M5UnitTest* app) {
|
|
app_ = app;
|
|
|
|
createToolbar(parent, handle, "PaHub");
|
|
createBanner(parent, "PaHub", "I2C", COLOR_I2C);
|
|
|
|
lv_obj_t* cont = lv_obj_create(parent);
|
|
lv_obj_set_width(cont, LV_PCT(100));
|
|
lv_obj_set_flex_grow(cont, 1);
|
|
lv_obj_set_layout(cont, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
|
|
lv_obj_set_style_pad_all(cont, uiPad(), 0);
|
|
lv_obj_set_style_pad_row(cont, uiRowGap(), 0);
|
|
lv_obj_set_style_bg_opa(cont, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_style_border_width(cont, 0, 0);
|
|
|
|
const lv_font_t* fnt = lvgl_get_text_font(uiFont());
|
|
int pad = uiPad();
|
|
int gap = uiRowGap();
|
|
|
|
// Row of channel buttons — flex-grow so they share space evenly at any width
|
|
lv_obj_t* btnRow = lv_obj_create(cont);
|
|
lv_obj_set_width(btnRow, LV_PCT(100));
|
|
lv_obj_set_height(btnRow, LV_SIZE_CONTENT);
|
|
lv_obj_set_layout(btnRow, LV_LAYOUT_FLEX);
|
|
lv_obj_set_flex_flow(btnRow, LV_FLEX_FLOW_ROW);
|
|
lv_obj_set_flex_align(btnRow, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
|
lv_obj_set_style_pad_column(btnRow, gap, 0);
|
|
lv_obj_set_style_bg_opa(btnRow, LV_OPA_TRANSP, 0);
|
|
lv_obj_set_style_border_width(btnRow, 0, 0);
|
|
lv_obj_set_style_pad_all(btnRow, 0, 0);
|
|
|
|
for (int i = 0; i < CH_COUNT; i++) {
|
|
lv_obj_t* btn = lv_button_create(btnRow);
|
|
lv_obj_set_flex_grow(btn, 1);
|
|
lv_obj_set_style_pad_hor(btn, pad, 0);
|
|
lv_obj_set_style_pad_ver(btn, gap, 0);
|
|
lv_obj_set_user_data(btn, (void*)(intptr_t)i);
|
|
lv_obj_add_event_cb(btn, onChannelBtn, LV_EVENT_CLICKED, this);
|
|
lv_obj_t* lbl = lv_label_create(btn);
|
|
lv_label_set_text_fmt(lbl, "CH%d", i);
|
|
lv_obj_set_style_text_font(lbl, fnt, 0);
|
|
lv_obj_align(lbl, LV_ALIGN_CENTER, 0, 0);
|
|
btnCh_[i] = btn;
|
|
}
|
|
|
|
lblStatus_ = lv_label_create(cont);
|
|
lv_obj_set_style_text_font(lblStatus_, fnt, 0);
|
|
lv_label_set_text(lblStatus_, "Select a channel to probe");
|
|
|
|
for (int i = 0; i < CH_COUNT; i++) {
|
|
lblCh_[i] = lv_label_create(cont);
|
|
lv_obj_set_style_text_font(lblCh_[i], fnt, 0);
|
|
lv_label_set_text_fmt(lblCh_[i], "CH%d: -", i);
|
|
}
|
|
|
|
Device* i2c = findGroveI2cDevice();
|
|
if (!i2c || !hub_.begin(i2c)) {
|
|
lv_label_set_text(lblStatus_, "PaHub not found");
|
|
return;
|
|
}
|
|
|
|
lv_label_set_text(lblStatus_, "PaHub ready - tap channel to probe");
|
|
|
|
timer_ = lv_timer_create(onTimer, 1000, this);
|
|
}
|
|
|
|
void TestUnitPaHub::onStop() {
|
|
if (timer_) { lv_timer_delete(timer_); timer_ = nullptr; }
|
|
if (hub_.isPresent()) hub_.deselect();
|
|
lblStatus_ = nullptr;
|
|
for (int i = 0; i < CH_COUNT; i++) { btnCh_[i] = nullptr; lblCh_[i] = nullptr; }
|
|
}
|
|
|
|
void TestUnitPaHub::onChannelBtn(lv_event_t* e) {
|
|
auto* self = static_cast<TestUnitPaHub*>(lv_event_get_user_data(e));
|
|
int ch = (int)(intptr_t)lv_obj_get_user_data(lv_event_get_target_obj(e));
|
|
self->selChannel_ = ch;
|
|
self->probeSelected();
|
|
}
|
|
|
|
void TestUnitPaHub::onTimer(lv_timer_t* t) {
|
|
auto* self = static_cast<TestUnitPaHub*>(lv_timer_get_user_data(t));
|
|
if (self->selChannel_ >= 0) self->probeSelected();
|
|
}
|
|
|
|
void TestUnitPaHub::probeSelected() {
|
|
if (!hub_.isPresent() || selChannel_ < 0 || selChannel_ >= CH_COUNT) return;
|
|
|
|
hub_.select((uint8_t)selChannel_);
|
|
|
|
// Probe known unit addresses only (full-range scan can wedge the ESP-IDF i2c_master bus FSM)
|
|
Device* i2c = findGroveI2cDevice();
|
|
if (!i2c) {
|
|
lv_label_set_text_fmt(lblCh_[selChannel_], "CH%d: grove0_i2c not found", selChannel_);
|
|
hub_.deselect();
|
|
return;
|
|
}
|
|
char found[256] = "Found: ";
|
|
bool any = false;
|
|
for (uint8_t addr : KNOWN_UNIT_ADDRS) {
|
|
if (i2c_controller_has_device_at_address(i2c, addr,
|
|
pdMS_TO_TICKS(10)) == ERROR_NONE) {
|
|
size_t remaining = sizeof(found) - strlen(found) - 1;
|
|
if (remaining < 7) {
|
|
strncat(found, "...", remaining);
|
|
break;
|
|
}
|
|
char hex[8];
|
|
snprintf(hex, sizeof(hex), "0x%02X ", addr);
|
|
strncat(found, hex, remaining);
|
|
any = true;
|
|
}
|
|
}
|
|
if (!any) strcpy(found, "No devices found");
|
|
|
|
lv_label_set_text_fmt(lblCh_[selChannel_], "CH%d: %s", selChannel_, found);
|
|
lv_label_set_text_fmt(lblStatus_, "Probed CH%d", selChannel_);
|
|
|
|
hub_.deselect();
|
|
}
|