Commit eb369c

2026-02-21 13:26:16 Peter van Dijk: document working pymc setup
devices/bobber/bobcat miner 300.md ..
@@ 12,8 12,6 @@
Currently unclear which CS line is which of 3/1 and 3/2
- this table needs a verification round
-
| Bobcat Miner 300 | Spec label | Top side | Bottom side | Spec label | Bobcat Miner 300 |
| ---------------------------------------- | ------------ | -------- | ----------- | ----------- | ---------------- |
| 4/21 (149) | WAKE# | 1 | 2 | 3.3V | |
@@ 43,3 41,113 @@
| i2c SDA 4/24 (152) or 4/23 (151) | Reserved* | 47 | 48 | +1.5V | |
| | Reserved* | 49 | 50 | GND | GND |
| | Reserved* | 51 | 52 | +3.3V | |
+
+ ## hacky working pymc setup
+
+ There is a `newradios` branch in pymc core & repeater that likely makes all of this possible without local patching (other than perhaps the board definition, in core, while repeater has configuration for that).
+
+ The pinout chosen here may not be the best.
+ Because the bobcat puts SPI on different pins than other boards seen so far, we need to figure out if routing SPI to two sets of pins can create a miniPCIe board that works for the bobcat -and- for other devices.
+
+ <details>
+ <summary>diff against pymc_core revision ba3ff4c26b9fadda1995c1ef6e21c7f143768c8d (main branch as of 12 Jan 2026)</summary>
+
+ ```diff
+ diff --git a/examples/common.py b/examples/common.py
+ index 826b542..8e68faa 100644
+ --- a/examples/common.py
+ +++ b/examples/common.py
+ @@ -121,6 +121,23 @@ def create_radio(radio_type: str = "waveshare", serial_port: str = "/dev/ttyUSB0
+ "coding_rate": 5,
+ "preamble_length": 17,
+ },
+ + "wibra": {
+ + "bus_id": 5,
+ + "cs_id": 0,
+ + "cs_pin": -1,
+ + "reset_pin": 150 - 128,
+ + "busy_pin": 147 - 128,
+ + "irq_pin": 149 - 128,
+ + "txen_pin": -1,
+ + "frequency": int(869.618 * 1000000), # EU: 869.525 MHz,
+ + "tx_power": 22,
+ + "spreading_factor": 8,
+ + "bandwidth": int(62.5 * 1000),
+ + "coding_rate": 8,
+ + "preamble_length": 17,
+ + "use_dio3_tcxo": True
+ + }
+ +
+ }
+
+ if radio_type not in configs:
+ diff --git a/examples/discover_nodes.py b/examples/discover_nodes.py
+ index 097be79..2db003f 100644
+ --- a/examples/discover_nodes.py
+ +++ b/examples/discover_nodes.py
+ @@ -44,6 +44,11 @@ async def discover_nodes(
+ """
+ mesh_node, identity = create_mesh_node("DiscoveryNode", radio_type, serial_port)
+
+ + print(mesh_node.radio)
+ + print(dir(mesh_node.radio))
+ + print(dir(mesh_node.radio.lora))
+ + print(''.join(map(chr, mesh_node.radio.lora.readRegister(0x320, 16))))
+ +
+ # Dictionary to store discovered nodes
+ discovered_nodes = {}
+
+ @@ -149,7 +154,7 @@ def main():
+ parser = argparse.ArgumentParser(description="Discover nearby mesh nodes")
+ parser.add_argument(
+ "--radio-type",
+ - choices=["waveshare", "uconsole", "meshadv-mini", "kiss-tnc"],
+ + choices=["waveshare", "uconsole", "meshadv-mini", "kiss-tnc", "wibra"],
+ default="waveshare",
+ help="Radio hardware type (default: waveshare)",
+ )
+ diff --git a/src/pymc_core/hardware/gpio_manager.py b/src/pymc_core/hardware/gpio_manager.py
+ index 399a5da..fa7f900 100644
+ --- a/src/pymc_core/hardware/gpio_manager.py
+ +++ b/src/pymc_core/hardware/gpio_manager.py
+ @@ -44,7 +44,7 @@ logger = logging.getLogger("GPIOPinManager")
+ class GPIOPinManager:
+ """Manages GPIO pins abstraction using Linux GPIO character device interface"""
+
+ - def __init__(self, gpio_chip: str = "/dev/gpiochip0"):
+ + def __init__(self, gpio_chip: str = "/dev/gpiochip4"):
+ """
+ Initialize GPIO Pin Manager
+
+ diff --git a/src/pymc_core/hardware/lora/LoRaRF/SX126x.py b/src/pymc_core/hardware/lora/LoRaRF/SX126x.py
+ index 31bedd4..3a672ef 100644
+ --- a/src/pymc_core/hardware/lora/LoRaRF/SX126x.py
+ +++ b/src/pymc_core/hardware/lora/LoRaRF/SX126x.py
+ @@ -468,7 +468,7 @@ class SX126x(BaseLoRa):
+ self._cs_define = 17 # Default to GPIO 17 (safe alternative)
+ else:
+ # Keep original hardcoded value for unknown buses
+ - self._cs_define = 21
+ + self._cs_define = 1
+
+ # open spi line and set bus id, chip select, and spi speed
+ spi.open(bus, cs)
+ @@ -1484,6 +1484,7 @@ class SX126x(BaseLoRa):
+ # Adaptive CS control based on CS pin type
+ if self._cs_define != 8: # Manual CS pin (like Waveshare GPIO 21)
+ # Simple CS control for manual pins
+ + print("_cs_define", self._cs_define)
+ _get_output(self._cs_define).write(False)
+ buf = [opCode]
+ for i in range(nBytes):
+ ```
+ </details>
+
+ pinout:
+
+ * SPI (CLK/MOSI/MISO/CE) on minipcie pins 3, 6, 5, 7.
+ * RST on 22
+ * BUSY on 19
+ * IRQ/DIO1 on 1
+
+ plus 3v3+GND from a wide choice of pins
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9