implemented changes from Jens review
This commit is contained in:
9
agents.md
Normal file
9
agents.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Agent Notes — cm4-nrf54
|
||||||
|
|
||||||
|
> **Only read the linked files below when they are directly relevant to the current task. Do not load them by default.**
|
||||||
|
|
||||||
|
## Available Documentation
|
||||||
|
|
||||||
|
| File | When to read |
|
||||||
|
|------|-------------|
|
||||||
|
| [readme/jlcpcb_parts_check.md](readme/jlcpcb_parts_check.md) | When verifying, auditing, or updating LCSC/JLCPCB part numbers in the schematic |
|
||||||
17868
cm4-nrf54.kicad_pcb
17868
cm4-nrf54.kicad_pcb
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 1,
|
"active_layer": 0,
|
||||||
"active_layer_preset": "",
|
"active_layer_preset": "",
|
||||||
"auto_track_width": true,
|
"auto_track_width": true,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"shapes"
|
"shapes"
|
||||||
],
|
],
|
||||||
"visible_layers": "ffffffff_ffffffff_fffffff5_ff5d5fff",
|
"visible_layers": "ffffffff_ffffffff_fffffff5_ff5d5fff",
|
||||||
"zone_display_mode": 1
|
"zone_display_mode": 0
|
||||||
},
|
},
|
||||||
"git": {
|
"git": {
|
||||||
"integration_disabled": false,
|
"integration_disabled": false,
|
||||||
|
|||||||
@@ -1194,7 +1194,7 @@
|
|||||||
"plot": "",
|
"plot": "",
|
||||||
"pos_files": "",
|
"pos_files": "",
|
||||||
"specctra_dsn": "",
|
"specctra_dsn": "",
|
||||||
"step": "../../../../../../repos/mechanical_beacon/cm4-nrf54_rev3.step",
|
"step": "../../../../../../repos/mechanical_beacon/cm4-nrf54_rev4.step",
|
||||||
"svg": "",
|
"svg": "",
|
||||||
"vrml": ""
|
"vrml": ""
|
||||||
},
|
},
|
||||||
|
|||||||
2785
cm4-nrf54.kicad_sch
2785
cm4-nrf54.kicad_sch
File diff suppressed because it is too large
Load Diff
104
readme/jlcpcb_parts_check.md
Normal file
104
readme/jlcpcb_parts_check.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# JLCPCB / LCSC Parts Check
|
||||||
|
|
||||||
|
How to verify that LCSC part numbers in the schematic match the intended components.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Extract All LCSC Numbers from the Schematic
|
||||||
|
|
||||||
|
Use the following Python snippet to parse `cm4-nrf54.kicad_sch` and dump all component references with their value and LCSC field:
|
||||||
|
|
||||||
|
```python
|
||||||
|
import re
|
||||||
|
|
||||||
|
with open('cm4-nrf54.kicad_sch', 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
lcsc_pattern = re.compile(r'\(property\s*"(?:LCSC|lcsc|LCSC Part)"\s*"([^"]+)"')
|
||||||
|
field_pattern = re.compile(r'\(property\s*"(LCSC|lcsc|LCSC Part)"\s*"([^"]+)"')
|
||||||
|
|
||||||
|
blocks = re.split(r'\n\s*\(symbol\s+\(lib_id', content)
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for block in blocks[1:]:
|
||||||
|
ref_m = re.search(r'\(property\s*"Reference"\s*"([^"]+)"', block)
|
||||||
|
val_m = re.search(r'\(property\s*"Value"\s*"([^"]+)"', block)
|
||||||
|
lcsc_m = lcsc_pattern.search(block)
|
||||||
|
field_m = field_pattern.search(block)
|
||||||
|
|
||||||
|
ref = ref_m.group(1) if ref_m else '?'
|
||||||
|
val = val_m.group(1) if val_m else '?'
|
||||||
|
lcsc = lcsc_m.group(1) if lcsc_m else ''
|
||||||
|
field = field_m.group(1) if field_m else ''
|
||||||
|
|
||||||
|
if ref.startswith('#') or ref == '?':
|
||||||
|
continue
|
||||||
|
results.append((ref, val, lcsc, field))
|
||||||
|
|
||||||
|
results.sort(key=lambda x: (
|
||||||
|
''.join(filter(str.isalpha, x[0])),
|
||||||
|
int(''.join(filter(str.isdigit, x[0])) or '0')
|
||||||
|
))
|
||||||
|
|
||||||
|
for ref, val, lcsc, field in results:
|
||||||
|
print(f'{ref:12} {val:42} {lcsc:15} {field}')
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note:** KiCad schematics use three different field names for the LCSC number:
|
||||||
|
> `LCSC`, `lcsc`, and `LCSC Part` — the script above catches all three.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Verify Each LCSC Number
|
||||||
|
|
||||||
|
For each non-trivial component, open the LCSC product page directly:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://www.lcsc.com/product-detail/C<NUMBER>.html
|
||||||
|
```
|
||||||
|
|
||||||
|
The page title shows the actual manufacturer part number. Cross-check against the schematic `Value` field.
|
||||||
|
|
||||||
|
### What to look for
|
||||||
|
|
||||||
|
- **Wrong part** — the LCSC number resolves to a completely different component (e.g. a 22Ω resistor assigned to a 220R position, or an ADC with the wrong channel count).
|
||||||
|
- **Package mismatch** — the part is the right IC but in a different package than the KiCad footprint (e.g. SOT-363 assigned to a SOT-23-5 footprint).
|
||||||
|
- **Wrong variant** — same family but different spec (e.g. PCM1862 vs PCM1863, which differ in channel count).
|
||||||
|
- **Part not found** — the LCSC number returns a 404 / "Page Not Found". The part may be new, discontinued, or the number is a typo.
|
||||||
|
- **Missing LCSC** — component has no LCSC field at all. If it is a real assembly part (not a mechanical hole, test point, or solder jumper), it needs one.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Check JLCPCB Assembly Availability
|
||||||
|
|
||||||
|
Not all LCSC parts can be assembled by JLCPCB. To check:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://jlcpcb.com/partdetail/<MANUFACTURER>-<PART>/C<NUMBER>
|
||||||
|
```
|
||||||
|
|
||||||
|
Or search directly at `https://jlcpcb.com/parts`.
|
||||||
|
|
||||||
|
### Stock status meanings
|
||||||
|
|
||||||
|
| Status | Meaning |
|
||||||
|
|--------|---------|
|
||||||
|
| **In-stock, qty shown** | Orderable, JLCPCB can assemble |
|
||||||
|
| **C9900xxxxxx** number | Consigned part — you must supply the component |
|
||||||
|
| *"unavailable for purchase but can still be used in assembly"* | Must be consigned; cannot be bought through JLCPCB |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Finding Alternatives
|
||||||
|
|
||||||
|
When a part is not available on LCSC/JLCPCB, search for drop-in alternatives:
|
||||||
|
|
||||||
|
- Search `site:lcsc.com <part number>` or `site:jlcpcb.com <part number>`
|
||||||
|
- Check the Raspberry Pi / EasyEDA forums for CM4-specific parts (e.g. RJ45 MagJack alternatives)
|
||||||
|
- Common compatible replacements for this project:
|
||||||
|
|
||||||
|
| Original | Alternative | LCSC | Notes |
|
||||||
|
|----------|-------------|------|-------|
|
||||||
|
| Bel Fuse A70-112-331N126 (MagJack) | LINK-PP LPJG0926HENL | **C22457393** | Pin-compatible, 387 pcs in stock at JLCPCB |
|
||||||
|
|
||||||
|
---
|
||||||
52
scripts/extract_lcsc.py
Normal file
52
scripts/extract_lcsc.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Extract all LCSC part numbers from a KiCad schematic and print a sorted table."""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
SCH_FILE = 'cm4-nrf54.kicad_sch'
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
SCH_FILE = sys.argv[1]
|
||||||
|
|
||||||
|
with open(SCH_FILE, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
lcsc_pattern = re.compile(r'\(property\s*"(?:LCSC|lcsc|LCSC Part)"\s*"([^"]+)"')
|
||||||
|
field_pattern = re.compile(r'\(property\s*"(LCSC|lcsc|LCSC Part)"\s*"([^"]+)"')
|
||||||
|
|
||||||
|
blocks = re.split(r'\n\s*\(symbol\s+\(lib_id', content)
|
||||||
|
|
||||||
|
dnp_pattern = re.compile(r'\(dnp\s+yes\)')
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for block in blocks[1:]:
|
||||||
|
ref_m = re.search(r'\(property\s*"Reference"\s*"([^"]+)"', block)
|
||||||
|
val_m = re.search(r'\(property\s*"Value"\s*"([^"]+)"', block)
|
||||||
|
lcsc_m = lcsc_pattern.search(block)
|
||||||
|
field_m = field_pattern.search(block)
|
||||||
|
|
||||||
|
ref = ref_m.group(1) if ref_m else '?'
|
||||||
|
val = val_m.group(1) if val_m else '?'
|
||||||
|
lcsc = lcsc_m.group(1) if lcsc_m else ''
|
||||||
|
field = field_m.group(1) if field_m else ''
|
||||||
|
dnp = bool(dnp_pattern.search(block))
|
||||||
|
|
||||||
|
if ref.startswith('#') or ref == '?':
|
||||||
|
continue
|
||||||
|
results.append((ref, val, lcsc, field, dnp))
|
||||||
|
|
||||||
|
def sort_key(x):
|
||||||
|
letters = ''.join(filter(str.isalpha, x[0]))
|
||||||
|
digits = ''.join(filter(str.isdigit, x[0]))
|
||||||
|
return (letters, int(digits) if digits else 0)
|
||||||
|
|
||||||
|
results.sort(key=sort_key)
|
||||||
|
|
||||||
|
print(f'{"REF":12} {"VALUE":42} {"LCSC":15} {"DNP":3} FIELD')
|
||||||
|
print('-' * 87)
|
||||||
|
for ref, val, lcsc, field, dnp in results:
|
||||||
|
dnp_str = 'DNP' if dnp else ' '
|
||||||
|
skip = dnp or ref.startswith(('H', 'JP', 'TP'))
|
||||||
|
flag = ' <-- MISSING' if not lcsc and not skip else ''
|
||||||
|
print(f'{ref:12} {val:42} {lcsc:15} {dnp_str} {field}{flag}')
|
||||||
Reference in New Issue
Block a user