<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://thomas.quinot.org/labnotes/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thomas.quinot.org/labnotes/" rel="alternate" type="text/html" /><updated>2026-09-29T20:16:01+00:00</updated><id>https://thomas.quinot.org/labnotes/feed.xml</id><title type="html">Thomas’ Lab Notes</title><subtitle>Stuff worth not forgetting</subtitle><entry><title type="html">Yamaha HTR-3064 receiver partial recap</title><link href="https://thomas.quinot.org/labnotes/2026/07/25/yamaha-receiver-recap.html" rel="alternate" type="text/html" title="Yamaha HTR-3064 receiver partial recap" /><published>2026-07-25T00:00:00+00:00</published><updated>2026-07-25T00:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2026/07/25/yamaha-receiver-recap</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2026/07/25/yamaha-receiver-recap.html"><![CDATA[<h1 id="problem-statement">Problem statement</h1>

<h2 id="device">Device</h2>

<p>Yamaha HTR-3064 receiver, version G (Europe)</p>

<h2 id="symptom">Symptom</h2>

<p>The unit powers up just fine, but when an HDMI source is switched on, the unit turns off.
Upon the next power-on, the display indicates a PS PRT alert protection, with a numeric indication between 098L and 100L. This does not happen, however, if the unit is powered up and left for 15-30 minutes to heat up before switching on the HDMI source.</p>

<figure>
<video class="video-js rounded" controls="" width="640" height="360" preload="metadata" data-setup="{}">
  <source src="assets/Yamaha-HTR-3064/PXL_20260725_083730384.TS.mp4" type="video/mp4" />
</video>
  <figcaption>Unit shutdown upon switching on an HDMI source</figcaption>
</figure>

<p>With the unit idle (no HDMI source active), enabling the self-diagnostic function and monitoring the PS voltage shows values varying significantly between values below 120 and slightly above 130.</p>

<figure>
<video class="video-js rounded" controls="" width="640" height="360" preload="metadata" data-setup="{}">
  <source src="assets/Yamaha-HTR-3064/PXL_20260725_083659547.TS.mp4" type="video/mp4" />
</video>
  <figcaption>PS reading fluctuations</figcaption>
</figure>

<h2 id="background-information-the-ps-value">Background information: the PS value</h2>

<p>PS appears to be an internal A/D monitoring point that averages several voltages in the power supply chain.
From the Service manual (p. 37):</p>

<blockquote>
  <p><strong>PS:</strong> Power supply voltage protection detection<br />
Detected: AC2, ±12A, S9, +7D, +5A, +5I, -VP<br />
Detection port: 93 pin (PS_PRT)<br />
Normal value: 101 to 155<br />
(Reference voltage: 3.3 V=255)</p>
</blockquote>

<p>which indicates that the normal range at that point is between 1.31 V and 2.01 V (circuit diagram mentions 1.7V). A 098 reading would correspond to 1.27V, a 100 reading to 1.29. So the observed PS shutdowns would correspond to undervoltage by a good fraction of a volt at this test point.</p>

<h2 id="service-manual-oddity">Service manual oddity</h2>

<p>In the documentation of messages displayed when starting the self-diagnostic function, the HTR-3064 service manual lists a number of possible protection faults at previous shutdown, with associated messages displayed on the device shown as illustrations.</p>

<figure>
<p><img src="assets/Yamaha-HTR-3064/htr-3064-PS_PRT.png" alt="HTR-3064 PS_PRT" />
<img src="assets/Yamaha-HTR-3064/htr-3064-PRV_PRT.png" alt="HTR-3064 PRV_PRT" /></p>
  <figcaption>HTR-3064 service manual: protection messages PS_PRT and PRV_PRT</figcaption>
</figure>

<table>
  <thead>
    <tr>
      <th>Paragraph</th>
      <th>Fault</th>
      <th>Message from illustration</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>2-1</td>
      <td>Excess current</td>
      <td>PS_PRT (with ADC reading)</td>
    </tr>
    <tr>
      <td>2-2</td>
      <td>Short between speaker terminals</td>
      <td>I PROTECT</td>
    </tr>
    <tr>
      <td>2-3</td>
      <td>Abnormal DC output</td>
      <td>DC_PRT (with ADC reading)</td>
    </tr>
    <tr>
      <td>2-4</td>
      <td>Abnormal power supply voltage</td>
      <td>PRV_PRT (with ADC reading)</td>
    </tr>
    <tr>
      <td>2-5</td>
      <td>Excessive temperature</td>
      <td>TMP_PRT (with ADC reading)</td>
    </tr>
  </tbody>
</table>

<p>The ADC conversions (section 9 of self diagnostics) and the IC221 pin list describe parameters monitored:</p>

<table>
  <thead>
    <tr>
      <th>Pin</th>
      <th>Pin name</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>53</td>
      <td>I_PRT</td>
      <td>Overcurrent protection</td>
    </tr>
    <tr>
      <td>93</td>
      <td>PS_PRT</td>
      <td>Power supply</td>
    </tr>
    <tr>
      <td>87</td>
      <td>DC_PRT</td>
      <td>Power amplifier DC output</td>
    </tr>
    <tr>
      <td>89</td>
      <td>THM1_PRT</td>
      <td>Temperature</td>
    </tr>
    <tr>
      <td>90</td>
      <td>THM2_PRT</td>
      <td>Temperature (U and C models)</td>
    </tr>
  </tbody>
</table>

<p>Examination of the circuit diagrams confirm that the PS_PRT pin indeed averages the voltages of various test points in the power supply section. So it looks like the wrong messages might be shown in the description of self-diagnostic conditions, and PS_PRT: xxxL on the display would indicate undervoltage in the power supply section (i.e. should be shown to illustrate 2-4 and not 2-1).</p>

<p>Interestingly, no ADC pin of the CPU is labeled as PRV_PRT.</p>

<p>The service manual for the HTR-3067 has very similar text, but shows the PS_PRT illustration for the “abnormal voltage in power supply” condition, which contributes to confirming the logic here:</p>

