shibosoftwaredev/f1c100s-linux-nema17-stepper-controller

A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.

Version
0.4.56
License
unset
Stars
0

scripts/install-software-current.mjs

import fs from "node:fs"
import assert from "node:assert/strict"
import crypto from "node:crypto"
import {spawnSync} from "node:child_process"
import { routingSignature } from "../routing-signature"

const read = p => JSON.parse(fs.readFileSync(p, "utf8"))
const sha = p => crypto.createHash("sha256").update(fs.readFileSync(p)).digest("hex")
const placementPath = "routing/review-placement.circuit.json"
const sessionPath = "routing/software-current-candidate.ses"
const physicalPath = "routing/software-current-physical-candidate.json"
const directory = "routing/software-current-import"
const imported = read(`${directory}/import-report.json`)
assert.deepEqual(imported.failures, [])
assert.equal(imported.physical_island_links, 0, "no synthesized electrical links")
assert.equal(imported.audit_only, false)
assert.equal(imported.ignored_protected, true, "the complete actual candidate replaces obsolete replay escapes")
assert.equal(imported.circuit_sha256, sha(placementPath))
assert.equal(imported.session_sha256, sha(sessionPath))
const preflight = read("reports/software-current-preflight/coil-all-copper-preflight-meta.json")
const findings = "reports/software-current-preflight/coil-all-copper-preflight.json"
assert.equal(preflight.circuitSha256, sha(placementPath))
assert.equal(preflight.physicalCopperSha256, sha(physicalPath))
assert.equal(preflight.findingsSha256, sha(findings))
assert.equal(preflight.failureCount, 0)
assert.deepEqual(read(findings), [])
const placement = read(placementPath)
assert.deepEqual(placement.filter(e => e.type.endsWith("_error")), [])
assert.equal(placement.find(e => e.type === "pcb_board").num_layers, 4)
assert.equal(placement.find(e => e.type === "source_component" && e.name === "U_CURRENT_DAC").manufacturer_part_number, "MCP4725A0T-E/CH")
assert.ok(process.env.ROUTING_PYTHON,"Use the pinned Python environment for physical-session preservation")
const preservation=spawnSync(process.env.ROUTING_PYTHON,["scripts/preserve-software-current-session.py"],{stdio:"inherit"})
if(preservation.error)throw preservation.error
assert.equal(preservation.status,0)
// Reuse the already-audited, directly authored 0.15 mm local connections.
// Dijkstra's pad-contact representation otherwise chooses a 0.12 mm chord
// inside an existing land. Do not lower the requested width or hide a warning.
const localNames=new Set(["CURRENT_DAC_SUPPLY","CURRENT_DAC_VDDA","CURRENT_DAC_BYPASS_GROUND","CURRENT_DAC_ADDRESS"])
const localSources=placement.filter(e=>e.type==="source_trace"&&localNames.has(e.name))
assert.equal(localSources.length,4)
const retained=read("routing/software-current-retained.json")
const ids=new Set(localSources.map(e=>e.source_trace_id))
const replay=read(`${directory}/full-copper-replay.json`).filter(e=>!ids.has(e.source_trace_id))
for(const source of localSources) {
  const routes=retained.filter(e=>e.source_trace_id===source.source_trace_id)
  assert.equal(routes.length,1)
  const trace=structuredClone(routes[0])
  assert.ok(trace.route.every(p=>p.route_type==="wire"&&p.layer==="bottom"&&p.width===.15))
  for(const [id,point,key] of [
    [source.connected_source_port_ids[0],trace.route[0],"start_pcb_port_id"],
    [source.connected_source_port_ids[1],trace.route.at(-1),"end_pcb_port_id"],
  ]) {
    const port=placement.find(e=>e.type==="pcb_port"&&e.source_port_id===id)
    assert.ok(port&&Math.hypot(point.x-port.x,point.y-port.y)<1e-7)
    point[key]=port.pcb_port_id
  }
  replay.push(trace)
}
const saved = "baseline/pre-software-current-routing"
fs.mkdirSync(saved, { recursive: true })
for (const name of ["complete-routes.json", "expected-input.json", "placement.json"])
  if (!fs.existsSync(`${saved}/${name}`)) fs.copyFileSync(`routing/${name}`, `${saved}/${name}`)
for (const [path, value] of [
  ["routing/complete-routes.json", replay.map((trace,index)=>({...trace,pcb_trace_id:`whole_board_${index}`}))],
  ["routing/expected-input.json", routingSignature(placement)],
  ["routing/placement.json", placement],
]) fs.writeFileSync(path, JSON.stringify(value, null, 2) + "\n")
console.log("Installed in isolated software-current trial only. Normal build, emitted-copper checks and regression gates remain mandatory. No publication performed.")