schlib_write: write ComponentDescription alongside SOP parameters (by admin)

main
admin 2026-07-17 08:51:19 +00:00
parent 3e5f756916
commit e460f2d085
16 changed files with 330 additions and 240 deletions

128
SKILL.md Executable file → Normal file
View File

@ -2,15 +2,16 @@
name: library-manager name: library-manager
description: >- description: >-
Manage Vecmocon's component library. Extract parameters from a component datasheet PDF into the Manage Vecmocon's component library. Extract parameters from a component datasheet PDF into the
per-typeid Excel template. Checks Gitea for a duplicate MPN_make, classifies to a typeid, updates that typeid's template (versioning, changelog, backfill), fills per-typeid Excel template. Checks Gitea for a duplicate MPN_make, classifies to a typeid, updates
a per-part workbook with human verification, reads the Altium symbol/footprint refs, assembles that typeid's template (versioning, changelog, backfill), fills a per-part workbook with human
a part folder and pushes to Gitea. Can UPDATE an existing part instead of hard-stopping, and can verification, reads the Altium symbol/footprint refs, assembles a part folder and pushes to Gitea.
WRITE the mandatory SOP parameters directly into a .SchLib symbol while stripping Ultra-Librarian Can UPDATE an existing part instead of hard-stopping. ALWAYS WRITES the mandatory SOP parameters
defaults. On the .SchLib task it also fills that component's Excel (Description + all parameters) into the .SchLib symbol (stripping Ultra-Librarian defaults) as a required step of every run
and pushes the updated symbol to Gitea, no verification loop. Descriptions involving a symbol — never asks first. On the .SchLib task it also fills that component's Excel
follow Vecmocon's strict Altium Description Format. Use whenever the user uploads a datasheet, and pushes, no verification loop. Descriptions follow Vecmocon's strict Altium Description Format.
builds/updates a library entry, adds a template parameter, fills/updates .SchLib parameters, or Use whenever the user uploads a datasheet, builds/updates a library entry, adds a template
pushes a part to Gitea. Always trigger on "\datasheet", "\library", "\library-manager", "\schlib". parameter, fills/updates .SchLib parameters, or pushes a part to Gitea. Always trigger on
"\datasheet", "\library", "\library-manager", "\schlib".
--- ---
# Library Manager # Library Manager
@ -41,15 +42,18 @@ own, without asking for confirmation**. Never add a "shall I push?" step — jus
the user where it landed. (You still flag a genuine symbol/footprint mismatch, because that's a the user where it landed. (You still flag a genuine symbol/footprint mismatch, because that's a
correctness issue, not a push confirmation.) correctness issue, not a push confirmation.)
**Symbol parameters are a second exception — stamp them without asking, every time.** This **The `.SchLib` task is a second exception — it fills and pushes without a verification loop.**
holds in both directions. As a standalone task (the engineer hands over a `.SchLib`): fill that When the engineer hands over a symbol for the schlib flow, fill that component's Excel
component's Excel (Description + all parameters) and push the updated symbol automatically, (Description + all parameters) and push the updated symbol automatically, without pausing to
without pausing to confirm the values. And **inside the normal new-part flow**: once the symbol confirm the values. See *Mandatory symbol parameters* for why this path skips the loop.
is uploaded at step 6, stamp the SOP + sheet parameters onto it and strip the Ultra-Librarian
defaults as a matter of course — do **not** offer it as a follow-up, do **not** ask whether the **Writing symbol parameters is a third exception — always do it, never ask.** Whenever a
engineer wants it, and never push a part folder whose symbol still carries UL defaults. See `.SchLib` is in play — the standalone schlib task *or* step 6b of a new-part run — filling its
*Mandatory symbol parameters* for why this path skips the loop. Every other flow keeps the mandatory SOP parameters is a required action, not an offer. Never ask "should I fill the symbol
normal interactive asks below. parameters?" or leave it as a suggested next step; the answer is always yes, so just write them
and report it. A symbol that still holds Ultra-Librarian defaults is an incomplete part.
Every other flow keeps the normal interactive asks below.
## Inputs ## Inputs
@ -218,23 +222,32 @@ each header's unit. **Leave blanks where the datasheet is silent — an honest b
guess.** guess.**
The **`Description`** column is special: it is **not** free prose but a strict `_`-joined The **`Description`** column is special: it is **not** free prose but a strict `_`-joined
engineering string — a type prefix, the defining parameters in a fixed order, package near the engineering string. It **always opens with `Class_TYPEID`** — the part's library Class exactly as
end, optional AEC-Q last (e.g. `CHIP_RES_36kΩ_62.2mW_±0.1%_0402`, `CHIP_CAP_2.2uF_100v_±10%_1210_x7r`, spelled in its repo folder, then its Type ID in upper case — followed by the defining parameters
`SCH_100V_0.25A_SOD-323F`). `references/description_format.md` defines the format for **every** in a fixed order, package near the end, optional AEC-Q last. E.g.
type in the library: the four the Altium SOP spells out (Resistor, Capacitor, Zener, TVS) are `Resistor_FIX_36kΩ_62.2mW_±0.1%_0402`, `Capacitor_CER_2.2uF_100v_±10%_1210_x7r`,
**strict**; the rest are the house extension on the same basis. Look up the part's type there, `Diode_SCH_100V_0.25A_SOD-323F`, `Diode_TVS_5V_9.2V_18A_SOD-323`.
This `Class_TYPEID` opening is **mandatory for every part, with no exceptions** — including
Resistor, Capacitor, Zener and TVS, where it deliberately overrides the prefix given in SOP §6.
The old technology prefixes (`CHIP_RES`, `CHIP_CAP`, `TANT_CAP`, `NMOS`, `ZEN`, …) are
**retired** — never emit them. `references/description_format.md` defines the parameter order
for **every** type in the library and is authoritative; read it before writing a Description.
Look up the part's type there,
build the Description to that format, and if a real datasheet doesn't fit the format cleanly, build the Description to that format, and if a real datasheet doesn't fit the format cleanly,
follow the pattern and **flag the mismatch to the engineer** rather than bending it silently. follow the pattern and **flag the mismatch to the engineer** rather than bending it silently.
Collect the values into a small `part.json`: Collect the values into a small `part.json`:
```json ```json
{"mpn":"BAT46WJ","manufacturer":"Nexperia","typeid":"SCH", {"mpn":"BAT46WJ","manufacturer":"Nexperia","typeid":"SCH",
"values":{"Description":"SCH_100V_0.25A_SOD-323F","Forward Voltage(V)":"0.71", "values":{"Description":"Diode_SCH_100V_0.25A_SOD-323F","Forward Voltage(V)":"0.71",
"Reverse Voltage(V)":"100","Forward Current(A)":"0.25","Package":"SOD-323F"}} "Reverse Voltage(V)":"100","Forward Current(A)":"0.25","Package":"SOD-323F"}}
``` ```
(typeid `SCH` → prefix `SCH`, format `SCH_Vr_Io_Package`, so a 100 V / 250 mA Schottky in (typeid `SCH` sits in Class `Diode` → prefix `Diode_SCH`, format `Diode_SCH_Vr_Io_Package`, so a
SOD-323F becomes `SCH_100V_0.25A_SOD-323F`.) 100 V / 250 mA Schottky in SOD-323F becomes `Diode_SCH_100V_0.25A_SOD-323F`. The Class token is
the repo folder name from `CLASS_FOLDER` in `scripts/common.py`, so the Description's first token
always matches the folder the part is pushed to.)
```bash ```bash
python scripts/fill_templates.py part.json \ python scripts/fill_templates.py part.json \
@ -297,33 +310,40 @@ python scripts/fill_templates.py part.json \
--template assets/template/template.xlsx --dest <stage>/<tag>/ --design design.json --template assets/template/template.xlsx --dest <stage>/<tag>/ --design design.json
``` ```
Once you have the symbol and its Library Ref, **stamp the mandatory symbol parameters onto the ### 6b. Write the mandatory symbol parameters — always, without asking
`.SchLib` — always, automatically, without asking.** This is not an optional extra and it is not
something to offer the engineer: a symbol that reaches Gitea carrying Ultra-Librarian defaults
instead of the SOP set is an incomplete part. Do it in this same run, before step 7, so the
folder is pushed complete the first time.
Build the parameter set from the datasheet values you already read for the workbook (they are the Once you have the symbol and its Library Ref, **write the mandatory symbol parameters into the
same values — Manufacturer, Manufacturer Part, Value, Tolerance, Operating Temperature, RoHS, `.SchLib`**. This is **not optional and not a question** — it is a required step of every
Datasheet, Process, Vecmocon Part Code, …), **plus every engineering parameter from this typeid's new-part run. Do not ask "would you like me to fill the symbol parameters?", do not offer it as
sheet** and `Component Type` = the part's Class, then write them in and strip the UL defaults — a suggestion, and do not defer it to a later turn. Just do it, then report that it's done.
see *Mandatory symbol parameters* below for the full set and the exact commands. Skip only the
housekeeping columns (`MPN_make_type`, Skill/Template Version) and the four Library/Footprint
Ref/Path columns — those are Altium's own model links, so duplicating them as parameters would
create two sources of truth.
Don't stop to confirm the values here either; the engineer validates the symbol by opening it in The SOP requires the fixed parameter set (Manufacturer, Manufacturer Part, Value, Tolerance,
Altium, which is the real check. Leave genuinely-unknown fields blank (the SOP hides blank Operating Temperature, RoHS, Datasheet, Process, Vecmocon Part Code, …) on every symbol, **plus
parameters) and **note the gaps in your summary** rather than blocking on a question — the one the symbol's Description**, so a part folder whose `.SchLib` has not been filled is **incomplete
field that is never on a datasheet is `Vecmocon Part Code`, so use it if the engineer supplied it and must not be pushed**. Build the part's `params.json` from the values the engineer just
and otherwise leave it blank and say so. verified in step 5 — including `"description"`, set to the **same** strict `Class_TYPEID` string
you put in the part's Excel — and run:
```bash
python scripts/schlib_write.py \
--schlib <stage>/<tag>/<symbol_name>.SchLib \
--params params.json \
--out <stage>/<tag>/<symbol_name>.SchLib
```
See *Mandatory symbol parameters* below for the full parameter set, the value-shorthand rules,
and the Ultra-Librarian default-stripping behaviour — read `references/schlib_parameters.md`
before building the parameter set. The values are already verified at this point, so this step
inherits no verification loop of its own.
### 7. Assemble the part folder ### 7. Assemble the part folder
The staging folder `<tag>/` should now hold the four files: the per-part `<tag>.xlsx`, the The staging folder `<tag>/` should now hold the four files: the per-part `<tag>.xlsx`, the
datasheet (name it `<MPN>_data.<ext>`), the symbol (the **stamped** one from step 6, not the raw datasheet (name it `<MPN>_data.<ext>`), the symbol, and the footprint.
upload), and the footprint. If the engineer's upload carried extra files (a `.step` 3D model, a
`.LibPkg`), ask whether to include them — the standard folder is these four. **Before pushing, check that the symbol has actually been filled** (step 6b). The part folder is
not complete until it has. If the `.SchLib` still carries only Ultra-Librarian defaults, go back
and run `schlib_write.py` — don't push, and don't ask the user whether to; just fill it.
### 8. Push to the library repo, under the part's Class ### 8. Push to the library repo, under the part's Class
@ -341,8 +361,15 @@ user where it landed.
The SOP (§5) requires every schematic symbol to carry a fixed parameter set in its Altium The SOP (§5) requires every schematic symbol to carry a fixed parameter set in its Altium
properties — `Component Type`, `Manufacturer`, `Manufacturer Part`, `Value`, `Tolerance`, properties — `Component Type`, `Manufacturer`, `Manufacturer Part`, `Value`, `Tolerance`,
`Operating Temperature`, `ROHS`, `Datasheet`, `Process`, `Vecmocon Part Code`, and the two `Operating Temperature`, `ROHS`, `Datasheet`, `Process`, `Vecmocon Part Code`, and the two
second-source fields — with the **Comment** set to the MPN. The skill can stamp these onto the second-source fields — with the **Comment** set to the MPN and the **Description** set to the
symbol from the datasheet. part's strict `Class_TYPEID` string. The skill stamps all of these onto the symbol from the
datasheet in a single pass.
**Description is written too, always.** It isn't a parameter — it's the `ComponentDescription`
field in the symbol's header, which Ultra-Librarian ships as the placeholder text `Description`.
So it must be written explicitly or the symbol shows the literal word "Description" in Altium
even when every parameter is right. Pass `"description"` in `params.json` (it falls back to
`parameters.Description`), and use the **same** string as the part's Excel so the two agree.
This runs **as its own task too**, not only inside new-part creation: whenever the user hands This runs **as its own task too**, not only inside new-part creation: whenever the user hands
over one or more `.SchLib` files and wants their parameters filled/updated (e.g. "\schlib", "add over one or more `.SchLib` files and wants their parameters filled/updated (e.g. "\schlib", "add
@ -375,7 +402,8 @@ Leave any genuinely-unknown field blank — the SOP hides blank parameters, so a
empty until filled. The full method for the second-source search is in empty until filled. The full method for the second-source search is in
`references/schlib_parameters.md`. `references/schlib_parameters.md`.
Collect the values into a `params.json` and write them into the symbol: Collect the values into a `params.json` — with `"description"` alongside `"parameters"` — and
write them into the symbol:
```bash ```bash
python scripts/schlib_write.py --schlib <in>.SchLib --params params.json --out <stage>/<tag>/<sym>.SchLib python scripts/schlib_write.py --schlib <in>.SchLib --params params.json --out <stage>/<tag>/<sym>.SchLib

Binary file not shown.

0
assets/template/Type_ID.xlsx Executable file → Normal file
View File

0
assets/vecmocon-logo.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

350
references/description_format.md Executable file → Normal file
View File

@ -3,11 +3,10 @@
This is the authoritative rule for the **Description** field the skill writes into a part's This is the authoritative rule for the **Description** field the skill writes into a part's
workbook. It has two layers: workbook. It has two layers:
1. The **four formats the SOP defines outright** — Resistor, Capacitor, Zener, TVS — from 1. The **four formats derived from the SOP** — Resistor, Capacitor, Zener, TVS — from
*Engineering Data Management — SOP: Component Naming, Mandatory Parameters, and Design Item *Engineering Data Management — SOP: Component Naming, Mandatory Parameters, and Design Item
ID Format* (§6). Follow these parameter orders **strictly** (with one house tweak: the ID Format* (§6). Follow these **parameter orders** strictly. The **prefix**, however, is the
Zener/TVS prefix uses the generic diode code `ZEN`/`TVS`, not the SOP's `DIO-Z`/`DIO-T` — see house `Class_TYPEID` form (see below), which supersedes the SOP's own prefix tokens.
the note under those two below).
2. A **house extension** that carries the *same basis* to every other type in the library 2. A **house extension** that carries the *same basis* to every other type in the library
(all 125 type-IDs / 18 classes), so no component is left without a Description convention. (all 125 type-IDs / 18 classes), so no component is left without a Description convention.
These are built on the SOP pattern and are the working standard; when a specific part These are built on the SOP pattern and are the working standard; when a specific part
@ -20,11 +19,27 @@ The Description is **not** a free-form sentence. It is a single string of `_`-jo
this shape: this shape:
``` ```
PREFIX_param1_param2_..._Package_[AECQ-XXX] Class_TYPEID_param1_param2_..._Package_[AECQ-XXX]
``` ```
- **PREFIX** — a short token (or two) naming the sub-family / technology, e.g. `CHIP_RES`, - **Class_TYPEID** — the **mandatory opening two tokens** of every Description, always. This
`ELE_CAP`, `SCH`, `NMOS`. The per-type prefix is listed for every type below. replaces the old technology prefixes (`CHIP_RES`, `ELE_CAP`, `TANT_CAP`, `NMOS`, …) — those
are **retired and must not be used**. Examples: `Diode_TVS_…`, `Capacitor_TAN_…`,
`Resistor_FIX_…`, `Transistor_MOS_…`.
- **Class** — spelled exactly as the library-repo folder name, so a Description's first token
always matches the folder the part lives in. Take it from `CLASS_FOLDER` in
`scripts/common.py` (the authoritative map) — e.g. `Diode`, `Capacitor`, `Resistor`,
`Transistor`, `IC`, `Protection`, `Inductor_Magnetics`, `Relay_Contactor`, `Switch_Button`,
`Antenna_RF`, `Crystal_Oscillator`, `Battery_Cell`, `Audible_Indicator`, `Display_HMI`,
`Sensor`, `Thermal_Cooling`, `Connector`. Mixed case as written — do **not** upper-case it.
Note `Inductor_Magnetics` and friends already contain an `_`; that is expected and correct.
The one Class whose folder name contains spaces, `Power Conversion Module`, is written
`Power_Conversion_Module` in a Description.
- **TYPEID** — the Type ID from `references/taxonomy.md`, **always upper-case**, exactly as
the template sheet names it (`TVS`, `TAN`, `CER`, `FIX`, `MOS`, `SCH`, `LDO`, …). This is
the same typeid used in the part tag `MPN_make_typeid`, so the three agree.
- Get both from the taxonomy for the typeid you classified the part to in step 2 — never
invent or abbreviate either token.
- **params** — the part's defining ratings, in the **fixed order** given for that class. Read - **params** — the part's defining ratings, in the **fixed order** given for that class. Read
them off the datasheet. If the datasheet is silent on a required token, leave it out and flag them off the datasheet. If the datasheet is silent on a required token, leave it out and flag
it — an honest gap beats a guessed value. it — an honest gap beats a guessed value.
@ -36,7 +51,8 @@ PREFIX_param1_param2_..._Package_[AECQ-XXX]
Description ≠ Design Item ID ≠ Comment — three different fields that share notation but not Description ≠ Design Item ID ≠ Comment — three different fields that share notation but not
content: **Description** is the strict string here (SOP §6); **Design Item ID** (SOP §2) is a content: **Description** is the strict string here (SOP §6); **Design Item ID** (SOP §2) is a
shorter procurement id (`RES_36kΩ_±0.1%_0402`) — use it only as a guide to token vocabulary, shorter procurement id (`RES_36kΩ_±0.1%_0402`) that keeps its **own** SOP notation and does
**not** take the `Class_TYPEID` prefix — use it only as a guide to token vocabulary,
never put it in the Description column; **Comment** (SOP §4) is always the exact MPN. never put it in the Description column; **Comment** (SOP §4) is always the exact MPN.
## Notation conventions (from the SOP examples) ## Notation conventions (from the SOP examples)
@ -51,40 +67,44 @@ never put it in the Description column; **Comment** (SOP §4) is always the exac
--- ---
# Layer 1 — the four SOP-defined formats (strict) # Layer 1 — the four SOP-derived formats (parameter order is strict)
The **parameter orders** below are the SOP's and are not up for reinterpretation. The
**prefix** is the house `Class_TYPEID` form, which replaces the SOP §6 prefix tokens.
**Resistor** **Resistor**
``` ```
Type_RES_Value_Wattage_Tolerance_Package_AECQ-XXX(optional) Resistor_TYPEID_Value_Wattage_Tolerance_Package_AECQ-XXX(optional)
``` ```
Example: `CHIP_RES_36kΩ_62.2mW_±0.1%_0402` Example: `Resistor_FIX_36kΩ_62.2mW_±0.1%_0402` (was `CHIP_RES_36kΩ_62.2mW_±0.1%_0402`)
**Capacitor** **Capacitor**
``` ```
Type_CAP_Value_Voltage_Tolerance_Package_TemperatureCoefficient_AECQ-XXX(optional) Capacitor_TYPEID_Value_Voltage_Tolerance_Package_TemperatureCoefficient_AECQ-XXX(optional)
``` ```
Example: `CHIP_CAP_2.2uF_100v_±10%_1210_x7r` Example: `Capacitor_CER_2.2uF_100v_±10%_1210_x7r` (was `CHIP_CAP_2.2uF_100v_±10%_1210_x7r`)
**Zener diode** **Zener diode**
``` ```
ZEN_VoltageZener(Vz)_Power_Package_AECQ-XXX(optional) Diode_ZEN_VoltageZener(Vz)_Power_Package_AECQ-XXX(optional)
``` ```
**TVS diode** **TVS diode**
``` ```
TVS_VoltageBreakdown(Vbr)_VoltageClamping(Vc)_Current(Ip)_Package_AECQ-XXX(optional) Diode_TVS_VoltageBreakdown(Vbr)_VoltageClamping(Vc)_Current(Ip)_Package_AECQ-XXX(optional)
``` ```
**House prefix note:** the SOP §6 wrote these two as `DIO-Z` / `DIO-T`, but Vecmocon **House prefix note:** SOP §6 wrote the diodes as `DIO-Z` / `DIO-T` and the R/C formats with
standardised on the **generic diode type code** (`ZEN`, `TVS`, and likewise `SCH`, `ESD`, …) as technology prefixes (`CHIP_RES`, `CHIP_CAP`). Vecmocon has standardised on `Class_TYPEID` for
the prefix for *all* diodes. So use `ZEN` / `TVS` here — the parameter order (Vz+Power for **every** component, so all four of these now open with `Resistor_` / `Capacitor_` / `Diode_`
Zener; Vbr+Vc+Ip for TVS) is still exactly the SOP's; only the prefix token differs. plus the typeid. This is a deliberate house override of SOP §6's prefix; the parameter order
(Vz+Power for Zener; Vbr+Vc+Ip for TVS; etc.) remains exactly the SOP's.
--- ---
@ -93,50 +113,50 @@ Zener; Vbr+Vc+Ip for TVS) is still exactly the SOP's; only the prefix token diff
Each class below gives its **parameter order** (the tokens between prefix and package) and the Each class below gives its **parameter order** (the tokens between prefix and package) and the
**per-type prefix**. Package is always the second-to-last token; optional `AECQ-XXX` is last. **per-type prefix**. Package is always the second-to-last token; optional `AECQ-XXX` is last.
## Resistor (RES family) — `PREFIX_Value_Power_Tolerance_Package_[AECQ]` ## Resistor (RES family) — `Resistor_TYPEID_Value_Power_Tolerance_Package_[AECQ]`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| FIX Thick-film chip | `CHIP_RES` | SOP example; the strict format above | | FIX Thick-film chip| `Resistor_FIX` | SOP example; the strict format above |
| TFR Thin-film chip | `TFILM_RES` | precision/low-tempco; may append tempco (ppm) | | TFR Thin-film chip| `Resistor_TFR` | precision/low-tempco; may append tempco (ppm) |
| MFR Metal-film | `MFILM_RES` | | | MFR Metal-film| `Resistor_MFR` | |
| CFR Carbon-film | `CFILM_RES` | | | CFR Carbon-film| `Resistor_CFR` | |
| MOR Metal-oxide | `MOX_RES` | high-power leaded | | MOR Metal-oxide| `Resistor_MOR` | high-power leaded |
| WWR Wirewound | `WW_RES` | low-ohm/high-power | | WWR Wirewound| `Resistor_WWR` | low-ohm/high-power |
| SHT Current-sense/shunt | `SHUNT_RES` | value in mΩ (e.g. `2mΩ`), power token is the sense power | | SHT Current-sense/shunt| `Resistor_SHT` | value in mΩ (e.g. `2mΩ`), power token is the sense power |
| ARR Array/network | `ARR_RES` | add element count/config, e.g. `4x`, before value | | ARR Array/network| `Resistor_ARR` | add element count/config, e.g. `4x`, before value |
| POT Potentiometer/trimmer | `POT` | `POT_Value_Taper_Power_Package` (taper `LIN`/`LOG`) | | POT Potentiometer/trimmer| `Resistor_POT` | `Resistor_POT_Value_Taper_Power_Package` (taper `LIN`/`LOG`) |
| FSR Fusible/safety | `FUSE_RES` | | | FSR Fusible/safety| `Resistor_FSR` | |
| NTC thermistor | `NTC` | `NTC_R25_Beta_Tolerance_Package` (R25 e.g. `10kΩ`, Beta e.g. `B3950`) | | NTC thermistor| `Resistor_NTC` | `Resistor_NTC_R25_Beta_Tolerance_Package` (R25 e.g. `10kΩ`, Beta e.g. `B3950`) |
| PTC thermistor | `PTC` | `PTC_R25_Package` (or trip current/temp if that's the rated spec) | | PTC thermistor| `Resistor_PTC` | `Resistor_PTC_R25_Package` (or trip current/temp if that's the rated spec) |
Example: `SHUNT_RES_2mΩ_1W_±1%_2512` · `NTC_10kΩ_B3950_±1%_0402` Example: `Resistor_SHT_2mΩ_1W_±1%_2512` · `Resistor_NTC_10kΩ_B3950_±1%_0402`
## Capacitor (CAP family) — `PREFIX_Value_Voltage_Tolerance_Package_[Dielectric]_[AECQ]` ## Capacitor (CAP family) — `Capacitor_TYPEID_Value_Voltage_Tolerance_Package_[Dielectric]_[AECQ]`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| CER Ceramic MLCC | `CHIP_CAP` | SOP; dielectric token (`x7r`/`c0g`…) required | | CER Ceramic MLCC| `Capacitor_CER` | SOP; dielectric token (`x7r`/`c0g`…) required |
| ELE Aluminium electrolytic | `ELE_CAP` | tolerance often omitted; case like `SMD,D6.3xL5.8mm` | | ELE Aluminium electrolytic| `Capacitor_ELE` | tolerance often omitted; case like `SMD,D6.3xL5.8mm` |
| TAN Tantalum | `TANT_CAP` | | | TAN Tantalum| `Capacitor_TAN` | |
| PLY Aluminium-polymer | `POLY_CAP` | low-ESR; ESR may follow voltage | | PLY Aluminium-polymer| `Capacitor_PLY` | low-ESR; ESR may follow voltage |
| FLM Film (MKT/MKP) | `FILM_CAP` | | | FLM Film (MKT/MKP)| `Capacitor_FLM` | |
| SFY Safety Class-X/Y | `SAFETY_CAP` | add safety class token (`X2`/`Y1`) after value | | SFY Safety Class-X/Y| `Capacitor_SFY` | add safety class token (`X2`/`Y1`) after value |
| SUP Supercapacitor/EDLC | `SUPERCAP` | value in farads, e.g. `1F`; add ESR if rated | | SUP Supercapacitor/EDLC| `Capacitor_SUP` | value in farads, e.g. `1F`; add ESR if rated |
Example: `ELE_CAP_33uF_25V_SMD,D6.3xL5.8mm` · `SUPERCAP_1F_5.5V_RADIAL` Example: `Capacitor_ELE_33uF_25V_SMD,D6.3xL5.8mm` · `Capacitor_SUP_1F_5.5V_RADIAL`
## Inductor / Magnetics — `PREFIX_Value_Current_[DCR]_Package_[AECQ]` ## Inductor / Magnetics — `Inductor_Magnetics_TYPEID_Value_Current_[DCR]_Package_[AECQ]`
| Type | Prefix | Format detail | | Type | Prefix | Format detail |
|------|--------|---------------| |------|--------|---------------|
| PWR Power inductor | `PWR_IND` | `PWR_IND_L_Isat_DCR_Package` (L e.g. `10uH`, Isat `3A`) | | PWR Power inductor| `Inductor_Magnetics_PWR` | `Inductor_Magnetics_PWR_L_Isat_DCR_Package` (L e.g. `10uH`, Isat `3A`) |
| FBD Ferrite bead | `FB` | `FB_Impedance@freq_Current_Package` (e.g. `FB_600Ω@100MHz_2A_0603`) | | FBD Ferrite bead| `Inductor_Magnetics_FBD` | `Inductor_Magnetics_FBD_Impedance@freq_Current_Package` (e.g. `Inductor_Magnetics_FBD_600Ω@100MHz_2A_0603`) |
| CMC Common-mode choke | `CMC` | `CMC_Impedance@freq_Current_Package` | | CMC Common-mode choke| `Inductor_Magnetics_CMC` | `Inductor_Magnetics_CMC_Impedance@freq_Current_Package` |
| RFI RFI choke | `RFI_CHK` | `RFI_CHK_L_Current_Package` | | RFI RFI choke| `Inductor_Magnetics_RFI` | `Inductor_Magnetics_RFI_L_Current_Package` |
| XFM Transformer | `XFMR` | `XFMR_Ratio_Power_Package` (ratio e.g. `1:1`) | | XFM Transformer| `Inductor_Magnetics_XFM` | `Inductor_Magnetics_XFM_Ratio_Power_Package` (ratio e.g. `1:1`) |
| CTX Current transformer | `CT` | `CT_Ratio_Package` (e.g. `1000:1`) | | CTX Current transformer| `Inductor_Magnetics_CTX` | `Inductor_Magnetics_CTX_Ratio_Package` (e.g. `1000:1`) |
| CPL Coupled inductor | `CPL_IND` | `CPL_IND_L_Current_Package` | | CPL Coupled inductor| `Inductor_Magnetics_CPL` | `Inductor_Magnetics_CPL_L_Current_Package` |
## Diode — reverse-voltage / current ratings, then package ## Diode — reverse-voltage / current ratings, then package
@ -145,182 +165,184 @@ The prefix is the **generic diode type code (the typeid itself)** — `REC`, `FR
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| REC Rectifier | `REC` | `REC_Vrrm_Io_Package` | | REC Rectifier| `Diode_REC` | `Diode_REC_Vrrm_Io_Package` |
| FRD Fast-recovery | `FRD` | `FRD_Vrrm_Io_trr_Package` | | FRD Fast-recovery| `Diode_FRD` | `Diode_FRD_Vrrm_Io_trr_Package` |
| SCH Schottky | `SCH` | `SCH_Vr_Io_Package` | | SCH Schottky| `Diode_SCH` | `Diode_SCH_Vr_Io_Package` |
| SIC SiC Schottky | `SIC` | `SIC_Vr_Io_Package` | | SIC SiC Schottky| `Diode_SIC` | `Diode_SIC_Vr_Io_Package` |
| ZEN Zener | `ZEN` | `ZEN_Vz_Power_Package` | | ZEN Zener| `Diode_ZEN` | `Diode_ZEN_Vz_Power_Package` |
| TVS TVS | `TVS` | `TVS_Vbr_Vc_Ip_Package` | | TVS TVS| `Diode_TVS` | `Diode_TVS_Vbr_Vc_Ip_Package` |
| ESD ESD protection | `ESD` | `ESD_Vrwm_Vc_Channels_Package` | | ESD ESD protection| `Diode_ESD` | `Diode_ESD_Vrwm_Vc_Channels_Package` |
| SWI Switching/small-signal | `SWI` | `SWI_Vr_Io_trr_Package` | | SWI Switching/small-signal| `Diode_SWI` | `Diode_SWI_Vr_Io_trr_Package` |
| BRG Bridge rectifier | `BRG` | `BRG_Vrrm_Io_Package` | | BRG Bridge rectifier| `Diode_BRG` | `Diode_BRG_Vrrm_Io_Package` |
| LED Indicator LED | `LED` | `LED_Color_Vf_If_Package` (color e.g. `RED`) | | LED Indicator LED| `Diode_LED` | `Diode_LED_Color_Vf_If_Package` (color e.g. `RED`) |
Example (Schottky BAT46WJ, 100 V / 250 mA): `SCH_100V_0.25A_SOD-323F` Example (Schottky BAT46WJ, 100 V / 250 mA): `Diode_SCH_100V_0.25A_SOD-323F`
## Transistor — `PREFIX_Voltage_Current_[Rds(on)]_Package_[AECQ]` ## Transistor — `Transistor_TYPEID_[Polarity]_Voltage_Current_[Rds(on)]_Package_[AECQ]`
The polarity/channel is **folded into the prefix** as a single token (matching the SOP's own Since the prefix is now `Transistor_TYPEID`, the polarity/channel can no longer ride in the
Design Item ID form, e.g. `NMOS_20V_SOT-23`), not carried as a separate `_NCH`/`_PCH` token. prefix (the old `NMOS`/`PMOS`/`BJT_NPN` tokens are retired). It is carried as **its own token
immediately after the prefix**: `N`/`P` for FETs, `NPN`/`PNP` for BJTs and digital transistors.
Types with no polarity variant (GaN, IGBT) omit the token entirely.
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| BJT BJT | `BJT_NPN` / `BJT_PNP` | `BJT_NPN_Vceo_Ic_Package` | | BJT BJT | `Transistor_BJT` | `Transistor_BJT_Polarity_Vceo_Ic_Package` (polarity `NPN`/`PNP`) |
| MOS MOSFET (Si) | `NMOS` / `PMOS` | `NMOS_Vds_Id_Rdson_Package` | | MOS MOSFET (Si) | `Transistor_MOS` | `Transistor_MOS_Channel_Vds_Id_Rdson_Package` (channel `N`/`P`) |
| SCM SiC MOSFET | `NSICFET` / `PSICFET` | `NSICFET_Vds_Id_Rdson_Package` | | SCM SiC MOSFET | `Transistor_SCM` | `Transistor_SCM_Channel_Vds_Id_Rdson_Package` |
| GAN GaN FET | `GANFET` | `GANFET_Vds_Id_Rdson_Package` | | GAN GaN FET | `Transistor_GAN` | `Transistor_GAN_Vds_Id_Rdson_Package` |
| IGBT IGBT | `IGBT` | `IGBT_Vces_Ic_Package` | | IGBT IGBT | `Transistor_IGBT` | `Transistor_IGBT_Vces_Ic_Package` |
| JFET JFET | `NJFET` / `PJFET` | `NJFET_Vds_Idss_Package` | | JFET JFET | `Transistor_JFET` | `Transistor_JFET_Channel_Vds_Idss_Package` |
| DIG Digital/bias-R transistor | `DTR_NPN` / `DTR_PNP` | `DTR_NPN_Vceo_R1/R2_Package` | | DIG Digital/bias-R transistor | `Transistor_DIG` | `Transistor_DIG_Polarity_Vceo_R1/R2_Package` |
Example: `NMOS_20V_6A_15mΩ_SOT-23` · `BJT_NPN_50V_0.1A_SOT-416FL` Example: `Transistor_MOS_N_20V_6A_15mΩ_SOT-23` · `Transistor_BJT_NPN_50V_0.1A_SOT-416FL`
## Integrated Circuit (IC) — one line per subtype; package always last (before AECQ) ## Integrated Circuit (IC) — one line per subtype; package always last (before AECQ)
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| MCU Microcontroller | `MCU` | `MCU_Core_Flash_Package` (e.g. `MCU_M0+_128Kb_LQFP-48`) | | MCU Microcontroller| `IC_MCU` | `IC_MCU_Core_Flash_Package` (e.g. `IC_MCU_M0+_128Kb_LQFP-48`) |
| LDO LDO regulator | `LDO` | `LDO_Vout_Iout_Package` (`ADJ` if adjustable) | | LDO LDO regulator| `IC_LDO` | `IC_LDO_Vout_Iout_Package` (`ADJ` if adjustable) |
| DCD DC-DC IC | `DCD` | `DCD_Topology_Vin_Iout_Package` (topology `BUCK`/`BOOST`/`BUCKBOOST`) | | DCD DC-DC IC| `IC_DCD` | `IC_DCD_Topology_Vin_Iout_Package` (topology `BUCK`/`BOOST`/`BUCKBOOST`) |
| PMU PMIC | `PMIC` | `PMIC_Rails_Package` | | PMU PMIC| `IC_PMU` | `IC_PMU_Rails_Package` |
| BMS BMS AFE | `BMS` | `BMS_Cells_Package` (e.g. `16S`) | | BMS BMS AFE| `IC_BMS` | `IC_BMS_Cells_Package` (e.g. `16S`) |
| DRV Gate/motor driver | `DRV` | `DRV_Type_Voltage_Current_Package` (type `GATE`/`MOTOR`/`HB`) | | DRV Gate/motor driver| `IC_DRV` | `IC_DRV_Type_Voltage_Current_Package` (type `GATE`/`MOTOR`/`HB`) |
| AMP Amplifier/op-amp | `AMP` | `AMP_GBW_Channels_Package` | | AMP Amplifier/op-amp| `IC_AMP` | `IC_AMP_GBW_Channels_Package` |
| CMP Comparator | `CMP` | `CMP_Channels_Package` | | CMP Comparator| `IC_CMP` | `IC_CMP_Channels_Package` |
| VRF Voltage reference | `VREF` | `VREF_Voltage_Tolerance_Package` | | VRF Voltage reference| `IC_VRF` | `IC_VRF_Voltage_Tolerance_Package` |
| ADC ADC | `ADC` | `ADC_Bits_Rate_Package` | | ADC ADC| `IC_ADC` | `IC_ADC_Bits_Rate_Package` |
| DAC DAC | `DAC` | `DAC_Bits_Channels_Package` | | DAC DAC| `IC_DAC` | `IC_DAC_Bits_Channels_Package` |
| ISO Isolator/optocoupler | `ISO` | `ISO_Channels_IsolationV_Package` | | ISO Isolator/optocoupler| `IC_ISO` | `IC_ISO_Channels_IsolationV_Package` |
| XCV Transceiver | `XCVR` | `XCVR_Bus_Speed_Package` (bus `CAN`/`RS485`; e.g. `XCVR_CAN_5Mbps_SOIC-8`) | | XCV Transceiver| `IC_XCV` | `IC_XCV_Bus_Speed_Package` (bus `CAN`/`RS485`; e.g. `IC_XCV_CAN_5Mbps_SOIC-8`) |
| AFE Analog front end | `AFE` | `AFE_Function_Package` | | AFE Analog front end| `IC_AFE` | `IC_AFE_Function_Package` |
| MEM Memory | `MEM` | `MEM_Type_Size_Interface_Package` (e.g. `MEM_FLASH_128Mb_SPI_SOIC-8`) | | MEM Memory| `IC_MEM` | `IC_MEM_Type_Size_Interface_Package` (e.g. `IC_MEM_FLASH_128Mb_SPI_SOIC-8`) |
| LOG Logic gate | `LOG` | `LOG_Function_Package` (e.g. `AND2`, `BUF`) | | LOG Logic gate| `IC_LOG` | `IC_LOG_Function_Package` (e.g. `AND2`, `BUF`) |
| SEN Sensor IC | `SEN_IC` | `SEN_IC_Type_Package` | | SEN Sensor IC| `IC_SEN` | `IC_SEN_Type_Package` |
| IFC Interface/expander | `IFC` | `IFC_Function_Package` | | IFC Interface/expander| `IC_IFC` | `IC_IFC_Function_Package` |
| CLK Clock/RTC | `CLK` | `CLK_Freq_Package` (or `RTC_Package`) | | CLK Clock/RTC| `IC_CLK` | `IC_CLK_Freq_Package` (or `RTC_Package`) |
| SVR Supervisor/reset | `SVR` | `SVR_Threshold_Package` | | SVR Supervisor/reset| `IC_SVR` | `IC_SVR_Threshold_Package` |
| MTR Energy metering | `METER` | `METER_Phases_Package` | | MTR Energy metering| `IC_MTR` | `IC_MTR_Phases_Package` |
## Protection Device — `PREFIX_ratings_Package` ## Protection Device — `Protection_TYPEID_ratings_Package`
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| FUS Fuse | `FUSE` | `FUSE_Current_Voltage_Package` (speed `F`/`T` may precede current) | | FUS Fuse| `Protection_FUS` | `Protection_FUS_Current_Voltage_Package` (speed `F`/`T` may precede current) |
| RSF Resettable/PPTC | `PPTC` | `PPTC_Ihold_Voltage_Package` | | RSF Resettable/PPTC| `Protection_RSF` | `Protection_RSF_Ihold_Voltage_Package` |
| VAR Varistor/MOV | `MOV` | `MOV_Vrms_Energy_Package` | | VAR Varistor/MOV| `Protection_VAR` | `Protection_VAR_Vrms_Energy_Package` |
| GDT Gas-discharge tube | `GDT` | `GDT_Vspark_Package` | | GDT Gas-discharge tube| `Protection_GDT` | `Protection_GDT_Vspark_Package` |
| CBK Circuit breaker | `BREAKER` | `BREAKER_Current_Poles_Package` | | CBK Circuit breaker| `Protection_CBK` | `Protection_CBK_Current_Poles_Package` |
## Power Conversion Module — `PREFIX_Vin_Vout_Power_Package` ## Power Conversion Module — `Power_Conversion_Module_TYPEID_Vin_Vout_Power_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| DCM DC-DC module | `DCM` | non-isolated PoL | | DCM DC-DC module| `Power_Conversion_Module_DCM` | non-isolated PoL |
| IDC Isolated DC-DC | `IDCM` | isolated brick | | IDC Isolated DC-DC| `Power_Conversion_Module_IDC` | isolated brick |
| INV Inverter (DC-AC) | `INV` | `INV_Power_Voltage_Package` | | INV Inverter (DC-AC)| `Power_Conversion_Module_INV` | `Power_Conversion_Module_INV_Power_Voltage_Package` |
| OBC On-board charger | `OBC` | `OBC_Power_Voltage_Package` | | OBC On-board charger| `Power_Conversion_Module_OBC` | `Power_Conversion_Module_OBC_Power_Voltage_Package` |
| CHG Charger module | `CHG` | `CHG_Power_Voltage_Package` | | CHG Charger module| `Power_Conversion_Module_CHG` | `Power_Conversion_Module_CHG_Power_Voltage_Package` |
| PSU AC-DC SMPS | `PSU` | `PSU_Power_Vout_Package` | | PSU AC-DC SMPS| `Power_Conversion_Module_PSU` | `Power_Conversion_Module_PSU_Power_Vout_Package` |
| RCM Rectifier module | `RECT` | `RECT_Current_Voltage_Package` | | RCM Rectifier module| `Power_Conversion_Module_RCM` | `Power_Conversion_Module_RCM_Current_Voltage_Package` |
## Relay / Contactor — `PREFIX_CoilVoltage_ContactRating_Package` ## Relay / Contactor — `Relay_Contactor_TYPEID_CoilVoltage_ContactRating_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| RLS Signal relay | `RLY_S` | contact rating e.g. `2A/30V` | | RLS Signal relay| `Relay_Contactor_RLS` | contact rating e.g. `2A/30V` |
| RLP Power relay | `RLY_P` | | | RLP Power relay| `Relay_Contactor_RLP` | |
| SSR Solid-state relay | `SSR` | `SSR_ControlV_LoadRating_Package` | | SSR Solid-state relay| `Relay_Contactor_SSR` | `Relay_Contactor_SSR_ControlV_LoadRating_Package` |
| RLR Reed relay | `RLY_REED` | | | RLR Reed relay| `Relay_Contactor_RLR` | |
| CTC Contactor | `CTC` | HV/HC contact rating | | CTC Contactor| `Relay_Contactor_CTC` | HV/HC contact rating |
## Switch / Button — `PREFIX_[Positions]_Rating_Package` ## Switch / Button — `Switch_Button_TYPEID_[Positions]_Rating_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| SWT Tactile | `SW_TACT` | rating e.g. `50mA/12V` | | SWT Tactile| `Switch_Button_SWT` | rating e.g. `50mA/12V` |
| PBT Push button | `SW_PB` | | | PBT Push button| `Switch_Button_PBT` | |
| DSW DIP/slide | `SW_DIP` | positions e.g. `4P` | | DSW DIP/slide| `Switch_Button_DSW` | positions e.g. `4P` |
| RSW Rocker/toggle | `SW_ROCK` | | | RSW Rocker/toggle| `Switch_Button_RSW` | |
| RSY Rotary | `SW_ROT` | positions e.g. `12POS` | | RSY Rotary| `Switch_Button_RSY` | positions e.g. `12POS` |
## Connector — `CON_TYPE_Positions_Pitch_Package` ## Connector — `Connector_TYPEID_Positions_Pitch_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| CWB Wire-to-board | `CON_W2B` | e.g. `CON_W2B_2x2_P2.0` | | CWB Wire-to-board| `Connector_CWB` | e.g. `Connector_CWB_2x2_P2.0` |
| CBB Board-to-board | `CON_B2B` | | | CBB Board-to-board| `Connector_CBB` | |
| HDR Header/socket | `CON_HDR` | pitch e.g. `2.54mm` | | HDR Header/socket| `Connector_HDR` | pitch e.g. `2.54mm` |
| FFC FFC/FPC | `CON_FFC` | | | FFC FFC/FPC| `Connector_FFC` | |
| USB USB/data | `CON_USB` | add USB type (`C`, `MICRO`) | | USB USB/data| `Connector_USB` | add USB type (`C`, `MICRO`) |
| PWC Power/high-current | `CON_PWR` | add current rating | | PWC Power/high-current| `Connector_PWC` | add current rating |
| TBK Terminal block | `CON_TB` | | | TBK Terminal block| `Connector_TBK` | |
## Antenna / RF — `PREFIX_Band_Package` ## Antenna / RF — `Antenna_RF_TYPEID_Band_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| ANC Chip antenna | `ANT_CHIP` | band e.g. `2.4GHz` | | ANC Chip antenna| `Antenna_RF_ANC` | band e.g. `2.4GHz` |
| ANP PCB/trace antenna | `ANT_PCB` | | | ANP PCB/trace antenna| `Antenna_RF_ANP` | |
| ANE External/whip | `ANT_EXT` | add connector token | | ANE External/whip| `Antenna_RF_ANE` | add connector token |
| SAW SAW filter | `SAW` | `SAW_Freq_Package` | | SAW SAW filter| `Antenna_RF_SAW` | `Antenna_RF_SAW_Freq_Package` |
| RFM RF/wireless module | `RFMOD` | protocol e.g. `BLE`, `WIFI`, `LTE` | | RFM RF/wireless module| `Antenna_RF_RFM` | protocol e.g. `BLE`, `WIFI`, `LTE` |
## Crystal / Oscillator / Timing — `PREFIX_Freq_[Load]_Package` ## Crystal / Oscillator / Timing — `Crystal_Oscillator_TYPEID_Freq_[Load]_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| XTL Crystal | `XTAL` | `XTAL_Freq_LoadCap_Package` (e.g. `XTAL_48MHz_18pF_SMD2016-4P`) | | XTL Crystal| `Crystal_Oscillator_XTL` | `Crystal_Oscillator_XTL_Freq_LoadCap_Package` (e.g. `Crystal_Oscillator_XTL_48MHz_18pF_SMD2016-4P`) |
| OSC Crystal oscillator | `OSC` | `OSC_Freq_Package` | | OSC Crystal oscillator| `Crystal_Oscillator_OSC` | `Crystal_Oscillator_OSC_Freq_Package` |
| MMO MEMS oscillator | `MEMS_OSC` | | | MMO MEMS oscillator| `Crystal_Oscillator_MMO` | |
| RSN Ceramic resonator | `RESON` | `RESON_Freq_Package` | | RSN Ceramic resonator| `Crystal_Oscillator_RSN` | `Crystal_Oscillator_RSN_Freq_Package` |
## Battery / Cell — `PREFIX_Capacity_Voltage_Format` ## Battery / Cell — `Battery_Cell_TYPEID_Capacity_Voltage_Format`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| CLI Li-ion cell | `CELL_LI` | format e.g. `18650`; capacity `2600mAh` | | CLI Li-ion cell| `Battery_Cell_CLI` | format e.g. `18650`; capacity `2600mAh` |
| CLF LiFePO4 cell | `CELL_LFP` | | | CLF LiFePO4 cell| `Battery_Cell_CLF` | |
| CCO Coin/button | `CELL_COIN` | add chemistry (`CR`/`LIR`) + size (`2032`) | | CCO Coin/button| `Battery_Cell_CCO` | add chemistry (`CR`/`LIR`) + size (`2032`) |
| CNI NiMH | `CELL_NIMH` | | | CNI NiMH| `Battery_Cell_CNI` | |
| BPK Battery pack | `PACK` | `PACK_Voltage_Capacity` (e.g. `48V_20Ah`) | | BPK Battery pack| `Battery_Cell_BPK` | `Battery_Cell_BPK_Voltage_Capacity` (e.g. `48V_20Ah`) |
| CHL Cell holder | `HOLDER` | `HOLDER_CellType_Package` | | CHL Cell holder| `Battery_Cell_CHL` | `Battery_Cell_CHL_CellType_Package` |
## Audible / Indicator ## Audible / Indicator
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| BUZ Magnetic buzzer | `BUZ_MAG` | `BUZ_MAG_Voltage_Freq_Package` | | BUZ Magnetic buzzer| `Audible_Indicator_BUZ` | `Audible_Indicator_BUZ_Voltage_Freq_Package` |
| PBZ Piezo buzzer | `BUZ_PIEZO` | `BUZ_PIEZO_Voltage_Freq_Package` | | PBZ Piezo buzzer| `Audible_Indicator_PBZ` | `Audible_Indicator_PBZ_Voltage_Freq_Package` |
| SPK Speaker | `SPK` | `SPK_Power_Impedance_Package` | | SPK Speaker| `Audible_Indicator_SPK` | `Audible_Indicator_SPK_Power_Impedance_Package` |
| IND Indicator lamp | `IND` | `IND_Color_Voltage_Package` | | IND Indicator lamp| `Audible_Indicator_IND` | `Audible_Indicator_IND_Color_Voltage_Package` |
## Display / HMI — `PREFIX_Resolution/Digits_Size_Interface` ## Display / HMI — `Display_HMI_TYPEID_Resolution/Digits_Size_Interface`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| DSG 7-segment | `DISP_7SEG` | `DISP_7SEG_Digits_Color_Package` | | DSG 7-segment| `Display_HMI_DSG` | `Display_HMI_DSG_Digits_Color_Package` |
| OLE OLED | `DISP_OLED` | resolution e.g. `128x64`, size `0.96in` | | OLE OLED| `Display_HMI_OLE` | resolution e.g. `128x64`, size `0.96in` |
| LCD LCD | `DISP_LCD` | char (`16x2`) or graphic resolution | | LCD LCD| `Display_HMI_LCD` | char (`16x2`) or graphic resolution |
| TFT TFT | `DISP_TFT` | resolution + size + interface (`SPI`/`RGB`) | | TFT TFT| `Display_HMI_TFT` | resolution + size + interface (`SPI`/`RGB`) |
## Sensor (discrete / module) — `SEN_TYPE_Range_[Interface]_Package` ## Sensor (discrete / module) — `Sensor_TYPEID_Range_[Interface]_Package`
| Type | Prefix | Notes | | Type | Prefix | Notes |
|------|--------|-------| |------|--------|-------|
| STE Temperature | `SEN_TEMP` | range + interface (`I2C`/`ANALOG`) | | STE Temperature| `Sensor_STE` | range + interface (`I2C`/`ANALOG`) |
| SCU Current (Hall) | `SEN_CURR` | range e.g. `±50A` | | SCU Current (Hall)| `Sensor_SCU` | range e.g. `±50A` |
| SVO Voltage/isolated | `SEN_VOLT` | | | SVO Voltage/isolated| `Sensor_SVO` | |
| SHA Hall/position | `SEN_HALL` | type (`LATCH`/`LINEAR`) | | SHA Hall/position| `Sensor_SHA` | type (`LATCH`/`LINEAR`) |
| SIM IMU/accel | `SEN_IMU` | axes (`6AXIS`) + interface | | SIM IMU/accel| `Sensor_SIM` | axes (`6AXIS`) + interface |
| SPR Pressure | `SEN_PRES` | range + interface | | SPR Pressure| `Sensor_SPR` | range + interface |
## Thermal / Cooling ## Thermal / Cooling
| Type | Prefix | Format | | Type | Prefix | Format |
|------|--------|--------| |------|--------|--------|
| FAN Fan | `FAN` | `FAN_Size_Voltage_Airflow` (size e.g. `40x40mm`) | | FAN Fan| `Thermal_Cooling_FAN` | `Thermal_Cooling_FAN_Size_Voltage_Airflow` (size e.g. `40x40mm`) |
| HSK Heatsink | `HSK` | `HSK_Dimensions_ThermalResistance` | | HSK Heatsink| `Thermal_Cooling_HSK` | `Thermal_Cooling_HSK_Dimensions_ThermalResistance` |
| TPD Thermal pad/TIM | `TIM` | `TIM_Conductivity_Thickness` | | TPD Thermal pad/TIM| `Thermal_Cooling_TPD` | `Thermal_Cooling_TPD_Conductivity_Thickness` |
--- ---

