Browse Source

Fix M5Stack Unit C6L: RX, flash size, pin conflicts

- Initialize PI4IOE5V6408 I2C GPIO expander for RF switch/LNA control
- Fix I2C bus pins (SDA=10, SCL=8) - ESP32-C6 only has one I2C peripheral
- Remove SX126X_RXEN=5 (RF switch is on expander, not ESP32 GPIO)
- Set flash size to 16MB (actual hardware, was defaulting to 4MB)
- Remove P_LORA_TX_LED=15 (GPIO15 is OLED reset, not TX LED)
- Fix TCXO voltage 1.8V -> 3.0V
- Remove unused GPS_RX/GPS_TX defines
- Add esp_mac.h include for ESP32-C6 BLE builds
- Add WiFi companion radio build target
pull/1875/head
Wouter Bijen 4 months ago
parent
commit
29c67c7c6e
  1. 1
      src/helpers/esp32/SerialBLEInterface.cpp
  2. 98
      variants/m5stack_unit_c6l/UnitC6LBoard.h
  3. 37
      variants/m5stack_unit_c6l/platformio.ini

1
src/helpers/esp32/SerialBLEInterface.cpp

@ -1,3 +1,4 @@
#include <esp_mac.h>
#include "SerialBLEInterface.h"
#include "esp_mac.h"

98
variants/m5stack_unit_c6l/UnitC6LBoard.h

