← Commit history

readme: pin-1 applet backed by adom-verify; declare its origin in applet_connect

Ray ·7deb67e8b8 ·2mo ago ·parent 99f88a2
2 files changed +231−3
page.json+7−3
@@ -4,7 +4,7 @@   "slug": "stm32f103c8t6",   "title": "STM32F103C8T6 - Arm Cortex-M3 MCU (Blue Pill)",   "brief": "STMicroelectronics mainstream Arm Cortex-M3 MCU. 72 MHz, 64 KB Flash, 20 KB SRAM, USB, CAN, LQFP-48. The workhorse Blue Pill microcontroller.",-  "version": "0.2.2",+  "version": "0.2.3",   "tags": [     "component",     "microcontroller",@@ -147,6 +147,7 @@   "dependencies": {},   "files": [     "page.json",+    "readme.html",     "README.md",     "STM32F103C8Tx.kicad_sym",     "STM32F103C8T6.kicad_mod",@@ -159,5 +160,8 @@     "stm32f103c8t6-board.glb",     "thumbnails/**"   ],-  "changelog": "0.2.2: add stm32f103c8t6-flashing (SWD/OpenOCD, UART ROM bootloader, the no-ROM-DFU gotcha, RDP unlock). Second skill: the #46 upgrade-delivery probe."-}\ No newline at end of file+  "changelog": "0.2.3: pin-1 applet in the readme, backed by the adom-verify service (applet_connect declares its origin).",+  "applet_connect": [+    "https://verify-3i7rt4do98l3.adom.cloud"+  ]+}
readme.html+224
@@ -135,6 +135,230 @@ tr[data-pin].hl td,tr[data-pin].hl td.data{color:var(--text)}   <div class=pintbl><div class=pingroup><h3>POWER <span style="color:var(--text-3);font-weight:400">(9)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="1"><td class=data>1</td><td class=data>VBAT</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Backup battery supply for RTC and backup registers. Typical operating range 1.8 to 3.6 V. Supplies the RTC and backup domain when VDD is off.</td></tr><tr data-pin="8"><td class=data>8</td><td class=data>VSSA</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Analog ground reference for ADC, reset block, PLL, and analog peripherals. Connect to digital ground at a single point.</td></tr><tr data-pin="9"><td class=data>9</td><td class=data>VDDA</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Analog supply for ADC, reset block, PLL, and analog I/O. 2.0 to 3.6 V. Decouple with 1 µF + 10 nF close to the pin.</td></tr><tr data-pin="23"><td class=data>23</td><td class=data>VSS_1</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital ground, group 1. Connect to the ground plane; keep short return path to VDD_1 decoupling.</td></tr><tr data-pin="24"><td class=data>24</td><td class=data>VDD_1</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital supply, group 1. 2.0 to 3.6 V. Decouple with 100 nF close to the pin.</td></tr><tr data-pin="35"><td class=data>35</td><td class=data>VSS_2</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital ground, group 2. Connect to the ground plane; pair with VDD_2 decoupling.</td></tr><tr data-pin="36"><td class=data>36</td><td class=data>VDD_2</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital supply, group 2. 2.0 to 3.6 V. Decouple with 100 nF close to the pin.</td></tr><tr data-pin="47"><td class=data>47</td><td class=data>VSS_3</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital ground, group 3. Connect to the ground plane; pair with VDD_3 decoupling.</td></tr><tr data-pin="48"><td class=data>48</td><td class=data>VDD_3</td><td><span class="tbadge t-power">Power</span></td><td class=note style="color:var(--text-2)">Digital supply, group 3. 2.0 to 3.6 V. Decouple with 100 nF close to the pin.</td></tr></tbody></table></div><div class=pingroup><h3>GPIO <span style="color:var(--text-3);font-weight:400">(26)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="2"><td class=data>2</td><td class=data>PC13-TAMPER-RTC</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port C bit 13, muxed with TAMPER input and RTC output. Supplied through the backup power switch (limited to 3 mA sink); output speed limited to 2 MHz with max 30 pF load; must not source current.</td></tr><tr data-pin="10"><td class=data>10</td><td class=data>PA0-WKUP</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 0, 5 V-tolerant when configured as digital input. Alternate functions: standby WKUP, USART2_CTS (remap), ADC12_IN0, TIM2_CH1_ETR.</td></tr><tr data-pin="11"><td class=data>11</td><td class=data>PA1</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 1. Alternate functions: USART2_RTS, ADC12_IN1, TIM2_CH2.</td></tr><tr data-pin="12"><td class=data>12</td><td class=data>PA2</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 2. Alternate functions: USART2_TX, ADC12_IN2, TIM2_CH3.</td></tr><tr data-pin="13"><td class=data>13</td><td class=data>PA3</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 3. Alternate functions: USART2_RX, ADC12_IN3, TIM2_CH4.</td></tr><tr data-pin="14"><td class=data>14</td><td class=data>PA4</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 4. Alternate functions: SPI1_NSS, USART2_CK, ADC12_IN4.</td></tr><tr data-pin="15"><td class=data>15</td><td class=data>PA5</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 5. Alternate functions: SPI1_SCK, ADC12_IN5.</td></tr><tr data-pin="16"><td class=data>16</td><td class=data>PA6</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 6. Alternate functions: SPI1_MISO, ADC12_IN6, TIM3_CH1; remap: TIM1_BKIN.</td></tr><tr data-pin="17"><td class=data>17</td><td class=data>PA7</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 7. Alternate functions: SPI1_MOSI, ADC12_IN7, TIM3_CH2; remap: TIM1_CH1N.</td></tr><tr data-pin="18"><td class=data>18</td><td class=data>PB0</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 0. Alternate functions: ADC12_IN8, TIM3_CH3; remap: TIM1_CH2N.</td></tr><tr data-pin="19"><td class=data>19</td><td class=data>PB1</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 1. Alternate functions: ADC12_IN9, TIM3_CH4; remap: TIM1_CH3N.</td></tr><tr data-pin="20"><td class=data>20</td><td class=data>PB2</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 2, 5 V-tolerant. Doubles as BOOT1 boot mode selection input sampled at reset.</td></tr><tr data-pin="21"><td class=data>21</td><td class=data>PB10</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 10, 5 V-tolerant. Alternate functions: I2C2_SCL, USART3_TX; remap: TIM2_CH3.</td></tr><tr data-pin="22"><td class=data>22</td><td class=data>PB11</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 11, 5 V-tolerant. Alternate functions: I2C2_SDA, USART3_RX; remap: TIM2_CH4.</td></tr><tr data-pin="25"><td class=data>25</td><td class=data>PB12</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 12, 5 V-tolerant. Alternate functions: SPI2_NSS, I2C2_SMBAl, USART3_CK, TIM1_BKIN.</td></tr><tr data-pin="26"><td class=data>26</td><td class=data>PB13</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 13, 5 V-tolerant. Alternate functions: SPI2_SCK, USART3_CTS, TIM1_CH1N.</td></tr><tr data-pin="27"><td class=data>27</td><td class=data>PB14</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 14, 5 V-tolerant. Alternate functions: SPI2_MISO, USART3_RTS, TIM1_CH2N.</td></tr><tr data-pin="28"><td class=data>28</td><td class=data>PB15</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 15, 5 V-tolerant. Alternate functions: SPI2_MOSI, TIM1_CH3N.</td></tr><tr data-pin="29"><td class=data>29</td><td class=data>PA8</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 8, 5 V-tolerant. Alternate functions: USART1_CK, TIM1_CH1, MCO (master clock output).</td></tr><tr data-pin="30"><td class=data>30</td><td class=data>PA9</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 9, 5 V-tolerant. Alternate functions: USART1_TX, TIM1_CH2.</td></tr><tr data-pin="31"><td class=data>31</td><td class=data>PA10</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 10, 5 V-tolerant. Alternate functions: USART1_RX, TIM1_CH3.</td></tr><tr data-pin="41"><td class=data>41</td><td class=data>PB5</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 5 (NOT 5 V-tolerant on this pin). Alternate functions: I2C1_SMBAl; remap: TIM3_CH2, SPI1_MOSI.</td></tr><tr data-pin="42"><td class=data>42</td><td class=data>PB6</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 6, 5 V-tolerant. Alternate functions: I2C1_SCL, TIM4_CH1; remap: USART1_TX.</td></tr><tr data-pin="43"><td class=data>43</td><td class=data>PB7</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 7, 5 V-tolerant. Alternate functions: I2C1_SDA, TIM4_CH2; remap: USART1_RX.</td></tr><tr data-pin="45"><td class=data>45</td><td class=data>PB8</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 8, 5 V-tolerant. Alternate functions: TIM4_CH3; remap: I2C1_SCL, CANRX.</td></tr><tr data-pin="46"><td class=data>46</td><td class=data>PB9</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 9, 5 V-tolerant. Alternate functions: TIM4_CH4; remap: I2C1_SDA, CANTX.</td></tr></tbody></table></div><div class=pingroup><h3>TIMING <span style="color:var(--text-3);font-weight:400">(4)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="3"><td class=data>3</td><td class=data>PC14-OSC32_IN</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port C bit 14, muxed with 32 kHz LSE oscillator input (OSC32_IN). Backup-domain pin routed through the power switch; same 2 MHz / 30 pF drive limitation as PC13.</td></tr><tr data-pin="4"><td class=data>4</td><td class=data>PC15-OSC32_OUT</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port C bit 15, muxed with 32 kHz LSE oscillator output (OSC32_OUT). Backup-domain pin routed through the power switch; same 2 MHz / 30 pF drive limitation as PC13/PC14.</td></tr><tr data-pin="5"><td class=data>5</td><td class=data>PD0-OSC_IN</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">HSE crystal oscillator input (OSC_IN) after reset; remappable to GPIO PD0 by software. In GPIO mode limited to 50 MHz output. Connect to 4-16 MHz crystal or external clock.</td></tr><tr data-pin="6"><td class=data>6</td><td class=data>PD1-OSC_OUT</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">HSE crystal oscillator output (OSC_OUT) after reset; remappable to GPIO PD1 by software. In GPIO mode limited to 50 MHz output.</td></tr></tbody></table></div><div class=pingroup><h3>CONTROL <span style="color:var(--text-3);font-weight:400">(2)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="7"><td class=data>7</td><td class=data>NRST</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">Active-low bidirectional device reset. Pulled low by internal or external reset sources; external pull-up recommended (typ 40 kΩ internal weak pull-up).</td></tr><tr data-pin="44"><td class=data>44</td><td class=data>BOOT0</td><td></td><td class=note style="color:var(--text-2)">Boot mode selection input sampled at reset (with BOOT1/PB2): selects boot from Flash, System memory (bootloader), or embedded SRAM. Must be tied to a defined logic level.</td></tr></tbody></table></div><div class=pingroup><h3>USB <span style="color:var(--text-3);font-weight:400">(2)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="32"><td class=data>32</td><td class=data>PA11</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 11, 5 V-tolerant. Alternate functions: USART1_CTS, CANRX, USBDM (USB D-), TIM1_CH4.</td></tr><tr data-pin="33"><td class=data>33</td><td class=data>PA12</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 12, 5 V-tolerant. Alternate functions: USART1_RTS, CANTX, USBDP (USB D+), TIM1_ETR.</td></tr></tbody></table></div><div class=pingroup><h3>DEBUG <span style="color:var(--text-3);font-weight:400">(5)</span></h3><table><thead><tr><th style=width:44px>Pin</th><th style=width:170px>Name</th><th style=width:70px>Type</th><th>Function (datasheet)</th></tr></thead><tbody><tr data-pin="34"><td class=data>34</td><td class=data>PA13</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 13, 5 V-tolerant. Default after reset: JTMS/SWDIO (serial-wire debug data/JTAG mode select). Can be released to GPIO via SWJ-DP disable.</td></tr><tr data-pin="37"><td class=data>37</td><td class=data>PA14</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 14, 5 V-tolerant. Default after reset: JTCK/SWCLK (serial-wire debug clock/JTAG clock).</td></tr><tr data-pin="38"><td class=data>38</td><td class=data>PA15</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port A bit 15, 5 V-tolerant. Default after reset: JTDI (JTAG data in). Remappable to TIM2_CH1_ETR/PA15/SPI1_NSS.</td></tr><tr data-pin="39"><td class=data>39</td><td class=data>PB3</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 3, 5 V-tolerant. Default after reset: JTDO / TRACESWO. Remappable to TIM2_CH2, PB3, SPI1_SCK.</td></tr><tr data-pin="40"><td class=data>40</td><td class=data>PB4</td><td><span class="tbadge t-io">I/O</span></td><td class=note style="color:var(--text-2)">GPIO port B bit 4, 5 V-tolerant. Default after reset: NJTRST (JTAG reset, active low). Remappable to TIM3_CH1, PB4, SPI1_MISO.</td></tr></tbody></table></div></div> </div> +<h2 id=pin1>Which pad is pin 1 <span class=s>an applet &mdash; your confirmation goes to a real back-end, and the pad is verified once three independent reviewers agree</span></h2>+<style>+.p1wrap{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:16px;align-items:start;margin:10px 0 6px}+@media(max-width:760px){.p1wrap{grid-template-columns:1fr}}+.p1stage{background:var(--surface);border:1px solid var(--border);border-radius:12px;position:relative;+  padding:14px;display:flex;align-items:center;justify-content:center;min-height:320px}+.p1stage svg{width:100%;max-width:420px;height:auto;display:block}+.p1badge{position:absolute;left:12px;top:10px;font:600 9.5px ui-monospace,monospace;letter-spacing:.12em;+  text-transform:uppercase;color:var(--text-3);border:1px solid var(--border);border-radius:6px;padding:4px 8px}+.p1hint{position:absolute;right:12px;bottom:10px;font-size:10.5px;color:var(--text-3)}+.p1panel{background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:16px;+  display:flex;flex-direction:column;gap:12px}+.p1cons{background:var(--elevated);border:1px solid var(--border);border-radius:10px;padding:12px;+  display:flex;flex-direction:column;gap:9px}+.p1lead{display:flex;justify-content:space-between;align-items:baseline}+.p1lk{font:600 9.5px ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}+.p1lv{font:600 14px ui-monospace,monospace;color:var(--text)}+.p1dots{display:flex;gap:6px}+.p1dot{height:7px;border-radius:4px;background:#243049;flex:1}+.p1dot.on{background:var(--accent-bright)}+.p1dot.ver{background:var(--green)}+.p1cs{font-size:12px;color:var(--text-2)}+.p1cs.ok{color:var(--green);font-weight:600}+.p1btn{background:var(--accent);color:#04110f;border:none;border-radius:9px;font:600 14px 'Satoshi',system-ui,sans-serif;+  padding:11px;cursor:pointer}+.p1btn:disabled{opacity:.5;cursor:default}+.p1auth{font-size:11.5px;color:var(--text-3);font-family:ui-monospace,monospace;display:flex;gap:6px;align-items:center;flex-wrap:wrap}+.p1auth b{color:var(--text-2)}+.p1auth a{color:var(--accent-bright);cursor:pointer}+.p1in{flex:1;min-width:110px;background:var(--elevated);border:1px solid var(--border);border-radius:8px;color:var(--text);+  font:500 12.5px 'Satoshi',system-ui,sans-serif;padding:8px 10px;outline:none}+.p1in:focus{border-color:var(--accent)}+.p1reason{display:none;flex-direction:column;gap:6px}+.p1reason.show{display:flex}+.p1rl{font:600 9.5px ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}+.p1rl i{color:var(--accent-bright);font-style:normal}+.p1notes{display:flex;flex-direction:column;gap:6px}+.p1nh{font:600 9.5px ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;color:var(--text-3)}+.p1row{display:flex;gap:7px;align-items:baseline;font-size:12px;line-height:1.4}+.p1row .nv{font:600 10.5px ui-monospace,monospace;color:var(--text-3);white-space:nowrap}+.p1row .npad{font:600 10.5px ui-monospace,monospace;color:var(--accent-bright);white-space:nowrap}+.p1row .ntxt{color:var(--text-2)}+.p1row .none{color:var(--text-3);font-style:italic}+.p1row.you .nv{color:var(--accent-bright)}+.p1row.src .nv{color:var(--blue)}+.p1row.src .ntxt{color:var(--text-3)}+.p1foot{font-size:11px;color:var(--text-3);line-height:1.5}+.p1foot code{color:var(--accent-bright);font-family:ui-monospace,monospace}+.p1pad{fill:#59657e;stroke:#8b98af;stroke-width:.6;cursor:pointer}+.p1pad:hover{fill:#7d8aa3}+.p1pad.ver{fill:var(--green);stroke:#04110f}+.p1pad.sel{fill:var(--accent-bright);stroke:#04110f}+.p1num{fill:#8592a8;font:600 8.5px ui-monospace,monospace;pointer-events:none;dominant-baseline:middle}+.p1body{fill:#141a22;stroke:#2f3d57;stroke-width:1.5}+.p1dimple{fill:#0d1117;stroke:#8b98af;stroke-width:1}+</style>+<div class=p1wrap>+  <div class=p1stage>+    <svg id=p1fp viewBox="0 0 560 560" xmlns="http://www.w3.org/2000/svg"></svg>+    <div class=p1badge id=p1badge>confirm or claim pin 1</div>+    <div class=p1hint>manufacturer pin-1 dimple = top-left</div>+  </div>+  <div class=p1panel>+    <div class=p1cons>+      <div class=p1lead><span class=p1lk>current pin 1</span><span class=p1lv id=p1lead>&mdash;</span></div>+      <div class=p1dots id=p1dots><div class=p1dot></div><div class=p1dot></div><div class=p1dot></div></div>+      <div class=p1cs id=p1cs>checking the service&hellip;</div>+    </div>+    <div class=p1reason id=p1reasonwrap>+      <div class=p1rl>Why is this pad pin 1? <i>&middot; required</i></div>+      <input class=p1in id=p1reason type=text maxlength=120 spellcheck=false placeholder="e.g. dimple + bevel are on this corner">+    </div>+    <button class=p1btn id=p1pick disabled>Confirm pin 1</button>+    <div class=p1auth id=p1auth></div>+    <div class=p1notes id=p1notes></div>+    <p class=p1foot>The button calls <code>adom-verify</code>, this page's declared back-end. A vote is tied to a+      signed-in account, so three independent reviewers means three people.</p>+  </div>+</div>+<script>+(function(){+  var MPN='STM32F103C8T6', FACT='pin-1';+  // The starting pin 1 is real provenance, not a seeded vote: the KiCad footprint+  // on this page declares it. Human confirmations start at zero.+  var AUTO_PIN='1', AUTO_SOURCE='footprint', AUTO_BASIS='declared as pin 1 in the KiCad footprint';+  var SVC='https://verify-3i7rt4do98l3.adom.cloud/';   // page.json applet_connect declares this origin+  var $=function(id){return document.getElementById(id);};+  // localStorage throws in the readme sandbox (opaque origin), so keep the session in memory there+  var store=(function(){try{localStorage.setItem('_p1','1');localStorage.removeItem('_p1');return localStorage;}+    catch(e){var m={};return{getItem:function(k){return m[k]||null;},setItem:function(k,v){m[k]=v;},removeItem:function(k){delete m[k];}};}})();+  var TOKEN=store.getItem('verifyToken')||'', ME=null, selected=null, currentPin1=AUTO_PIN, signingIn=false;+  function esc(s){return String(s).replace(/[&<>"]/g,function(c){return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c];});}+  function hdrs(){return TOKEN?{'Authorization':'Bearer '+TOKEN}:{};}++  // ---- LQFP-48 top view: 12 pads a side, pin 1 top-left, counter-clockwise ----+  var NS='http://www.w3.org/2000/svg', N=12, BODY=310, PADL=36, PADW=11, GAP=BODY/N, bl=280-BODY/2;+  var svg=$('p1fp');+  function el(t,a){var e=document.createElementNS(NS,t);for(var k in a)e.setAttribute(k,a[k]);svg.appendChild(e);return e;}+  el('rect',{x:bl,y:bl,width:BODY,height:BODY,rx:10,'class':'p1body'});+  el('circle',{cx:bl+22,cy:bl+22,r:9,'class':'p1dimple'});+  function pad(x,y,w,h,n){var r=el('rect',{x:x,y:y,width:w,height:h,rx:2.5,'class':'p1pad'});r.setAttribute('data-pin',n);return r;}+  function num(x,y,anchor,n){var t=el('text',{x:x,y:y,'text-anchor':anchor,'class':'p1num'});t.textContent=n;}+  var pin=1,i,yc,xc;+  for(i=0;i<N;i++){yc=bl+GAP/2+i*GAP;pad(bl-PADL,yc-PADW/2,PADL,PADW,pin);num(bl-PADL-7,yc,'end',pin);pin++;}+  for(i=0;i<N;i++){xc=bl+GAP/2+i*GAP;pad(xc-PADW/2,bl+BODY,PADW,PADL,pin);num(xc,bl+BODY+PADL+13,'middle',pin);pin++;}+  for(i=0;i<N;i++){yc=bl+BODY-GAP/2-i*GAP;pad(bl+BODY,yc-PADW/2,PADL,PADW,pin);num(bl+BODY+PADL+7,yc,'start',pin);pin++;}+  for(i=0;i<N;i++){xc=bl+BODY-GAP/2-i*GAP;pad(xc-PADW/2,bl-PADL,PADW,PADL,pin);num(xc,bl-PADL-8,'middle',pin);pin++;}++  function targetPin(){return selected||currentPin1;}+  function confirming(){var t=targetPin();return t&&t===currentPin1;}+  function updateBtn(){+    var b=$('p1pick'), t=targetPin();+    if(!ME){$('p1reasonwrap').classList.remove('show');b.disabled=false;b.textContent='Sign in to vote';return;}+    if(!t){b.disabled=true;b.textContent='Pick a pad';return;}+    if(confirming()){$('p1reasonwrap').classList.remove('show');b.disabled=false;b.textContent='Confirm pad '+t+' is pin 1';return;}+    $('p1reasonwrap').classList.add('show');+    if(!$('p1reason').value.trim()){b.disabled=true;b.textContent='Add a reason to claim pad '+t;return;}+    b.disabled=false;b.textContent='Claim pad '+t+' is pin 1';+  }+  svg.addEventListener('click',function(e){+    var p=e.target.closest('.p1pad');if(!p)return;+    [].forEach.call(svg.querySelectorAll('.p1pad.sel'),function(x){x.classList.remove('sel');});+    selected=p.getAttribute('data-pin');+    if(selected!==currentPin1)p.classList.add('sel');       // teal marks a claim on a different pad+    updateBtn();+    if($('p1reasonwrap').classList.contains('show'))$('p1reason').focus();+  });+  $('p1reason').addEventListener('input',updateBtn);++  // ---- identity (no prompt(): modals are blocked in the readme sandbox) ----+  function renderAuth(msg){+    var el=$('p1auth');+    if(ME){el.innerHTML='signed in as <b>'+esc(ME.name)+'</b> &middot; <a id=p1out>sign out</a>';+      $('p1out').onclick=function(){TOKEN='';store.removeItem('verifyToken');ME=null;renderAuth();updateBtn();};return;}+    if(signingIn){el.innerHTML='<input class=p1in id=p1handle placeholder="your name or handle" maxlength=40>'+        +'<a id=p1go>sign in</a> <a id=p1cancel style="color:var(--text-3)">cancel</a>';+      var h=$('p1handle');h.focus();+      h.onkeydown=function(e){if(e.key==='Enter')doSignIn();};+      $('p1go').onclick=doSignIn;+      $('p1cancel').onclick=function(){signingIn=false;renderAuth();};return;}+    el.innerHTML=(msg?'<span style="color:var(--red)">'+esc(msg)+'</span> &middot; ':'')+'<a id=p1in2>Sign in</a> to vote';+    $('p1in2').onclick=function(){signingIn=true;renderAuth();};+  }+  function doSignIn(){+    var handle=($('p1handle')&&$('p1handle').value||'').trim();+    if(!handle)return;+    fetch(SVC+'auth/dev',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({handle:handle})})+      .then(function(r){return r.json();})+      .then(function(j){+        if(!j.token)throw new Error(j.error||'sign-in failed');+        TOKEN=j.token;store.setItem('verifyToken',TOKEN);signingIn=false;+        return loadMe().then(function(){renderAuth();updateBtn();load();});+      })+      .catch(function(e){signingIn=false;renderAuth(e.message);});+  }+  function loadMe(){+    if(!TOKEN){ME=null;return Promise.resolve();}+    return fetch(SVC+'me',{headers:hdrs()}).then(function(r){return r.json();})+      .then(function(j){ME=j.authed?j:null;}).catch(function(){ME=null;});+  }++  // ---- consensus ----+  function renderNotes(picks){+    var src='<div class="p1row src"><span class=nv>'+esc(AUTO_SOURCE)+'</span><span class=npad>pad '+esc(AUTO_PIN)+      +'</span><span class=ntxt>'+esc(AUTO_BASIS)+'</span></div>';+    var human='';+    if(picks&&picks.length){+      human=picks.slice().sort(function(a,b){return (a.value-b.value)||String(a.name).localeCompare(String(b.name));})+        .map(function(p){+          var you=ME&&p.voter===ME.voter;+          var txt=p.reason?('&ldquo;'+esc(p.reason)+'&rdquo;'):'<span class=none>no reason given</span>';+          return '<div class="p1row'+(you?' you':'')+'"><span class=nv>'+esc(you?'you':p.name)+'</span>'+            +'<span class=npad>pad '+esc(p.value)+'</span><span class=ntxt>'+txt+'</span></div>';+        }).join('');+    }+    $('p1notes').innerHTML='<div class=p1nh>provenance &amp; reviewer picks</div>'+src+human;+  }+  function render(s){+    currentPin1=s.verified_value||s.leader||AUTO_PIN;+    var c=(s.tally&&s.tally[currentPin1])||0;+    $('p1lead').textContent='pad '+currentPin1;+    var dots=$('p1dots').children;+    for(var i=0;i<3;i++)dots[i].className='p1dot'+(i<c?(s.verified?' ver':' on'):'');+    [].forEach.call(svg.querySelectorAll('.p1pad.ver'),function(x){x.classList.remove('ver');});+    var vp=svg.querySelector('.p1pad[data-pin="'+currentPin1+'"]');if(vp)vp.classList.add('ver');+    if(s.verified){+      $('p1cs').textContent='verified ✓ pin 1 = pad '+s.verified_value+' ('+c+'/'+s.needed+' agree)';+      $('p1cs').classList.add('ok');$('p1badge').textContent='pin 1 verified';+    }else{+      $('p1cs').classList.remove('ok');$('p1badge').textContent='confirm or claim pin 1';+      $('p1cs').textContent=c>0+        ? 'pad '+currentPin1+' · '+c+' of '+s.needed+' reviewer confirmations · '+(s.needed-c)+' more needed'+        : 'from the '+AUTO_SOURCE+' · 0 of '+s.needed+' reviewer confirmations';+    }+    renderNotes(s.picks);updateBtn();+  }+  function load(){+    return fetch(SVC+'status?page='+encodeURIComponent(MPN)+'&fact='+FACT)+      .then(function(r){return r.json();}).then(render)+      .catch(function(){$('p1cs').textContent='verification service unreachable';});+  }+  $('p1pick').addEventListener('click',function(){+    if(!ME){signingIn=true;renderAuth();return;}+    var t=targetPin();if(!t)return;+    var conf=confirming(), note=$('p1reason').value.trim();+    if(!conf&&!note)return;+    $('p1pick').disabled=true;$('p1pick').textContent='Submitting…';+    fetch(SVC+'vote?page='+encodeURIComponent(MPN)+'&fact='+FACT+'&value='+t+'&reason='+encodeURIComponent(conf?'':note),+          {method:'POST',headers:hdrs()})+      .then(function(r){+        if(r.status===401){TOKEN='';store.removeItem('verifyToken');ME=null;renderAuth('session expired');updateBtn();return null;}+        return r.json();})+      .then(function(s){+        if(!s)return;+        selected=null;$('p1reason').value='';+        [].forEach.call(svg.querySelectorAll('.p1pad.sel'),function(x){x.classList.remove('sel');});+        render(s);})+      .catch(function(e){$('p1cs').textContent='vote failed: '+e.message;updateBtn();});+  });+  svg.querySelector('.p1pad[data-pin="'+AUTO_PIN+'"]').classList.add('ver');+  loadMe().then(function(){renderAuth();updateBtn();return load();});+})();+</script>+ <h2>Datasheet key pages <span class=s>the pages worth looking at first &middot; pick a page, click it to go full screen</span></h2> <div class=dsviewer>   <div class=dsrail><button data-i="0" class="on" title="Features (datasheet p.1)"><img src="https://wiki.adom.inc/blob/component/stm32f103c8t6/keypages/features.png" loading=lazy alt="Features"><span class=rl>Features</span></button><button data-i="1" class="" title="Block diagram (datasheet p.11)"><img src="https://wiki.adom.inc/blob/component/stm32f103c8t6/keypages/block-diagram.png" loading=lazy alt="Block diagram"><span class=rl>Block diagram</span></button><button data-i="2" class="" title="Pinout (datasheet p.29)"><img src="https://wiki.adom.inc/blob/component/stm32f103c8t6/keypages/pinout.png" loading=lazy alt="Pinout"><span class=rl>Pinout</span></button><button data-i="3" class="" title="Pin table (datasheet p.28)"><img src="https://wiki.adom.inc/blob/component/stm32f103c8t6/keypages/pin-table.png" loading=lazy alt="Pin table"><span class=rl>Pin table</span></button><button data-i="4" class="" title="Package (datasheet p.101)"><img src="https://wiki.adom.inc/blob/component/stm32f103c8t6/keypages/package.png" loading=lazy alt="Package"><span class=rl>Package</span></button></div>