Reader

Blog

Welcome to the Blog.

Debugging Noisy Power Rails

Measurement hygiene before chasing firmware ghosts

Noisy power rails cause some of the most frustrating hardware bugs because the symptoms look random while the root cause is often deterministic. A board that “usually works” at room temperature can fail after five minutes under load, pass again after reboot, and mislead you into chasing firmware ghosts for days.

A useful mindset shift is this: unstable power is not a side issue. It is a primary signal path. If voltage integrity is poor, every digital subsystem becomes statistically unreliable, and software symptoms are just the final expression.

My default workflow starts with measurement hygiene before diagnosis:

Bad probing creates fake ripple. Good probing reveals real coupling.

First pass checks are simple: ... continue

Debouncing with Time and State

Not hope: explicit stability windows instead of ISR delays

Button debouncing is one of the smallest problems in embedded systems and one of the most frequently mishandled. That combination makes it a perfect teaching case. Engineers know contacts bounce, yet many designs still rely on ad-hoc delays or lucky timing. These solutions pass demos and fail in real operation. A robust approach treats debouncing as a tiny state machine with explicit time policy.

Mechanical bounce is not mysterious. On transition, contacts physically oscillate before settling. During that interval, GPIO sampling can see multiple edges. If firmware interprets every edge as intent, one press becomes many events. The correct objective is not “filter noise” in the abstract; it is to infer a human action from unstable electrical evidence with defined latency and false-trigger bounds.

The naive pattern is edge interrupt plus delay_ms(20) inside the handler. This feels simple but causes collateral damage: blocked interrupt handling, jitter in unrelated tasks, and poor power behavior. Worse, fixed delays are often too long for responsive UIs and still too short for worst-case switches. Delays treat symptoms while creating scheduling side effects.

A better pattern separates observation from decision. Observation samples pin state periodically or on edge notifications. Decision logic advances through states: Idle, CandidatePress, Pressed, CandidateRelease. Each transition is gated by elapsed stable time. This design is cheap, deterministic, and testable. It also composes naturally with long-press and double-click features.

Sampling frequency matters less than many assume. You do not need MHz polling for human input. A 1 ms tick is usually enough, and even 2–5 ms can be acceptable with careful thresholds. What matters is consistent sampling and explicit stability windows. If a signal remains stable for N ticks, commit the state transition. If it flips early, reset candidate state. ... continue

CONFIG.SYS as Architecture

Runtime policy before your application loads

In DOS culture, CONFIG.SYS is often remembered as a startup file full of cryptic lines. That memory is accurate and incomplete. In practice, CONFIG.SYS was architecture: a compact declaration of runtime policy, resource allocation, compatibility strategy, and operational profile.

Before your application loaded, your architecture was already making decisions:

The shape of your software experience depended on this pre-application contract.

Take a typical line like:

DOS=HIGH,UMB ... continue

Clarity Is an Operational Advantage

Teams often describe clarity as a communication virtue, something nice to have when there is time. In practice, clarity is operational leverage. It lowers incident duration, reduces rework, improves onboarding, and compresses decision cycles. Ambiguity is not neutral. Ambiguity is a hidden tax that compounds across every handoff.

Most organizations do not fail because they lack intelligence. They fail because intent degrades as it travels. Requirements become slogans. Architecture becomes folklore. Ownership becomes “someone probably handles that.” By the time work reaches production, the system reflects accumulated interpretation drift more than original design intent.

Clear writing is one antidote, but clarity is broader than prose. It includes naming, interfaces, boundaries, defaults, and escalation paths. A variable named vaguely can mislead a future refactor. An API contract with optional security checks invites accidental bypass. A runbook with missing preconditions turns outage response into improvisation theater.

A useful test is whether a tired engineer at 2 AM can make a safe decision from available information. If not, the system is unclear regardless of how elegant it looked in daytime planning meetings. Reliability is partly a documentation quality problem and partly an interface design problem.

One reason ambiguity survives is that it can feel fast in the short term. Vague decisions reduce immediate debate. Deferred precision preserves momentum. But deferred precision is debt with high interest. The discussion still happens later, now under pressure, with higher stakes and worse context. Clarity front-loads effort to avoid emergency interpretation costs. ... continue

C:\> After Midnight

A DOS chronicle

There is a particular blue that only old screens know how to make. Not sky blue, not electric blue, not any brand color from modern design systems. It is the blue of waiting, the blue of discipline, the blue of possibility. It is the blue that appears when a machine, after clearing its throat with a POST beep, hands you a bare prompt and says: now it is your turn.

