Optimize pin mapping for direct bitwise GPIO ops
Rewire GPIO↔HMC472A so GPIO(n) = step bit (n-1): GPIO1→V6(0.5dB), GPIO2→V5(1dB), ... GPIO6→V1(16dB) This enables single-instruction GPIO updates: GPIO.out_w1tc = (step & 0x3F) << 1 GPIO.out_w1ts = (~step) & 0x7E Replaces 28-line loop with 4-line bitwise code.
This commit is contained in:
parent
b5794c5f8d
commit
86a5db5b08
@ -18,21 +18,30 @@
|
|||||||
#define WIFI_TIMEOUT_MS 15000
|
#define WIFI_TIMEOUT_MS 15000
|
||||||
|
|
||||||
// --- HMC472A Control Pins (active-low) ---
|
// --- HMC472A Control Pins (active-low) ---
|
||||||
// GPIOs 1-6: contiguous block in lower 32-bit register
|
// Optimized mapping: GPIO number = step bit position + 1
|
||||||
// Enables glitch-free simultaneous writes via GPIO.out_w1ts/w1tc
|
// Enables single-instruction bitwise ops instead of loop
|
||||||
static constexpr uint8_t PIN_V1 = 1; // 16 dB (MSB)
|
//
|
||||||
static constexpr uint8_t PIN_V2 = 2; // 8 dB
|
// Wiring (GPIO → HMC472A pin):
|
||||||
static constexpr uint8_t PIN_V3 = 3; // 4 dB
|
// GPIO1 → V6 (0.5 dB) = step bit 0 (LSB)
|
||||||
static constexpr uint8_t PIN_V4 = 4; // 2 dB
|
// GPIO2 → V5 (1 dB) = step bit 1
|
||||||
static constexpr uint8_t PIN_V5 = 5; // 1 dB
|
// GPIO3 → V4 (2 dB) = step bit 2
|
||||||
static constexpr uint8_t PIN_V6 = 6; // 0.5 dB (LSB)
|
// GPIO4 → V3 (4 dB) = step bit 3
|
||||||
|
// GPIO5 → V2 (8 dB) = step bit 4
|
||||||
|
// GPIO6 → V1 (16 dB) = step bit 5 (MSB)
|
||||||
|
//
|
||||||
|
static constexpr uint8_t PIN_V6 = 1; // 0.5 dB (LSB) - step bit 0
|
||||||
|
static constexpr uint8_t PIN_V5 = 2; // 1 dB - step bit 1
|
||||||
|
static constexpr uint8_t PIN_V4 = 3; // 2 dB - step bit 2
|
||||||
|
static constexpr uint8_t PIN_V3 = 4; // 4 dB - step bit 3
|
||||||
|
static constexpr uint8_t PIN_V2 = 5; // 8 dB - step bit 4
|
||||||
|
static constexpr uint8_t PIN_V1 = 6; // 16 dB (MSB) - step bit 5
|
||||||
|
|
||||||
|
// Pin array ordered by attenuation value (V1=16dB first)
|
||||||
static constexpr uint8_t ATTEN_PINS[6] = {PIN_V1, PIN_V2, PIN_V3, PIN_V4, PIN_V5, PIN_V6};
|
static constexpr uint8_t ATTEN_PINS[6] = {PIN_V1, PIN_V2, PIN_V3, PIN_V4, PIN_V5, PIN_V6};
|
||||||
static constexpr float ATTEN_DB[6] = {16.0f, 8.0f, 4.0f, 2.0f, 1.0f, 0.5f};
|
static constexpr float ATTEN_DB[6] = {16.0f, 8.0f, 4.0f, 2.0f, 1.0f, 0.5f};
|
||||||
|
|
||||||
// Bitmask covering all 6 control pins in the GPIO register
|
// Bitmask: 0b01111110 = bits 1-6 in GPIO register
|
||||||
static constexpr uint32_t ATTEN_PIN_MASK = (1 << PIN_V1) | (1 << PIN_V2) | (1 << PIN_V3) |
|
static constexpr uint32_t ATTEN_PIN_MASK = 0x7E;
|
||||||
(1 << PIN_V4) | (1 << PIN_V5) | (1 << PIN_V6);
|
|
||||||
|
|
||||||
// --- Status LED ---
|
// --- Status LED ---
|
||||||
static constexpr uint8_t PIN_LED = 15; // Built-in LED, active HIGH
|
static constexpr uint8_t PIN_LED = 15; // Built-in LED, active HIGH
|
||||||
|
|||||||
@ -79,33 +79,18 @@ bool Attenuator::getGPIOState(uint8_t index) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Attenuator::applyToGPIO() {
|
void Attenuator::applyToGPIO() {
|
||||||
// Calculate which pins should be HIGH (bit=0, not attenuating)
|
// Optimized bitwise GPIO update — no loop needed!
|
||||||
// and which should be LOW (bit=1, attenuating)
|
|
||||||
//
|
//
|
||||||
// Active-low logic: step bit set → GPIO LOW → attenuation engaged
|
// Pin mapping: GPIO(n) = step bit (n-1), so step << 1 aligns with GPIOs 1-6
|
||||||
|
// Active-low: step bit 1 → GPIO LOW, step bit 0 → GPIO HIGH
|
||||||
//
|
//
|
||||||
// Using register writes for glitch-free simultaneous update:
|
// Example: step=5 (0b000101 = 2.5dB) → GPIO1,3 LOW, GPIO2,4,5,6 HIGH
|
||||||
// GPIO.out_w1ts = pins to set HIGH (write-1-to-set)
|
|
||||||
// GPIO.out_w1tc = pins to set LOW (write-1-to-clear)
|
|
||||||
|
|
||||||
uint32_t pins_high = 0; // Bits to set HIGH
|
uint32_t step_bits = (_step & 0x3F) << 1; // Step value shifted to GPIO positions
|
||||||
uint32_t pins_low = 0; // Bits to set LOW
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < 6; i++) {
|
// Atomic register writes for glitch-free update
|
||||||
uint32_t pin_bit = 1 << ATTEN_PINS[i];
|
GPIO.out_w1tc = step_bits; // Set LOW where step bit = 1
|
||||||
if (getBit(i)) {
|
GPIO.out_w1ts = (~step_bits) & ATTEN_PIN_MASK; // Set HIGH where step bit = 0
|
||||||
// Step bit is 1 → engage attenuation → GPIO LOW
|
|
||||||
pins_low |= pin_bit;
|
|
||||||
} else {
|
|
||||||
// Step bit is 0 → pass signal → GPIO HIGH
|
|
||||||
pins_high |= pin_bit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atomic-ish register writes (as atomic as we can get without disabling interrupts)
|
|
||||||
// Clear first, then set — ensures no glitch to opposite state
|
|
||||||
GPIO.out_w1tc = pins_low;
|
|
||||||
GPIO.out_w1ts = pins_high;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Attenuator::saveToNVS() {
|
void Attenuator::saveToNVS() {
|
||||||
|
|||||||
@ -1,47 +1,47 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500" width="800" height="500">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 520" width="800" height="520">
|
||||||
<defs>
|
<defs>
|
||||||
<style>
|
<style>
|
||||||
.board { fill: #1a472a; stroke: #0d2818; stroke-width: 2; }
|
.board { fill: #1a472a; stroke: #0d2818; stroke-width: 2; }
|
||||||
.board-label { font-family: monospace; font-size: 14px; font-weight: bold; fill: white; }
|
.board-label { font-family: monospace; font-size: 14px; font-weight: bold; fill: white; }
|
||||||
.pin-label { font-family: monospace; font-size: 11px; fill: #333; }
|
.pin-label { font-family: monospace; font-size: 11px; fill: #333; }
|
||||||
.pin-label-white { font-family: monospace; font-size: 10px; fill: #e0e0e0; }
|
.pin-label-white { font-family: monospace; font-size: 10px; fill: #e0e0e0; }
|
||||||
.wire { stroke-width: 2; fill: none; }
|
.wire { stroke-width: 2.5; fill: none; }
|
||||||
.wire-data { stroke: #2196F3; }
|
.wire-data { stroke: #2196F3; }
|
||||||
.wire-power { stroke: #f44336; }
|
.wire-power { stroke: #f44336; }
|
||||||
.wire-gnd { stroke: #333; }
|
.wire-gnd { stroke: #333; }
|
||||||
.title { font-family: sans-serif; font-size: 18px; font-weight: bold; fill: #333; }
|
.title { font-family: sans-serif; font-size: 18px; font-weight: bold; fill: #333; }
|
||||||
.subtitle { font-family: sans-serif; font-size: 12px; fill: #666; }
|
.subtitle { font-family: sans-serif; font-size: 12px; fill: #666; }
|
||||||
.note { font-family: sans-serif; font-size: 11px; fill: #555; }
|
.note { font-family: sans-serif; font-size: 11px; fill: #555; }
|
||||||
.note-box { fill: #fff8e1; stroke: #ffb300; stroke-width: 1; }
|
.note-box { fill: #e3f2fd; stroke: #1976d2; stroke-width: 1; rx: 5; }
|
||||||
.header { fill: #333; }
|
.header { fill: #333; }
|
||||||
.pin { fill: #c9a227; stroke: #8b7355; stroke-width: 1; }
|
.pin { fill: #c9a227; stroke: #8b7355; stroke-width: 1; }
|
||||||
.sma { fill: #c9a227; stroke: #8b7355; stroke-width: 1; }
|
.sma { fill: #c9a227; stroke: #8b7355; stroke-width: 1; }
|
||||||
.usb { fill: #333; stroke: #222; stroke-width: 1; }
|
.usb { fill: #333; stroke: #222; stroke-width: 1; }
|
||||||
.chip { fill: #1a1a1a; stroke: #333; stroke-width: 1; }
|
.chip { fill: #1a1a1a; stroke: #333; stroke-width: 1; }
|
||||||
|
.code { font-family: monospace; font-size: 10px; fill: #1565c0; }
|
||||||
</style>
|
</style>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
<!-- Title -->
|
<!-- Title -->
|
||||||
<text x="400" y="30" text-anchor="middle" class="title">HMC472A Attenuator Controller Wiring</text>
|
<text x="400" y="28" text-anchor="middle" class="title">HMC472A Attenuator Controller Wiring</text>
|
||||||
<text x="400" y="50" text-anchor="middle" class="subtitle">ESP32-S2 Mini to HMC472A Module Connection Diagram</text>
|
<text x="400" y="46" text-anchor="middle" class="subtitle">Optimized Mapping: GPIO(n) = Step Bit (n-1) — Enables Direct Bitwise Ops</text>
|
||||||
|
|
||||||
<!-- ESP32-S2 Mini Board -->
|
<!-- ESP32-S2 Mini Board -->
|
||||||
<rect x="80" y="100" width="180" height="280" rx="5" class="board"/>
|
<rect x="80" y="80" width="180" height="260" rx="5" class="board"/>
|
||||||
<text x="170" y="125" text-anchor="middle" class="board-label">ESP32-S2 Mini</text>
|
<text x="170" y="102" text-anchor="middle" class="board-label">ESP32-S2 Mini</text>
|
||||||
<text x="170" y="140" text-anchor="middle" class="pin-label-white">(WEMOS/LOLIN)</text>
|
<text x="170" y="116" text-anchor="middle" class="pin-label-white">(WEMOS/LOLIN)</text>
|
||||||
|
|
||||||
<!-- USB-C on S2 Mini -->
|
<!-- USB-C on S2 Mini -->
|
||||||
<rect x="145" y="90" width="50" height="15" rx="3" class="usb"/>
|
<rect x="145" y="70" width="50" height="14" rx="3" class="usb"/>
|
||||||
<text x="170" y="101" text-anchor="middle" style="font-size:8px;fill:#888;">USB-C</text>
|
<text x="170" y="80" text-anchor="middle" style="font-size:8px;fill:#888;">USB-C</text>
|
||||||
|
|
||||||
<!-- ESP32 chip representation -->
|
<!-- ESP32 chip representation -->
|
||||||
<rect x="130" y="155" width="80" height="60" rx="2" class="chip"/>
|
<rect x="130" y="130" width="80" height="50" rx="2" class="chip"/>
|
||||||
<text x="170" y="190" text-anchor="middle" style="font-size:9px;fill:#666;">ESP32-S2</text>
|
<text x="170" y="160" text-anchor="middle" style="font-size:9px;fill:#666;">ESP32-S2</text>
|
||||||
|
|
||||||
<!-- S2 Mini Pin Header (left side, top to bottom) -->
|
<!-- S2 Mini Pin Header (left side) -->
|
||||||
<g transform="translate(85, 230)">
|
<g transform="translate(85, 195)">
|
||||||
<!-- Pin rectangles -->
|
|
||||||
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="30" y="9" class="pin-label-white">3V3</text>
|
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="30" y="9" class="pin-label-white">3V3</text>
|
||||||
<rect x="0" y="15" width="25" height="10" class="pin"/><text x="30" y="24" class="pin-label-white">GPIO1</text>
|
<rect x="0" y="15" width="25" height="10" class="pin"/><text x="30" y="24" class="pin-label-white">GPIO1</text>
|
||||||
<rect x="0" y="30" width="25" height="10" class="pin"/><text x="30" y="39" class="pin-label-white">GPIO2</text>
|
<rect x="0" y="30" width="25" height="10" class="pin"/><text x="30" y="39" class="pin-label-white">GPIO2</text>
|
||||||
@ -53,86 +53,91 @@
|
|||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- S2 Mini Pin Header (right side) -->
|
<!-- S2 Mini Pin Header (right side) -->
|
||||||
<g transform="translate(210, 230)">
|
<g transform="translate(210, 195)">
|
||||||
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="-5" y="9" text-anchor="end" class="pin-label-white">5V</text>
|
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="-5" y="9" text-anchor="end" class="pin-label-white">5V</text>
|
||||||
<rect x="0" y="105" width="25" height="10" class="pin"/><text x="-5" y="114" text-anchor="end" class="pin-label-white">GND</text>
|
<rect x="0" y="105" width="25" height="10" class="pin"/><text x="-5" y="114" text-anchor="end" class="pin-label-white">GND</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- HMC472A Module Board -->
|
<!-- HMC472A Module Board -->
|
||||||
<rect x="520" y="100" width="200" height="280" rx="5" class="board"/>
|
<rect x="520" y="80" width="200" height="260" rx="5" class="board"/>
|
||||||
<text x="620" y="125" text-anchor="middle" class="board-label">HMC472A Module</text>
|
<text x="620" y="102" text-anchor="middle" class="board-label">HMC472A Module</text>
|
||||||
<text x="620" y="140" text-anchor="middle" class="pin-label-white">6-bit RF Attenuator</text>
|
<text x="620" y="116" text-anchor="middle" class="pin-label-white">6-bit RF Attenuator</text>
|
||||||
|
|
||||||
<!-- HMC472A chip representation -->
|
<!-- HMC472A chip representation -->
|
||||||
<rect x="555" y="155" width="60" height="40" rx="2" class="chip"/>
|
<rect x="555" y="130" width="60" height="40" rx="2" class="chip"/>
|
||||||
<text x="585" y="180" text-anchor="middle" style="font-size:8px;fill:#666;">HMC472A</text>
|
<text x="585" y="155" text-anchor="middle" style="font-size:8px;fill:#666;">HMC472A</text>
|
||||||
|
|
||||||
<!-- SMA Connectors -->
|
<!-- SMA Connectors -->
|
||||||
<ellipse cx="540" y="230" rx="15" ry="20" class="sma"/>
|
<ellipse cx="540" cy="200" rx="15" ry="20" class="sma"/>
|
||||||
<text x="540" y="260" text-anchor="middle" class="pin-label-white">RF IN</text>
|
<text x="540" y="228" text-anchor="middle" class="pin-label-white">RF IN</text>
|
||||||
<ellipse cx="700" cy="230" rx="15" ry="20" class="sma"/>
|
<ellipse cx="700" cy="200" rx="15" ry="20" class="sma"/>
|
||||||
<text x="700" y="260" text-anchor="middle" class="pin-label-white">RF OUT</text>
|
<text x="700" y="228" text-anchor="middle" class="pin-label-white">RF OUT</text>
|
||||||
|
|
||||||
<!-- HMC472A Control Header (8-pin) -->
|
<!-- HMC472A Control Header (8-pin) - optimized order -->
|
||||||
<g transform="translate(595, 280)">
|
<g transform="translate(595, 250)">
|
||||||
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="30" y="9" class="pin-label-white">+5V</text>
|
<rect x="0" y="0" width="25" height="10" class="pin"/><text x="30" y="9" class="pin-label-white">+5V</text>
|
||||||
<rect x="0" y="15" width="25" height="10" class="pin"/><text x="30" y="24" class="pin-label-white">V6 (0.5dB)</text>
|
<rect x="0" y="15" width="25" height="10" class="pin"/><text x="30" y="24" class="pin-label-white">V6 (0.5dB) bit0</text>
|
||||||
<rect x="0" y="30" width="25" height="10" class="pin"/><text x="30" y="39" class="pin-label-white">V5 (1dB)</text>
|
<rect x="0" y="30" width="25" height="10" class="pin"/><text x="30" y="39" class="pin-label-white">V5 (1dB) bit1</text>
|
||||||
<rect x="0" y="45" width="25" height="10" class="pin"/><text x="30" y="54" class="pin-label-white">V4 (2dB)</text>
|
<rect x="0" y="45" width="25" height="10" class="pin"/><text x="30" y="54" class="pin-label-white">V4 (2dB) bit2</text>
|
||||||
<rect x="0" y="60" width="25" height="10" class="pin"/><text x="30" y="69" class="pin-label-white">V3 (4dB)</text>
|
<rect x="0" y="60" width="25" height="10" class="pin"/><text x="30" y="69" class="pin-label-white">V3 (4dB) bit3</text>
|
||||||
<rect x="0" y="75" width="25" height="10" class="pin"/><text x="30" y="84" class="pin-label-white">V2 (8dB)</text>
|
<rect x="0" y="75" width="25" height="10" class="pin"/><text x="30" y="84" class="pin-label-white">V2 (8dB) bit4</text>
|
||||||
<rect x="0" y="90" width="25" height="10" class="pin"/><text x="30" y="99" class="pin-label-white">V1 (16dB)</text>
|
<rect x="0" y="90" width="25" height="10" class="pin"/><text x="30" y="99" class="pin-label-white">V1 (16dB) bit5</text>
|
||||||
<rect x="0" y="105" width="25" height="10" class="pin"/><text x="30" y="114" class="pin-label-white">GND</text>
|
<rect x="0" y="105" width="25" height="10" class="pin"/><text x="30" y="114" class="pin-label-white">GND</text>
|
||||||
</g>
|
</g>
|
||||||
|
|
||||||
<!-- Wiring: Power (5V) - Red -->
|
<!-- Wiring: Power (5V) - Red -->
|
||||||
<path d="M 235 235 H 280 V 120 H 560 V 280 H 595" class="wire wire-power"/>
|
<path d="M 235 200 H 280 V 100 H 560 V 250 H 595" class="wire wire-power"/>
|
||||||
<circle cx="235" cy="235" r="4" fill="#f44336"/>
|
<circle cx="235" cy="200" r="4" fill="#f44336"/>
|
||||||
<circle cx="595" cy="285" r="4" fill="#f44336"/>
|
<circle cx="595" cy="255" r="4" fill="#f44336"/>
|
||||||
|
|
||||||
<!-- Wiring: GND - Black -->
|
<!-- Wiring: GND - Black -->
|
||||||
<path d="M 110 340 H 70 V 400 H 580 V 390 H 595" class="wire wire-gnd"/>
|
<path d="M 110 305 H 65 V 375 H 575 V 360 H 595" class="wire wire-gnd"/>
|
||||||
<circle cx="110" cy="340" r="4" fill="#333"/>
|
<circle cx="110" cy="305" r="4" fill="#333"/>
|
||||||
<circle cx="595" cy="390" r="4" fill="#333"/>
|
<circle cx="595" cy="360" r="4" fill="#333"/>
|
||||||
|
|
||||||
<!-- Wiring: GPIO1 → V1 (16dB) - Blue -->
|
<!-- Straight-through data wiring (optimized - no crossovers!) -->
|
||||||
<path d="M 110 250 H 50 V 415 H 590 V 375 H 595" class="wire wire-data"/>
|
<!-- GPIO1 → V6 -->
|
||||||
<circle cx="110" cy="250" r="3" fill="#2196F3"/>
|
<path d="M 110 215 H 60 V 365 H 590 V 270 H 595" class="wire wire-data"/>
|
||||||
<circle cx="595" cy="375" r="3" fill="#2196F3"/>
|
<circle cx="110" cy="215" r="3" fill="#2196F3"/>
|
||||||
|
<circle cx="595" cy="270" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
<!-- Wiring: GPIO2 → V2 (8dB) -->
|
<!-- GPIO2 → V5 -->
|
||||||
<path d="M 110 265 H 55 V 410 H 585 V 360 H 595" class="wire wire-data"/>
|
<path d="M 110 230 H 55 V 370 H 585 V 285 H 595" class="wire wire-data"/>
|
||||||
<circle cx="110" cy="265" r="3" fill="#2196F3"/>
|
<circle cx="110" cy="230" r="3" fill="#2196F3"/>
|
||||||
<circle cx="595" cy="360" r="3" fill="#2196F3"/>
|
<circle cx="595" cy="285" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
<!-- Wiring: GPIO3 → V3 (4dB) -->
|
<!-- GPIO3 → V4 -->
|
||||||
<path d="M 110 280 H 60 V 405 H 580 V 345 H 595" class="wire wire-data"/>
|
<path d="M 110 245 H 50 V 375 H 580 V 300 H 595" class="wire wire-data"/>
|
||||||
<circle cx="110" cy="280" r="3" fill="#2196F3"/>
|
<circle cx="110" cy="245" r="3" fill="#2196F3"/>
|
||||||
<circle cx="595" cy="345" r="3" fill="#2196F3"/>
|
|
||||||
|
|
||||||
<!-- Wiring: GPIO4 → V4 (2dB) -->
|
|
||||||
<path d="M 110 295 H 65 V 395 H 575 V 330 H 595" class="wire wire-data"/>
|
|
||||||
<circle cx="110" cy="295" r="3" fill="#2196F3"/>
|
|
||||||
<circle cx="595" cy="330" r="3" fill="#2196F3"/>
|
|
||||||
|
|
||||||
<!-- Wiring: GPIO5 → V5 (1dB) -->
|
|
||||||
<path d="M 110 310 H 70 V 385 H 570 V 315 H 595" class="wire wire-data"/>
|
|
||||||
<circle cx="110" cy="310" r="3" fill="#2196F3"/>
|
|
||||||
<circle cx="595" cy="315" r="3" fill="#2196F3"/>
|
|
||||||
|
|
||||||
<!-- Wiring: GPIO6 → V6 (0.5dB) -->
|
|
||||||
<path d="M 110 325 H 75 V 375 H 565 V 300 H 595" class="wire wire-data"/>
|
|
||||||
<circle cx="110" cy="325" r="3" fill="#2196F3"/>
|
|
||||||
<circle cx="595" cy="300" r="3" fill="#2196F3"/>
|
<circle cx="595" cy="300" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
|
<!-- GPIO4 → V3 -->
|
||||||
|
<path d="M 110 260 H 45 V 380 H 575 V 315 H 595" class="wire wire-data"/>
|
||||||
|
<circle cx="110" cy="260" r="3" fill="#2196F3"/>
|
||||||
|
<circle cx="595" cy="315" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
|
<!-- GPIO5 → V2 -->
|
||||||
|
<path d="M 110 275 H 40 V 385 H 570 V 330 H 595" class="wire wire-data"/>
|
||||||
|
<circle cx="110" cy="275" r="3" fill="#2196F3"/>
|
||||||
|
<circle cx="595" cy="330" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
|
<!-- GPIO6 → V1 -->
|
||||||
|
<path d="M 110 290 H 35 V 390 H 565 V 345 H 595" class="wire wire-data"/>
|
||||||
|
<circle cx="110" cy="290" r="3" fill="#2196F3"/>
|
||||||
|
<circle cx="595" cy="345" r="3" fill="#2196F3"/>
|
||||||
|
|
||||||
<!-- Legend -->
|
<!-- Legend -->
|
||||||
<rect x="280" y="420" width="240" height="70" rx="5" class="note-box"/>
|
<rect x="270" y="410" width="260" height="100" rx="5" class="note-box"/>
|
||||||
<text x="400" y="438" text-anchor="middle" style="font-weight:bold;" class="note">Wiring Summary</text>
|
<text x="400" y="428" text-anchor="middle" style="font-weight:bold;" class="note">Optimized Bitwise Mapping</text>
|
||||||
<line x1="290" y1="445" x2="310" y2="445" stroke="#f44336" stroke-width="3"/>
|
|
||||||
<text x="315" y="449" class="note">Power (+5V)</text>
|
<line x1="285" y1="445" x2="305" y2="445" stroke="#2196F3" stroke-width="3"/>
|
||||||
<line x1="400" y1="445" x2="420" y2="445" stroke="#333" stroke-width="3"/>
|
<text x="310" y="449" class="note">Data: GPIO(n) → V(7-n)</text>
|
||||||
<text x="425" y="449" class="note">Ground</text>
|
|
||||||
<line x1="290" y1="465" x2="310" y2="465" stroke="#2196F3" stroke-width="3"/>
|
<line x1="285" y1="465" x2="305" y2="465" stroke="#f44336" stroke-width="3"/>
|
||||||
<text x="315" y="469" class="note">Data (GPIO→Vx)</text>
|
<text x="310" y="469" class="note">Power (+5V from USB)</text>
|
||||||
<text x="400" y="483" text-anchor="middle" class="note" style="font-style:italic;">Active-LOW: LOW=Attenuate, HIGH=Pass</text>
|
|
||||||
|
<line x1="285" y1="485" x2="305" y2="485" stroke="#333" stroke-width="3"/>
|
||||||
|
<text x="310" y="489" class="note">Ground</text>
|
||||||
|
|
||||||
|
<text x="400" y="503" text-anchor="middle" class="code">GPIO.out_w1tc = (step & 0x3F) << 1</text>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.8 KiB |
@ -4,33 +4,51 @@
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Pin Mapping Table
|
## Pin Mapping (Optimized for Bitwise Ops)
|
||||||
|
|
||||||
| ESP32-S2 Mini | HMC472A Module | Function | Attenuation |
|
The wiring is arranged so GPIO number = step bit position + 1, enabling single-instruction bitwise operations in firmware.
|
||||||
|
|
||||||
|
| ESP32-S2 Mini | HMC472A Module | Step Bit | Attenuation |
|
||||||
|---------------|----------------|----------|-------------|
|
|---------------|----------------|----------|-------------|
|
||||||
| GPIO1 | V1 | Bit 5 (MSB) | 16 dB |
|
| GPIO1 | V6 | Bit 0 (LSB) | 0.5 dB |
|
||||||
| GPIO2 | V2 | Bit 4 | 8 dB |
|
| GPIO2 | V5 | Bit 1 | 1 dB |
|
||||||
| GPIO3 | V3 | Bit 3 | 4 dB |
|
| GPIO3 | V4 | Bit 2 | 2 dB |
|
||||||
| GPIO4 | V4 | Bit 2 | 2 dB |
|
| GPIO4 | V3 | Bit 3 | 4 dB |
|
||||||
| GPIO5 | V5 | Bit 1 | 1 dB |
|
| GPIO5 | V2 | Bit 4 | 8 dB |
|
||||||
| GPIO6 | V6 | Bit 0 (LSB) | 0.5 dB |
|
| GPIO6 | V1 | Bit 5 (MSB) | 16 dB |
|
||||||
| 5V (VBUS) | +5V | Power | — |
|
| 5V (VBUS) | +5V | — | Power |
|
||||||
| GND | GND | Ground | — |
|
| GND | GND | — | Ground |
|
||||||
|
|
||||||
|
### Why This Mapping?
|
||||||
|
|
||||||
|
```c
|
||||||
|
// Old approach (loop required):
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
pin = ATTEN_PINS[5-i]; // Reverse mapping
|
||||||
|
if (step & (1 << i)) set_low(pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New approach (pure bitwise):
|
||||||
|
GPIO.out_w1tc = (step & 0x3F) << 1; // Set LOW where step=1
|
||||||
|
GPIO.out_w1ts = (~step & 0x3F) << 1 & 0x7E; // Set HIGH where step=0
|
||||||
|
```
|
||||||
|
|
||||||
|
The step value bits map directly to GPIO register positions. No loop, no lookup table.
|
||||||
|
|
||||||
## HMC472A Module Header Pinout
|
## HMC472A Module Header Pinout
|
||||||
|
|
||||||
The 8-pin header on the HMC472A module (top to bottom when viewing from component side):
|
The 8-pin header on the HMC472A module (top to bottom when viewing from component side):
|
||||||
|
|
||||||
| Pin | Signal | Description |
|
| Pin | Signal | ESP32 GPIO | Description |
|
||||||
|-----|----------|--------------------------|
|
|-----|----------|------------|--------------------------|
|
||||||
| 1 | +5V | Power supply (+5V DC) |
|
| 1 | +5V | 5V VBUS | Power supply (+5V DC) |
|
||||||
| 2 | V6 | 0.5 dB control (active-low) |
|
| 2 | V6 | GPIO1 | 0.5 dB (step bit 0, LSB) |
|
||||||
| 3 | V5 | 1 dB control (active-low) |
|
| 3 | V5 | GPIO2 | 1 dB (step bit 1) |
|
||||||
| 4 | V4 | 2 dB control (active-low) |
|
| 4 | V4 | GPIO3 | 2 dB (step bit 2) |
|
||||||
| 5 | V3 | 4 dB control (active-low) |
|
| 5 | V3 | GPIO4 | 4 dB (step bit 3) |
|
||||||
| 6 | V2 | 8 dB control (active-low) |
|
| 6 | V2 | GPIO5 | 8 dB (step bit 4) |
|
||||||
| 7 | V1 | 16 dB control (active-low) |
|
| 7 | V1 | GPIO6 | 16 dB (step bit 5, MSB) |
|
||||||
| 8 | GND | Ground |
|
| 8 | GND | GND | Ground |
|
||||||
|
|
||||||
## Logic Levels
|
## Logic Levels
|
||||||
|
|
||||||
@ -42,36 +60,59 @@ The HMC472A accepts 0–5V TTL/CMOS logic. The ESP32-S2's 3.3V GPIO output is fu
|
|||||||
|
|
||||||
## Attenuation Examples
|
## Attenuation Examples
|
||||||
|
|
||||||
| GPIO State (1-6) | Step | Total Attenuation |
|
| Step | Binary | GPIO State (1-6) | Total Attenuation |
|
||||||
|------------------|------|-------------------|
|
|------|------------|------------------|-------------------|
|
||||||
| `111111` (all HIGH) | 0 | 0 dB (insertion loss only) |
|
| 0 | `0b000000` | `HHHHHH` | 0 dB |
|
||||||
| `111110` | 1 | 0.5 dB |
|
| 1 | `0b000001` | `LHHHHH` | 0.5 dB |
|
||||||
| `111100` | 3 | 1.5 dB |
|
| 5 | `0b000101` | `LHLHHH` | 2.5 dB |
|
||||||
| `110000` | 15 | 7.5 dB |
|
| 31 | `0b011111` | `LLLLLH` | 15.5 dB |
|
||||||
| `100000` | 31 | 15.5 dB |
|
| 63 | `0b111111` | `LLLLLL` | 31.5 dB |
|
||||||
| `000000` (all LOW) | 63 | 31.5 dB |
|
|
||||||
|
|
||||||
Formula: `attenuation = step × 0.5 dB` where step = 0–63
|
Formula: `attenuation = step × 0.5 dB` where step = 0–63
|
||||||
|
|
||||||
|
## Wiring Diagram (Text)
|
||||||
|
|
||||||
|
```
|
||||||
|
ESP32-S2 Mini HMC472A Module
|
||||||
|
(Left Header) (8-pin Header)
|
||||||
|
|
||||||
|
3V3 ─┤ 1 ┌─────┐
|
||||||
|
──────────────────────────────┐ │ +5V │← 1
|
||||||
|
GPIO1 ─┤ 2 ───────────────────│ V6 │← 2 (0.5 dB)
|
||||||
|
GPIO2 ─┤ 3 ───────────────────│ V5 │← 3 (1 dB)
|
||||||
|
GPIO3 ─┤ 4 ───────────────────│ V4 │← 4 (2 dB)
|
||||||
|
GPIO4 ─┤ 5 ───────────────────│ V3 │← 5 (4 dB)
|
||||||
|
GPIO5 ─┤ 6 ───────────────────│ V2 │← 6 (8 dB)
|
||||||
|
GPIO6 ─┤ 7 ───────────────────│ V1 │← 7 (16 dB)
|
||||||
|
GND ─┤ 8 ───────────────────│ GND │← 8
|
||||||
|
└─────┘
|
||||||
|
(Right Header)
|
||||||
|
5V ─┤ 16 ─────────────────┘ (to +5V)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** The diagram shows straight-through wiring (no crossovers) because the optimized mapping aligns GPIO numbers with the module header in reverse order.
|
||||||
|
|
||||||
## ESP32-S2 Mini Physical Pinout
|
## ESP32-S2 Mini Physical Pinout
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────┐
|
┌─────────────────┐
|
||||||
│ USB-C │
|
│ USB-C │
|
||||||
└─────────────────┘
|
└─────────────────┘
|
||||||
3V3 ─┤ 1 16 ├─ 5V (VBUS) ◄── Power to HMC472A
|
3V3 ─┤ 1 16 ├─ 5V (VBUS) ──► +5V
|
||||||
GPIO1 ─┤ 2 15 ├─ GPIO15 (LED)
|
GPIO1 ─┤ 2 15 ├─ GPIO15 (LED) │
|
||||||
GPIO2 ─┤ 3 14 ├─ GPIO14
|
GPIO2 ─┤ 3 14 ├─ GPIO14 │
|
||||||
GPIO3 ─┤ 4 13 ├─ GPIO13
|
GPIO3 ─┤ 4 13 ├─ GPIO13 │
|
||||||
GPIO4 ─┤ 5 12 ├─ GPIO12
|
GPIO4 ─┤ 5 12 ├─ GPIO12 │
|
||||||
GPIO5 ─┤ 6 11 ├─ GPIO11
|
GPIO5 ─┤ 6 11 ├─ GPIO11 │
|
||||||
GPIO6 ─┤ 7 10 ├─ GPIO10
|
GPIO6 ─┤ 7 10 ├─ GPIO10 │
|
||||||
GND ─┤ 8 9 ├─ GPIO9
|
GND ─┤ 8 9 ├─ GPIO9 │
|
||||||
└─────────────────┘
|
└─────────────────┘ │
|
||||||
(Left header)
|
↓ ↓ ↓ ↓ ↓ ↓ │
|
||||||
|
V6 V5 V4 V3 V2 V1 ◄───────────┘
|
||||||
|
(HMC472A control pins + power)
|
||||||
```
|
```
|
||||||
|
|
||||||
GPIOs 1–6 are on the left header, pins 2–7. Convenient sequential layout for ribbon cable.
|
GPIOs 1–6 are on the left header, pins 2–7. Direct ribbon cable from S2 Mini left header to HMC472A control header (reversed).
|
||||||
|
|
||||||
## KiCad Schematic
|
## KiCad Schematic
|
||||||
|
|
||||||
@ -81,5 +122,6 @@ A full KiCad schematic is available at `hmc472-controller.kicad_sch` for detaile
|
|||||||
|
|
||||||
1. **No level shifting required** — ESP32-S2 3.3V GPIO drives HMC472A directly
|
1. **No level shifting required** — ESP32-S2 3.3V GPIO drives HMC472A directly
|
||||||
2. **Boot state** — GPIOs default HIGH at boot = 0 dB attenuation (safe)
|
2. **Boot state** — GPIOs default HIGH at boot = 0 dB attenuation (safe)
|
||||||
3. **Glitch-free switching** — Firmware uses register-level writes (`GPIO.out_w1ts`/`GPIO.out_w1tc`) to change all 6 bits atomically
|
3. **Glitch-free switching** — Firmware uses register-level writes (`GPIO.out_w1ts`/`GPIO.out_w1tc`)
|
||||||
4. **Power** — The S2 Mini's 5V pin sources USB VBUS directly, sufficient for HMC472A's 2.5 mA draw
|
4. **Power** — The S2 Mini's 5V pin sources USB VBUS directly, sufficient for HMC472A's 2.5 mA draw
|
||||||
|
5. **Bitwise optimization** — GPIO = bit + 1 mapping eliminates loop in firmware
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user