<figure>
<p><img src="assets/Yamaha-HTR-3064/htr-3067-I_PROTECT.png" alt="HTR-3067 I_PROTECT" />
<img src="assets/Yamaha-HTR-3064/htr-3067-PS_PRT.png" alt="HTR-3067 PS_PRT" /></p>
  <figcaption>HTR-3067 service manual: protection messages I_PROTECT and PS_PRT</figcaption>
</figure>

<h1 id="investigation">Investigation</h1>

<h2 id="visual-inspection">Visual inspection</h2>

<p>Opening the case reveals <em>two swollen electrolytic capacitors</em> C1317 and C1320 on the OPERATION (2) board.</p>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_093620132.jpg" alt="Swollen C1320 and C1317 (1)" />
<img src="assets/Yamaha-HTR-3064/PXL_20260725_093349715.MP.jpg" alt="Swollen C1320 and C1317 (2)" /></p>
  <figcaption>Swollen C1320 and C1317</figcaption>
</figure>

<p>Both are smoothing capacitors located right after rectifier bridges fed from the main transformer.</p>
<ul>
  <li>C1320 is 10,000 µF and smoothes the +7D rail monitored by PS_PRT.</li>
  <li>C1317 is 4,700 µF and smoothes the input of IC132, a 7805 regulator providing the +5I rail also monitored by PS_PRT.</li>
</ul>

<figure>
<p><img src="assets/Yamaha-HTR-3064/circuit-C1317-C1320.png" alt="Circuit schematic excerpt" /></p>
  <figcaption>Circuit schematic excerpt</figcaption>
</figure>

<h2 id="in-circuit-measurement">In-circuit measurement</h2>

<p>In-circuit measurement of course cannot provide reliable component values but suggested that the capacitance for both caps was way off. By comparison, measurement for other caps on the board (C1318, C1319) showed values within range of the nominal ones.</p>

<h2 id="out-of-circuit-measurement">Out-of-circuit measurement</h2>

<p>Once the two swollen capacitors were desoldered (using a power desoldering pump, which posed no difficulty), out-of-circuit measurement confirmed values way off the nominal ones, as well as substantial voltage loss. The ESR figure was not remarkably high, but still one order of magnitude higher than the one observed on new replacement parts.</p>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_093925410.jpg" alt="C1317: defective part" /></p>
  <figcaption>C1317: defective part</figcaption>
</figure>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_094131784.jpg" alt="C1320: defective part" /></p>
  <figcaption>C1320: defective part</figcaption>
</figure>

<h1 id="parts-replacement">Parts replacement</h1>

<p>I ordered replacement caps from Reichelt, which has the lowest shipping rates for small orders among reputable online sellers. I wanted to avoid cheap Chinese knockoffs this time, as I don’t fancy going through the whole repair process too often.</p>

<h2 id="component-tester-readings-for-the-replacement-parts">Component tester readings for the replacement parts</h2>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_094351390.jpg" alt="C1317: replacement part" /></p>
  <figcaption>C1317: replacement part</figcaption>
</figure>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_094441516.jpg" alt="C1320: replacement part" /></p>
  <figcaption>C1320: replacement part</figcaption>
</figure>

<h2 id="soldering-new-caps">Soldering new caps</h2>

<p>Soldering the two new caps in place proved more difficult than anticipated. The solder tended to ball instead of flowing nicely onto the pads. This is likely due to using too high a temperature on the soldering iron, resulting in burning the flux before it had a chance to actually remove the thin oxydization layer on the pads. Light scraping of the pad with a fiberglass abrasive pen likely would have helped as well.</p>

<figure>
<p><img src="assets/Yamaha-HTR-3064/PXL_20260725_102247708.jpg" alt="New caps on reassembled board" /></p>
  <figcaption>New caps on reassmebled board</figcaption>
</figure>

<h1 id="post-repair-testing">Post-repair testing</h1>

<p>Once the two new caps were installed, the readings for the PS ADC value in the self-diagnostic function became much more stable, both before and after switching on the HDMI source. It remains in the vicinity of 130, consistent with the expected 1.7V (reading 131) shown on the service manual circuit diagram.</p>

<p>The amplifier no longer shut down upon connecting an HDMI signal: <strong>repair was declared successful</strong>.</p>

<figure>
<video class="video-js rounded" controls="" width="640" height="360" preload="metadata" data-setup="{}">
  <source src="assets/Yamaha-HTR-3064/PXL_20260725_111910550.TS.mp4" type="video/mp4" />
</video>
  <figcaption>Unit shutdown upon switching on an HDMI source</figcaption>
</figure>]]></content><author><name></name></author><summary type="html"><![CDATA[Problem statement]]></summary></entry><entry><title type="html">Panel mounting JS-910B binding posts</title><link href="https://thomas.quinot.org/labnotes/2026/05/30/js-910b-binding-post.html" rel="alternate" type="text/html" title="Panel mounting JS-910B binding posts" /><published>2026-05-30T00:00:00+00:00</published><updated>2026-05-30T00:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2026/05/30/js-910b-binding-post</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2026/05/30/js-910b-binding-post.html"><![CDATA[<h2 id="hardware-description">Hardware description</h2>

<p>JS-910B is the designation for generic Chinese binding posts with 4mm banana socket connections for panel mounting.
(<a href="https://s.click.aliexpress.com/e/_c4NsWvXf">AliExpress</a>).</p>

<figure>
<p><img src="assets/JS-910B/JS-910B-assembly.jpg" alt="Binding post structure" /></p>
  <figcaption>Binding post assembly</figcaption>
</figure>

<p>The order in which all of the parts go is not 100% obvious until you have figured it out:</p>
<ul>
  <li>socket body</li>
  <li>plastic insulating ring (hollow)</li>
  <li>panel</li>
  <li>shouldered plastic ring</li>
  <li>metal washer</li>
  <li>connection tab</li>
  <li>tightening nut</li>
  <li>locking nut</li>
</ul>

<figure>
<p><img src="assets/JS-910B/JS-910B-diagram.jpg" alt="Panel mounting diagram" /></p>
  <figcaption>Panel mounting diagram</figcaption>
</figure>

<h2 id="panel-mounting-details">Panel mounting details</h2>