@ -1,15 +1,111 @@
#pragma once
#include <Arduino.h>
#include <Wire.h>
#include <helpers/ESP32Board.h>
// PI4IOE5V6408 I2C GPIO expander - controls RF switch, LNA, and LoRa reset
// Sits on the internal I2C bus (SDA=10, SCL=8), which is configured as
// the primary Wire bus via PIN_BOARD_SDA/SCL in platformio.ini.
// ESP32-C6 only has ONE I2C hardware peripheral - do NOT use TwoWire(1).
#define PI4IO_ADDR 0x43
#define PI4IO_REG_CHIP_RESET 0x01
#define PI4IO_REG_IO_DIR 0x03
#define PI4IO_REG_OUT_SET 0x05
#define PI4IO_REG_OUT_H_IM 0x07
#define PI4IO_REG_IN_DEF_STA 0x09
#define PI4IO_REG_PULL_EN 0x0B
#define PI4IO_REG_PULL_SEL 0x0D
#define PI4IO_REG_INT_MASK 0x11
#define PI4IO_REG_IRQ_STA 0x13
class UnitC6LBoard : public ESP32Board {
public:
void begin() {
ESP32Board::begin();
ESP32Board::begin(); // This calls Wire.begin(10, 8) via PIN_BOARD_SDA/SCL
initGPIOExpander();
}
const char* getManufacturerName() const override {
return "Unit C6L";
}
private:
void i2cWrite(uint8_t reg, uint8_t value) {
Wire.beginTransmission(PI4IO_ADDR);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
uint8_t i2cRead(uint8_t reg) {
Wire.beginTransmission(PI4IO_ADDR);
Wire.write(reg);
Wire.endTransmission();
Wire.requestFrom((uint8_t)PI4IO_ADDR, (uint8_t)1);
return Wire.read();
}
bool i2cProbe() {
Wire.beginTransmission(PI4IO_ADDR);
return Wire.endTransmission() == 0;
}
void initGPIOExpander() {
// Matches Meshtastic's c6l_init() in variant.cpp
// Uses Wire (already on SDA=10, SCL=8 from ESP32Board::begin)
if (!i2cProbe()) {
Serial.printf("C6L: ERROR - PI4IOE5V6408 not found at 0x%02X\n", PI4IO_ADDR);
return;
}
Serial.println("C6L: PI4IOE5V6408 found, initializing...");
// Reset expander
i2cWrite(PI4IO_REG_CHIP_RESET, 0xFF);
delay(10);
i2cRead(PI4IO_REG_CHIP_RESET);
delay(10);
// P6 (RF switch) and P7 (LoRa reset) as outputs
i2cWrite(PI4IO_REG_IO_DIR, 0b11000000);
delay(10);
// Disable high-impedance on P2-P5
i2cWrite(PI4IO_REG_OUT_H_IM, 0b00111100);
delay(10);
// Pull-up on P0, P1, P6, P7; pull-down on others
i2cWrite(PI4IO_REG_PULL_SEL, 0b11000011);
delay(10);
i2cWrite(PI4IO_REG_PULL_EN, 0b11000011);
delay(10);
// Button defaults (P0, P1 default HIGH - active low buttons)
i2cWrite(PI4IO_REG_IN_DEF_STA, 0b00000011);
delay(10);
// Interrupt mask: only P0, P1 generate interrupts
i2cWrite(PI4IO_REG_INT_MASK, 0b11111100);
delay(10);
// Set P7 HIGH (LoRa out of reset)
i2cWrite(PI4IO_REG_OUT_SET, 0b10000000);
delay(10);
// Clear pending IRQ
i2cRead(PI4IO_REG_IRQ_STA);
// Set P6 HIGH (RF switch -> routes antenna to LoRa)
uint8_t out = i2cRead(PI4IO_REG_OUT_SET);
out |= (1 << 6);
i2cWrite(PI4IO_REG_OUT_SET, out);
// Verify
uint8_t verify = i2cRead(PI4IO_REG_OUT_SET);
Serial.printf("C6L: OUT_SET=0x%02X (expect 0xC0: P6=RF_SW, P7=LORA_RST)\n", verify);
Serial.printf("C6L: IO_DIR=0x%02X (expect 0xC0: P6,P7 outputs)\n", i2cRead(PI4IO_REG_IO_DIR));
}
};

37
variants/m5stack_unit_c6l/platformio.ini

@ -1,12 +1,15 @@
[M5Stack_Unit_C6L]
extends = esp32c6_base
board = esp32-c6-devkitm-1
board_upload.flash_size = 16MB
board_build.flash_size = 16MB
board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
build_flags =
${esp32c6_base.build_flags}
${sensor_base.build_flags}
-I variants/m5stack_unit_c6l
-D P_LORA_TX_LED=15
; P_LORA_TX_LED removed - GPIO15 is SSD1306 OLED reset pin, not a TX LED
; (C6L has WS2812C RGB LED on GPIO2, no discrete TX LED)
-D P_LORA_SCLK=20
-D P_LORA_MISO=22
-D P_LORA_MOSI=21
@ -15,19 +18,19 @@ build_flags =
-D P_LORA_BUSY=19
-D P_LORA_RESET=-1
-D PIN_BUZZER=11
-D PIN_BOARD_SDA=16
-D PIN_BOARD_SCL=17
-D SX126X_RXEN=5
; I2C bus: primary bus goes to PI4IOE5V6408 GPIO expander (internal)
; ESP32-C6 only has ONE I2C hardware peripheral, so Wire must be on these pins.
-D PIN_BOARD_SDA=10
-D PIN_BOARD_SCL=8
; SX126X_RXEN removed - RF switch is on I2C expander (PI4IOE5V6408), not ESP32 GPIO
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_DIO3_TCXO_VOLTAGE=3.0
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D DISABLE_WIFI_OTA=1
-D GPS_RX=4
-D GPS_TX=5
build_src_filter = ${esp32c6_base.build_src_filter}
+<../variants/m5stack_unit_c6l>
+<UnitC6LBoard.cpp>
@ -88,6 +91,26 @@ lib_deps =
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:M5Stack_Unit_C6L_companion_radio_wifi]
extends = M5Stack_Unit_C6L
build_flags = ${M5Stack_Unit_C6L.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${M5Stack_Unit_C6L.build_src_filter}
+<helpers/esp32/*.cpp>
-<helpers/esp32/ESPNOWRadio.cpp>
+<../examples/companion_radio/*.cpp>
lib_deps =
${M5Stack_Unit_C6L.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:M5Stack_Unit_C6L_companion_radio_usb]
extends = M5Stack_Unit_C6L
build_flags = ${M5Stack_Unit_C6L.build_flags}

Loading…
Cancel
Save