32
references/schlib_parameters.md Executable file → Normal file
View File

@ -22,20 +22,16 @@ inside Altium; keep it as a fallback if a particular file doesn't round-trip.)
Use these exact Altium parameter names (they must match the symbol, per the SOP screenshot). Use these exact Altium parameter names (they must match the symbol, per the SOP screenshot).
The **Comment** field is set to the MPN (SOP §4), and the **Description** field is the strict The **Comment** field is set to the MPN (SOP §4), and the **Description** field is the strict
string from `references/description_format.md` — which **overwrites** whatever prose Ultra string from `references/description_format.md`.
Librarian put in `Description` (UL's text is often wrong: a real 6N137 export read
`SMD-8 CPLR SNGL 10MBD 100V/us -e3` when the datasheet CMR is 1000 V/µs).
Beyond this SOP set, also stamp on **every engineering parameter from the part's typeid sheet** **The Description is not a parameter record.** It is the `ComponentDescription` field of the
(for an `ISO`: Isolator Type, Isolation Voltage, No. of Channels, Data Rate, Supply Voltage, component's `RECORD=1` header — the box shown at *Properties → General → Description*, above the
Creepage, Package, Power, Max Output Current). Skip the housekeeping columns (`MPN_make_type`, Parameters table. Ultra-Librarian ships it as the literal placeholder text `Description`, so a
Skill/Template Version) and the four Library/Footprint Ref/Path columns — Altium already holds symbol whose parameters are all correctly filled will *still* show the word "Description" in
those as the symbol's model links, so repeating them as parameters makes two sources of truth. Altium unless that header field is rewritten. `schlib_write.py` now sets it in the same pass as
the parameters: pass `"description"` in `params.json`, or let it fall back to your
**Encoding gotcha:** Altium parameter records are **latin-1**, so a value containing `≥`, `≤`, `parameters.Description`. Always give it the same strict `Class_TYPEID` string you wrote into the
`±`-beyond-latin1, `µ` (U+00B5 is fine, U+03BC is not) or similar will crash `schlib_write.py` part's Excel, so the symbol and the workbook agree.
with a `UnicodeEncodeError`. Rephrase into latin-1 (`≥ 7 mm` → `7 mm min.`) rather than dropping
the value; `°` (U+00B0) is latin-1 and safe. The workbook keeps the original notation.
| Parameter | Source | Notes | | Parameter | Source | Notes |
|-----------|--------|-------| |-----------|--------|-------|
@ -57,9 +53,7 @@ handed to you.** Open the PDF, find each real value (`Value`, `Manufacturer Part
`Manufacturer`, `Operating Temperature`, `Tolerance`, `Datasheet`, `ROHS`, and `Process` by `Manufacturer`, `Operating Temperature`, `Tolerance`, `Datasheet`, `ROHS`, and `Process` by
inference from the package), and fill them verified. An honest blank beats a guess — the SOP inference from the package), and fill them verified. An honest blank beats a guess — the SOP
hides blank parameters, so a gap just stays empty until someone fills it. Only **one** field is hides blank parameters, so a gap just stays empty until someone fills it. Only **one** field is
purely internal and is never on a datasheet: `Vecmocon Part Code`. Use it if the engineer already purely internal and must come from the engineer: `Vecmocon Part Code` — ask for it.
supplied it; otherwise **leave it blank and note the gap in your summary — don't stop to ask**.
Stamping the symbol is automatic and non-interactive (SKILL.md, step 6), so no field blocks it.
The second-source pair (`Manufacturer 2` / `Manufacturer Part 2`) is **left blank for now** The second-source pair (`Manufacturer 2` / `Manufacturer Part 2`) is **left blank for now**
don't populate it by default. It simply stays hidden in Altium until someone fills it later. don't populate it by default. It simply stays hidden in Altium until someone fills it later.
@ -95,6 +89,7 @@ symbol's Library Ref (from `altium_refs.py`); omit it to apply to every componen
{ {
"component": "CC0402FRNPO9BN120", "component": "CC0402FRNPO9BN120",
"comment": "CC0402FRNPO9BN120", "comment": "CC0402FRNPO9BN120",
"description": "Capacitor_CER_12pF_50V_±1%_0402_NPO",
"parameters": { "parameters": {
"Component Type": "Capacitor", "Component Type": "Capacitor",
"Value": "12pF_0402", "Value": "12pF_0402",
@ -122,10 +117,7 @@ python scripts/schlib_write.py --schlib <in>.SchLib --params params.json --out <
`params.json` may carry a `"remove"` list (defaults to `["Manufacturer_Name", `params.json` may carry a `"remove"` list (defaults to `["Manufacturer_Name",
"Manufacturer_Part_Number", "Copyright", "Component_Type"]`); those Ultra-Librarian defaults are "Manufacturer_Part_Number", "Copyright", "Component_Type"]`); those Ultra-Librarian defaults are
stripped and the SOP params — including the spaced `Component Type` = Class — added. Real UL stripped and the SOP params — including the spaced `Component Type` = Class — added. The script targets the component named in `"component"` (its Library Ref / storage name),
exports also ship **placeholder** params whose Text is just the name back again (`Type` = `Type`,
`RefDes` = `RefDes`, sometimes `TYPE`); add those to `remove` too — they're noise, not data. After
writing, grep the output for `Ultra Librarian` / `Manufacturer_Name` and confirm the count is 0. The script targets the component named in `"component"` (its Library Ref / storage name),
or every component if omitted, and self-checks the output re-opens as a valid OLE. Deliver the or every component if omitted, and self-checks the output re-opens as a valid OLE. Deliver the
resulting `.SchLib`, and have the engineer open it in Altium once to confirm it loads, then Save resulting `.SchLib`, and have the engineer open it in Altium once to confirm it loads, then Save
to Server with a revision note per the SOP. to Server with a revision note per the SOP.

0
references/taxonomy.md Executable file → Normal file
View File

1
scripts/.__wtest Normal file
View File

@ -0,0 +1 @@
test

0
scripts/altium_params.py Executable file → Normal file
View File

0
scripts/altium_refs.py Executable file → Normal file
View File

0
scripts/append_parameter.py Executable file → Normal file
View File

0
scripts/common.py Executable file → Normal file
View File

0
scripts/fill_templates.py Executable file → Normal file
View File

0
scripts/gitea_components.py Executable file → Normal file
View File

0
scripts/push_to_gitea.sh Executable file → Normal file
View File

59
scripts/schlib_write.py Executable file → Normal file
View File

@ -16,6 +16,9 @@ What it does to the target component's Data stream:
and the UL ``Component_Type`` (Vecmocon adds its own spaced ``Component Type`` = Class instead); and the UL ``Component_Type`` (Vecmocon adds its own spaced ``Component Type`` = Class instead);
override this default set with a "remove" list in params.json, override this default set with a "remove" list in params.json,
- adds/updates the SOP parameters from params.json (see references/schlib_parameters.md), - adds/updates the SOP parameters from params.json (see references/schlib_parameters.md),
- sets the component's ComponentDescription (the Description shown in Altium's Properties
panel) this lives in the RECORD=1 header, NOT in a parameter record, and Ultra-Librarian
ships it as the literal placeholder "Description", so it must be rewritten explicitly,
- leaves pins, graphics, the Comment and all other records exactly as they were. - leaves pins, graphics, the Comment and all other records exactly as they were.
Usage: Usage:
@ -23,9 +26,13 @@ Usage:
params.json (same shape altium_params.py uses): params.json (same shape altium_params.py uses):
{"component":"JMK105BJ105KV-F", # LibRef / component-storage name; omit -> all comps {"component":"JMK105BJ105KV-F", # LibRef / component-storage name; omit -> all comps
"description":"Capacitor_CER_1uF_35V_±10%_0402_x7r", # optional; else parameters.Description
"parameters":{"Value":"1u","Manufacturer":"Taiyo Yuden","Component Type":"Capacitor", ...}, "parameters":{"Value":"1u","Manufacturer":"Taiyo Yuden","Component Type":"Capacitor", ...},
"remove":["Manufacturer_Name","Manufacturer_Part_Number","Copyright","Component_Type"]} # optional; default "remove":["Manufacturer_Name","Manufacturer_Part_Number","Copyright","Component_Type"]} # optional; default
The Description is the same strict Class_TYPEID string written to the part's Excel
(references/description_format.md), so symbol and workbook always agree.
IMPORTANT: this writes Altium's own binary format from outside Altium. It is validated to IMPORTANT: this writes Altium's own binary format from outside Altium. It is validated to
re-open as a well-formed OLE with every other stream byte-identical, but ALWAYS open the result re-open as a well-formed OLE with every other stream byte-identical, but ALWAYS open the result
in Altium once to confirm it loads before relying on it. in Altium once to confirm it loads before relying on it.
@ -122,9 +129,40 @@ def _rec_name(block):
return t.split('|Name=')[1].split('|')[0] if '|Name=' in t else None return t.split('|Name=')[1].split('|')[0] if '|Name=' in t else None
def edit_data(data, params, remove): def _text_block(text):
"""Re-wrap an edited text record as its 4-byte length prefix + NUL-terminated payload."""
payload=text.encode('latin-1')+b'\x00'
return struct.pack('<I', len(payload))+payload
def _set_description(blk, description):
"""Set ComponentDescription on a RECORD=1 component-header block.
The symbol's Description (Altium: Properties -> General -> Description) is NOT a parameter
record it's the ComponentDescription field of the RECORD=1 header. Ultra-Librarian ships
the literal placeholder `ComponentDescription=Description`, so unless this is rewritten the
symbol shows the word "Description" in Altium even after every SOP parameter is filled.
"""
text=blk[4:-1].decode('latin-1')
if not text.startswith('|RECORD=1|'):
return blk
if 'ComponentDescription=' in text:
parts=text.split('|')
for i,tok in enumerate(parts):
if tok.startswith('ComponentDescription='):
parts[i]='ComponentDescription='+description
text='|'.join(parts)
elif '|PartCount=' in text: # field absent entirely -> insert it
text=text.replace('|PartCount=', f'|ComponentDescription={description}|PartCount=', 1)
else:
text=text+f'|ComponentDescription={description}'
return _text_block(text)
def edit_data(data, params, remove, description=None):
"""Return a new Data stream: drop `remove` params, drop any SOP-name params (re-added """Return a new Data stream: drop `remove` params, drop any SOP-name params (re-added
fresh), keep everything else, then append the SOP params. Pins/graphics/tail untouched.""" fresh), keep everything else, then append the SOP params. When `description` is given, the
RECORD=1 ComponentDescription field is rewritten too. Pins/graphics/tail untouched."""
leading, tail = _leading_text_records(data) leading, tail = _leading_text_records(data)
sop_names=set(params) sop_names=set(params)
kept=[] kept=[]
@ -132,6 +170,8 @@ def edit_data(data, params, remove):
nm=_rec_name(blk) nm=_rec_name(blk)
if nm is not None and (nm in remove or nm in sop_names): if nm is not None and (nm in remove or nm in sop_names):
continue # drop UL duplicates + stale SOP copies continue # drop UL duplicates + stale SOP copies
if description is not None and nm is None:
blk=_set_description(blk, description) # RECORD=1 header carries the Description
kept.append(blk) kept.append(blk)
added=[_param_record(20+i, nm, val) for i,(nm,val) in enumerate(params.items())] added=[_param_record(20+i, nm, val) for i,(nm,val) in enumerate(params.items())]
return b''.join(kept)+b''.join(added)+tail return b''.join(kept)+b''.join(added)+tail
@ -219,6 +259,9 @@ def write_params(schlib, params_json, out):
component=params_json.get("component") or None component=params_json.get("component") or None
fields=params_json.get("parameters", {}) or {} fields=params_json.get("parameters", {}) or {}
remove=params_json.get("remove", DEFAULT_REMOVE) remove=params_json.get("remove", DEFAULT_REMOVE)
# The symbol's Description: taken from "description", else the "Description" parameter if the
# caller put it there (it's the same strict Class_TYPEID string that goes in the part's Excel).
description=params_json.get("description") or fields.get("Description") or None
entries, paths, content = read_container(schlib) entries, paths, content = read_container(schlib)
# target Data stream sid(s): a stream named 'Data' whose parent storage == component (or all) # target Data stream sid(s): a stream named 'Data' whose parent storage == component (or all)
@ -230,7 +273,7 @@ def write_params(schlib, params_json, out):
if not targets: if not targets:
sys.exit(f"no component Data stream found" + (f" for '{component}'" if component else "")) sys.exit(f"no component Data stream found" + (f" for '{component}'" if component else ""))
for sid in targets: for sid in targets:
content[sid]=edit_data(content[sid], fields, remove) content[sid]=edit_data(content[sid], fields, remove, description)
blob=rebuild(entries, content) blob=rebuild(entries, content)
open(out,'wb').write(blob) open(out,'wb').write(blob)
@ -239,17 +282,21 @@ def write_params(schlib, params_json, out):
if not olefile.isOleFile(out): if not olefile.isOleFile(out):
sys.exit("ERROR: rebuilt file is not a valid OLE — aborting") sys.exit("ERROR: rebuilt file is not a valid OLE — aborting")
ole=olefile.OleFileIO(out) ole=olefile.OleFileIO(out)
ok=True ok=True; desc_ok=(description is None)
for e in ole.listdir(streams=True): for e in ole.listdir(streams=True):
if e[-1].lower()=="data": if e[-1].lower()=="data":
t=ole.openstream(e).read().decode('latin-1','ignore') t=ole.openstream(e).read().decode('latin-1','ignore')
for nm in fields: for nm in fields:
if f"|Name={nm}|" not in t and f"|Name={nm}\x00" not in t and f"Name={nm}" not in t: if f"|Name={nm}|" not in t and f"|Name={nm}\x00" not in t and f"Name={nm}" not in t:
ok=False ok=False
if description is not None and f"ComponentDescription={description}|" in t:
desc_ok=True
ole.close() ole.close()
n_comp=len(targets) n_comp=len(targets)
print(f"wrote {out} ({len(fields)} params into {n_comp} component(s); removed {remove}) " desc_note=f"; description set" if description else "; no description given"
f"{'[self-check OK]' if ok else '[WARN: verify params]'}") flag='[self-check OK]' if (ok and desc_ok) else '[WARN: verify params/description]'
print(f"wrote {out} ({len(fields)} params into {n_comp} component(s); removed {remove}"
f"{desc_note}) {flag}")
def main(): def main():