<p>The clever part of the design is the shouldered plastic ring: the shoulder goes through the panel hole, to ensure insulation between the metal body of the socket and the panel (essential in the case of a conductive panel!). The hollow ring goes on the front and covers whatever height of the shoulder protrudes through the panel hole (in case the panel is thinner than the height of the shoulder).</p>

<p>:warning: <em>Of course this means that the panel must be drilled to the outer diameter of the shoulder (8mm).</em></p>

<figure>
<p><img src="assets/JS-910B/JS-910B-shoulder-protruding.jpg" alt="Shouldered ring protruding from panel (front)" /></p>
  <figcaption>Shouldered ring protruding from panel (front)</figcaption>
</figure>

<p>Here is what the completed panel mounting looks like:</p>

<figure>
<p><img src="assets/JS-910B/JS-910B-front.jpg" alt="Mounted binding post (front)" /></p>
  <figcaption>Mounted binding post (front)</figcaption>
</figure>

<figure>
<p><img src="assets/JS-910B/JS-910B-back.jpg" alt="Mounted binding post (back)" /></p>
  <figcaption>Mounted binding post (back)</figcaption>
</figure>]]></content><author><name></name></author><summary type="html"><![CDATA[Hardware description]]></summary></entry><entry><title type="html">Migrating from Drone CI to Woodpecker CI</title><link href="https://thomas.quinot.org/labnotes/2026/04/18/drone-to-woodpecker.html" rel="alternate" type="text/html" title="Migrating from Drone CI to Woodpecker CI" /><published>2026-04-18T00:00:00+00:00</published><updated>2026-04-18T00:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2026/04/18/drone-to-woodpecker</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2026/04/18/drone-to-woodpecker.html"><![CDATA[<p><a href="https://woodpecker-ci.org/">Woodpecker CI</a> is a community fork of Drone CI, created when Drone changed its licensing model around 2021 and moved features behind a paid enterprise tier. Woodpecker continues as a fully open-source (Apache 2.0) project with active development, while Drone itself has been largely absorbed into Harness CI and is in maintenance mode.</p>

<p>If you’re running Drone with Gitea, Woodpecker is a natural migration target — it has strong Gitea integration and an actively maintained codebase. Here is what the migration actually involves, based on a real setup using Docker Compose and Traefik.</p>

<h2 id="docker-compose">Docker Compose</h2>

<p>The server and runner/agent images change, and there are several environment variable renames. Woodpecker also uses different ports: the web UI runs on <strong>8000</strong> (not 80), and the agent communicates with the server over gRPC on port <strong>9000</strong>.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="na">woodpecker</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">woodpeckerci/woodpecker-server:latest</span>
    <span class="na">container_name</span><span class="pi">:</span> <span class="s">woodpecker</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_HOST=https://drone.example.org</span>   <span class="c1"># full URL including scheme</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_GITEA=true</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_GITEA_URL=https://gitea.example.org</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_CRON_DISABLED=true</span>
    <span class="na">env_file</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./woodpecker.env</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">woodpecker:/var/lib/woodpecker</span>   <span class="c1"># different path from Drone's /data</span>
    <span class="na">networks</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">services</span>
      <span class="pi">-</span> <span class="s">woodpecker</span>
    <span class="na">labels</span><span class="pi">:</span>
      <span class="na">traefik.enable</span><span class="pi">:</span> <span class="s2">"</span><span class="s">true"</span>
      <span class="na">traefik.http.services.woodpecker.loadbalancer.server.port</span><span class="pi">:</span> <span class="m">8000</span>  <span class="c1"># not 80!</span>

  <span class="na">woodpecker-agent</span><span class="pi">:</span>
    <span class="na">image</span><span class="pi">:</span> <span class="s">woodpeckerci/woodpecker-agent:latest</span>
    <span class="na">restart</span><span class="pi">:</span> <span class="s">unless-stopped</span>
    <span class="na">environment</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_SERVER=woodpecker:9000</span>   <span class="c1"># gRPC port, not HTTP</span>
      <span class="pi">-</span> <span class="s">WOODPECKER_GRPC_SECURE=false</span>
    <span class="na">env_file</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">./woodpecker.env</span>
    <span class="na">volumes</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">/var/run/docker.sock:/var/run/docker.sock</span>
    <span class="na">networks</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="s">woodpecker</span>
</code></pre></div></div>

<p>Make sure both the server and agent containers are on the <strong>same Docker network</strong>. If the agent can resolve the server’s hostname but port 9000 is refused, it is likely a startup ordering issue — simply restarting the agent container after the server is fully up will fix it.</p>

<h2 id="environment-variables">Environment Variables</h2>

<p>Your <code class="language-plaintext highlighter-rouge">drone.env</code> secrets need to be renamed in a new <code class="language-plaintext highlighter-rouge">woodpecker.env</code> file:</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">drone.env</code></th>
      <th><code class="language-plaintext highlighter-rouge">woodpecker.env</code></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DRONE_GITEA_CLIENT_ID</code></td>
      <td><code class="language-plaintext highlighter-rouge">WOODPECKER_GITEA_CLIENT</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DRONE_GITEA_CLIENT_SECRET</code></td>
      <td><code class="language-plaintext highlighter-rouge">WOODPECKER_GITEA_SECRET</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DRONE_RPC_SECRET</code></td>
      <td><code class="language-plaintext highlighter-rouge">WOODPECKER_AGENT_SECRET</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">DRONE_COOKIE_SECRET</code></td>
      <td><code class="language-plaintext highlighter-rouge">WOODPECKER_SECRET</code></td>
    </tr>
  </tbody>
</table>

<p>Note that <code class="language-plaintext highlighter-rouge">WOODPECKER_AGENT_SECRET</code> (RPC) and <code class="language-plaintext highlighter-rouge">WOODPECKER_SECRET</code> (cookie signing) are <strong>separate variables</strong> — do not conflate them.</p>

<p>You also need to set <code class="language-plaintext highlighter-rouge">WOODPECKER_ADMIN</code> to your Gitea username, otherwise Woodpecker will not allow you to register or access the admin panel:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>WOODPECKER_ADMIN=yourusername
</code></pre></div></div>