C:\>

No dock, no notifications, no assistant bubble, no pretense of helping you think. Only an invitation and a challenge. The operating system has done almost nothing. You must do the rest.

This is not an article about nostalgia as decoration. It is about a working world that existed inside limits so hard they became architecture. A world where your startup sequence was a design document, your tools fit on a few floppies, your failures had names, and your victories often looked like reclaiming 37 kilobytes of conventional memory so a game or compiler could start. It is also a story, because DOS was never just a technical environment. It was a culture of rituals: boot rituals, backup rituals, anti-virus rituals, debugging rituals, and social rituals that happened in school labs, basements, bedrooms, and noisy clubs where people traded disks like rare books.

So let us spend one long night there. Let us walk into a fictional but faithful 1994 room that smells like warm plastic and printer paper. Let us build and run a complete DOS life from dusk to dawn. Every choice in this chronicle is plausible. Most of them were common. Some of them were mistakes. All of them are true to the era.

18:42 - The Room Before Boot

... continue

Building Repeatable Triage Kits

Packaging workflow so every analyst starts the same way

Security triage often fails for a boring reason: every analyst starts from a different local setup. Different aliases, different tool versions, different output assumptions, different artifact paths. The result is inconsistent decisions and hard-to-compare findings.

A repeatable triage kit solves this by packaging workflow, not just binaries.

Think of a triage kit as a portable operating system for first-pass analysis. It should answer, consistently:

Without those answers, triage quality depends on individual heroics.

The kit design should be opinionated and minimal. Start with four modules: ... continue

BGI Lab: Drivers and Diagnostics

Dynamic drivers, linked drivers, and startup harnesses in Turbo Pascal

This tutorial gives you a practical BGI workflow that survives deployment:

Preflight: what you need

TP5 baseline reminder:

Step 1: dynamic loading baseline

Create BGITEST.PAS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
program BgiTest;

uses
  Graph, Crt;

var
  gd, gm, gr: Integer;

begin
  gd := Detect;
  InitGraph(gd, gm, '.\BGI');
  gr := GraphResult;
  Writeln('Driver=', gd, ' Mode=', gm, ' GraphResult=', gr);
  if gr <> grOk then
    Halt(1);

  SetColor(15);
  OutTextXY(8, 8, 'BGI OK');
  Rectangle(20, 20, 200, 120);
  ReadKey;
  CloseGraph;
end.

Expected outcome:

Important TP5 behavior: GraphResult resets to zero after being called. Always store it to a variable once, then evaluate that value. ... continue

Benchmarking with a Stopwatch

Experimental discipline before high-resolution timers

When people imagine benchmarking, they picture automated harnesses, high-resolution timers, and dashboards with percentile charts. Useful tools, absolutely. But many core lessons of performance engineering can be learned with much humbler methods, including one old trick from retro workflows: benchmarking with a stopwatch and disciplined procedure.

On vintage systems, instrumentation was often limited, intrusive, or unavailable. So users built practical measurement habits with what they had:

It sounds primitive until you realize it enforces the exact thing modern teams often skip: experimental discipline.

The first rule was baseline control. Before measuring anything, define the environment:

Without this, numbers are stories, not data. ... continue

Assumption-Led Security Reviews

Testing claims instead of running checklists

Many security reviews fail before they begin because they are framed as checklist compliance rather than assumption testing. Checklists are useful for coverage. Assumptions are where real risk hides.

Every system has assumptions:

When assumptions are wrong, controls built on top of them become decorative.

An assumption-led review starts by collecting claims from architecture, docs, and team memory, then converting each claim into a testable statement. Not “is auth secure?” but “can an untrusted caller obtain action X through path Y under condition Z?”

This shift changes review quality immediately. ... continue

Archive Discipline for the Floppy Era

Naming, verification, and restore habits that still matter

People remember floppy disks as inconvenience, but they were also a strict training ground for information discipline. Limited capacity, media fragility, and transfer friction forced users to become intentional about naming, versioning, verification, and recovery. Those habits remain useful even in cloud-heavy workflows.

A floppy-era archive was never just “copy files somewhere.” It was an operating procedure:

Each step existed because failure was common and expensive.

Naming conventions carried real weight. You could not hide disorder behind full-text search and huge storage. A good archive label included date, project, and version. A bad label produced weeks of confusion later. Many users adopted compact but expressive patterns like:

Crude by modern standards, but operationally effective. ... continue