diff --git a/doc/devices/SWTG018AS_A_V2_0.md b/doc/devices/SWTG018AS_A_V2_0.md index 0d12ecd..5165ebc 100644 --- a/doc/devices/SWTG018AS_A_V2_0.md +++ b/doc/devices/SWTG018AS_A_V2_0.md @@ -1,4 +1,10 @@ # SWTG018AS-A V2.0 +## Brands +| Brand | Type |Managed| PCB | Flash | Chip RTL | +|--------|------------------|-------|------------------|-----------------|---------------| +| Ampcom | SWTG018AS-A V2.0 | No | SWTG018AS-A V2.0 | 2MB | 8273N + 8224N | +| Horaco | HC-SWTGW218AS-A | Yes | SWTG018AS-A V2.0 | 2MB(25Q16JVSIQ) | 8273N + 8224N | + The following is a documentation for the unmanaged switch marked as `SWTG018AS-A V2.0`. It is e.g. sold under the Ampcom brand, but no branh-markings are found on the device. diff --git a/doc/devices/SWTG024AS-V2.0.md b/doc/devices/SWTG024AS-V2.0.md new file mode 100644 index 0000000..c787428 --- /dev/null +++ b/doc/devices/SWTG024AS-V2.0.md @@ -0,0 +1,49 @@ +### SWTG024AS-V2.0 + +## Brands +|Brand|Type|Managed|PCB|Flash|Chip RTL| +|---|---|---|---|---|---| +| hongyavision | LG-SG5T1 | No | PCB-SWTG024AS-V2.0_16895 | 25Q40 | 8272 | + +### Label specifications + +- **Name**: +- **Ports**: + - 5 × RJ45: 10/100/1000/2500 Mbps + - 1 × SFP+: 1000 / 2500 / 10000 Mbps +- **Power**: 12V DC, 1A 5525 connector + + + +### What works +The device is fully supported: +- ALL 2.5GBASE-T RJ45 ports work at 10/100/1000/2500 Mbps +- The SFP+ port supports 1G, 2.5G and 10G modules +- LEDs work with the same indiciations as the OEM firmware +- Online update does not work with 512KiB flash. +### PCB overview + +**Board markings** +- Top silkscreen: PCB-SWTG024AS-V2.0 + +Top side + + + +Bottom + + + +### J1, serial console + +| `J1` pin | Signal | +| -------- | ----------- | +| 1 | GND | +| 2 | RX (Input) | +| 3 | TX (Output) | + +Note,`R52`、`R53`may not be installed.You need to bridge them using either solder or resistors. + +## Power supply + +Input power is delivered via barell plug, `12V 1A` adapter was provided. \ No newline at end of file diff --git a/doc/devices/SWTGW218AS.md b/doc/devices/SWTGW218AS.md index c8777f2..4797125 100644 --- a/doc/devices/SWTGW218AS.md +++ b/doc/devices/SWTGW218AS.md @@ -6,6 +6,7 @@ | Mokerlink | ZX-SWTGW218AS | Yes| SWTG118AS-V2.0-16029 | 2MB (FM25Q16A)| 8273N + 8224N | | Sodola | | | | | | | Horaco | | | | | | +| XikeStor | SKS3200-8E1X | Yes | SWTG118AS-V2.1-17462 | 2MB (25Q16JVSIQ) | | ## Photos diff --git a/doc/devices/photos/SWTG024AS-V2.0/label.jpg b/doc/devices/photos/SWTG024AS-V2.0/label.jpg new file mode 100644 index 0000000..f2c628a Binary files /dev/null and b/doc/devices/photos/SWTG024AS-V2.0/label.jpg differ diff --git a/doc/devices/photos/SWTG024AS-V2.0/pcb_bottom.jpg b/doc/devices/photos/SWTG024AS-V2.0/pcb_bottom.jpg new file mode 100644 index 0000000..c1ac456 Binary files /dev/null and b/doc/devices/photos/SWTG024AS-V2.0/pcb_bottom.jpg differ diff --git a/doc/devices/photos/SWTG024AS-V2.0/pcb_top.jpg b/doc/devices/photos/SWTG024AS-V2.0/pcb_top.jpg new file mode 100644 index 0000000..496391b Binary files /dev/null and b/doc/devices/photos/SWTG024AS-V2.0/pcb_top.jpg differ diff --git a/doc/supported_devices.md b/doc/supported_devices.md index c1b3f9a..b367c1e 100644 --- a/doc/supported_devices.md +++ b/doc/supported_devices.md @@ -1,18 +1,35 @@ # Supported Hardware The following devices have been tested and are fully working: -- Horaco ZX_SG4T2 -- keepLINK KP-9000-6XH-X2 / KP-9000-6XHML-X2 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+); - select the machine target by PCB revision, see [KP-9000-6XH-X2](devices/KP-9000-6XH-X2.md) -- keepLINK kp-9000-6hx-x (RTL8372 + RTL8221B 2.5GBit PHY: 5 x 2.5GBit + 1x 10GBit SFP+) -- keepLINK kp-9000-9xh-x-eu (1 x RTL8373 + RTL8224: 8x 2.5GBit + 1x 10GBit SFP+) -- Lianguo LG-SWTGW218AS (RTL8373 + RTL8224 PHY: 8x 2.5GBit + 1x 10GBit SFP+) -- No-Name ZX-SWTGW215AS, managed version of kp-9000-6hx-x, ordered on - AliExpress as keepLINK 5+1 port managed -- TrendNet TEG-S562 (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+) -- FNS-1200P (RTL8372: 4x 2.5GBit + 2x 10GBit SFP+) -Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide] -(https://github.com/up-n-atom/SWTG118AS) +| Brand | Type | Managed | PCB | Flash | Ports | +|----------|-----------------|---------|------------------------------------------------------------------------------------------------------------------|-------|-------| +| Ampcom | WAM902-SWTG018AS| No | [SWTG018AS-A V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG018AS_A_V2_0.md) | | 8 + 1 | +| Davuaz | Da-K6501W | No | [PCB-K0501W-V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/K0501W_V2_0.md) | | 5 + 1 | +| FOXNEO | FNS-1200P | No | [PCB-K0402W-U13-V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/FNS-1200P.md) | 2M | 4 + 2 | +| Hisource | Hi-K0402WS | No | [PCB-K0402WS-V3.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/PCB-K0402WS-V3.0.md) | | 4 + 2 | +| Hisource | Hi-K0801WS | No | [PCB-KO801W-V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/HI-K0801WS.md) | | 8 + 1 | +| hongyavision | LG-SG5T1 | No | [PCB-SWTG024AS-V2.0_16895](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG024AS-V2.0.md) | 0.5M | 5 + 1 | +| Horaco | HC-SWTGW218AS | Yes | [SWTG018AS-A V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG018AS_A_V2_0.md) | | 8 + 1 | +| Horaco | ZX310S-4T2XH | Yes | [PCB-SL310S-4T1T1X-V1.0.1-24107](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/ZX310S-4T2XH.md) | 2M | 5 + 1 | +| Horaco | ZX310S-4T2XT | Yes | [PCB-SL310S-4T2XT-V1.0.0-22273](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/ZX310S-4T2XT.md) | 2M | 6 | +| Horaco | ZX-SWTG124AS | Yes | [SWTG024AS-v2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG024AS.md) | | 4 + 2 | +| Keeplink | KP-9000-6XH-X2 / KP-9000-6XHML-X2 | No/Yes | [2M-PCB43-V1.2 / V2.1](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/KP-9000-6XH-X2.md) | | 4 + 2 | +| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V2.2](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/2M-PCB23-V2_2.md) | 2M | 8 + 1 | +| keepLINK | KP-9000-9XHML-X | Yes | [2M-PCB23-V3.1](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/2M-PCB23-V3_1.md) | 2M | 8 + 1 | +| LIANGUO | SWTG024AS | No | [SWTG024AS-v2.0-17452](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG024AS.md) | 0.5M | 4 + 2 | +| Lianguo | ZX-SWTGW215AS | Yes | [PCB-SWTG115AS-V2.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTGW215AS.md) | 2M | 5 + 1 | +| Mokerlink| ZX-SWTGW218AS | Yes | [SWTG118AS-V2.0-16029](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTGW218AS.md) | 2M | 8 + 1 | +| Sodola | SL-SWTG124AS-D | Yes | [SWTG024AS-v2.0-17452](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG024AS.md) | 2M | 4 + 2 | +| Steamemo | IG204-V1 | No | [PB-2131](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/STEAMEMO_IG204_V1.md) | | 4 + 2 | +| TrendNet | TEG-S562 | No | [TEG-S563/EU H/W: V1.0R](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/TEG-S562.md) | 2M | 4 + 2 | +| Xikestore| SKS3200M-4GPY2XF| Yes | [SWTG024AS-v1.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTG024AS.md) | | 4 + 2 | +| XikeStor | SKS3200-8E1X | Yes | [SWTG118AS-V2.1-17462](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/SWTGW218AS.md) | 2M | 8 + 1 | +| Ztyuav | Z-QWYT0402 | No | [PCB-K0402WS-V3.0](https://github.com/logicog/RTLPlayground/blob/main/doc/devices/PCB-K0402WS-V3.0.md) | | 4 + 2 | + +For KP-9000-6XH-X2 / KP-9000-6XHML-X2 devices, select the machine target by PCB +revision. The managed/unmanaged label alone does not identify the wiring. + +Other device based on RTL8272/3 that may work are described here: [Up-N-Atoms 2.5 GBit RTL Switch hacking guide](https://github.com/up-n-atom/SWTG118AS) Many of the RTL8272/3 devices come in versions with PoE support. The RTLPlayground usually also works on these, however, no support for configuring PoE is provided, simply because these diff --git a/html/config.js b/html/config.js index dd8512b..6efa283 100644 --- a/html/config.js +++ b/html/config.js @@ -14,6 +14,7 @@ const conf_cmds = [ /^pvid\s+\d{1,2}\s+\d{1,4}$/, /^ingress(\s+\d{1,2}[tua])+$/, /^ingress\s+[tua]$/, + /^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/, /^port\s+\d{1,2}\s+name\s+\S+$/, /^eee(\s+\d{1,2})?\s+(on|off)$/, /^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/, @@ -36,6 +37,7 @@ const conf_overwrite = [ /^vlan\s+\d{1,4}(?!\s+mgmt\b)/, /^pvid\s+\d{1,2}\b/, /^ingress\b/, + /^port\s+\d{1,2}(?!\s+name\b)/, /^port\s+\d{1,2}\s+name\b/, /^eee\s+\d{1,2}\b/, /^eee\b/, @@ -57,8 +59,7 @@ function parseConf(s){ const deleteMatch = line.match(/^vlan\s+(\d{1,4})\s+d$/); if (deleteMatch) { const prefix = "vlan " + deleteMatch[1] + " "; - configuration = configuration.filter(c => - c !== "vlan " + deleteMatch[1] && !c.startsWith(prefix)); + configuration = configuration.filter(c => !c.startsWith(prefix)); continue; } console.log(l + ' --> ' + line); @@ -71,10 +72,13 @@ function parseConf(s){ let m = line.match(x); let matchStr = m[0]; configuration = configuration.filter(item => - !(item === matchStr || item.startsWith(matchStr + " "))); + !(item === matchStr || (item.startsWith(matchStr + " ") && !item.endsWith(" mgmt") && !item.startsWith(matchStr + " name ")))); break; } } + // Only one management VLAN can be active, so drop any previous mgmt entry + if (/^vlan\s+\d{1,4}\s+mgmt$/.test(line)) + configuration = configuration.filter(item => !/^vlan\s+\d{1,4}\s+mgmt$/.test(item)); configuration.push(line); } console.log("Configuration now:"); diff --git a/machine.c b/machine.c index 96c6f0b..a25fe98 100644 --- a/machine.c +++ b/machine.c @@ -365,7 +365,7 @@ __code const struct machine machine = { .sfp_port[0].pin_tx_disable = GPIO_NA, .sfp_port[0].sds = 1, .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, - .reset_pin = GPIO_NA, + .reset_pin = GPIO48_I2C_SCL1, .high_leds = { .mux = LED_27 | LED_29, .enable = LED_28_SYS | LED_29 }, .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1}, .led_sets = { @@ -917,6 +917,68 @@ void machine_custom_init(void) reg_bit_clear(RTL837X_REG_LED_MODE, 7); } +#elif defined MACHINE_SWTG024AS_V2_0 +__code const struct machine machine = { + .machine_name = "SWTG024AS-V2.0", + .isRTL8373 = 0, + .min_port = 3, + .max_port = 8, + .n_sfp = 1, + .log_to_phys_port = {0, 0, 0, 5, 1, 2, 3, 4, 6}, + .phys_to_log_port = {4, 5, 6, 7, 3, 8, 0, 0, 0}, + .is_sfp = {0, 0, 0, 0, 0, 0, 0, 0, 1}, + .sfp_port[0].pin_detect = GPIO30_ACL_BIT3_EN, + .sfp_port[0].pin_los = GPIO37, + .sfp_port[0].pin_tx_disable = GPIO_NA, + .sfp_port[0].sds = 1, + .sfp_port[0].i2c = { .sda = GPIO39_I2C_SDA4, .scl = GPIO40_I2C_SCL3_MDC1 }, + + .reset_pin = GPIO_NA, + .high_leds = { .mux = LED_28_SYS | LED_29, .enable = LED_27 | LED_28_SYS | LED_29 }, + .port_led_set = { 0, 0, 0, 0, 0, 0, 0, 0, 1}, + /* Ports 1-5 RJ45 use set 0, port 9 SFP uses set 1 + * Ports 1-5: Green: 2.5GBit, Amber: 10/100/1000MBit + * SFP-port: Blue: 10GBit, Amber: 100MBit-2.5GBit + */ + .led_sets = { + { + LEDS_2G5 | LEDS_LINK | LEDS_ACT, + LEDS_1G | LEDS_100M | LEDS_10M | LEDS_LINK | LEDS_ACT, + LEDS_DUPLEX, + LEDS_2G5 | LEDS_LINK | LEDS_ACT + }, + { + LEDS_2G5 | LEDS_1G | LEDS_100M | LEDS_LINK | LEDS_ACT, + LEDS_10G | LEDS_LINK | LEDS_ACT, + LEDS_2G5 | LEDS_LINK, + LEDS_COL | LEDS_DUPLEX + }, + }, + .led_mux_custom = 1, + .led_mux = { + 0x00,0x01,0x04,0x05,0x08,0x09,0x0c,0x3f,0x0d,0x10,0x11,0x0e,0x14,0x11,0x12,0x15,0x15,0x16,0x18,0x19,0x1a,0x19,0x1d,0x1e,0x1c,0x1d,0x20,0x21 + }, + }; + +void machine_custom_init(void) +{ + uint16_t pval; + + reg_bit_set(RTL837X_REG_LED_GLB_IO_EN, 6); + reg_bit_set(RTL837X_REG_LED_MODE, 17); + reg_bit_clear(RTL837X_REG_LED_MODE, 9); + reg_bit_clear(RTL837X_REG_LED_MODE, 7); + + // OEM firmware sets these companion SDS0 polarity bits for the RTL8221B. + sds_read(0, 0, 0); + pval = SFR_DATA_U16; + sds_write_v(0, 0, 0, pval | 0x100); + + sds_read(0, 6, 2); + pval = SFR_DATA_U16; + sds_write_v(0, 6, 2, pval | 0x4000); +} + #elif defined MACHINE_ZX310S_4T2XT __code const struct machine machine = { .machine_name = "ZX310S_4T2XT", diff --git a/machine.h b/machine.h index 3483f2e..5ae75c9 100644 --- a/machine.h +++ b/machine.h @@ -31,6 +31,7 @@ // #define MACHINE_HI_K0801WS // #define MACHINE_FNS1200P // #define MACHINE_PCB_SWTG024AS_A_2_0_1 +// #define MACHINE_SWTG024AS_V2_0 typedef struct { // GPIO pins for SDA/SCL diff --git a/tools/led_gpio_utils/README.md b/tools/led_gpio_utils/README.md new file mode 100644 index 0000000..e0ac336 --- /dev/null +++ b/tools/led_gpio_utils/README.md @@ -0,0 +1,149 @@ +# LED GPIO Utilities + +This directory contains utility talking to RTL837x switch IC via I2C bus. +These scripts are designed to help with monitoring, debugging GPIO, and identifying LED configurations. +(Only tested in Linux) + +## Hardware requirements + +To use these utilities, you need: + + - A hardware dongle that can communicate with I2C devices. One example is the [I2C-Pico-USB](https://github.com/dquadros/I2C-Pico-USB) which provides USB-to-I2C connectivity. + - Connection between the hardware dongle and the RTL837x's I2C communication port. + +## Scripts + +### 1. `i2c_read_rtl_gpio.py` + +This script reads RTL GPIO register values via I2C and displays changes in GPIO states. + +**Features:** + + - Reads live RTL GPIO register values via I2C (default address 0x5C) + - Monitors GPIO changes with delta detection + - Allows specification of I2C bus, sleep interval, and ignored GPIO pins + - Shows changes in real-time with GPIO index display + +**Usage:** +```bash +# Basic usage (defaults to I2C bus 1, 2s sleep interval) +python3 i2c_read_rtl_gpio.py + +# Specify I2C bus +python3 i2c_read_rtl_gpio.py --i2c-bus 0 + +# Specify sleep interval in seconds +python3 i2c_read_rtl_gpio.py --sleep-interval 5 + +# Ignore specific GPIO pins +python3 i2c_read_rtl_gpio.py --ignored-ios 28 31 34 44 + +# Combine options +python3 i2c_read_rtl_gpio.py --i2c-bus 2 --sleep-interval 1 --ignored-ios 28 31 +``` + +**Output Format:** + + - Displays register address and data in hex format + - Shows GPIO pins that have changed since last read + - Example: `0044: 00 00 00 00 00 00 00 00` + +### 2. `i2c_dump_rtl_regs.py` + +This script dumps all register values from an RTL device via I2C. + +**Features:** + + - Dumps registers sequentially from address 0x0000 to 0xFFFF + - Reads 16 bytes at a time for efficiency + - Configurable I2C bus number + - Provides complete register dump in hex format + +**Usage:** +```bash +# Basic usage (defaults to I2C bus 1) +python3 i2c_dump_rtl_regs.py >reg_dump.txt + +# Specify I2C bus +python3 i2c_dump_rtl_regs.py --bus 0 >reg_dump.txt + +# Or using short option +python3 i2c_dump_rtl_regs.py -b 2 >reg_dump.txt +``` + +**Output Format:** + + - Displays address and 16 bytes of data in hex format + - Example: `0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00` + +### 3. `dec_leds_from_dump.py` + +This script decodes LED configuration from a register dump file ( the output from `i2c_dump_rtl_regs.py`). + +**Features:** + + - Parses register dump files (reg_dump.txt format) + - Decodes LED pad configurations and LED sets + - Maps LED types to bit positions based on configuration + - Outputs LED mux configuration and set mappings + +**Usage:** +```bash +# Must be run in same directory as reg_dump.txt +python3 dec_leds_from_dump.py +``` + +**Output Format:** + + - LED pad configuration (hex values for each pad) + - LED set configurations with descriptions of LED types + - Port selection mappings + +**Requirements:** + + - Requires a `reg_dump.txt` file containing the register dump output + +## Requirements + +All scripts require: + + - Python 3 + - `smbus2` Python package + +(Depend upon Linux distribution) Install with: +```bash +apt install python3-smbus2 +``` +OR +```bash +pip3 install smbus2 +``` + + +## Common Use Cases + +Both `i2c_read_rtl_gpio.py` and `i2c_dump_rtl_regs.py` shall run with the **original** firmware, not RTLPlayground firmware. + + +### Monitoring GPIO Changes +```bash +# Monitor GPIO changes on bus 1 with 1-second intervals +python3 i2c_read_rtl_gpio.py --i2c-bus 1 --sleep-interval 1 +``` + +### Register Analysis +```bash +# Dump all device registers +python3 i2c_dump_rtl_regs.py --bus 2 > reg_dump.txt + +# Analyze the register dump to understand LED configuration +python3 dec_leds_from_dump.py +``` + +## Configuration + +All scripts support command-line arguments for flexible configuration: + + - `--i2c-bus` or `-b`: Specify I2C bus (default: 1) + - `--sleep-interval` or `-s`: Sleep between reads in seconds (default: 2) + - `--ignored-ios` or `-i`: GPIO pins to ignore (default: [28, 31, 34, 44]) diff --git a/tools/led_gpio_utils/dec_leds_from_dump.py b/tools/led_gpio_utils/dec_leds_from_dump.py new file mode 100755 index 0000000..5885068 --- /dev/null +++ b/tools/led_gpio_utils/dec_leds_from_dump.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +regs = list(range(65536)) + +glb_mux = 0x65E0 + +led3_0_set1 = 0x6528 +led1_0_set0 = 0x6548 +led_port_sel = 0x654C + + +def get_word(i): + val = (regs[i + 3] << 24) + (regs[i + 2] << 16) + (regs[i + 1] << 8) + regs[i] + # print(f"READING {i:04x} : {val:08x}") + return val + + +with open("reg_dump.txt", "r") as file: + for line in file: + addr, data = line.split(":") + data = [int(x, 16) for x in data.strip().split(" ")] + addr = int(addr, 16) + for x in range(len(data)): + regs[addr + x] = data[x] + +ledstr = [] +ledfmt = [] +print("LED pad Configuration:") +for i in range(28): + j = i % 5 + if j == 0: + idx = glb_mux + (i // 5) * 4 + val = get_word(idx) + ledval = (val >> (6 * j)) & 0x3F + ledstr.append(f"{ledval:02x}") + ledfmt.append(f"{i:02x}") +print(f"{' '.join(ledfmt)}") +print(f"{' '.join(ledstr)}") +print(f".led_mux = {{ 0x{', 0x'.join(ledstr)} }},") + +LED_TYPES = [ + " 10G", + 16, + " TWO_5G", + 17, + " 5G", + 18, + " TWO_2G5", + 19, + " 2G5", + 0, + " TWO_1G", + 1, + " 1G", + 2, + " 500M", + 3, + " 100M", + 4, + " 10M", + 5, + " LINK", + 6, + " LINK_FLASH", + 7, + " ACT", + 8, + " RX", + 9, + " TX", + 10, + " COL", + 11, + " DUPLEX", + 12, + " TRAINING", + 13, + " MASTER", + 14, + "", + 15, +] + +led_set = [] +led_set_str = [] +print("\nLED-set Configuration:") +print("LED-ID 0 1 2 3") +for i in range(4): + idval = [] + idvalstr = [] + for id in range(4): + val = 0xFFFF & ( + get_word(led1_0_set0 - 8 * i - ((id >> 1) << 2)) >> (16 * (id & 1)) + ) + valhi = ( + 0xF & (get_word(led3_0_set1 - 4 * (i >> 1)) >> (16 * (i & 1) + 4 * id)) + ) << 16 + val += valhi + idval.append(val) + valstr = "(" + for bit in range(0, len(LED_TYPES), 2): + if val & (1 << (LED_TYPES[bit + 1])): + valstr += LED_TYPES[bit] + valstr += ")" + idvalstr.append(valstr) + led_set.append(idval) + led_set_str.append(idvalstr) + idstr = " ".join([f"{d:05x}" for d in idval]) + print(f"SET {i}: {idstr}") + # print(f"{idvalstr}") + +portsel = get_word(led_port_sel) +for i in range(3, 9): + sel = (portsel >> (i << 1)) & 3 + print(f"Port {i}: SET {sel}: {', '.join(led_set_str[sel])}") diff --git a/tools/led_gpio_utils/i2c_dump_rtl_regs.py b/tools/led_gpio_utils/i2c_dump_rtl_regs.py new file mode 100755 index 0000000..e90ac00 --- /dev/null +++ b/tools/led_gpio_utils/i2c_dump_rtl_regs.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +import argparse +from smbus2 import SMBus, i2c_msg + +# Configuration +DEVICE_ADDR = 0x5C # Replace with your device address +NUM_BYTES = 16 # Bytes to read + +# Parse command line arguments +parser = argparse.ArgumentParser(description="Dump RTL registers via I2C") +parser.add_argument( + "-b", + "--i2c-bus", + type=int, + required=True, + help="I2C bus number (use i2cdetect -l to find out the bus number of the dongle)", +) +args = parser.parse_args() + +# Open I2C bus +with SMBus(args.i2c_bus) as bus: + + for addr in range(0, 65536, NUM_BYTES): + # Create write message (send register address) + write = i2c_msg.write(DEVICE_ADDR, [addr >> 8, addr & 0xFF]) + + # Create read message (read 2 bytes) + read = i2c_msg.read(DEVICE_ADDR, NUM_BYTES) + + # Perform combined transaction + bus.i2c_rdwr(write, read) + + new_data = list(read) + + # Convert read message to string + datastr = " ".join([f"{x:02x}" for x in new_data]) + print(f"{addr:04x}: {datastr}") diff --git a/tools/led_gpio_utils/i2c_read_rtl_gpio.py b/tools/led_gpio_utils/i2c_read_rtl_gpio.py new file mode 100755 index 0000000..12612ed --- /dev/null +++ b/tools/led_gpio_utils/i2c_read_rtl_gpio.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +import time +import argparse +from smbus2 import SMBus, i2c_msg + +# Configuration +I2C_BUS = 1 +DEVICE_ADDR = 0x5C # Replace with your device address +NUM_BYTES = 8 # Bytes to read +SLEEP_INTERVAL = 1 + +# Handle command line arguments for ignored IOs +# default to ignore IOs related to SYS_LED, UART, SMI, SPI +IGNORED_IOS = [28, 31, 32, 34, 35, 42, 43, 44, 45] + +# Setup argument parser +parser = argparse.ArgumentParser(description="Read I2C data from RTL GPIO expander") +parser.add_argument( + "-b", + "--i2c-bus", + type=int, + required=True, + help="I2C bus number (use i2cdetect -l to find out the bus number of the dongle)", +) +parser.add_argument( + "-s", + "--sleep-interval", + type=int, + default=SLEEP_INTERVAL, + help=f"Sleep interval in seconds (default: {SLEEP_INTERVAL})", +) +parser.add_argument( + "-i", + "--ignored-ios", + nargs="*", + type=int, + default=IGNORED_IOS, + help=f"List of GPIO pins to ignore (default: {IGNORED_IOS})", +) +args = parser.parse_args() +I2C_BUS = args.i2c_bus + +first_read = True +last_data = [0 for x in range(NUM_BYTES)] + +# Open I2C bus +with SMBus(I2C_BUS) as bus: + addr = 0x44 + + while True: + # Create write message (send register address) + write = i2c_msg.write(DEVICE_ADDR, [addr >> 8, addr & 0xFF]) + + # Create read message (read NUM_BYTES bytes) + read = i2c_msg.read(DEVICE_ADDR, NUM_BYTES) + + # Perform combined transaction + bus.i2c_rdwr(write, read) + + new_data = list(read) + if first_read: + delta_data = last_data + first_read = False + else: + delta_data = [new_data[x] ^ last_data[x] for x in range(NUM_BYTES)] + last_data = new_data + + # Convert read message to list + datastr = " ".join([f"{x:02x}" for x in new_data]) + deltastr = "" + chg_list = [] + for x in range(NUM_BYTES): + if delta_data[x] == 0: + continue + for y in range(8): + if delta_data[x] & (1 << y): + idx = x * 8 + y + if idx not in args.ignored_ios: + deltastr += f"\n{' ':8s}GPIO{idx}" + # deltastr = " ".join([ f"{x:02x}" for x in delta_data]) + print(f"{addr:04x}: {datastr}{deltastr}") + time.sleep(args.sleep_interval)