<p>You will also need to create a <strong>new OAuth application in Gitea</strong> pointing at your Woodpecker URL, since the callback URL changes.</p>

<h2 id="pipeline-files">Pipeline Files</h2>

<p><strong>You must rename <code class="language-plaintext highlighter-rouge">.drone.yml</code> to <code class="language-plaintext highlighter-rouge">.woodpecker.yml</code>.</strong> Despite what the documentation suggests, Woodpecker (at least on the <code class="language-plaintext highlighter-rouge">next</code> tag) does not fall back to <code class="language-plaintext highlighter-rouge">.drone.yml</code> — it will silently ignore it, and pushes will not trigger any pipelines.</p>

<p>The pipeline syntax is largely compatible. Steps, images, commands, secrets, and <code class="language-plaintext highlighter-rouge">when</code> conditions mostly work as-is. A few things to check:</p>

<p><strong>Move <code class="language-plaintext highlighter-rouge">trigger</code> to the pipeline level.</strong> In Drone it was sometimes written under individual steps; in Woodpecker it must be a top-level key.</p>

<p><strong>Drone plugins still work.</strong> They are just Docker images, so plugins like <code class="language-plaintext highlighter-rouge">drillster/drone-rsync</code> are fully compatible.</p>

<p><strong><code class="language-plaintext highlighter-rouge">DRONE_*</code> environment variables become <code class="language-plaintext highlighter-rouge">CI_*</code>.</strong> If your pipeline scripts reference injected variables like <code class="language-plaintext highlighter-rouge">DRONE_COMMIT</code>, these are renamed in Woodpecker (e.g. <code class="language-plaintext highlighter-rouge">CI_COMMIT_SHA</code>).</p>

<h2 id="what-does-not-migrate">What Does Not Migrate</h2>

<p>Woodpecker does not import Drone’s database. This means:</p>

<ul>
  <li><strong>Build history is lost</strong> — you start with a clean slate</li>
  <li><strong>Secrets must be re-entered</strong> via the Woodpecker UI for each repository</li>
  <li><strong>Repos must be re-activated</strong> in Woodpecker</li>
</ul>

<p>If retaining build history matters, you can keep the old Drone instance running read-only alongside Woodpecker temporarily, since they can coexist on different hostnames.</p>

<h2 id="summary">Summary</h2>

<p>For a straightforward Drone + Gitea + Docker Compose setup, the migration is low effort. The main steps are:</p>

<ol>
  <li>Update <code class="language-plaintext highlighter-rouge">docker-compose.yml</code> with the new images and port numbers</li>
  <li>Rename secrets in your env file and set <code class="language-plaintext highlighter-rouge">WOODPECKER_ADMIN</code></li>
  <li>Create a new OAuth app in Gitea</li>
  <li>Rename <code class="language-plaintext highlighter-rouge">.drone.yml</code> to <code class="language-plaintext highlighter-rouge">.woodpecker.yml</code> in each repository</li>
  <li>Move any pipeline-level <code class="language-plaintext highlighter-rouge">trigger</code> blocks to the top level</li>
  <li>Re-activate repos and re-enter secrets in the Woodpecker UI</li>
</ol>]]></content><author><name></name></author><category term="ci" /><category term="devops" /><category term="drone" /><category term="woodpecker" /><category term="gitea" /><category term="docker" /><summary type="html"><![CDATA[Woodpecker CI is a community fork of Drone CI, created when Drone changed its licensing model around 2021 and moved features behind a paid enterprise tier. Woodpecker continues as a fully open-source (Apache 2.0) project with active development, while Drone itself has been largely absorbed into Harness CI and is in maintenance mode.]]></summary></entry><entry><title type="html">Fix: macOS 15 Sequoia CUPS printing fails with Validate-Job client-error-not-found</title><link href="https://thomas.quinot.org/labnotes/2026/03/08/printing-for-macos-to-cups.html" rel="alternate" type="text/html" title="Fix: macOS 15 Sequoia CUPS printing fails with Validate-Job client-error-not-found" /><published>2026-03-08T00:00:00+00:00</published><updated>2026-03-08T00:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2026/03/08/printing-for-macos-to-cups</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2026/03/08/printing-for-macos-to-cups.html"><![CDATA[<p>When adding a remote CUPS print server on macOS 15 Sequoia, print jobs may fail immediately with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Validate-Job client-error-not-found
</code></pre></div></div>

<h2 id="cause">Cause</h2>

<p>macOS sends a <code class="language-plaintext highlighter-rouge">Validate-Job</code> IPP request before submitting the actual print job. If the queue URI is incorrect, the server cannot find the printer and rejects it with this error.</p>

<p>The most common culprit is the <strong>queue name</strong> field when adding the printer via System Settings → Printers &amp; Scanners → Add Printer → IP tab. Leaving it blank or entering just the printer name causes macOS to target the wrong IPP endpoint.</p>

<h2 id="fix">Fix</h2>

<p>When adding the printer, set the <strong>Queue</strong> field to:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/printers/&lt;printername&gt;
</code></pre></div></div>

<p>(note <code class="language-plaintext highlighter-rouge">/printers/</code> prefix, it’s not <strong>just the CUPS queue name</strong>)</p>

<p>For example, if your printer is named <code class="language-plaintext highlighter-rouge">office-laser</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/printers/office-laser
</code></pre></div></div>

<p>The full URI should resolve to:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ipp://&lt;server&gt;:631/printers/&lt;printername&gt;
</code></pre></div></div>

<h2 id="fixing-an-already-added-printer">Fixing an already-added printer</h2>

<p>No need to remove and re-add it. Update the URI in place with <code class="language-plaintext highlighter-rouge">lpadmin</code>:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lpadmin <span class="nt">-p</span> &lt;printername&gt; <span class="nt">-v</span> ipp://&lt;server&gt;:631/printers/&lt;printername&gt;
</code></pre></div></div>

<h2 id="verifying-the-correct-uri">Verifying the correct URI</h2>

<p>You can confirm the printer name and path on the CUPS server with:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lpstat <span class="nt">-v</span>
</code></pre></div></div>

<p>And test the endpoint directly from the Mac before adding the printer:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ipptool <span class="nt">-tv</span> ipp://&lt;server&gt;:631/printers/&lt;printername&gt; get-printer-attributes.test
</code></pre></div></div>]]></content><author><name></name></author><category term="macos" /><category term="cups" /><category term="printing" /><category term="linux" /><summary type="html"><![CDATA[When adding a remote CUPS print server on macOS 15 Sequoia, print jobs may fail immediately with:]]></summary></entry><entry><title type="html">Recovering an ESP32 DevKit from Reverse Polarity on the 3V3 Pin</title><link href="https://thomas.quinot.org/labnotes/electronics/esp32/tasmota/2026/03/07/esp32-reverse-polarity-recovery.html" rel="alternate" type="text/html" title="Recovering an ESP32 DevKit from Reverse Polarity on the 3V3 Pin" /><published>2026-03-07T00:00:00+00:00</published><updated>2026-03-07T00:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/electronics/esp32/tasmota/2026/03/07/esp32-reverse-polarity-recovery</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/electronics/esp32/tasmota/2026/03/07/esp32-reverse-polarity-recovery.html"><![CDATA[<p><em>Writeup generated with AI</em></p>

<p>What started as an accidental reverse polarity event on an ESP32-U DevKit board turned into a surprisingly successful recovery. This post documents the full diagnostic process and the steps that ultimately brought the board back to life running Tasmota.</p>

<h2 id="the-incident">The Incident</h2>

<p>Reverse polarity was applied directly to the <strong>3V3 pin</strong> of an ESP32-U DevKit board. This is arguably worse than reversing the 5V input, because it bypasses the onboard LDO regulator entirely — the reversed voltage goes straight onto the 3.3V rail feeding the ESP32 and all other components directly.</p>

<h2 id="initial-symptoms">Initial Symptoms</h2>

<ul>
  <li>The USB-to-UART bridge was alive and enumerating correctly (expected, as it is powered from the 5V USB rail, upstream of the LDO)</li>
  <li>The board was unresponsive to flashing attempts</li>
  <li><strong>0V measured on the 3V3 pin</strong> while powered from USB</li>
</ul>

<h2 id="diagnosis">Diagnosis</h2>

<h3 id="ruling-out-a-shorted-rail">Ruling out a shorted rail</h3>

<p>Measuring resistance between GND and 3V3 with the board unpowered showed <strong>750Ω</strong> — a healthy value indicating no shorted decoupling capacitors or blown ESD diodes on the rail. This was an encouraging sign pointing to the LDO as the failed component rather than the ESP32 itself.</p>

<h3 id="ldo-thermal-shutdown">LDO thermal shutdown</h3>

<p>The AMS1117-3.3 LDO on ESP32 DevKit boards includes built-in thermal shutdown protection. The reverse polarity event likely caused excessive current through the LDO, triggering thermal shutdown. After sufficient cooling time during the resistance measurements, the LDO <strong>recovered on its own</strong> and 3V3 was restored — consistent with thermal shutdown behaviour rather than permanent damage.</p>

<h3 id="flash-chip-diagnosis">Flash chip diagnosis</h3>

<p>With power restored, flashing still failed with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Warning: Failed to communicate with the flash chip, read/write operations will fail.
</code></pre></div></div>

<p>Using <code class="language-plaintext highlighter-rouge">esptool</code> with the <code class="language-plaintext highlighter-rouge">--no-stub</code> flag also failed, and <code class="language-plaintext highlighter-rouge">flash-id</code> returned <code class="language-plaintext highlighter-rouge">0xff/0xffff</code> — indicating no response on the SPI bus from the ROM bootloader.</p>

<p>However, running <code class="language-plaintext highlighter-rouge">flash-id</code> <strong>with</strong> the stub flasher returned a valid response:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Manufacturer: 68
Device: 4016
Detected flash size: 4MB
</code></pre></div></div>

<p>Manufacturer <code class="language-plaintext highlighter-rouge">0x68</code> is <strong>Boya Micro (BY25Q32)</strong> — a legitimate, working flash chip. The discrepancy between ROM bootloader and stub was due to different SPI bus initialisation methods; the stub’s optimised driver worked where the ROM’s did not.</p>

<h2 id="recovery-steps">Recovery Steps</h2>

<h3 id="1-erasing-the-flash-in-chunks">1. Erasing the flash in chunks</h3>

<p>A full <code class="language-plaintext highlighter-rouge">erase-flash</code> operation failed mid-way with:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>A fatal error occurred: Packet content transfer stopped (received 9 bytes).
</code></pre></div></div>

<p>This was consistent with marginal LDO stability under sustained load. Erasing in smaller regions worked reliably:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>esptool erase-region 0x3D0000 0x20000
</code></pre></div></div>

<h3 id="2-reflashing-tasmota">2. Reflashing Tasmota</h3>

<p>Direct reflash via esptool succeeded:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>esptool <span class="nt">--baud</span> 115200 write-flash 0x0 tasmota32-FR.bin
</code></pre></div></div>

<h3 id="3-diagnosing-the-safeboot-loop">3. Diagnosing the safeboot loop</h3>

<p>After reflashing, the device booted but the web interface was unresponsive (IP pinged but empty HTTP answer from http://192.168.4.1/).
Serial console output revealed:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Project tasmota - Tasmota Version 15.3.0(release-safeboot)-3.3.7(2026-02-19T13:53:54)
WARNING This version does not support persistent settings
</code></pre></div></div>

<p>The erase operations had wiped the OTA selection flag at <code class="language-plaintext highlighter-rouge">0xe000</code>, causing the bootloader to fall back to the safeboot partition instead of the main firmware.</p>

<p>The safeboot firmware is a special trimmed down version of Tasmota used during OTA upgrades. It specifically does not include the <em>initial configuration</em> web page.</p>

<h3 id="4-full-platformio-reflash">4. Full PlatformIO reflash</h3>

<p>A complete PlatformIO rebuild and reflash restored all partition components including the OTA flag:</p>

<table>
  <thead>
    <tr>
      <th>Offset</th>
      <th>File</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0x1000</code></td>
      <td><code class="language-plaintext highlighter-rouge">bootloader.bin</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0x8000</code></td>
      <td><code class="language-plaintext highlighter-rouge">partitions.bin</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0xe000</code></td>
      <td><code class="language-plaintext highlighter-rouge">boot_app0.bin</code> ← OTA selection flag</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0x10000</code></td>
      <td><code class="language-plaintext highlighter-rouge">tasmota32-safeboot.bin</code></td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0xe0000</code></td>
      <td><code class="language-plaintext highlighter-rouge">firmware.bin</code> ← main firmware</td>
    </tr>
  </tbody>
</table>

<p>This restored normal boot into the full <code class="language-plaintext highlighter-rouge">tasmota32-FR</code> firmware.</p>

<h2 id="how-the-tasmota32-safeboot-system-works">How the Tasmota32 Safeboot System Works</h2>

<p>The Tasmota32 dual-partition safeboot architecture is worth understanding:</p>

<ul>
  <li>On every normal boot, the OTA flag at <code class="language-plaintext highlighter-rouge">0xe000</code> points the bootloader to the main firmware at <code class="language-plaintext highlighter-rouge">0xe0000</code></li>
  <li>If the device <strong>reboots 4 times in quick succession</strong> (crash loop), Tasmota automatically switches the OTA flag to the safeboot partition as a recovery mechanism</li>
  <li>Safeboot can also be triggered manually via <code class="language-plaintext highlighter-rouge">Restart 99</code> from the Tasmota console</li>
  <li>From the safeboot web interface, you can OTA flash a new main firmware, which resets the OTA flag back to normal</li>
</ul>

<p>The safeboot partition is intentionally minimal (~300–400KB) — it includes only a web server, OTA flash capability, basic WiFi AP, and a stripped console. It has no persistent settings, no MQTT, and most Tasmota commands are unavailable.</p>

<h2 id="outcome">Outcome</h2>

<p>The board made a <strong>full recovery</strong> with no permanent damage:</p>

<ul>
  <li>ESP32 SoC: intact</li>
  <li>Flash chip: intact</li>
  <li>LDO: recovered from thermal shutdown</li>
  <li>Tasmota: running normally</li>
</ul>

<h2 id="lessons-learned">Lessons Learned</h2>

<ul>
  <li>Reverse polarity on the 3V3 pin is more dangerous than on the 5V pin as it bypasses the LDO entirely</li>
  <li>The AMS1117 thermal shutdown can mimic permanent failure but recover after cooling</li>
  <li>Always use the stub flasher (<code class="language-plaintext highlighter-rouge">esptool</code> without <code class="language-plaintext highlighter-rouge">--no-stub</code>) for flash communication — the ROM bootloader SPI initialisation can fail where the stub succeeds</li>
  <li>Partial flash erase operations can corrupt the OTA selection flag, causing unexpected safeboot behaviour</li>
  <li>A full PlatformIO reflash is the safest way to restore a complete and correct partition layout</li>
  <li>Consider adding reverse polarity protection (Schottky diode or P-channel MOSFET) on power inputs in future designs</li>
</ul>

<h2 id="alternate-exit-path-from-safeboot">Alternate exit path from Safeboot</h2>

<p>I could have reset the safeboot flag using:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>esptool write-flash 0xe000 ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin
</code></pre></div></div>

<p>This just rewrites the OTA selection flag directly, telling the bootloader to boot the main firmware partition — without touching anything else. A full reflash would not have been necessary.
From within the safeboot console, there isn’t a direct command to flip the flag — that’s intentional, since the whole point of safeboot is to force you through the OTA web interface to upload known-good firmware before returning to normal boot.</p>]]></content><author><name></name></author><category term="electronics" /><category term="esp32" /><category term="tasmota" /><category term="esp32" /><category term="tasmota" /><category term="reverse-polarity" /><category term="recovery" /><category term="esptool" /><category term="platformio" /><summary type="html"><![CDATA[Writeup generated with AI]]></summary></entry><entry><title type="html">nVidia kernel module: key rejected</title><link href="https://thomas.quinot.org/labnotes/2025/08/02/nvidia-kmod-key-rejected.html" rel="alternate" type="text/html" title="nVidia kernel module: key rejected" /><published>2025-08-02T14:00:00+00:00</published><updated>2025-08-02T14:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2025/08/02/nvidia-kmod-key-rejected</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2025/08/02/nvidia-kmod-key-rejected.html"><![CDATA[<h1 id="situation">Situation</h1>

<p>On a Dell Precision 7520 running Debian, I found myself switching between UEFI / secure boot and legacy BIOS boot, and having trouble restoring the right boot settings after reenabling secure boot.</p>

<p>The first problem was to identify the correct file to boot from: <code class="language-plaintext highlighter-rouge">EFI/debian/shimx64.efi</code>.</p>

<h1 id="kernel-module-load-issue">Kernel module load issue</h1>

<p>After disabling secure boot and then reenabling it again, kernel modules not loading despite updating nvidia-driver and kernel-image</p>

<p>solution: reenroll MOK (Machine Owner Key):</p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">mokutil --import /var/lib/dkms/mok.pub</code> (set an import password)</li>
  <li><code class="language-plaintext highlighter-rouge">mokutil --list-new</code></li>
  <li>reboot into MOK management =&gt; provide import password =&gt; key reenrolled</li>
  <li>modules loding :thumsbup:</li>
</ul>

<p>Debian documentation: <a href="https://wiki.debian.org/fr/SecureBoot">Secure Boot</a></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Situation]]></summary></entry><entry><title type="html">Restoring the TI 99/4A, ep. 6</title><link href="https://thomas.quinot.org/labnotes/2025/07/06/ti99-4a-restoration-ep6.html" rel="alternate" type="text/html" title="Restoring the TI 99/4A, ep. 6" /><published>2025-07-06T14:40:00+00:00</published><updated>2025-07-06T14:40:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2025/07/06/ti99-4a-restoration-ep6</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2025/07/06/ti99-4a-restoration-ep6.html"><![CDATA[<h2 id="where-we-are-funny-l600">Where we are: funny L600</h2>

<p>I captured more traces showing voltage before L600 (i.e. at the net labeled “8” from the power supply in Sams Computer Facts) (<span style="background-color: #f8fc00;">yellow</span>) and after it (i.e. at the CPU’s Vcc pin) (<span style="background-color: #b800b8;">purple</span>), also recording the min and max voltage.</p>

<figure>
<p><img src="assets/TI-resto/20250703-oldCPU-L600.png" alt="Old CPU, L600 not shunted (bad)" /></p>
  <figcaption>Old CPU, L600 not shunted (bad)</figcaption>
</figure>

<figure>
<p><img src="assets/TI-resto/20250703-oldCPU-shuntL600.png" alt="Old CPU, L600 shunted (OK)" /></p>
  <figcaption>Old CPU, L600 shunted (OK)</figcaption>
</figure>

<p>We are seeing:</p>
<ul>
  <li>very large voltage variations downstream of L600 when it’s not shunted</li>
  <li>interstingly, slightly different readings on the two probes even when shunted with a wire :thinking:</li>
</ul>

<h2 id="replacing-the-cpu--a-provisional-conclusion">Replacing the CPU &amp; a provisional conclusion</h2>

<p>The hypothesis at this stage is a marginal CPU that draws a little too much current, so I’m trying to replace it with another one from eBay.</p>

<figure>
<p><img src="assets/TI-resto/20250703-newCPU.png" alt="New CPU, L600 not shunted (OK)" /></p>
  <figcaption>New CPU – it works!</figcaption>
</figure>

<p>… and this time it works (and no longer shows large variations on Vcc) even with L600 not shunted :tada:</p>

<p>So I’m considering the machine repaired, and hoping that there isn’t some other issue with the power supply or the mainboard that will fry one CPU after another…</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Where we are: funny L600]]></summary></entry><entry><title type="html">Importer des notices depuis MoCCAM vers PMB</title><link href="https://thomas.quinot.org/labnotes/2025/07/06/import-moccam-records-into-pmb.html" rel="alternate" type="text/html" title="Importer des notices depuis MoCCAM vers PMB" /><published>2025-07-06T14:20:00+00:00</published><updated>2025-07-06T14:20:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2025/07/06/import-moccam-records-into-pmb</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2025/07/06/import-moccam-records-into-pmb.html"><![CDATA[<h1 id="export-depuis-moccam">Export depuis MoCCAM</h1>

<ul>
  <li>Exporter les notices ouvrages en UNIMARC ISO PMB (:warning: ISO se rapporte à la flaveur d’Unimarc, pas à l’encodage !)</li>
  <li>Exporter les notices autorité associées</li>
</ul>

<h1 id="import-dans-pmb">Import dans PMB</h1>

<h2 id="notices-autorités">Notices autorités</h2>

<p>Autorités &gt; Gestion &gt; Import</p>

<p>Encodage: <strong>Forcer en ISO 5426</strong></p>

<h2 id="notices-ouvrages">Notices ouvrages</h2>

<p>Administration &gt; Modules &gt; Imports &gt; Notices UNIMARC</p>

<p>Fonction d’import: <strong>PMB</strong></p>

<p>Encodage: <strong>Forcer en ISO 5426</strong></p>]]></content><author><name></name></author><summary type="html"><![CDATA[Export depuis MoCCAM]]></summary></entry><entry><title type="html">Velux troubleshooting</title><link href="https://thomas.quinot.org/labnotes/2025/06/25/velux-troubleshooting.html" rel="alternate" type="text/html" title="Velux troubleshooting" /><published>2025-06-25T19:30:00+00:00</published><updated>2025-06-25T19:30:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2025/06/25/velux-troubleshooting</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2025/06/25/velux-troubleshooting.html"><![CDATA[<h1 id="description-du-matériel">Description du matériel</h1>

<ul>
  <li>fenêtres de toit oscillantes motorisées sur secteur Integra GGU avec stores intérieurs motorisés sur secteur DML (4 UK08, 1 SK06)</li>
  <li>télécommandes unidirectionnelles
    <ul>
      <li>KLI 311 (fenêtres)</li>
      <li>KLI 312 (stores)</li>
    </ul>
  </li>
  <li>passerelle Internet/HomeKit Velux Active KIX 300
    <ul>
      <li>capteur intérieur KLA 300</li>
      <li>commande de départ KLN 300</li>
    </ul>
  </li>
</ul>

<h1 id="fermeture-incomplète">Fermeture incomplète</h1>

<h2 id="symptôme">Symptôme</h2>

<p>Fermeture imparfaite avec le clapet d’aération pas complètement rabattu</p>

<ul>
  <li>détecté comme ouverture manuelle donc plus d’ouverture motorisée</li>
  <li>ne se referme pas plus car déjà en fin de cycle de fermeture</li>
  <li>sur fermeture manuelle
    <ul>
      <li>échoue à rouvrir avec le moteur</li>
      <li>ne désengage pas la chaîne =&gt; ouverture manuelle impossible</li>
    </ul>
  </li>
</ul>

<h2 id="solution">Solution</h2>

<ul>
  <li>forcer la fermeture manuellement</li>
  <li>essayer d’ouvrir avec le moteur
    <ul>
      <li>si ça marche, OK</li>
    </ul>
  </li>
  <li>essayer d’ouvrir manuellement
    <ul>
      <li>impossible si la chaîne n’est pas dégagée</li>
    </ul>
  </li>
  <li>
    <p>sinon ouvrir avec le moteur en accompangnant l’ouverture à la main</p>
  </li>
  <li>une fois en position ouverte, dégager la chaîne</li>
  <li>réinitialiser (pression 5-10 s sur bouton test) chaîne dégagée, la chaîne rentre complètement</li>
  <li>la chaîne revenue en position de fermeture complète, refermer manuellement</li>
</ul>

<h1 id="perte-dappairage">Perte d’appairage</h1>

<h2 id="reonnexion-des-télécommandes-unidirectionnelles">Reonnexion des télécommandes unidirectionnelles</h2>

<ul>
  <li>Ouvrir manuellement la fenêtre</li>
  <li>Réinitialiser (appui 10 s sur le bouton, le store puis la chaîne bougent)</li>
  <li>Sur chacune des télécommandes (fenêtre et store)
    <ul>
      <li>appuyer 5 s sur le bouton d’appairage (deux rectangles)</li>
      <li>appuyer 1 s sur STOP</li>
      <li>appuyer 1 s sur DOWN</li>
    </ul>
  </li>
</ul>

<h2 id="reconnexion-à-la-passerelle">Reconnexion à la passerelle</h2>

<p>Pour chaque appareil (store, fenêtre) :</p>
<ul>
  <li>Appuyer 5 s sur * : l’appareil va et vient</li>
  <li>Sur la passerelle : appuyer longuement sur *
    <ul>
      <li>la lumière se met d’abord à clignoter blanc</li>
      <li>continuer d’appuyer</li>
      <li>la lumière se met à clignoter bleu : c’est bon, c’est en train d’appairer</li>
      <li>attendre que ça ne clignote plus</li>
    </ul>
  </li>
</ul>

<p>Si l’appareil était injoignable, il peut être nécessaire de le supprimer de l’app avant de réappairer.</p>

<p>Pour associer un store à une fenêtre, dans Gestion de la maison, aller sur la fenêtre, menu ⠇, Éditer le groupe.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Description du matériel]]></summary></entry><entry><title type="html">Restoring the TI 99/4A, ep. 5</title><link href="https://thomas.quinot.org/labnotes/2025/05/18/ti99-4a-restoration-ep5.html" rel="alternate" type="text/html" title="Restoring the TI 99/4A, ep. 5" /><published>2025-05-18T11:00:00+00:00</published><updated>2025-05-18T11:00:00+00:00</updated><id>https://thomas.quinot.org/labnotes/2025/05/18/ti99-4a-restoration-ep5</id><content type="html" xml:base="https://thomas.quinot.org/labnotes/2025/05/18/ti99-4a-restoration-ep5.html"><![CDATA[<h2 id="checking-l600">Checking L600</h2>

<p>Vcc (pin 2) of the CPU is oscillating wildly unless I shunt L600. With L600 shunted, the machine seems to start up just fine (nice beep, and title screen displays).</p>

<p>Desoldering L600 and testing it off circuit is inconclusive: it seems to behave just fine.
Measuring its inductance with the oscilloscope (through the period of amortized oscillation with a known capacitor) as shown <a href="https://0x9900.com/measure-an-inductance-or-capacitance-using-an-oscilloscope/">here</a> shows a consistent behaviour vs a new replacement part.</p>

<figure>
<p><img src="assets/TI-resto/20250517-old-L-waveform.png" alt="general amortization shape" />
<img src="assets/TI-resto/20250517-old-L-meas.png" alt="period measurement" /></p>
  <figcaption>Old L600 desoldered from board</figcaption>
</figure>

<figure>
<p><img src="assets/TI-resto/20250517-new-L-waveform.png" alt="general amortization shape" />
<img src="assets/TI-resto/20250517-new-L-meas.png" alt="period measurement" /></p>
  <figcaption>New replacement L600</figcaption>
</figure>

<p>The old part’s amortized oscillation damps down faster, which is consistent with a higher resistance (on the LCR-T7, the old part reads at 0.50 Ω, whereas the new one reads at 0.25 Ω), but both measure a period of 520 ns, which is ballpark-consistent with a 6.8 μH inductance.</p>

<p>I soldered the new part instead of the old one, and I’m seeing a similar behaviour as before: failure when starting up (continuous tone, wild variations at TMS9900 Vcc), apparently working fine when shunting L600.</p>

<p>Just to be sure, with L600 shunted I hooked up the display and confirmed that:</p>
<ul>
  <li>the title screen displays fine;</li>
  <li>when pressing a key, I get the main menu;</li>
  <li>when pressing 1, I get the TI basic prompt, and key strokes appear on screen.</li>
</ul>

<p><strong>So L600 may not be the culprit, but some other connected part.</strong></p>

<h2 id="could-it-be-c611">Could it be C611?</h2>

<p>Another possible culprit nearby might be C611. Desoldering it and measuring it off-circuit, it reads just under 1000 pF on the LCR-T7, which is as expected, so I’m deciding it’s good and soldering it back.</p>

<h2 id="something-else-near-memen">Something else near ~MEMEN~?</h2>

<p>Next hypothesis is a marginal component sinking too much current from Vcc:</p>
<ul>
  <li>either R607, which looks like a pullup on ~MEMEN~</li>
  <li>or U605 input pin 2?</li>
</ul>

<h3 id="a-closer-look-at-r607">A closer look at R607</h3>

<p>In-circuit, R607 reads at 4.6 kΩ, which seems in a reasonable ballpark, so I’m disinclined to desolder it, which is fortunate because annonyingly, the new L600 is a bigger form factor than the original one, and so it’s blocking access. I could desolder it and solder back the original one: since the original one measures fine, and replacing it didn’t change the behaviour, I’m assuming that the problem was not there. But since the in-circuit reading looks within spec, that would really be a shot in the dark.</p>

<h3 id="vcc-fighting-memen">Vcc fighting ~MEMEN~?</h3>

<p>Next step is to look at Vcc and ~MEMEN~ simultaneously to see if there’s a correlation between changes on MEMEN and Vcc variations.</p>

<p><strong>Finging: The Vcc variations do <em>not</em> appear to be correlated with ~MEMEN~: there are big oscillations on Vcc even when ~MEMEN~ is stable (whether low or high).</strong></p>

<figure>
<p><img src="assets/TI-resto/20250518-Vcc-MEMEN-bad1.png" alt="bad 1" />
<img src="assets/TI-resto/20250518-Vcc-MEMEN-bad2.png" alt="bad 2" /></p>
  <figcaption>Vcc vs ~MEMEN~ / no shunt on L600: KO</figcaption>
</figure>

<figure>
<p><img src="assets/TI-resto/20250518-Vcc-MEMEN-ok1.png" alt="ok 1" />
<img src="assets/TI-resto/20250518-Vcc-MEMEN-ok2.png" alt="ok 2" /></p>
  <figcaption>Vcc vs ~MEMEN~ / shunt on L600: OK</figcaption>
</figure>]]></content><author><name></name></author><summary type="html"><![CDATA[Checking L600]]></summary></entry></feed>