<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3220006345447041404</id><updated>2026-10-01T02:30:19.895-07:00</updated><category term="travel"/><category term="electronics"/><category term="beagleboard"/><category term="energy monitor"/><category term="python"/><category term="sar"/><category term="worldwind"/><category term="arduino"/><category term="otb"/><category term="economics"/><category term="philosophy"/><category term="arts"/><category term="open source"/><category term="quadcopter"/><category term="kinect"/><category term="opencv"/><category term="phd"/><category term="conference"/><category term="simulation"/><category term="teardown"/><category term="GPS"/><category term="qgis"/><category term="forest"/><category term="imu"/><category term="kenya"/><category term="solar"/><category term="energy harvesting"/><category term="gpgpu"/><category term="hackerspace"/><category term="imagery"/><category term="nodemcu"/><category term="point clouds"/><category term="radar"/><category term="3d reconstruction"/><category term="AWS"/><category term="Design patterns"/><category term="KiCAD"/><category term="MPI"/><category term="ads1115"/><category term="amazon aws"/><category term="art"/><category term="augmented reality"/><category term="blender"/><category term="csiro"/><category term="eclipse"/><category term="electronics manufacture"/><category term="esp8266"/><category term="gpu"/><category term="gsoc 2011"/><category term="hawkboard"/><category term="hobart"/><category term="igarss"/><category term="java"/><category term="matlab"/><category term="medieval fair"/><category term="modem"/><category term="nearmap"/><category term="netcdf"/><category term="neuroscience"/><category term="ossim"/><category term="photography"/><category term="physics"/><category term="rust"/><category term="sift"/><category term="stereo"/><category term="udoo"/><category term="unity3d"/><category term="weather"/><category term="ATM90E26"/><category term="BTC"/><category term="IoT"/><category term="LEDs"/><category term="MSVC"/><category term="Open-Source"/><category term="Xadow"/><category term="agents"/><category term="android"/><category term="armor"/><category term="atmel"/><category term="avr"/><category term="bengal"/><category term="bitcoin"/><category term="bundler"/><category term="c++"/><category term="calibration"/><category term="camera"/><category term="clustering"/><category term="cmake"/><category term="cognitive antenna"/><category term="collada"/><category term="community"/><category term="craft"/><category term="cuda"/><category term="demographics"/><category term="drums"/><category term="earth-observation"/><category term="evolution"/><category term="fdtd"/><category term="fiji"/><category term="floating point"/><category term="foss4g"/><category term="fpga"/><category term="gdal"/><category term="geoserver"/><category term="geospatial"/><category term="gumstix"/><category term="hongkong"/><category term="initial conditions"/><category term="javascript"/><category term="jpeg2000"/><category term="jtag"/><category term="kernel"/><category term="liblas"/><category term="lidar"/><category term="linux"/><category term="litecoin"/><category term="makerfaire"/><category term="mapping"/><category term="mesh networks"/><category term="nasa"/><category term="oil spill"/><category term="openscenegraph"/><category term="osgi"/><category term="raspberry-pi"/><category term="recreation"/><category term="religion"/><category term="samba"/><category term="security"/><category term="singapore"/><category term="skills"/><category term="space"/><category term="start-ups"/><category term="statistics"/><category term="subsurface"/><category term="surf"/><category term="teensy"/><category term="ublox"/><category term="unit tests"/><category term="vacation"/><category term="vlc"/><category term="volunteering"/><category term="x64"/><category term="3-phase AC"/><category term="3D printing"/><category term="3G"/><category term="3mt"/><category term="8051 CPU"/><category term="ADE7880"/><category term="AI"/><category term="Analog Devices"/><category term="Bike riding"/><category term="CC3200"/><category term="Code Logistics"/><category term="Cortex-M0"/><category term="DAC"/><category term="DIN Rail"/><category term="David Walsh"/><category term="Deep Learning. Technology"/><category term="DevOps"/><category term="EC2"/><category term="Energia"/><category term="FreeCAD"/><category term="HUD"/><category term="LTC"/><category term="Linuguistics"/><category term="MEEP"/><category term="MONA"/><category term="MYO"/><category term="NVCL"/><category term="NXP"/><category term="PCB Design"/><category term="R"/><category term="RDS"/><category term="RedBearLab"/><category term="Replication"/><category term="SD storage"/><category term="STM32"/><category term="Software Architecture"/><category term="Workarounds"/><category term="acolite"/><category term="acp"/><category term="adafruit feather"/><category term="ade7763"/><category term="ade9000"/><category term="agriculture"/><category term="airports"/><category term="alternator"/><category term="aluminium"/><category term="angel finance"/><category term="anthropology"/><category term="apache hive"/><category term="apple mapping"/><category term="approach"/><category term="ardor"/><category term="ardor3d"/><category term="arduino-cli"/><category term="artix-7"/><category term="artwork"/><category term="atm90e36"/><category term="auckland"/><category term="austender"/><category term="australia"/><category term="australia day"/><category term="autorouter"/><category term="banana"/><category term="bazaar"/><category term="beer"/><category term="beer goggles"/><category term="benchmark"/><category term="bil"/><category term="biochemistry"/><category term="biomass"/><category term="blynk"/><category term="bridgestone"/><category term="business idea"/><category term="butterfly"/><category term="cambodia"/><category term="canberra"/><category term="carbon accounting"/><category term="cartography"/><category term="cgminer"/><category term="chicago"/><category term="classifiers"/><category term="cloud"/><category term="cloud-native-geospatial"/><category term="code review"/><category term="cognition"/><category term="cognitive-technology"/><category term="collections"/><category term="colours"/><category term="control"/><category term="copyrights"/><category term="cosmology"/><category term="crops"/><category term="curl"/><category term="darts"/><category term="darwin"/><category term="data structures"/><category term="data-centers"/><category term="database"/><category term="dds"/><category term="denmark"/><category term="diagrams"/><category term="digital-atlas-australia"/><category term="dinosaur"/><category term="drawing"/><category term="dsm"/><category term="ducklake"/><category term="eagle"/><category term="earthhour"/><category term="earthquake"/><category term="ecp5"/><category term="education"/><category term="eeepc"/><category term="embedded"/><category term="encryption"/><category term="energy"/><category term="energy-monitor"/><category term="energy-monitoring"/><category term="enterprise-ai"/><category term="entertainment"/><category term="envisat"/><category term="eoepca"/><category term="eoli"/><category term="esp32"/><category term="exoskeleton"/><category term="facebook"/><category term="family"/><category term="family time"/><category term="feko"/><category term="firmware"/><category term="fishing"/><category term="flickr"/><category term="flight test"/><category term="flow"/><category term="forms"/><category term="france"/><category term="game"/><category term="gaming"/><category term="gazetteer"/><category term="generalist"/><category term="generative-art"/><category term="geocoding"/><category term="geotools"/><category term="giraffe"/><category term="git"/><category term="github-copilot"/><category term="globerender"/><category term="go"/><category term="gold"/><category term="golf"/><category term="google"/><category term="google api"/><category term="graffiti"/><category term="gsoc 2012"/><category term="gstreamer"/><category term="haiti"/><category term="harris"/><category term="hash"/><category term="helicopter"/><category term="heroku"/><category term="hexiwear"/><category term="hfss"/><category term="high availabilty"/><category term="history"/><category term="holiday"/><category term="hype-cycle"/><category term="ide"/><category term="iglobe"/><category term="india"/><category term="industrial policy"/><category term="inkscape"/><category term="installer"/><category term="interpolation"/><category term="jakarta"/><category term="jalapeno"/><category term="japan"/><category term="jni"/><category term="jogl"/><category term="jsr-223"/><category term="jupyter"/><category term="kd-tree"/><category term="kml"/><category term="knife-sharpening"/><category term="kogan"/><category term="kolkata"/><category term="kriging"/><category term="kubernetes"/><category term="lamu"/><category term="latex"/><category term="learning"/><category term="limits"/><category term="literature"/><category term="litex"/><category term="loc"/><category term="logic analyser"/><category term="logic-analyzer"/><category term="lyx"/><category term="maintenance"/><category term="management"/><category term="maps"/><category term="mars"/><category term="mars rover"/><category term="materials"/><category term="maxim"/><category term="mcp"/><category term="meetup"/><category term="meetup. AI"/><category term="melbourne"/><category term="mentoring"/><category term="mercurial"/><category term="mercury"/><category term="meshlab"/><category term="meta-art"/><category term="metalwork"/><category term="microcontroller"/><category term="microwave"/><category term="mingw"/><category term="mining"/><category term="mobile monday"/><category term="modular java"/><category term="motion tracking"/><category term="mountain bike"/><category term="mountain view"/><category term="multiresolution"/><category term="munich"/><category term="muti-spectral"/><category term="nairobi"/><category term="netv2"/><category term="neur.io"/><category term="nikon d800"/><category term="notes"/><category term="object tracking"/><category term="ocds"/><category term="onion"/><category term="open artwork"/><category term="open hardware"/><category term="openeo"/><category term="openkinect"/><category term="openocd"/><category term="opticks"/><category term="optics"/><category term="orbital-manufacturing"/><category term="organic structures"/><category term="osdc"/><category term="pandaboard"/><category term="pangeo"/><category term="patents"/><category term="pcb assembly"/><category term="pcb-design"/><category term="pcileech"/><category term="penguin"/><category term="perception"/><category term="performance"/><category term="picasso"/><category term="piezo"/><category term="pirr"/><category term="politics"/><category term="polyglot"/><category term="polygons"/><category term="processor"/><category term="promotion"/><category term="public service"/><category term="publication"/><category term="pulse counting"/><category term="pxa"/><category term="python. csiro"/><category term="qt"/><category term="quickbird"/><category term="ray tracing"/><category term="re-earth"/><category term="reality television"/><category term="recycled cans"/><category term="reflow"/><category term="regression"/><category term="relativity"/><category term="rendering"/><category term="rendering throughput"/><category term="rendermonkey"/><category term="reprap"/><category term="research"/><category term="robot"/><category term="robotics"/><category term="ros"/><category term="saleae"/><category term="samoa"/><category term="science"/><category term="science-platforms"/><category term="scraping"/><category term="scripting"/><category term="scrypt"/><category term="semiconductors"/><category term="sense"/><category term="serendipity"/><category term="serial"/><category term="shed"/><category term="shell"/><category term="shopping"/><category term="silicon"/><category term="single phase"/><category term="sketchbook"/><category term="smart-plug"/><category term="sms"/><category term="sociology"/><category term="soldering"/><category term="spaceapps"/><category term="speculation"/><category term="spelling"/><category term="stability"/><category term="stac"/><category term="streaming"/><category term="students"/><category term="sunderbans"/><category term="supernovas"/><category term="surfer"/><category term="swarm"/><category term="swig"/><category term="sydney"/><category term="terrasar"/><category term="tesla"/><category term="thermodynamics"/><category term="thingspeak"/><category term="tindie"/><category term="tools"/><category term="tp-link"/><category term="turing"/><category term="tvheadend"/><category term="twitter"/><category term="uart"/><category term="ubuntu"/><category term="ugrid"/><category term="uncertainity"/><category term="utilities"/><category term="valuation"/><category term="vancouver"/><category term="vangotech"/><category term="videos"/><category term="vision"/><category term="water meter"/><category term="wattwatchers"/><category term="weather radar"/><category term="webgl"/><category term="webgpu"/><category term="wifi"/><category term="wilderness society"/><category term="wind profiling"/><category term="windows"/><category term="work"/><category term="xbee"/><category term="xbmc"/><category term="xctu"/><category term="xenophobia"/><category term="zarr"/><title type='text'>Confused Life - Reloaded</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>514</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-2996039067624704159</id><published>2026-08-07T17:00:00.000-07:00</published><updated>2026-08-08T01:12:22.603-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai"/><category scheme="http://www.blogger.com/atom/ns#" term="data-centers"/><category scheme="http://www.blogger.com/atom/ns#" term="orbital-manufacturing"/><category scheme="http://www.blogger.com/atom/ns#" term="semiconductors"/><category scheme="http://www.blogger.com/atom/ns#" term="space"/><category scheme="http://www.blogger.com/atom/ns#" term="thermodynamics"/><title type='text'>Terminators at the Terminator</title><content type='html'>&lt;p&gt;The nicest thing about the word terminator is that it already sounds like a machine sent back from the future to explain your capital expenditure problem, or to make you realize the capital expenditure will not save you from a distant AI dominated dystopian doomsday.&lt;/p&gt;
&lt;p&gt;In orbital mechanics it means something calmer and stranger: the line between day and night. A dawn-dusk sun-synchronous orbit rides that line around Earth, keeping the spacecraft in near-continuous sunlight. For Earth observation satellites this is useful because the illumination geometry stays predictable. For solar-powered orbital infrastructure it is more tempting: maximum duty cycle, fewer battery cycles, and the delicious thought that your data center can spend most of its life with the Sun on tap.&lt;/p&gt;
&lt;p&gt;So yes, the terminators at the terminator. AI training and inference workloads running in low Earth orbit, fed by photovoltaics, cooled by radiators, and connected through optical links to ground stations and other satellites. A nice science-fiction phrase once you have solved the heat and materials balance to get up the gravity well.&lt;/p&gt;
&lt;h2 id=&quot;the-dawn-dusk-sales-pitch&quot;&gt;The dawn-dusk sales pitch&lt;/h2&gt;
&lt;p&gt;The pitch is not silly. It starts from real constraints.&lt;/p&gt;
&lt;p&gt;AI data centers are going to become giant electrical-to-heat converters with a side effect of model weights. Reminds me of the time when I used to dry my laundry on my bitcoin miners. On Earth we feed them through grids, substations, diesel backup contracts, cooling towers, chillers, water rights, fibre backbones, and increasingly awkward community meetings. In orbit you can imagine skipping some of that. Put the compute near continuous sunlight. Use high-efficiency solar arrays. Use direct-to-space radiators instead of evaporating water or warming a river. Place inference near space-borne sensors. Put pre-processing close to Earth observation instruments so the useful bits come down instead of the whole firehose.&lt;/p&gt;
&lt;p&gt;NVIDIA’s Vera Rubin platform is the more immediate reference. Vera is the CPU and Rubin is the GPU, assembled with networking, memory, and rack-scale infrastructure as the successor generation to Blackwell. The roadmap promises another large increase in AI training and inference throughput, but throughput arrives with denser power delivery, cooling, and interconnect requirements. An orbital operator would inherit the useful work per watt and every unresolved watt of heat. Rubin therefore belongs in the radiator calculation as much as in the model-training benchmark.&lt;/p&gt;
&lt;p&gt;Sensor-side inference offers a different use for that compute. The instrument looks down, the processor sits nearby, and the network carries detections, embeddings, tiles, compressed products, or model updates instead of raw sensor exhaust. A satellite constellation does not want to be a fleet of USB drives with antennas. It wants to be a distributed science platform with a power budget.&lt;/p&gt;
&lt;p&gt;That is where dawn-dusk orbit starts to look like a scheduling primitive. Solar availability shapes the compute cluster. Training jobs, inference bursts, checkpointing, downlink windows, thermal soak, battery reserves, and radiator orientation all become part of the same planner.&lt;/p&gt;
&lt;p&gt;The cloud scheduler gets an ephemeris.&lt;/p&gt;
&lt;h2 id=&quot;the-thermal-model-is-the-business-model&quot;&gt;The thermal model is the business model&lt;/h2&gt;
&lt;p&gt;On Earth, a data center engineer can cheat emotionally because air exists. It may be hot air, badly ducted air, or air pushed around by fans with punishing maintenance schedules, but it is there. You can move heat by convection. You can move it into water. You can bury part of the problem in a cooling tower plume and another part in a utility bill.&lt;/p&gt;
&lt;p&gt;In orbit, there is no convenient atmosphere to carry the embarrassment away. Heat leaves by radiation, which puts the radiator alongside the processors and power supply in the core computer architecture.&lt;/p&gt;
&lt;p&gt;The governing shape is brutally simple:&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;span class=&quot;math display&quot;&gt;&lt;em&gt;P&lt;/em&gt; = &lt;em&gt;ϵ&lt;/em&gt;&lt;em&gt;σ&lt;/em&gt;&lt;em&gt;A&lt;/em&gt;&lt;em&gt;T&lt;/em&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/span&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Radiated power depends on emissivity, area, and the fourth power of absolute temperature. Want to reject more heat without growing a ridiculous radiator? Run hotter. Want to run hotter? Your semiconductors, packages, solder joints, optics, interconnects, dielectrics, memory, and power electronics all need to tolerate it. A space data center is a semiconductor materials problem wearing solar panels.&lt;/p&gt;
&lt;p&gt;This is why the recent attention around high-temperature semiconductors is interesting. Wide-bandgap devices such as silicon carbide and gallium nitride are already changing terrestrial power electronics because they switch efficiently and tolerate higher temperatures than conventional silicon in many roles. Push the idea further into ultra-wide-bandgap materials, diamond substrates, high-temperature packaging, and radiation-tolerant device physics, and the space qualified semiconductor variant emerges: hotter electronics can make every square metre of radiator work harder.&lt;/p&gt;
&lt;p&gt;But that sentence hides several doctoral theses and a lot of broken hardware.&lt;/p&gt;
&lt;p&gt;A transistor surviving a hot test coupon proves very little about the complete system. The whole compute stack has to behave: memory retention, timing margins, optical alignment, thermal cycling, electromigration, single-event effects, packaging stress, and the boring connectors that always become interesting at the worst possible time. Better high-temperature semiconductors help, but orbital data centers need a complete materials and packaging stack. A spectacular junction-temperature result does not provide one. We do not have the advanced PDK’s or foundries to do this today, but definitely a warm blue ocean of high temperature hardware to swim into.&lt;/p&gt;
&lt;h2 id=&quot;insulation-is-not-the-opposite-of-cooling&quot;&gt;Insulation is not the opposite of cooling&lt;/h2&gt;
&lt;p&gt;The intuitive mistake is to think space is cold, so cooling must be easy.&lt;/p&gt;
&lt;p&gt;Space is not cold in the way a cold beer is cold. Space is mostly empty. A surface in sunlight gets blasted by roughly 1,361 W/m^2 before geometry and efficiency. A surface looking into deep space can radiate beautifully, but only if it is allowed to see deep space and only if the heat can get there.&lt;/p&gt;
&lt;p&gt;So the architecture becomes a discipline of separation. Keep solar absorption away from the radiator side. Keep hot compute planes thermally connected to heat pipes, pumped loops, or thermal straps. Keep sensitive optics and timing hardware isolated from thermal gradients. Use multi-layer insulation where you want less radiative coupling. Use high-emissivity radiator coatings where you want more. Stop random structure from becoming a thermal short. Decide what gets to be warm, what must stay stable, and what can swing through orbital day-night transients without walking itself out of calibration.&lt;/p&gt;
&lt;p&gt;In a dawn-dusk orbit, you buy continuous solar availability, but you do not buy a waiver from geometry. Solar arrays want one orientation. Radiators want another. Antennas and optical links want line of sight. Drag wants attention. Radiation shielding wants mass. Stationkeeping wants propellant or electrodynamic cleverness. The thermal design is coupled to everything else.&lt;/p&gt;
&lt;p&gt;The radiator is not downstream of the business plan. It is in the first spreadsheet , or Claude conversation if you are not that good at maths.&lt;/p&gt;
&lt;h2 id=&quot;light-moves-from-power-source-to-processor&quot;&gt;Light moves from power source to processor&lt;/h2&gt;
&lt;p&gt;Orbital thermal constraints give optical computing a practical job beyond producing laboratory headlines.&lt;/p&gt;
&lt;p&gt;The ENGtechnica write-up on &lt;a href=&quot;https://engtechnica.com/light-as-compute-microsofts-energy-lean-optical-computer/&quot;&gt;Microsoft’s analog optical computer&lt;/a&gt; points at a useful direction: micro-LED arrays, spatial light modulators, and photodetectors doing vector-matrix operations in analog form, paired with a digital twin. The article claims promising results across image classification, nonlinear regression, MRI reconstruction, and financial modelling tasks, with Microsoft estimating up to 100x the energy efficiency of leading GPUs for suitable workloads.&lt;/p&gt;
&lt;p&gt;The prototype is a specialised machine for particular AI inference and optimisation workloads, not a general-purpose replacement for digital computers. That narrow scope suits orbital compute, where general-purpose waste carries a physical penalty. Every joule that enters the box becomes a thermal export problem. Every ADC, DAC, memory movement, SerDes hop, and cache miss consumes both time and radiator area.&lt;/p&gt;
&lt;p&gt;If you can do part of the workload optically, with fewer electrical conversions and less heat per useful operation, you change the orbital equation. Not enough to abolish thermodynamics, but enough to move a design from absurd to maybe annoying. That is a respectable improvement category in space engineering. Optical compute has the advantage of moving in fun new directions , couplint with the advances in quantum photonics or directly to laser comms module to get data off compute nodes to earth or between compute nodes in orbit.&lt;/p&gt;
&lt;p&gt;There is a broader lesson here too. We keep treating compute as abstract symbol manipulation, then acting surprised when the factory bill arrives as heat. Landauer’s principle gives the tiny theoretical floor, &lt;span class=&quot;math inline&quot;&gt;&lt;em&gt;k&lt;/em&gt;&lt;em&gt;T&lt;/em&gt;ln 2&lt;/span&gt; per irreversible bit operation, but modern compute lives many floors above that. The practical losses are in data movement, leakage, switching, conversion, cooling overhead, and the human decision to train another model because the previous benchmark table had one unclaimed column.&lt;/p&gt;
&lt;p&gt;Bits are not immaterial. Organising them has a thermodynamic cost.&lt;/p&gt;
&lt;h2 id=&quot;training-inference-and-the-ugly-logistics-of-usefulness&quot;&gt;Training, inference, and the ugly logistics of usefulness&lt;/h2&gt;
&lt;p&gt;Orbital AI training sounds glamorous, but inference is probably the more immediate fit.&lt;/p&gt;
&lt;p&gt;Training wants enormous, tightly coupled clusters, rapid hardware refresh, dense networking, fault tolerance, huge data ingestion, and painful amounts of memory bandwidth. It wants technicians nearby when the expensive thing throws an unhelpful error. It wants the newest accelerators, because model economics are tied to performance per watt and performance per dollar, and both curves move quickly.&lt;/p&gt;
&lt;p&gt;Inference near sensors is cleaner. Detect the smoke plume, ship the alert. Find the illegal fishing vessel, ship the track. Segment the flood boundary, ship the polygon. Compress the asteroid candidate stream before the downlink becomes the bottleneck. Turn imagery into geospatial events and only send raw data when the event deserves it.&lt;/p&gt;
&lt;p&gt;Training still has a role, especially for models tuned to orbital sensors, onboard compression, anomaly detection, or autonomous operations. But the training argument has to survive hardware obsolescence. A terrestrial data center can swap GPU generations with forklifts, technicians, and a recycling vendor who may or may not deserve the word recycling. An orbital data center has a worse version of the same problem: the expensive solar arrays, radiators, pointing systems, communications hardware, and orbital slot may still be useful after the compute payload becomes embarrassingly old.&lt;/p&gt;
&lt;p&gt;That is the stranded asset problem in orbit.&lt;/p&gt;
&lt;p&gt;The answer cannot be to throw away the whole platform every time NVIDIA, AMD, Intel, Cerebras, Groq, Google, Microsoft, or some optical-compute startup moves the Pareto frontier. The more plausible architecture separates relatively static infrastructure from rapidly ageing compute: power bus, radiator fields, optical comms, attitude control, and docking interfaces on one side; replaceable compute, memory, and storage modules on the other.&lt;/p&gt;
&lt;p&gt;In other words, orbital data centers need boring maintainability before they need cinematic scale like on the cover of latest &lt;a href=&quot;https://spectrum.ieee.org/orbital-data-center-hype&quot;&gt;IEEE Spectrum&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;close-the-silicon-loop-or-dont-build-it&quot;&gt;Close the silicon loop or don’t build it&lt;/h2&gt;
&lt;p&gt;A space data center that cannot be serviced is just delayed debris making a business case for companies like &lt;a href=&quot;https://www.paladinspace.com/&quot;&gt;Paladin Space&lt;/a&gt;. When a territory politician asks over dinner why she should care about space, I can scare her by saying if she doesn’t orbital data centers will be falling through her roof. A risk that is uninsurable since the probabilities cannot be measured, and not suable against because the counter party is in China.&lt;/p&gt;
&lt;p&gt;If we build orbital compute infrastructure, the end-of-life story has to be in the architecture from the beginning. Decommissioned compute modules need capture, removal, refurbishment, recycling, or controlled disposal. Radiator booms and solar arrays cannot be left as heritage sculpture in useful orbits. A failed training cluster should not become a fragmentation risk with tensor cores.&lt;/p&gt;
&lt;p&gt;This is where orbital manufacturing stops being a novelty and starts looking like maintenance infrastructure. Silicon manufacturing in space has been discussed for reasons that range from microgravity crystal growth to vacuum processing and contamination control. Some of those benefits may turn out to be niche. Some may be overwhelmed by launch logistics and process control. But if the orbital asset base grows, the question changes from “can space make a perfect wafer?” to “which parts of the silicon, packaging, repair, and recycling loop are worth closing off Earth?”&lt;/p&gt;
&lt;p&gt;Maybe the first useful loop is not wafer fabrication at all. Maybe it is inspection, module swap, radiator cleaning, connector replacement, board-level refurbishment, propellant top-up, or recycling aluminium structures. Maybe high-value semiconductor steps stay terrestrial while bulky static infrastructure stays orbital. Maybe microgravity does matter for particular crystals, optical components, or thermal interface materials. The answer should be found by process engineers, not by a launch animation.&lt;/p&gt;
&lt;p&gt;But the principle is clear enough: keep the slow, massive, durable assets in place; rotate the fast-moving compute through them. Do not strand the power, cooling, networking, and orbital mechanics every time the accelerator roadmap changes.&lt;/p&gt;
&lt;h2 id=&quot;the-earth-is-in-space-too&quot;&gt;The Earth is in space too&lt;/h2&gt;
&lt;p&gt;The tempting conclusion is that orbital data centers are exotic because they have thermodynamic problems. I think the opposite is true. They are interesting because they make the thermodynamic problems visible.&lt;/p&gt;
&lt;p&gt;Earth-based data centers are also bounded by energy, entropy, materials, and waste heat. They just have more ways to export the consequences. A conventional data center can dump heat into air, water, district heating loops, neighbouring property, local weather, or a permitting process. Private property law lets the operator draw a fence around the useful part of the machine and call the heat someone else’s problem.&lt;/p&gt;
&lt;p&gt;Physics does not recognise the cadastral boundary.&lt;/p&gt;
&lt;p&gt;At planetary scale, Earth cools the same way an orbital data center does: by radiation to space. There is no cosmic cooling tower waiting outside the atmosphere. Add energy demand, trap more outgoing infrared, move heat around with clever plumbing, and the final balance still ends at the top of the atmosphere.&lt;/p&gt;
&lt;p&gt;The terminator dual-meaning feels like a meme pill I have given myself. A data center on the dawn-dusk line cannot hide behind convection, and a data center in a suburb cannot hide behind property law forever. In both cases the question is the same: how much useful order can we create per joule, what materials make that possible, where does the waste heat go, and who is responsible for closing the loop when the hardware ages out?&lt;/p&gt;
&lt;p&gt;Orbital data centers may one day make sense for particular AI inference, Earth observation, autonomy, and maybe specialised training workloads. But they will only be serious if they are designed as thermodynamic systems: power, compute, radiators, shielding, networking, servicing, debris removal, and silicon loops all in one ecosystem.&lt;/p&gt;
&lt;p&gt;The Earth is in space too, and radiation is the only way the planet pays its final cooling bill.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/2996039067624704159/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/2996039067624704159' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2996039067624704159'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2996039067624704159'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/08/terminators-at-terminator.html' title='Terminators at the Terminator'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-8688379215497532068</id><published>2026-07-22T17:00:00.000-07:00</published><updated>2026-07-27T06:38:02.810-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="craft"/><category scheme="http://www.blogger.com/atom/ns#" term="japan"/><category scheme="http://www.blogger.com/atom/ns#" term="knife-sharpening"/><category scheme="http://www.blogger.com/atom/ns#" term="robotics"/><category scheme="http://www.blogger.com/atom/ns#" term="tools"/><category scheme="http://www.blogger.com/atom/ns#" term="travel"/><title type='text'>Finding the Edge in Japan</title><content type='html'>&lt;p&gt;Tsukiji Market smells like grilled seafood, wet stone, soy, tourists and logistics. Somewhere between the fish stalls and the slow current of people carrying breakfast on sticks, I walked into a knife shop and found a wall of edges pretending to be a retail display.&lt;/p&gt;
&lt;p&gt;The commitment was not subtle. Rows of Santoku knives sat behind glass with the calm seriousness of lab instruments. Not the Don Quijote souvenir version, but the shops where the object is expected to do work for decades if you respect it. Around USD 250 felt like the going entry point for a decent Santoku in the places we wandered into, and it rose very quickly from there.&lt;/p&gt;
&lt;p&gt;Then in Kyoto, the scale changed. A sword shop had a katana listed at 7 million yen. At that price you are no longer buying a long sharp object. You are buying metallurgy, lineage, polishing, paperwork, scarcity, and a whole cultural machine for deciding that a particular edge has survived long enough to deserve reverence.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczOEDHKVf9nhurBsGpAzJ40QRM3M8I3C3N03xfYn5iQpiauT7cEmZKNRgjRY9GWBAR9OkNLNrLRGxW0-gjfXe5IiWg4mL7B9d93QDwJbIG31iBhJld6_=w1200-h900-no&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;Knives in Tsukiji Market&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We visited two knife shops in Tsukiji, a sword shop in Kyoto, and another knife shop near the Pokemon Center in the Takashimaya building in Shibuya. The geography helped the idea settle. Tsukiji had the working-market feeling, knives as seafood infrastructure. Kyoto carried the ceremonial weight of blades as history. Shibuya had the polished department-store version, still serious, but now sitting in the same urban stack as Pokemon, fashion, food halls and escalators.&lt;/p&gt;
&lt;p&gt;Japan does this particularly well: the ordinary tool is allowed to become obsessive without becoming kitsch. A kitchen knife can remain a kitchen knife while also being a small thesis on steel, heat treatment, hand skill, regional specialisation, and daily maintenance.&lt;/p&gt;
&lt;h2 id=&quot;sharpening-as-culture&quot;&gt;Sharpening as Culture&lt;/h2&gt;
&lt;p&gt;The part that caught me most was the sharpening. The edge is the temporary part of the knife. It is the part you create, lose, recreate, neglect, rescue and eventually learn to feel before you can see it. A beautiful blade with a dull edge is mostly theatre. A modest blade with a good edge is useful.&lt;/p&gt;
&lt;p&gt;That is a very Japanese thing to make visible in a shop: the maintenance is not a sad afterthought after the purchase. It is the point. Stones, angles, pressure, slurry, patience. The object keeps working because someone returns to the boundary between metal and material and restores it.&lt;/p&gt;
&lt;p&gt;The one time I got into trouble in Japan, amidst mostly friendly people, was in Tsukiji when I accidentally bumped someone sharpening a knife. There are mistakes that can be fixed with a smile, and there are mistakes where the animal part of your brain notices the blade first. I walked backwards slowly, muttering “gomen” with every available ounce of tourist sincerity.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczOyt0E-c4KO4bo8YkFVXcl7Jfzgkr21qZaS2MSftxAqqftc01tklwXnZmzeHwcerx0kQdpky0_aa6zJNo2qh5XWkWK_-f1U5ANPv0chTdzMZ6qmjxHu=w900-h1200-no&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;Santoku knives behind glass&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;There is a pleasing physics to this. Cutting is not brute force. Cutting is pressure concentrated along a thin enough line that the material gives up locally. The wedge finds a gap, opens it, and moves through. When the edge rolls or blunts, the same hand and the same steel suddenly need more force, more damage, more mess.&lt;/p&gt;
&lt;p&gt;That is where the metaphor starts doing actual work instead of sitting on the mantelpiece.&lt;/p&gt;
&lt;h2 id=&quot;sharp-words-sharp-tools&quot;&gt;Sharp Words, Sharp Tools&lt;/h2&gt;
&lt;p&gt;We use knife language everywhere when we talk about thought. Smart people are sharp. Arguments have an edge. Teams lose their edge. We sharpen our axe when we build up skills before attacking the next task. We cut scope. We carve out time. We slice a problem into pieces. We decompose something hard into smaller pieces so the first incision becomes possible.&lt;/p&gt;
&lt;p&gt;Doing new things often feels like pushing a blade into something that does not yet have a natural opening. You do not smash the whole surface. You look for the gap. You test the grain. You find the weak plane, the softer layer, the place where a small movement changes the geometry of the rest of the problem.&lt;/p&gt;
&lt;p&gt;Software architecture has this hidden inside it. Debugging has it even more. A failing build, a strange sensor trace, a dataset that refuses to behave: none of these usually yield to force. You find the narrowest question that can split the problem. Does the voltage sag under load? Does the request fail before authentication or after it? Does the geospatial reprojection break before tiling or during the write path? A good diagnostic question is a sharp tool.&lt;/p&gt;
&lt;p&gt;The wrong question is a dull knife. It still consumes effort, but mostly by bruising the work.&lt;/p&gt;
&lt;h2 id=&quot;the-robot-with-an-old-edge&quot;&gt;The Robot With an Old Edge&lt;/h2&gt;
&lt;p&gt;Then, at the space forum, I met Abhay, who has been working with a 1980s knife-sharpening robot.&lt;/p&gt;
&lt;p&gt;That sentence felt like Japan had followed me home with a punchline.&lt;/p&gt;
&lt;p&gt;The theme was suddenly not just knives as craft objects, but knives as an interface between craft and automation. A sharpening robot from the 1980s is old enough to predate most of our current robotics hype cycles, old enough to belong to the world of industrial control cabinets, teach pendants, custom jigs, limit switches, and stubborn mechanical repeatability. It has to keep the angle, pressure and abrasive contact honest while the steel pushes back.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczN6sEoCkU5UuFQYMuG1tFz6K8Vxxju5BwjWKhIs6DugBJd8a0eTmIftE8GqFuJCT1wOrmK_KtwaKD2JhsV58U75fZeEK5NSB8qaapTMnlh1-7PW13Wg=w1200-h900-no&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;Sword display in Kyoto&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;That is the useful tension. Sharpening looks simple until you try to automate it. The robot has to hold an angle, manage pressure, follow a changing profile, deal with abrasive wear, heat, burr formation and the awkward fact that every blade has a history. The edge is not a CAD line. It is a lived boundary on a piece of steel. The exact usage of the knife accumulates and determines its fate, reality is a stochastic process.&lt;/p&gt;
&lt;p&gt;This is why robotics remains humbling. The easy demo is motion. The hard part is contact. Once a robot touches the world, the world starts negotiating back. Knives make that negotiation visible because the result is brutally honest. The knife is either sharp, or it is not. The tomato knows, as does the audience watching a &lt;a href=&quot;https://futurism.com/robot-dance-moves-flames-out&quot;&gt;Unitree humanoid lose the dance floor&lt;/a&gt;, or the &lt;a href=&quot;https://www.edge-ai-vision.com/2026/06/introducing-the-qualcomm-dragonwing-iq10-rrd-a-full-stack-robotics-reference-design/&quot;&gt;Qualcomm Dragonwing IQ10 robotics platform&lt;/a&gt; show up in an &lt;a href=&quot;https://www.facebook.com/etnow/videos/robot-powered-by-qualcomms-new-ai-chip-collapses-mid-presentationrobot-qualcomm-/28569236365997428/&quot;&gt;ET NOW clip of a mid-presentation collapse&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;tools-that-teach-hands&quot;&gt;Tools That Teach Hands&lt;/h2&gt;
&lt;p&gt;There is a lazy version of automation where machines replace skill, and a better version where machines expose what skill actually contains. A knife-sharpening robot is interesting because it cannot escape the craft problem. It has to encode something a human sharpener may feel through wrist, sound, drag and accumulated failure.&lt;/p&gt;
&lt;p&gt;That makes it a useful object to think with. Japan’s knife shops showed the cultural end of the spectrum: reverence for the edge, the maker, the steel and the ritual of maintenance. Abhay’s robot showed the industrial end: repeatability, fixtures, kinematics, control loops and the stubborn desire to mechanise a subtle hand skill.&lt;/p&gt;
&lt;p&gt;Between those two ends sits most serious engineering.&lt;/p&gt;
&lt;p&gt;We do not build new things by being generally clever. We build them by maintaining edges. The edge of a discipline. The edge of a toolchain. The edge of a team that still remembers how the machinery works beneath the interface. The edge of a question sharp enough to enter a hard problem without shattering it.&lt;/p&gt;
&lt;p&gt;The holiday version of Japan gave me knives behind glass, stones on counters, a 7 million yen katana, and Santoku knives priced like serious instruments rather than kitchen accessories. The space-forum version gave me a 1980s robot still trying to make an edge repeatable.&lt;/p&gt;
&lt;p&gt;That is the thought I wanted to keep: sharpening is not preparation for the work.&lt;/p&gt;
&lt;p&gt;Sharpening is part of the work.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/8688379215497532068/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/8688379215497532068' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8688379215497532068'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8688379215497532068'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/07/finding-edge-in-japan.html' title='Finding the Edge in Japan'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/pw/AP1GczOEDHKVf9nhurBsGpAzJ40QRM3M8I3C3N03xfYn5iQpiauT7cEmZKNRgjRY9GWBAR9OkNLNrLRGxW0-gjfXe5IiWg4mL7B9d93QDwJbIG31iBhJld6_=s72-w1200-h900-c-no" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-2450183166027196645</id><published>2026-06-25T16:30:00.000-07:00</published><updated>2026-06-29T14:03:15.886-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="cloud-native-geospatial"/><category scheme="http://www.blogger.com/atom/ns#" term="earth-observation"/><category scheme="http://www.blogger.com/atom/ns#" term="eoepca"/><category scheme="http://www.blogger.com/atom/ns#" term="jupyter"/><category scheme="http://www.blogger.com/atom/ns#" term="openeo"/><category scheme="http://www.blogger.com/atom/ns#" term="pangeo"/><category scheme="http://www.blogger.com/atom/ns#" term="science-platforms"/><title type='text'>EO Platforms, Science Platforms, and the Apartment Between Binder and Earth Engine</title><content type='html'>&lt;p&gt;When you think of running code in the browser, you probably think of
Binder or Google Colab. If you are at an AWS house, you think of
Sagemaker.&lt;/p&gt;
&lt;p&gt;That is the visible end of the digital science platform story: a
notebook appears in a tab, Python imports something, a chart lands on
the screen, and for a moment the whole research infrastructure problem
looks solved. If you are fan of a different paradigm, Python can be
replaced with R, or a programming language replaced by a chat session
which has its side effects as Science/Engineering plans and some
code.&lt;/p&gt;
&lt;p&gt;Then the real workflow arrives. The data is 100 TB of imagery from a
High-Altitude Balloon and it is sitting at the HPC; you will have to
wait in the queue for the job to submit, but the proposal deadline is
tomorrow and you really need preliminary exploration graphics to
illustrate your story, since humans are inherently visual creatures. Do
you fake it till you make it using Nano Banana, or do you commit to a
fraction of the actual work you are applying for the funding to do in
full?&lt;/p&gt;
&lt;p&gt;The HPC credentials are institutional. The analysis needs Dask
workers near cloud object storage. It will take two hours for Globus to
haul the data over to the nearest AWS Region. The output, when the grant
is completed, should become a tile service, a STAC collection, a policy
brief, a model run, and a thing someone can repeat six months later when
the next sensor collection lands after that much needed CMOS and Lens
upgrade. For now you really need that plot showing how a thermal mosaic
align with the visible spectrum satellite imagery.&lt;/p&gt;
&lt;p&gt;At that point the browser notebook is the doorway, not the platform.
The doorway opens onto a howling void of needs and unfilled
expectations.&lt;/p&gt;
&lt;h2 id=&quot;the-apartment-the-hotel-room-and-the-empty-block&quot;&gt;The apartment,
the hotel room, and the empty block&lt;/h2&gt;
&lt;p&gt;The continuum feels a bit like the Django versus Flask argument,
except measured in satellite scenes, climate arrays, grant budgets, and
institutional risk. If you don’t know what Django or Flask is, perhaps
opinionated vs minimalistic are more understandable.&lt;/p&gt;
&lt;p&gt;A managed science namespace is the Flask or FastAPI option. You get a
well-tested core, working access controls, shared storage, a scheduler,
a route to scalable compute, and enough freedom to design your own
universe. It is like buying an empty apartment in a good part of town.
The walls are sound. The plumbing works. The rooms are yours, you will
not get robbed if you step outside.&lt;/p&gt;
&lt;p&gt;A highly managed platform is closer to a hotel room at the Ritz.
Everything is convenient, polished, and serviced. You get a desk, a bed,
a view, and a button to press when something breaks. You probably cannot
knock down a wall.&lt;/p&gt;
&lt;p&gt;Then there is the empty block of land: Kubernetes, object storage,
IAM, container registries, workflow engines, data catalogs, and a team
with enough scars to make them all behave. Maximum control, maximum
blast radius.&lt;/p&gt;
&lt;p&gt;The interesting work sits between those extremes. Digital science
platforms are not one product category. They are a gradient of
convenience, control, reproducibility, and institutional memory.&lt;/p&gt;
&lt;h2
id=&quot;the-first-split-interactive-science-versus-production-exploitation&quot;&gt;The
first split: interactive science versus production exploitation&lt;/h2&gt;
&lt;p&gt;Earth observation platforms and broader science platforms grew from
different pressures.&lt;/p&gt;
&lt;p&gt;Science platforms usually start with researchers. They need
notebooks, environments, collaboration spaces, package installation,
teaching material, shared compute, and a path from experiment to
publication. The center of gravity is interactive work: Jupyter,
RStudio, Dask, documentation, executable papers, and a community that
can teach the next person how to reproduce the result.&lt;/p&gt;
&lt;p&gt;EO exploitation platforms usually start with data gravity. They need
catalogs, tiling, pixel access, area-of-interest filtering, atmospheric
correction, process graphs, long-running jobs, and application
packaging. The center of gravity is operational work: find the scenes,
run the process near the archive, publish the output, and make the
result portable across platforms.&lt;/p&gt;
&lt;p&gt;In practice those two worlds are merging. The Pangeo stack wants
cloud-native scientific computing. EOEPCA wants interoperable EO
exploitation building blocks. Digital Earth platforms want curated
national-scale data cubes. NASA-style platforms such as MAAP and VEDA
want science teams to move from discovery to analysis to communication
without rebuilding the pipes each time.&lt;/p&gt;
&lt;p&gt;Choosing a winner is not the problem. Knowing which layer you are
buying is.&lt;/p&gt;
&lt;h2 id=&quot;a-rough-map-of-the-ecosystem&quot;&gt;A rough map of the ecosystem&lt;/h2&gt;
&lt;p&gt;The ecosystem makes more sense sorted by the job each platform does
rather than by brand.&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Main job&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;th&gt;What you gain&lt;/th&gt;
&lt;th&gt;What you give up&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ephemeral notebooks&lt;/td&gt;
&lt;td&gt;Launch a runnable environment from code&lt;/td&gt;
&lt;td&gt;Binder, repo2docker-backed demos&lt;/td&gt;
&lt;td&gt;Low friction, great teaching surface&lt;/td&gt;
&lt;td&gt;Weak persistence, weak governance, limited scale&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosted notebooks&lt;/td&gt;
&lt;td&gt;Put compute in a managed browser workspace&lt;/td&gt;
&lt;td&gt;Google Colab, Kaggle notebooks, SageMaker Studio Lab-style
services&lt;/td&gt;
&lt;td&gt;Fast start, familiar interface, low admin load&lt;/td&gt;
&lt;td&gt;Runtime limits, cloudy provenance, platform-specific behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Community hubs&lt;/td&gt;
&lt;td&gt;Give a research community a managed shared workspace&lt;/td&gt;
&lt;td&gt;2i2c hubs, JupyterHub deployments, Pangeo hubs&lt;/td&gt;
&lt;td&gt;Shared identity, shared environments, scalable Dask, community
ownership&lt;/td&gt;
&lt;td&gt;Still needs platform stewardship and cost discipline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open science practice layers&lt;/td&gt;
&lt;td&gt;Teach teams how to work reproducibly&lt;/td&gt;
&lt;td&gt;OpenScapes, Project Pythia, Jupyter Book, MyST&lt;/td&gt;
&lt;td&gt;Social machinery for reproducible science&lt;/td&gt;
&lt;td&gt;Not a compute platform by itself&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud-native geoscience stacks&lt;/td&gt;
&lt;td&gt;Make large arrays workable near object storage&lt;/td&gt;
&lt;td&gt;Pangeo, Xarray, Dask, Zarr, Kerchunk, Intake&lt;/td&gt;
&lt;td&gt;Open, composable scientific computing&lt;/td&gt;
&lt;td&gt;You assemble and operate the stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data cube and EO libraries&lt;/td&gt;
&lt;td&gt;Organize analysis-ready EO collections&lt;/td&gt;
&lt;td&gt;Open Data Cube, xcube, stackstac, odc-stac&lt;/td&gt;
&lt;td&gt;EO-shaped data abstractions&lt;/td&gt;
&lt;td&gt;Needs catalog, storage, and operations around it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed planetary platforms&lt;/td&gt;
&lt;td&gt;Bring data catalog and compute together&lt;/td&gt;
&lt;td&gt;Google Earth Engine, Microsoft Planetary Computer&lt;/td&gt;
&lt;td&gt;Convenient data proximity and APIs&lt;/td&gt;
&lt;td&gt;Platform dependence and varying escape hatches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standards-based EO exploitation&lt;/td&gt;
&lt;td&gt;Package processing for portability&lt;/td&gt;
&lt;td&gt;openEO, OGC API - Processes, EOEPCA, CWL-style application
packages&lt;/td&gt;
&lt;td&gt;Repeatable jobs across back ends&lt;/td&gt;
&lt;td&gt;More ceremony and specification work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Science mission platforms&lt;/td&gt;
&lt;td&gt;Align infrastructure to a mission community&lt;/td&gt;
&lt;td&gt;NASA MAAP, NASA VEDA, AquaWatch, ESA EarthCODE-style efforts&lt;/td&gt;
&lt;td&gt;Domain-specific data, workflows, and communication&lt;/td&gt;
&lt;td&gt;Mission boundaries shape what is easy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Institutional digital earths&lt;/td&gt;
&lt;td&gt;Curate national or sectoral data products&lt;/td&gt;
&lt;td&gt;Digital Earth Australia, Africa, Pacific, and related platforms&lt;/td&gt;
&lt;td&gt;Trusted local data products, policy relevance&lt;/td&gt;
&lt;td&gt;Sustained funding and data governance required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;That table is too tidy, of course. Real platforms straddle rows. A
Pangeo hub can be a community hub, a cloud-native geoscience stack, and
the working surface for a Digital Earth program. Earth Engine is both a
managed planetary platform and a workflow language. EOEPCA is both
architecture and open-source building blocks. A Digital Earth platform
can host notebooks, APIs, dashboards, STAC catalogs, and products built
from Open Data Cube.&lt;/p&gt;
&lt;p&gt;The taxonomy still helps because “we need a science platform” can
mean a teaching hub, a production EO processing system, a mission
workbench, a public communication portal, or a Kubernetes tenancy model
for research groups. Those are different purchases.&lt;/p&gt;
&lt;h2 id=&quot;pangeo-is-a-community-before-it-is-a-stack&quot;&gt;Pangeo is a
community before it is a stack&lt;/h2&gt;
&lt;p&gt;Pangeo is often described through its software: Xarray for labelled
N-dimensional arrays, Dask for parallel compute, Zarr for chunked
cloud-friendly storage, Jupyter for interactive work, Kerchunk for
virtualizing old file formats, Intake for catalogs, hvPlot for quick
visualization, XPublish for serving datasets, and newer bounded-memory
or serverless experiments such as Cubed and Xarray-Beam.&lt;/p&gt;
&lt;p&gt;What goes into the requirements / constraints file of a notebooks
repo is all and good, but like all code its value really depends on the
people who read it and run it, Anne Frank’s diary is no good, if it is
never found and read. The written word of any form be is a notebook or a
painful diary, reaches its true potential when it transmits the ideas
contained there in to the minds of thousands of others. Pangeo describes
itself as a community for open, reproducible, scalable geoscience.
Project Pythia is its education working group and a training hub for the
geoscientific Python community. The infrastructure, documentation,
showcase talks, working groups, cookbooks, and foundation tutorials are
part of the platform. Project Pythia can be found, it has a lot of
words, but no concrete infrastructure to run on, no printing press to
replicate the proposed patterns and keep publishing them across planning
cycles.&lt;/p&gt;
&lt;p&gt;Many institutional platform programs miss this. You can install
JupyterHub and Dask Gateway in a week. You cannot apt install a culture
of reproducible workflows, documented environments, data access
patterns, and examples that match the local science questions.&lt;/p&gt;
&lt;p&gt;2i2c and OpenScapes occupy this gap. 2i2c turns the hub into managed
open infrastructure with access control, custom environments, scalable
compute, and a “Right to Replicate” philosophy, which is a useful
antidote to the managed-service trap. OpenScapes works on the human
operating system: habits, onboarding, documentation, and shared
practice. The difference shows up when one champion leaves and the
platform either survives or becomes a quiet monthly cloud bill, that
everyone questions every quarter and decides to shutdown in a much
“killed by Google” fashion. It have shut down a service or two in my
time as well.&lt;/p&gt;
&lt;h2 id=&quot;earth-engine-is-the-polished-hotel-room&quot;&gt;Earth Engine is the
polished hotel room&lt;/h2&gt;
&lt;p&gt;Google Earth Engine remains the reference point for convenient
planetary-scale EO analysis. It combines a multi-petabyte public
catalog, server-side geospatial computation, JavaScript and Python APIs,
and a browser code editor that made remote sensing feel weirdly
immediate.&lt;/p&gt;
&lt;p&gt;The trade-off is the same one that makes it attractive. You get the
hotel room. You do not own the building.&lt;/p&gt;
&lt;p&gt;For many users that is exactly right. If the job is land-cover change
detection, trend mapping, rapid prototyping, teaching, or humanitarian
analysis, Earth Engine collapses a brutal infrastructure problem into an
API, and it has unlocked a large amount of science and public-interest
work.&lt;/p&gt;
&lt;p&gt;A national agency or regulated enterprise eventually asks harder
questions. Can we run this against restricted internal data? Can we
reproduce the process outside the platform? Can the cost model survive
operational use? Can the workflow be audited? Can the output become an
internal service rather than a script in someone else’s editor? What if
Google does not like the economics and GEE gets “Killed by Google” ?&lt;/p&gt;
&lt;p&gt;Those questions mark the boundary between convenience and
control.&lt;/p&gt;
&lt;h2 id=&quot;planetary-computer-stac-and-the-cloud-native-middle&quot;&gt;Planetary
Computer, STAC, and the cloud-native middle&lt;/h2&gt;
&lt;p&gt;Microsoft Planetary Computer pushed a different shape: open catalogs,
STAC metadata, cloud-hosted environmental datasets, Hub-style analysis
environments, and APIs that fit the broader Python geospatial ecosystem.
It did not only put data in the cloud; it made the catalog and assets
legible to ordinary tools.&lt;/p&gt;
&lt;p&gt;That middle ground is where STAC, Cloud Optimized GeoTIFF, Zarr,
GeoParquet, and object storage conventions earn their keep. STAC calls
itself a common language for geospatial information, with a core JSON
structure for describing and cataloguing spatiotemporal assets. That
sounds dull until you have inherited five satellite archives, three
naming conventions, and one research assistant who left for a postdoc in
Bremen.&lt;/p&gt;
&lt;p&gt;These are the unglamorous freight standards of cloud-native
geospatial work. Once data is published in these shapes, platforms
compete on experience and operations instead of trapping users at the
file boundary.&lt;/p&gt;
&lt;p&gt;The same applies inside Digital Earth programs. Open Data Cube,
odc-stac, xcube, stackstac, and Pangeo tooling become more powerful when
the data model is boring and inspectable. Boring is good. Boring is how
a wet-season flood product, a crop monitoring workflow, and a methane
detection experiment can reuse the same infrastructure without
pretending they are the same science.&lt;/p&gt;
&lt;h2 id=&quot;openeo-and-eoepca-are-the-uncomfortable-middle&quot;&gt;openEO and
EOEPCA are the uncomfortable middle&lt;/h2&gt;
&lt;p&gt;At the other end from free-form notebooks are workflow and process
standards.&lt;/p&gt;
&lt;p&gt;openEO gives users a unified API for Earth observation cloud back
ends. It is a process graph world: define operations, submit work, let
the back end execute near the data, and avoid rewriting the same
analysis for every platform. In 2026 openEO became an OGC Community
Standard, which is a useful signal that the idea has moved beyond a
single project vocabulary.&lt;/p&gt;
&lt;p&gt;OGC API - Processes handles a related need: wrap computational tasks
as executable processes that a server can offer through a JSON-over-HTTP
Web API. It is the unromantic contract that lets processing become a
service instead of a notebook cell someone has to rerun by memory.&lt;/p&gt;
&lt;p&gt;EOEPCA then packages a broader exploitation platform architecture
around this world: reusable building blocks, open standards, federation
between EO cloud platforms, application packaging, identity, data
access, processing, and publication. Its mission is practical: enhance
interoperability between cloud-based EO platforms and unify the
fragmented cloud ecosystem for ground segment, EO science, R&amp;amp;D, and
applications.&lt;/p&gt;
&lt;p&gt;This middle is uncomfortable because it asks scientists to describe
workflows with more ceremony than a notebook while asking infrastructure
teams to expose more flexibility than a fixed portal. That ceremony
earns its keep only when portability, audit, repeatability, and
multi-platform execution are real requirements.&lt;/p&gt;
&lt;h2 id=&quot;maap-veda-and-aquawatch-show-mission-shaped-patterns&quot;&gt;MAAP,
VEDA, and AquaWatch show mission-shaped patterns&lt;/h2&gt;
&lt;p&gt;NASA’s Multi-Mission Algorithm and Analysis Platform (MAAP),
Visualization, Exploration, and Data Analysis (VEDA), and AquaWatch
point at another category: mission-shaped science platforms.&lt;/p&gt;
&lt;p&gt;MAAP is built around collaborative algorithm development and analysis
for biomass, carbon, and related mission data. It combines data,
algorithms, and cloud computation for Earth science work at scale,
including GEDI, ICESat-2, BIOMASS, NISAR, and related mission products.
Its centre is not a generic notebook. It is a community of practice
around specific data products, algorithms, and validation work.&lt;/p&gt;
&lt;p&gt;VEDA is more communication and exploration oriented: science data,
dashboards, stories, APIs, and applications that help users move from
dataset to visible public insight. Its public dashboard talks about
cloud-enabled analysis without writing code or downloading data, plus
stories for science communication. In the geospatial agent stack draft I
have been calling this the presentation and evidence layer: not just
compute, but a way to package outputs for humans without losing
provenance.&lt;/p&gt;
&lt;p&gt;AquaWatch is the mission model closer to my own recent work: water
quality intelligence rather than a generic EO workbench. Its platform
shape is dictated by the problem. Satellite products, in-situ
observations, calibration and validation workflows, data services,
state-government users, and operational water decisions all have to sit
in one fabric. Nobody wants an elegant notebook if the harmful algal
bloom window has already closed and the river manager is still waiting
for a plot.&lt;/p&gt;
&lt;p&gt;Mission platforms should not be embarrassed by their specificity. A
platform that knows its science domain can make strong defaults: data
already mounted, examples already relevant, units already sensible,
common plots already nearby, and metadata that matches the decisions
people actually make.&lt;/p&gt;
&lt;h2 id=&quot;digital-earth-platforms-are-institutional-memory&quot;&gt;Digital Earth
platforms are institutional memory&lt;/h2&gt;
&lt;p&gt;Digital Earth platforms are a cousin of science platforms, but with
more institutional weight.&lt;/p&gt;
&lt;p&gt;Digital Earth Australia, Digital Earth Africa, Digital Earth Pacific,
and related efforts are not merely places to run notebooks. They are
long-running data product factories, national or regional knowledge
systems, and trust infrastructure. They turn raw satellite archives into
analysis-ready data and derived products that policy, environment,
agriculture, water, and disaster teams can use.&lt;/p&gt;
&lt;p&gt;The local flavours carry the point. Digital Earth Australia talks
about trusted imagery and freely available analysis-ready datasets for
researchers, land managers, agriculture, and emergency management.
Digital Earth Africa frames the work as decision-ready products for
sustainable growth across social, environmental, and economic
challenges. Digital Earth Pacific is explicitly about decision-making
for Pacific peoples at EO scale, with regional products, dashboards, an
analytical hub, data, community, and governance in the same frame. This
is not just a different skin on the same JupyterHub.&lt;/p&gt;
&lt;p&gt;If you need a global flavour you can check out &lt;a
href=&quot;https://research.csiro.au/easi/&quot;&gt;EASI&lt;/a&gt; from CSIRO under the
AquaWatch program delivery, it flips the regional data cube approach to
provide a global datacube from STAC using cloud native primitives.
Almost a build your own Google Earth Engine approach, with associated
DevOps and Platform Engineering burdens which you have to pay for to
get.&lt;/p&gt;
&lt;p&gt;That is a different job from a research notebook service. The value
is not that one scientist can compute something, but that many people
can rely on the same corrected, versioned, documented product line. Open
Data Cube sits under many of these programs as an open-source way to
manage analysis-ready data and has been used for continental-scale
products such as Australian land-cover mapping from decades of Landsat
imagery.&lt;/p&gt;
&lt;p&gt;Here the apartment analogy changes. A Digital Earth platform is not
an apartment you furnish. It is an apartment building with strata rules,
fire exits, a maintenance schedule, and residents who will complain if
the lift stops working, and I have been a super on such apartment
buildings across 3 platforms now.&lt;/p&gt;
&lt;h2 id=&quot;what-must-be-portable&quot;&gt;What must be portable?&lt;/h2&gt;
&lt;p&gt;Most platform debates get stuck on user interface preference.
Notebooks versus portals. Python versus JavaScript. Managed service
versus Kubernetes. Proprietary convenience versus open stack purity. The
relevant debate is around what must be portable.&lt;/p&gt;
&lt;p&gt;If only the result is needed, a polished managed platform may be
perfect. If the method must move between agencies, clouds, and missions,
then STAC, openEO, OGC API - Processes, CWL-style packaging, and open
data formats become non-negotiable. If the community must outlive one
grant, then docs, examples, governance, and training are platform
features. If restricted data is involved, then identity, audit, and
network controls are part of the science platform, not enterprise
up-sell (don’t get me started on the SSO premium most SaaS platforms
charge).&lt;/p&gt;
&lt;p&gt;There are at least five kinds of portability hiding inside this one
word:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Data portability: can assets move or be read by standard tools?&lt;/li&gt;
&lt;li&gt;Workflow portability: can the analysis run on a different back
end?&lt;/li&gt;
&lt;li&gt;Environment portability: can the software stack be rebuilt?&lt;/li&gt;
&lt;li&gt;Evidence portability: can another person inspect how the result was
produced?&lt;/li&gt;
&lt;li&gt;Community portability: can another team inherit the practice without
oral tradition?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The best platform choice depends on which of those you actually
need.&lt;/p&gt;
&lt;h2 id=&quot;agents-make-the-old-platform-boundary-fuzzier&quot;&gt;Agents make the
old platform boundary fuzzier&lt;/h2&gt;
&lt;p&gt;Agentic tooling is the next complication.&lt;/p&gt;
&lt;p&gt;Once agents can call a STAC API, resolve a place name, submit an
openEO job, monitor an Argo Workflow, query a Digital Atlas, open a
notebook, and draft a VEDA-style story, the visible platform recedes
behind the contracts underneath it.&lt;/p&gt;
&lt;p&gt;Portals do not disappear. The durable value moves down into services,
catalogs, workflow engines, identity boundaries, and audit trails, and
the UI becomes one client among many.&lt;/p&gt;
&lt;p&gt;This is where EO and enterprise AI rhyme. A user should be able to
ask a normal question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Show me whether wet-season surface water around this catchment is
outside the last ten-year range, and give me the data sources and
caveats.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The system behind that question might need a gazetteer, a STAC
catalog, a data cube, Dask workers, an openEO process graph, a workflow
engine, a notebook artifact, and a short written summary. Calling all of
that a chatbot misses the point. It is a digital science platform with a
language-shaped front door.&lt;/p&gt;
&lt;h2 id=&quot;science-platform-advantage&quot;&gt;Science Platform advantage&lt;/h2&gt;
&lt;p&gt;There is a less glamorous question hiding under the agent story: who
operates and pays for the tooling and compute fabric the agents
call?&lt;/p&gt;
&lt;p&gt;If a user asks the wet-season surface-water question and an agent
fans out across a slew of tools, somebody owns every link in that chain.
Somebody pays for object storage requests, scheduler time, network
egress, GPU or CPU minutes, model tokens, human review, and the
maintenance of the small apis that make the orchestration possible.&lt;/p&gt;
&lt;p&gt;A serious science platform needs weight propagation in both
directions. Backward propagation attributes each output to the tools,
datasets, people, grants, teams, and compute fabric it consumed. Forward
propagation estimates what the next run will cost before the button is
pressed. Without both, the presenter of the agentic tooling with
customer touch point gets all the glory and gets to keep all the
revenue, while the sustaining ecosystem underneath withers on the vine
and the agentic tool ends up being a toy in the long run.&lt;/p&gt;
&lt;p&gt;This is where the phrase “Science Platform advantage” starts to be
useful, in the same way people talk about quantum advantage. The claim
is not that a platform is clever. The claim is that a connected,
orchestrated chain of task-specific tooling, assembled on demand and
cost-tracked properly, delivers more value than doing the same work any
other way.&lt;/p&gt;
&lt;p&gt;For the utilitarians in the room, that claim needs a benchmark. Pose
a real problem. Solve it fully the old way first: portal clicks,
downloads, hand-written scripts, email threads, queue waits, manual
plots, confused provenance, and the final slide dropped into a proposal
at 11:47 pm. Then build the agentic way and run the same class of
problem a thousand times, so the cost of building the new fabric is
amortized across many analyses rather than charged to the first heroic
demo.&lt;/p&gt;
&lt;p&gt;The trouble is that no one was keeping clean accounts while we did it
the old way. We rarely know how much the portal-clicking cost once staff
time, failed runs, duplicate downloads, local storage, interpretation
drift, and meetings are counted. So we cannot honestly promise cheaper
or faster without measuring both sides. We can be more certain about the
energy bill: silicon currently delivers far less useful scientific
reasoning per watt than the human brain fed on caffeine and
croissants.&lt;/p&gt;
&lt;p&gt;That does not weaken the platform argument. It makes the accounting
part of the platform. The useful question is not “can an agent do this?”
The useful question is whether the platform can tell us what it did, who
paid, who benefited, and whether the next thousand runs beat the old way
by enough to justify the extra silicon. Will the environmental solution
we are building preserve the environment or become yet another nail in
the anthropogenic coffin we are putting around our planet.&lt;/p&gt;
&lt;h2 id=&quot;my-current-bias&quot;&gt;My current bias&lt;/h2&gt;
&lt;p&gt;I lean toward the apartment model.&lt;/p&gt;
&lt;p&gt;Give science teams a managed namespace with identity, storage,
standard catalogs, scalable compute, observability, and a small number
of blessed paths to production. Keep the walls movable. Let the team
bring Pangeo, Open Data Cube, xcube, DuckDB, GDAL, QGIS plugins, or
specialist models where the science demands it. Make the durable
contracts boring: STAC, COG, Zarr, GeoParquet, openEO, OGC APIs,
container images, reproducible environments, and documented
workflows.&lt;/p&gt;
&lt;p&gt;Use the hotel room when speed beats ownership. Use the empty block
only when the institution is ready to become a platform operator.
Everything else is a furnishing choice.&lt;/p&gt;
&lt;p&gt;EO platforms and science platforms are not rival tribes. They are
different answers to the same infrastructure question: how much freedom
do you need, how much responsibility can you carry, and what parts of
the science must still make sense when the browser tab is closed?&lt;/p&gt;
&lt;h2 id=&quot;sources-and-threads-to-pull-next&quot;&gt;Sources and threads to pull
next&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pangeo.io/&quot;&gt;Pangeo&lt;/a&gt; and &lt;a
href=&quot;https://projectpythia.org/&quot;&gt;Project Pythia&lt;/a&gt; for the open,
reproducible, scalable geoscience community and its education
layer.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://2i2c.org/&quot;&gt;2i2c&lt;/a&gt; and &lt;a
href=&quot;https://openscapes.org/&quot;&gt;OpenScapes&lt;/a&gt; for managed open
infrastructure, community hubs, right-to-replicate thinking, and
reproducible research practice.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stacspec.org/en&quot;&gt;STAC&lt;/a&gt;, &lt;a
href=&quot;https://www.ogc.org/standard/ogcapi-processes/&quot;&gt;OGC API -
Processes&lt;/a&gt;, &lt;a href=&quot;https://openeo.org/&quot;&gt;openEO&lt;/a&gt;, and &lt;a
href=&quot;https://eoepca.org/&quot;&gt;EOEPCA&lt;/a&gt; for catalog, process, workflow,
and platform-interoperability contracts.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://earthengine.google.com/&quot;&gt;Google Earth Engine&lt;/a&gt; as
the canonical managed planetary-scale EO analysis environment.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://planetarycomputer.microsoft.com/&quot;&gt;Microsoft
Planetary Computer&lt;/a&gt; as the open-catalog, cloud-hosted environmental
data, and scientific API pattern.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://maap-project.org/&quot;&gt;NASA MAAP&lt;/a&gt;, &lt;a
href=&quot;https://www.earthdata.nasa.gov/dashboard/&quot;&gt;NASA VEDA&lt;/a&gt;, and
AquaWatch as mission-shaped platform patterns around collaboration,
analysis, visualization, communication, and operational water-quality
intelligence.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.dea.ga.gov.au/&quot;&gt;Digital Earth Australia&lt;/a&gt;, &lt;a
href=&quot;https://www.digitalearthafrica.org/&quot;&gt;Digital Earth Africa&lt;/a&gt;, &lt;a
href=&quot;https://www.digitalearthpacific.org/&quot;&gt;Digital Earth Pacific&lt;/a&gt;,
&lt;a href=&quot;https://research.csiro.au/easi/&quot;&gt;CSIRO EASI&lt;/a&gt;, and &lt;a
href=&quot;https://www.opendatacube.org/&quot;&gt;Open Data Cube&lt;/a&gt; for
institutional data product platforms and analysis-ready data
infrastructure.&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/2450183166027196645/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/2450183166027196645' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2450183166027196645'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2450183166027196645'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/06/eo-platforms-science-platforms-and.html' title='EO Platforms, Science Platforms, and the Apartment Between Binder and Earth Engine'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-1971538342557153861</id><published>2026-05-29T17:00:00.000-07:00</published><updated>2026-05-31T05:44:34.617-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ai"/><category scheme="http://www.blogger.com/atom/ns#" term="bridgestone"/><category scheme="http://www.blogger.com/atom/ns#" term="cognitive-technology"/><category scheme="http://www.blogger.com/atom/ns#" term="exoskeleton"/><category scheme="http://www.blogger.com/atom/ns#" term="generative-art"/><category scheme="http://www.blogger.com/atom/ns#" term="hype-cycle"/><category scheme="http://www.blogger.com/atom/ns#" term="philosophy"/><category scheme="http://www.blogger.com/atom/ns#" term="rust"/><title type='text'>We Don&#39;t Have Hooves: AI Logos, Cognitive Shedding, and the Exoskeleton Economy</title><content type='html'>&lt;p&gt;I spent a weekend writing a &lt;a href=&quot;https://github.com/whatnick/ai_logos_shirt&quot;&gt;small Rust tool&lt;/a&gt; that composites AI company logos onto a Redbubble full-print t-shirt canvas. Not because anyone asked. Halfway through tuning the layout I noticed something faintly absurd: every logo I was tiling looked like a tyre tread. OpenAI’s swirl is a directional rain pattern. Gemini’s four-pointed star is a Bridgestone Blizzak winter sipe. Anthropic’s ringed A is a sidewall stamp. Nvidia’s eye is a hub cap. Lay them next to each other on a 7000-pixel canvas and the whole thing reads less like an industry portrait and more like a Beaurepaires catalogue page.&lt;/p&gt;
&lt;h2 id=&quot;logos-from-loops&quot;&gt;Logos From Loops&lt;/h2&gt;
&lt;p&gt;The visual grammar of AI companies has converged on a small family of forms: radial symmetry, interlocking arcs, gradients from cool to warm, the occasional offset chevron. They are tread patterns. They are tread patterns because tread patterns are what you draw when you want to suggest motion, grip, and continuous contact with a surface you are moving over – which is exactly the brand promise of a model that turns prompts into outputs without you needing to know how the road underneath works.&lt;/p&gt;
&lt;p&gt;The tool generates 21 of these tread-pattern logos – the leaders, challengers, niche players, and visionaries from the April 2026 Gartner Magic Quadrant for Enterprise AI Coding Agents, plus the dozen companies tracked by &lt;a href=&quot;https://isaiprofitable.com&quot;&gt;isaiprofitable.com&lt;/a&gt; – and tiles them across the canvas under four layouts: a jittered grid, a hex pack, an arabesque mask built from Lissajous curves under a wallpaper symmetry group, and a Voronoi packer that wraps cleanly at the edges. The arabesque mode is the one that looks most like a real design, which is fitting because the brand identities themselves are arabesques of the same underlying motif.&lt;/p&gt;
&lt;p&gt;Nothing in the code is novel. What is striking is how little code it takes to produce something that passes for a branding agency deliverable. Spend a few minutes tweaking curve density and symmetry group and you can cover most of the Fortune 500’s recent AI rebrand portfolio without engaging a designer. None of it requires aesthetic judgement. All of it requires a loop.&lt;/p&gt;
&lt;p&gt;That is worth sitting with before moving on to the money.&lt;/p&gt;
&lt;h2 id=&quot;the-gartner-thermometer-and-the-sequoia-deficit&quot;&gt;The Gartner Thermometer and the Sequoia Deficit&lt;/h2&gt;
&lt;p&gt;The 2024 and 2025 Gartner Hype Cycles placed generative AI at or near the Peak of Inflated Expectations, the top of the curve before the long slide into the Trough of Disillusionment. That topological framing is rough but useful. More arresting is the arithmetic underneath it.&lt;/p&gt;
&lt;p&gt;Sequoia Capital published a piece in mid-2024 estimating that AI infrastructure – primarily Nvidia GPU clusters – required roughly $600 billion in annual revenue to justify the capital being committed, while observable AI-attributable revenue across the industry was a fraction of that figure. The gap has a name in finance: “productive deployment lag.” In plain language: the shovels are being sold, the mines are being dug, and the gold has not appeared at the rate the tunnel length implies it should. On &lt;a href=&quot;https://isaiprofitable.com&quot;&gt;isaiprofitable.com&lt;/a&gt;, the only company with a green checkmark next to its name is Nvidia, the one selling the shovels.&lt;/p&gt;
&lt;p&gt;The 21-tread-pattern t-shirt is a small monument to this gap. Nvidia at the hub, eleven others on the sidewall burning through capital at rates that make the GPU revenue arithmetic interesting, one wallpaper symmetry group holding them all together on a cotton substrate.&lt;/p&gt;
&lt;p&gt;The more interesting question is not whether AI is profitable yet. It is why AI is already affecting how we think, even before the P&amp;amp;L sheets catch up.&lt;/p&gt;
&lt;h2 id=&quot;the-fur-analogy-and-cognitive-shedding&quot;&gt;The Fur Analogy and Cognitive Shedding&lt;/h2&gt;
&lt;p&gt;Around 1.5 million years ago, Homo erectus started losing body hair. The proximate cause was almost certainly thermoregulation: an upright, running hunter on the African savannah generates core heat faster than a fur coat can dissipate it under midday sun. So the fur went. But heat still needed managing. The solution was clothing, an external thermal regulation artifact that did the job the body had previously handled internally.&lt;/p&gt;
&lt;p&gt;This is a pattern that runs through the entire history of human technology. We replace innate biological functions with external artifacts. We then build manufacturing chains around those artifacts. We build economic systems around those chains. The original biological capacity atrophies from disuse or is simply never developed in the first place, because the artifact is already there when the individual arrives.&lt;/p&gt;
&lt;p&gt;We do not have hooves. We have shoes. We do not have gills. We have submarines. We do not have the magnetoreceptors that birds use on migration routes. We have GPS. In each case the external artifact is not merely a substitute; it is a platform. It invites elaboration. The shoe becomes the boot, the boot becomes the orthotic, the orthotic becomes a running shoe industry, and the running shoe industry eventually funds the biomechanics research that feeds back into the next generation of the artifact.&lt;/p&gt;
&lt;p&gt;I spent six months in late 2022 and early 2023 as an Enterprise Architect contractor at Bridgestone Australia in Adelaide, wiring up the interfaces between SAP, Salesforce, and the mobile mechanic booking platforms that schedule a van to a customer’s driveway to swap a set of tyres. The work was unglamorous integration plumbing – canonical data models, idempotent message contracts, the usual distributed-systems hygiene – but it gave me a tourist’s window into how a tyre and car parts business actually operates. Every node in the system was eventually a physical thing: a passenger radial sitting on a pallet in a Wingfield warehouse, a wheel alignment slot at a Beaurepaires bay, a truck retread coming back from its second life on a B-double. The software was a thin coordination layer over a very heavy industrial substrate.&lt;/p&gt;
&lt;p&gt;The history of the company that owns that substrate is the part that stuck with me. Bridgestone – ブリヂストン – started in 1931 not as a tyre company but as a spinoff of a 久留米 (Kurume), 九州 (Kyushu) maker of 足袋 (tabi) split-toe footwear. The founder, 石橋正二郎 (Shojiro Ishibashi), had been adding rubber soles to cotton tabi since 1923 under the Asahi brand, and rubber soles turned out to be the gateway material to rubber tyres. The name Bridgestone is a literal English inversion of his surname: 石 (ishi, stone) and 橋 (hashi, bridge), reversed and translated, picked partly because it sounded export-ready and partly to echo Firestone, the American tyre company he admired. (Bridgestone would eventually acquire Firestone in 1988 for $2.6 billion, which is the kind of historical loop that only happens in long-lived industrial companies.) The katakana spelling ブリヂストン preserves an archaic ヂ where modern Japanese would write ジ, a piece of pre-war orthography the brand keeps the way Mitsubishi keeps its three diamonds.&lt;/p&gt;
&lt;p&gt;What I took away from those six months is that Bridgestone is not really a tyre conglomerate that used to make shoes. It is a rubber compounding and supply-chain organisation that noticed rubber was useful for several different external human exoskeletons – first feet, then cars, then conveyor belts, hoses, seismic isolators under buildings, and now sustainably-sourced guayule and dandelion-derived natural rubber to hedge against Hevea brasiliensis geopolitics. The material is the through-line. The product is whichever exoskeleton the century happens to need.&lt;/p&gt;
&lt;p&gt;I always jokingly refer to BridgeStone as - “Big Rubber”.&lt;/p&gt;
&lt;h2 id=&quot;the-car-was-always-an-exoskeleton&quot;&gt;The Car Was Always an Exoskeleton&lt;/h2&gt;
&lt;p&gt;The automotive vocabulary has colonised AI discourse so completely it has become invisible. We “steer” language models. We apply “guardrails.” We talk about “autopilot” and “co-pilot” and “lanes” and “on-ramps.” There is a vehicle for sale right now whose entire value proposition is that the steering wheel becomes optional once the AI is mature enough. Almost nobody stops to ask why this particular metaphor landed so naturally.&lt;/p&gt;
&lt;p&gt;Here is one answer: cars and AI are both exoskeletons.&lt;/p&gt;
&lt;p&gt;A car is not a vehicle in the narrow sense. It is a kinetic exoskeleton that extends the range, speed, load-bearing capacity, and weather tolerance of a soft-bodied primate who would otherwise top out at 5 km/h on a good day. The car does not move instead of the human; it extends the human’s movement by several orders of magnitude at the cost of an elaborate support infrastructure: roads, fuel networks, insurance markets, traffic law, emissions regulation, and, yes, tyre companies.&lt;/p&gt;
&lt;p&gt;AI is doing the same thing to cognition. The language model does not think instead of the human; it extends the human’s language-generation and pattern-retrieval capacity by several orders of magnitude at the cost of an equally elaborate support infrastructure: GPU clusters, training pipelines, safety teams, regulatory frameworks, and eventually a Gartner hype cycle or two. The car vocabulary arrived so naturally because the thing being described was already familiar. We built the kinetic exoskeleton first. The cognitive one came later, but the shape of the dependency relationship – human plus artifact plus infrastructure – is identical.&lt;/p&gt;
&lt;h2 id=&quot;what-gets-shed&quot;&gt;What Gets Shed&lt;/h2&gt;
&lt;p&gt;The cognitive functions most visibly affected are the ones that involve generation under uncertainty: drafting a first sentence, naming a variable, composing an email, sketching a logo. These are precisely the tasks that feel slow and effortful without assistance, and precisely the tasks that AI handles smoothly. The friction is real. The assistance is real. The atrophy risk is also real.&lt;/p&gt;
&lt;p&gt;Musicians who practise scales develop neural pathways that do not form if the scales are skipped. Writers who struggle through first drafts develop a tolerance for ambiguity that does not develop if a model always resolves it for them. The logos from the code above look entirely plausible. They look like every other AI logo in the current design vocabulary. They were generated without any cognitive friction whatsoever, which is both the point and the problem. The friction was where the design decision lived.&lt;/p&gt;
&lt;p&gt;This does not mean AI assistance is bad, any more than wearing shoes is bad. It means the physiotherapy question matters: are you also doing the cognitive equivalent of the exercises that keep the underlying capacity from going the way of the body hair or your quads since you have spent 2 days chasing the zebra you speared and are waiting to run out of steam and die.&lt;/p&gt;
&lt;h2 id=&quot;the-shoe-company-principle&quot;&gt;The Shoe Company Principle&lt;/h2&gt;
&lt;p&gt;Ishibashi’s insight in 1931 was not that feet needed covering; the Asahi tabi side of the business already had that locked up. His insight was that rubber was a platform material for exoskeletal extension, and that the same compounding science, vulcanisation know-how, and distribution muscle that made a good rubber-soled tabi could make a good passenger tyre. He followed the material from one form of human locomotion extension to the next, and a hundred years later that bet is still paying out across tyres, conveyor belts, and seismic isolators.&lt;/p&gt;
&lt;p&gt;The AI companies following the GPU stack from language generation to reasoning to planning to embodied robotics are doing exactly this. The H100 is the rubber: a platform material whose applications are not exhausted by the first product built on it. The chat interfaces, the co-pilots, the logo generators – these are the 足袋. What comes next on that manufacturing chain – the 自動車 (jidousha, automobile) tyre equivalent for cognition – is the part worth watching, and worth surviving the trough of disillusionment for.&lt;/p&gt;
&lt;p&gt;Whether the current crop of AI businesses is profitable by the time the next Gartner report drops is the wrong question. Whether the infrastructure being built can outlast the hype cycle long enough to produce the genuine platform shift is the question Ishibashi would have asked, probably while measuring rubber tensile strength in a factory that used to make footwear. Japanese has a phrase for that patient industrial cultivation: 改善 (kaizen, continuous improvement). It is not the same word as ハイプ (haipu, hype), and the two have rarely been observed in the same building.&lt;/p&gt;
&lt;p&gt;The last shoe company that asked the wrong question about its own product is still making pneumatic rubber cylinders for the machines that replaced the horses we no longer needed to breed. Every AI logo on the t-shirt is a tread pattern drawn by people who do not yet know which century of exoskeleton they are designing for. That beats a PowerPoint ecosystem built around the profitability question, and it is the bet I would rather be inside of when the trough arrives.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The code is at &lt;a href=&quot;https://github.com/whatnick/ai_logos_shirt&quot;&gt;ai_logos_shirt&lt;/a&gt; – a small Rust crate, MIT licensed, build instructions in the README. Ping me if you have strong opinions about cognitive atrophy, the Sequoia revenue gap, or split-toe rubber footwear.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/1971538342557153861/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/1971538342557153861' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1971538342557153861'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1971538342557153861'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/05/we-dont-have-hooves-ai-logos-cognitive.html' title='We Don&#39;t Have Hooves: AI Logos, Cognitive Shedding, and the Exoskeleton Economy'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-2237937563532444494</id><published>2026-05-23T16:30:00.000-07:00</published><updated>2026-05-24T02:00:35.478-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="agents"/><category scheme="http://www.blogger.com/atom/ns#" term="digital-atlas-australia"/><category scheme="http://www.blogger.com/atom/ns#" term="enterprise-ai"/><category scheme="http://www.blogger.com/atom/ns#" term="gazetteer"/><category scheme="http://www.blogger.com/atom/ns#" term="geocoding"/><category scheme="http://www.blogger.com/atom/ns#" term="geospatial"/><category scheme="http://www.blogger.com/atom/ns#" term="mcp"/><title type='text'>From Digital Atlas to Gazet: Building a Geospatial Agent Stack for Enterprise AI</title><content type='html'>&lt;p&gt;The same thought keeps coming back whenever I look at geospatial AI: too much useful work is still trapped in slow, manual interfaces.&lt;/p&gt;
&lt;p&gt;Someone opens a portal, clicks through search forms, downloads files, copies a bounding box, jumps to a geocoder, then checks an internal approvals tool. None of this is mysterious; it is just fragmented.&lt;/p&gt;
&lt;p&gt;That is why MCP matters here. Not because every problem needs another chatbot, but because a composed agent stack can turn UI choreography into a question, a traceable tool chain, and a defensible answer.&lt;/p&gt;
&lt;p&gt;The shape of that stack is getting clearer:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;A discovery layer for authoritative datasets and services.&lt;/li&gt;
&lt;li&gt;A place-resolution layer for turning ambiguous human geography into valid geometry.&lt;/li&gt;
&lt;li&gt;A retrieval and processing layer for actual data operations.&lt;/li&gt;
&lt;li&gt;A governance layer so this can survive contact with enterprise reality.&lt;/li&gt;
&lt;li&gt;An orchestration layer that routes work to the right model and the right tool at the right time.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;themes-carried-from-the-earlier-linkedin-post&quot;&gt;Themes carried from the earlier LinkedIn post&lt;/h2&gt;
&lt;p&gt;The LinkedIn thread that led to this draft had four recurring ideas, and they still hold:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Most geospatial AI pain is not in model quality. It is in UI choreography.&lt;/li&gt;
&lt;li&gt;Narrow components with explicit contracts beat one giant, vague “do-everything” agent.&lt;/li&gt;
&lt;li&gt;Portals are temporary. Durable value sits in services, workflows, and evidence trails.&lt;/li&gt;
&lt;li&gt;The end state is not one-shot answers. It is persistent monitoring plus governed recomputation.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This post extends those ideas with concrete stack boundaries, standards, and orchestration patterns.&lt;/p&gt;
&lt;h2 id=&quot;digital-atlas-of-australia-as-the-discovery-layer&quot;&gt;Digital Atlas of Australia as the discovery layer&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://github.com/whatnick/daa_mcp&quot;&gt;&lt;code&gt;daa_mcp&lt;/code&gt;&lt;/a&gt;, I wrapped the Digital Atlas of Australia search API as a Go MCP server. The target is the Digital Atlas endpoint at &lt;code&gt;https://digital.atlas.gov.au/api/search/v1&lt;/code&gt;, with a very narrow tool surface:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;atlas_list_collections&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;atlas_search_items&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;atlas_answer_query&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That narrowness is deliberate. Discovery tools should be boring, explicit, and provenance-heavy. If an agent cannot reliably name the dataset, map, or document it found, and where it came from, it should not improvise higher-order spatial reasoning.&lt;/p&gt;
&lt;p&gt;This is the first important pattern for enterprise AI engineering: do not ask the model to remember the catalog. Ask the catalog.&lt;/p&gt;
&lt;p&gt;In practice, a user should be able to ask “what hazard datasets are relevant around this place?” and get source URLs, approximate bounds, and the inventory used to produce the answer. That alone is a major improvement over portal-clicking.&lt;/p&gt;
&lt;h2 id=&quot;devseeds-gazet-is-the-missing-place-resolution-layer&quot;&gt;DevSeed’s Gazet is the missing place-resolution layer&lt;/h2&gt;
&lt;p&gt;The more interesting development lately is not another catalog wrapper. It is the rise of narrower geospatial AI components that do one thing well.&lt;/p&gt;
&lt;p&gt;Development Seed’s &lt;a href=&quot;https://github.com/developmentseed/gazet&quot;&gt;Gazet&lt;/a&gt; is a very good example. It is a lightweight natural-language geocoder and GIS operations system over Overture and Natural Earth parquet datasets. The point is not to sound impressive. The point is to turn a phrase like “the northern half of India” or “districts along the Ganges” into valid geometry and spatial SQL.&lt;/p&gt;
&lt;p&gt;That matters because geospatial systems usually break before the raster math starts. They break at the human-language boundary: fuzzy place names, overlapping regions, ambiguous jurisdictions, rivers that matter politically but not administratively, borders people describe one way and datasets encode another.&lt;/p&gt;
&lt;p&gt;DevSeed’s public write-up on Gazet is refreshing because it avoids frontier-model mysticism. They fine-tuned a Qwen 3.5 0.8B model, generated around 70k validated training pairs, and built a system that runs on CPU, packages into a single container, and emits valid geometry. The model card shows an 812 MB Q8 GGUF artifact. That is software engineering.&lt;/p&gt;
&lt;p&gt;The surrounding design is exactly the structure geospatial AI needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fuzzy candidate search against Overture divisions and Natural Earth&lt;/li&gt;
&lt;li&gt;DuckDB-backed in-memory spatial SQL&lt;/li&gt;
&lt;li&gt;GeoJSON output rather than vague textual summaries&lt;/li&gt;
&lt;li&gt;a path toward execution-feedback loops and CodeAct-style tool use&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gazet is not an MCP server today, but it is exactly the kind of component that should sit behind one. A Digital Atlas MCP answers “what data exists?”. A Gazet-style place tool answers “what geometry did the user mean?”. Keeping those jobs separate reduces hallucination at both layers.&lt;/p&gt;
&lt;h2 id=&quot;skills-and-mcps-are-complementary-not-interchangeable&quot;&gt;Skills and MCPs are complementary, not interchangeable&lt;/h2&gt;
&lt;p&gt;Development Seed’s public &lt;a href=&quot;https://github.com/developmentseed/skills&quot;&gt;skills repository&lt;/a&gt; reinforces the same architectural idea from another angle. Skills package workflow knowledge and output structure; MCP servers package live tool access.&lt;/p&gt;
&lt;p&gt;That distinction matters. A skill can tell an agent how to build a VEDA story, export an issue to markdown, or set up a Python repo. An MCP server lets that same agent call live APIs, inspect datasets, or resolve fresh operational context.&lt;/p&gt;
&lt;p&gt;Enterprise AI work needs both. One gives you procedure. The other gives you reach.&lt;/p&gt;
&lt;h2 id=&quot;stac-gdal-and-the-rest-of-the-operational-path&quot;&gt;STAC, GDAL, and the rest of the operational path&lt;/h2&gt;
&lt;p&gt;Once discovery and place resolution are handled, the rest of the geospatial chain looks familiar again.&lt;/p&gt;
&lt;p&gt;STAC remains the right interoperability layer for item and asset selection. GDAL, QGIS-style tooling, OSM connectors, Earthdata accessors, and similar MCPs remain the right place for the sharp-edged operational work: clipping, reprojection, vector joins, raster access, metadata inspection, and export.&lt;/p&gt;
&lt;p&gt;This is why I still do not buy the idea of a single universal geospatial MCP. Real systems are layered:&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 33%&quot; /&gt;
&lt;col style=&quot;width: 33%&quot; /&gt;
&lt;col style=&quot;width: 33%&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Discovery&lt;/td&gt;
&lt;td&gt;Find authoritative datasets, maps, and documents&lt;/td&gt;
&lt;td&gt;&lt;code&gt;daa_mcp&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Place resolution&lt;/td&gt;
&lt;td&gt;Turn language into geometry&lt;/td&gt;
&lt;td&gt;Gazet-style geocoder / gazetteer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Catalog handoff&lt;/td&gt;
&lt;td&gt;Resolve items and assets&lt;/td&gt;
&lt;td&gt;STAC MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Workflow orchestration&lt;/td&gt;
&lt;td&gt;Schedule and monitor long-running jobs&lt;/td&gt;
&lt;td&gt;Argo Workflows via MCP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Spatial compute&lt;/td&gt;
&lt;td&gt;Transform and analyze data&lt;/td&gt;
&lt;td&gt;GDAL / QGIS / OSM style MCPs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Presentation&lt;/td&gt;
&lt;td&gt;Package outputs for humans&lt;/td&gt;
&lt;td&gt;VEDA-style skills, notebooks, apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The protocol is the plumbing. The quality comes from giving each part of the stack a narrow responsibility.&lt;/p&gt;
&lt;p&gt;This is the same systems lesson in geospatial form: trying to make one component do discovery, place semantics, heavy compute, and governance usually creates brittle architecture. Small explicit layers look less magical, but they survive production.&lt;/p&gt;
&lt;h2 id=&quot;eo-processing-standards-are-now-part-of-the-same-stack&quot;&gt;EO processing standards are now part of the same stack&lt;/h2&gt;
&lt;p&gt;This is where real operations begin. Once a question needs heavy lifting, you need a standards-aligned processing path, not just another API call.&lt;/p&gt;
&lt;p&gt;I think of it as three aligned pieces:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;eoAPI as the service substrate (STAC, tiles, PostGIS-adjacent query surfaces)&lt;/li&gt;
&lt;li&gt;openEO UDFs for custom analysis logic that does not fit built-in processes&lt;/li&gt;
&lt;li&gt;OGC API - Processes as a portable execution contract for geospatial jobs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This matters because of execution portability, not standards purity. If a workflow is represented through openEO process graphs, UDF hooks, and OGC process semantics, you are no longer trapped in one vendor UI or one internal notebook convention.&lt;/p&gt;
&lt;p&gt;The openEO side is especially useful because it is explicit about chunked execution and long-running back-end jobs. &lt;code&gt;run_udf&lt;/code&gt; and related process patterns (&lt;code&gt;apply_dimension&lt;/code&gt;, &lt;code&gt;apply_neighborhood&lt;/code&gt;, &lt;code&gt;reduce_dimension&lt;/code&gt;) are built for data-cube scale operations where synchronous request/response is the wrong abstraction.&lt;/p&gt;
&lt;p&gt;OGC API - Processes complements this by giving a common HTTP interface for process descriptions, inputs, execution, and result retrieval. That is the bridge between geospatial compute and enterprise service design: you can expose processing as a governed capability, not just a script somebody knows how to run.&lt;/p&gt;
&lt;p&gt;eoAPI then provides a practical packaging layer around STAC-first infrastructure (pgSTAC, stac-fastapi, titiler-pgstac, tipg). Data discovery and data services stay first-class while compute orchestration grows around them.&lt;/p&gt;
&lt;h2 id=&quot;long-running-analysis-needs-workflow-orchestration-not-prompt-retries&quot;&gt;Long-running analysis needs workflow orchestration, not prompt retries&lt;/h2&gt;
&lt;p&gt;When EO analysis becomes asynchronous (tiling, temporal composites, model inference over large extents, zonal stats at scale), agent architecture must move from “call tool, get answer” to “submit job, monitor, collect artifacts, summarize result”.&lt;/p&gt;
&lt;p&gt;This is exactly where Argo Workflows patterns fit, and why Argo-flavored MCP servers are interesting. The MCP Market Argo server by &lt;code&gt;jakkaj&lt;/code&gt; exposes workflow submission/status/result retrieval through JSON-RPC. That maps naturally to agent behavior:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;build a workflow payload from resolved geometry + selected assets&lt;/li&gt;
&lt;li&gt;submit to workflow engine&lt;/li&gt;
&lt;li&gt;poll status with bounded retries and timeout policy&lt;/li&gt;
&lt;li&gt;fetch outputs and register artifact locations&lt;/li&gt;
&lt;li&gt;return a grounded summary with links to outputs and provenance&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Critically, outputs here are not only text. They can be Cloud Optimized GeoTIFFs, STAC Items, GeoParquet extracts, vector tiles, QA reports, or model feature embeddings. For geospatial agents, the right response class is generated artifacts plus explainable metadata, not just a paragraph.&lt;/p&gt;
&lt;p&gt;If you combine this with gateway policy (auth, quotas, audit) and model routing, you end up with a more durable operating model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;language models interpret intent and coordinate tools&lt;/li&gt;
&lt;li&gt;workflow systems execute expensive, long-running spatial jobs&lt;/li&gt;
&lt;li&gt;standards-based APIs keep outputs portable across teams and platforms&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is much closer to “EO production system” than “chatbot with map screenshots”.&lt;/p&gt;
&lt;h2 id=&quot;why-enterprises-should-care-this-is-really-about-ui-replacement&quot;&gt;Why enterprises should care: this is really about UI replacement&lt;/h2&gt;
&lt;p&gt;The bigger opportunity is not just geospatial search. It is enterprise task conversion.&lt;/p&gt;
&lt;p&gt;Most corporate and government knowledge work still lives in forms, portals, dashboards, policy systems, and browser tabs. Much of it is manual API orchestration done by humans through UIs.&lt;/p&gt;
&lt;p&gt;We should be blunt about portal economics. Most are disposable visual sales tools, one level up from a PowerPoint deck. They are useful while an initiative is being socialized or funded, but once that phase passes, maintenance becomes hard to justify.&lt;/p&gt;
&lt;p&gt;The exception is when the interface itself is the monetized product. If the UI is a booking or experience engine, like Airbnb, Uber, or Netflix, the interface is the business and ongoing investment is obvious. If it is only a discovery surface, the long-term value is usually in the underlying services and automations, not the glossy front end.&lt;/p&gt;
&lt;p&gt;That is where agent stacks become interesting: not “replace staff with a bot”, but “replace repetitive navigation with question answering backed by orchestrated tools”.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use a Digital Atlas MCP to find relevant public datasets&lt;/li&gt;
&lt;li&gt;use a Gazet-style tool to resolve the place phrase into geometry&lt;/li&gt;
&lt;li&gt;use STAC or downstream data APIs to locate assets&lt;/li&gt;
&lt;li&gt;use GDAL or analytics tools to extract what matters&lt;/li&gt;
&lt;li&gt;use an internal engineering or policy system to fetch approvals, tickets, or previous decisions&lt;/li&gt;
&lt;li&gt;return one answer with links, bounds, intermediate evidence, and the exact tools invoked&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is a much more defensible enterprise AI story than a generic assistant sitting on top of a screen scraper.&lt;/p&gt;
&lt;h2 id=&quot;the-enterprise-layer-above-the-tools-gateway-patterns&quot;&gt;The enterprise layer above the tools: gateway patterns&lt;/h2&gt;
&lt;p&gt;Of course, the moment you try to productionize this, you run into the boring parts that actually matter: auth, quotas, observability, data leakage, audit, policy, and cost.&lt;/p&gt;
&lt;p&gt;At that point, the conversation should move from product selection to gateway patterns. Martin Fowler’s gateway pattern framing is useful because it centers controlled mediation between clients and backend capabilities, which maps directly onto agent-to-tool and agent-to-service boundaries.&lt;/p&gt;
&lt;p&gt;The first pattern is identity mediation. Agent calls need to carry a clear identity boundary between user, agent, and downstream systems, with policy checks at each boundary.&lt;/p&gt;
&lt;p&gt;The second pattern is protocol normalization. Teams will mix chat payloads, tool calls, MCP traffic, and legacy APIs. The gateway has to normalize those flows so routing and controls are consistent.&lt;/p&gt;
&lt;p&gt;The third pattern is cost and budget governance. Token and request spend cannot be an afterthought. Per-key, per-team, and per-tier budgets need to be enforceable in the traffic path, not in a monthly spreadsheet.&lt;/p&gt;
&lt;p&gt;The fourth pattern is safety policy composition. Guardrails are rarely one thing. In practice you need layered controls: authentication, content moderation, prompt-injection checks, data-loss prevention, and explicit deny behavior.&lt;/p&gt;
&lt;p&gt;The fifth pattern is telemetry with replayable evidence. A useful gateway record is not just “request succeeded”. It is who called what, with which policy version, routed to which provider or tool, at what cost, with what outcome.&lt;/p&gt;
&lt;p&gt;I still mention Kong mainly as a signal of category maturity, not as a single implementation path. The same pattern language also shows up in Otoroshi’s AI gateway model: provider abstraction, OpenAI-compatible route surfaces, API-key enforcement, metadata-driven budgets, moderation and regex guardrails, plus extension-based control points.&lt;/p&gt;
&lt;p&gt;Whether a team uses Kong, Otoroshi, or another gateway stack is less important than whether these patterns are explicit. Enterprises want MCPs and agent flows, but they need them behind durable control planes instead of scattered sidecars with weak visibility.&lt;/p&gt;
&lt;p&gt;Once agents start calling internal systems, this layer becomes unavoidable. Someone will want to know who called what, with which identity, against which policy, and how many tokens or requests that answer burned to produce.&lt;/p&gt;
&lt;h2 id=&quot;small-models-are-not-a-concession-they-are-often-the-right-architecture&quot;&gt;Small models are not a concession, they are often the right architecture&lt;/h2&gt;
&lt;p&gt;The other part of this conversation that is becoming more honest is model size.&lt;/p&gt;
&lt;p&gt;Development Seed’s Gazet makes the point very clearly: many geospatial tasks are structured enough that a small model, grounded to the right schema and surrounded with the right tooling, is better engineering than throwing a giant model at the problem.&lt;/p&gt;
&lt;p&gt;That also lines up with what NVIDIA has been highlighting around agentic workloads. Their recent MiniMax M2.7 material is not about a universal oracle; it is about efficient agentic harnesses, tool calling, and orchestration-friendly serving with explicit tool-call parsers, auto-tool-choice, and a runtime story through vLLM, SGLang, NIM, and NemoClaw.&lt;/p&gt;
&lt;p&gt;MiniMax M2.7 is not “small” in total parameter count, but it is architected in the direction the market is moving: sparse activation, efficient serving, orchestration hooks, and infrastructure that treats tools as first-class. The important lesson is not the specific model; it is the pattern.&lt;/p&gt;
&lt;p&gt;The pattern looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;small or moderate specialist models where the task is structured&lt;/li&gt;
&lt;li&gt;larger reasoning models only where the ambiguity genuinely demands them&lt;/li&gt;
&lt;li&gt;explicit tool routing rather than one giant model pretending to be every subsystem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For geospatial and enterprise workflows, that is just common sense.&lt;/p&gt;
&lt;h2 id=&quot;the-real-end-state&quot;&gt;The real end state&lt;/h2&gt;
&lt;p&gt;The end state here is not “chat with your maps”.&lt;/p&gt;
&lt;p&gt;It is something more useful:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;take a question expressed in normal language&lt;/li&gt;
&lt;li&gt;resolve the place semantics properly&lt;/li&gt;
&lt;li&gt;discover the authoritative data sources&lt;/li&gt;
&lt;li&gt;retrieve or compute what is needed, including expensive long-running analytics when required&lt;/li&gt;
&lt;li&gt;enforce enterprise controls on the path&lt;/li&gt;
&lt;li&gt;return an answer that is fast, inspectable, and grounded in tools&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Beyond one-shot questions, run persistent agents that watch for change over time. For hazard operations, that means continuously tracking weather, flood signals, fire risk, and related event streams, then escalating when deviation from steady state crosses defined thresholds.&lt;/p&gt;
&lt;p&gt;The same pattern applies to slower domains such as seasonal wheat growth. A persistent agent should infer baseline behavior from historical and current EO catalogs, run heavy analysis when confidence drops, and react when observed trajectories diverge from expected seasonal dynamics.&lt;/p&gt;
&lt;p&gt;This is where long-running workflows and persistent agents work together: the workflow engine handles expensive catalog-scale computation, while the agent handles temporal monitoring, trigger logic, and action routing.&lt;/p&gt;
&lt;p&gt;That operational loop was the key point in the earlier LinkedIn post, and it is worth repeating: in enterprise geospatial systems, value compounds when agents watch state over time and selectively escalate computation, not when they generate one more static summary.&lt;/p&gt;
&lt;p&gt;That is what turns manual UI work into operational question answering.&lt;/p&gt;
&lt;p&gt;For geospatial work, it means less tab-hopping and more reproducible spatial reasoning. For enterprise AI more broadly, it means agents stop being a decorative chat layer and start looking more like a disciplined API and workflow orchestration fabric.&lt;/p&gt;
&lt;p&gt;Better than another dashboard, frankly.&lt;/p&gt;
&lt;p&gt;If you are building in this direction, the interesting design questions are no longer “which model is smartest?” They are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;where should discovery stop and reasoning begin?&lt;/li&gt;
&lt;li&gt;which place-resolution tasks deserve their own narrow model?&lt;/li&gt;
&lt;li&gt;which tools should be exposed directly as MCPs versus hidden behind workflow skills?&lt;/li&gt;
&lt;li&gt;what sits at the gateway for auth, quotas, audit, and A2A telemetry?&lt;/li&gt;
&lt;li&gt;which monitoring loops should run continuously, and what deviations should trigger expensive recomputation or human escalation?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is engineering, not theatre.&lt;/p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;DAA MCP repo: &lt;a href=&quot;https://github.com/whatnick/daa_mcp&quot;&gt;https://github.com/whatnick/daa_mcp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Development Seed Gazet blog: &lt;a href=&quot;https://developmentseed.org/blog/2026-04-29-gazet/&quot;&gt;https://developmentseed.org/blog/2026-04-29-gazet/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Development Seed Gazet repo: &lt;a href=&quot;https://github.com/developmentseed/gazet&quot;&gt;https://github.com/developmentseed/gazet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Development Seed Gazet model: &lt;a href=&quot;https://huggingface.co/developmentseed/gazet-model&quot;&gt;https://huggingface.co/developmentseed/gazet-model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Development Seed skills repo: &lt;a href=&quot;https://github.com/developmentseed/skills&quot;&gt;https://github.com/developmentseed/skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Development Seed skills directory: &lt;a href=&quot;https://github.com/developmentseed/skills/tree/main/skills&quot;&gt;https://github.com/developmentseed/skills/tree/main/skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Kong AI Gateway: &lt;a href=&quot;https://konghq.com/products/kong-ai-gateway&quot;&gt;https://konghq.com/products/kong-ai-gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Otoroshi AI gateway tutorial: &lt;a href=&quot;https://www.otoroshi.io/docs/tutorials/setup-ai-gateway-with-otoroshictl?_highlight=ai&quot;&gt;https://www.otoroshi.io/docs/tutorials/setup-ai-gateway-with-otoroshictl?_highlight=ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Otoroshi AI gateway topic: &lt;a href=&quot;https://www.otoroshi.io/docs/topics/ai-gateway&quot;&gt;https://www.otoroshi.io/docs/topics/ai-gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Martin Fowler, gateway pattern: &lt;a href=&quot;https://martinfowler.com/articles/gateway-pattern.html&quot;&gt;https://martinfowler.com/articles/gateway-pattern.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Geospatial MCP search: &lt;a href=&quot;https://mcpmarket.com/search?q=Geospatial&quot;&gt;https://mcpmarket.com/search?q=Geospatial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;eoAPI: &lt;a href=&quot;https://eoapi.dev&quot;&gt;https://eoapi.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OGC API - Processes overview: &lt;a href=&quot;https://ogcapi.ogc.org/processes/&quot;&gt;https://ogcapi.ogc.org/processes/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;openEO UDFs: &lt;a href=&quot;https://openeo.org/documentation/1.0/udfs.html&quot;&gt;https://openeo.org/documentation/1.0/udfs.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;openEO process definitions (&lt;code&gt;run_udf&lt;/code&gt;, &lt;code&gt;run_ogcapi&lt;/code&gt;, etc.): &lt;a href=&quot;https://processes.openeo.org/&quot;&gt;https://processes.openeo.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Argo Workflows docs: &lt;a href=&quot;https://argo-workflows.readthedocs.io/en/latest/&quot;&gt;https://argo-workflows.readthedocs.io/en/latest/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Argo MCP listing (&lt;code&gt;jakkaj/mcp-argo-server&lt;/code&gt;): &lt;a href=&quot;https://mcpmarket.com/server/argo&quot;&gt;https://mcpmarket.com/server/argo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;NVIDIA MiniMax M2.7 agentic workflows: &lt;a href=&quot;https://developer.nvidia.com/blog/minimax-m2-7-advances-scalable-agentic-workflows-on-nvidia-platforms-for-complex-ai-applications/&quot;&gt;https://developer.nvidia.com/blog/minimax-m2-7-advances-scalable-agentic-workflows-on-nvidia-platforms-for-complex-ai-applications/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;STAC MCP listing: &lt;a href=&quot;https://mcpmarket.com/server/stac&quot;&gt;https://mcpmarket.com/server/stac&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/2237937563532444494/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/2237937563532444494' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2237937563532444494'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2237937563532444494'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/05/from-digital-atlas-to-gazet-building.html' title='From Digital Atlas to Gazet: Building a Geospatial Agent Stack for Enterprise AI'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-1512784206937436262</id><published>2026-05-13T17:00:00.000-07:00</published><updated>2026-05-17T07:33:32.406-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ade9000"/><category scheme="http://www.blogger.com/atom/ns#" term="ai"/><category scheme="http://www.blogger.com/atom/ns#" term="autorouter"/><category scheme="http://www.blogger.com/atom/ns#" term="electronics"/><category scheme="http://www.blogger.com/atom/ns#" term="energy-monitoring"/><category scheme="http://www.blogger.com/atom/ns#" term="kicad"/><category scheme="http://www.blogger.com/atom/ns#" term="pcb-design"/><title type='text'>AI-assisted PCB design for energy monitoring (and scaling up don&#39;t trust the autorouter)</title><content type='html'>&lt;p&gt;There is a specific smell to late-stage PCB work. A mix of coffee, solder mask anxiety, and the faint optimism that one more route pass will magically make analog behave. The poking around with oscilloscope probes and poring at datasheets to find out that you failed to pull reset low, out comes the magnet wires for a bodge.&lt;/p&gt;
&lt;p&gt;Over the last week I have been building out an ADE9000 breakout with an AI-assisted workflow wrapped around KiCAD scripting. The results are useful, occasionally impressive, and still very far from “hands-off” for precision energy monitoring.&lt;/p&gt;
&lt;p&gt;If you grew up with “don’t trust the autorouter” as muscle memory, good news: the saying still holds. We just scaled the blast radius from one menu click to an entire AI pipeline.&lt;/p&gt;
&lt;p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/whatnick/ADE9000_Breakout/main/docs/images/ai_aided_kicad.png&quot; alt=&quot;AI-aided KiCad schematic work in VS Code and KiCad&quot; /&gt;
&lt;/p&gt;
&lt;h2 id=&quot;what-changed-on-the-board-not-just-on-a-slide-deck&quot;&gt;What changed on the board, not just on a slide deck&lt;/h2&gt;
&lt;p&gt;The recent commit sequence in &lt;a href=&quot;https://github.com/whatnick/ADE9000_Breakout&quot;&gt;ADE9000_Breakout&lt;/a&gt; tells the story better than any marketing copy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;d1e3352 (2026-05-07): “Initial AI Creation”&lt;/li&gt;
&lt;li&gt;043161c (2026-05-08): “Complete routing”&lt;/li&gt;
&lt;li&gt;b8c8132 (2026-05-09): “Reroute with JST connector for SPI”&lt;/li&gt;
&lt;li&gt;a469246 (2026-05-09): “Move decoupling closer”&lt;/li&gt;
&lt;li&gt;84b86e7 (2026-05-12): “Relayout using connectors for analog inputs”&lt;/li&gt;
&lt;li&gt;7d4b420 (2026-05-16): “Rerouted with Groundplanes and new skills”&lt;/li&gt;
&lt;li&gt;c40e40a (2026-05-16): “Added License”&lt;/li&gt;
&lt;li&gt;9b2d97e (2026-05-17): “Add project-local 3D CAD assets”&lt;/li&gt;
&lt;li&gt;cf8ba2c (2026-05-17): “Fix CT jack STEP orientation”&lt;/li&gt;
&lt;li&gt;f5a11b2 (2026-05-17): “Remove CT jack pad overlays”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was not a single-shot generation. It was iterative engineering with scripting and machine assistance in the loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Placement and connector mapping in scripts like &lt;code&gt;place_pcb.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Deterministic route passes in &lt;code&gt;route_pcb.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Critical route seeding and patching in &lt;code&gt;seed_critical_routes.py&lt;/code&gt; and &lt;code&gt;patch_remaining_routes.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mechanical/silk cleanup with &lt;code&gt;apply_board_markings.py&lt;/code&gt; and &lt;code&gt;move_refs_to_silkscreen.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Continuous ERC/DRC artifacts (&lt;code&gt;erc.json&lt;/code&gt;, &lt;code&gt;drc.json&lt;/code&gt;) committed as hard checkpoints.&lt;/li&gt;
&lt;li&gt;3D STEP model handling pushed into the reusable layout and size-shape skills so mechanical review can keep pace with PCB edits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/whatnick/ADE9000_Breakout/main/docs/images/ai_aided_pcb.png&quot; alt=&quot;AI-aided ADE9000 PCB layout in KiCad&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;That pattern matters. The AI and automation stack gave speed and repeatability, but the engineering value came from repeated correction passes driven by board physics.&lt;/p&gt;
&lt;p&gt;The same iteration loop is now visible in &lt;a href=&quot;https://github.com/whatnick/whatnick-energy-monitor-skills&quot;&gt;whatnick-energy-monitor-skills&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;335a718 (2026-05-16): Initial whatnick energy monitor skills&lt;/li&gt;
&lt;li&gt;78bfc44 (2026-05-17): Document STEP model workflow&lt;/li&gt;
&lt;li&gt;79d925d (2026-05-17): Clarify connector STEP model matching&lt;/li&gt;
&lt;li&gt;af57c2d (2026-05-17): Document connector CAD alignment workflow&lt;/li&gt;
&lt;li&gt;32adeff (2026-05-17): Correct ADE9000 jack CAD guidance&lt;/li&gt;
&lt;li&gt;d4167f6 (2026-05-17): Remove ADE9000 jack overlay guidance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That repo now captures reusable circuit, layout, routing, and board-shape guidance, plus the ADE9000 project overlay. The 3D model side was not a first-pass success either. STEP exports and connector models took multiple iterations before the project-local paths, model matching, and export workflow were stable enough to trust in a mechanical review. The later commits are the best evidence: first add local CAD assets, then discover the CT jack STEP orientation is wrong, then remove pad overlays that made the model look plausible while hiding the fact that the footprint and mechanical story needed to line up properly.&lt;/p&gt;
&lt;p&gt;This is where AI-assisted hardware feels different from AI-assisted code. In software, a bad abstraction usually fails in tests or production logs. In PCB work, a bad abstraction can become a connector body floating neatly above the wrong pads in the 3D viewer. It looks professional right up until the part, enclosure, or cable says otherwise.&lt;/p&gt;
&lt;p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/whatnick/ADE9000_Breakout/main/docs/images/pivot_to_larger_board.png&quot; alt=&quot;Pivoting the ADE9000 board toward the larger analog-connector layout&quot; /&gt;
&lt;/p&gt;
&lt;h2 id=&quot;notebooklm-research-good-at-methodology-weaker-on-analog-edge-cases&quot;&gt;NotebookLM research: good at methodology, weaker on analog edge cases&lt;/h2&gt;
&lt;p&gt;I started on this adventure with posts from Samuel Beek promoting AI PCB design. I blended in my research background and curated a set of academic papers on AI/Algorithm usage in PCB place-n-route. I queried my pre-created NotebookLM notebook “PCB Place and Route Algorithms” specifically for mixed-signal energy-monitoring constraints.&lt;/p&gt;
&lt;p&gt;The useful part of that synthesis:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Current AI placement/routing research still optimizes mostly for geometric proxies (wirelength, overlap, congestion).&lt;/li&gt;
&lt;li&gt;Newer approaches improve constraint capture and collaboration, but are explicitly human-in-the-loop.&lt;/li&gt;
&lt;li&gt;Model quality degrades on low-frequency pattern classes and novel interface combinations (cold-start behavior).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The important caveat from the same query was even more telling: source coverage was strong on AI placement methodology, but thinner on precision metering specifics like safety creepage strategy, return-current choreography around split references, and “what actually ruins ENOB on a real board at 2am”.&lt;/p&gt;
&lt;p&gt;That gap is exactly the point.&lt;/p&gt;
&lt;h2 id=&quot;schematik-snapmagic-and-the-new-hardware-workflow-stack&quot;&gt;Schematik, SnapMagic, and the new hardware workflow stack&lt;/h2&gt;
&lt;p&gt;Samuel Beek’s &lt;a href=&quot;https://news-factory.app/news/schematik-raises-dollar46-million-to-turn-ai-into-a-cursor-for-hardware&quot;&gt;Schematik&lt;/a&gt; story is almost too perfect as an origin myth for this moment. An AI-generated wiring guide for a home-grown door opener took out the fuses in his apartment, which is a fairly direct way for physics to reject your prompt. Schematik has since raised $4.6 million from Lightspeed Venture Partners and is positioning itself as a “Cursor for Hardware”: describe a device in plain language, get a bill of materials, purchase links, and assembly instructions.&lt;/p&gt;
&lt;p&gt;The interesting engineering choice is the safety boundary. Schematik is deliberately aiming at low-voltage circuits, typically 3-5 V IoT and maker projects, because that is where the promise is large and the downside can still be bounded. That is a sensible line. It is also a reminder that “AI for hardware” is not one market. The assistant that helps someone build an MP3 player is not the same system I would trust near mains metering, isolated sensing, or a DIN rail enclosure without a lot more constraint machinery around it.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.snapmagic.com/&quot;&gt;SnapMagic&lt;/a&gt; is attacking a nearby but different layer of the stack. Its pitch is an AI copilot for electronics design, built on the huge CAD model base that started as SnapEDA: symbols, footprints, 3D models, part discovery, BOM optimization, supply-chain substitution, and integration with existing EDA tools including KiCad. That matters because a surprising amount of PCB time is not heroic analog insight; it is finding the right model, importing it cleanly, checking whether the footprint is sane, and making sure the thing still exists at Mouser or Digi-Key.&lt;/p&gt;
&lt;p&gt;Schematik is closer to natural-language project generation. SnapMagic is closer to CAD-data and component-selection acceleration. My little ADE9000 workflow sits in the garage between them: NotebookLM for research synthesis, KiCad Python for deterministic changes, Freerouting for a first pass, project-local skills for repeatable domain knowledge, and human review for the parts that still smell like physics.&lt;/p&gt;
&lt;p&gt;That is the practical opening for individual designers. You do not need to wait for one perfect vendor platform. You can build a small, opinionated workflow from pieces you already control:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Put your design rules and recurring board-family choices into a local skill or checklist.&lt;/li&gt;
&lt;li&gt;Use AI for datasheet digestion, net naming, script generation, and alternative exploration.&lt;/li&gt;
&lt;li&gt;Keep KiCad, ERC, DRC, STEP export, and git history as the accountability layer.&lt;/li&gt;
&lt;li&gt;Treat external libraries like SnapMagic/SnapEDA as accelerators, then verify footprints, symbols, pin numbers, and 3D models against datasheets and mechanical reality.&lt;/li&gt;
&lt;li&gt;Let autorouters and AI propose routes, but hand-check return currents, decoupling loops, creepage, clocks, testability, and enclosure fit.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That sounds less magical than “hardware Cursor”, but it is much closer to how individual designers can safely get leverage today.&lt;/p&gt;
&lt;h2 id=&quot;why-this-hurts-more-on-energy-monitoring-boards&quot;&gt;Why this hurts more on energy monitoring boards&lt;/h2&gt;
&lt;p&gt;An ADE9000-style board is not just “digital plus some analog”. It is a negotiated peace treaty between:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tiny differential analog signals,&lt;/li&gt;
&lt;li&gt;noisy clocks and digital SPI edges,&lt;/li&gt;
&lt;li&gt;shared ground structures,&lt;/li&gt;
&lt;li&gt;high-voltage interfacing constraints,&lt;/li&gt;
&lt;li&gt;and assembly realities.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can route what it can score. Physics punishes what you forgot to score.&lt;/p&gt;
&lt;p&gt;For energy monitoring, the failure modes are often subtle first and expensive later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A seemingly short route with a terrible return path becomes an EMI antenna.&lt;/li&gt;
&lt;li&gt;“Close enough” decoupling in XY turns into high loop inductance in 3D.&lt;/li&gt;
&lt;li&gt;Digital fanout convenience leaks noise into the measurement front end.&lt;/li&gt;
&lt;li&gt;Clearance passes in one view while creepage silently fails along real surfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-scaled-up-autorouter-adage&quot;&gt;The scaled-up autorouter adage&lt;/h2&gt;
&lt;p&gt;Classic autorouter distrust was about ugly traces and cleanup effort.&lt;/p&gt;
&lt;p&gt;AI-assisted distrust is about &lt;em&gt;false confidence&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You now get cleaner visuals, plausible routing, and confidence scores. The board can look more “engineered” while still violating analog intent. That is worse than obviously bad output, because it delays the moment when a human gets suspicious.&lt;/p&gt;
&lt;p&gt;In the ADE9000_Breakout commits, that showed up as repeated topology and placement adjustments:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;decoupling moved closer,&lt;/li&gt;
&lt;li&gt;connector strategy revised,&lt;/li&gt;
&lt;li&gt;critical nets explicitly seeded,&lt;/li&gt;
&lt;li&gt;remaining logical gaps patched after freeroute import,&lt;/li&gt;
&lt;li&gt;then relayout for analog input connector realism.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
&lt;img src=&quot;https://raw.githubusercontent.com/whatnick/ADE9000_Breakout/main/docs/images/pivot_to_inputs_clamp.png&quot; alt=&quot;ADE9000 input clamp and analog connector pivot&quot; /&gt;
&lt;/p&gt;
&lt;p&gt;None of that is anti-AI. It is pro-accountability.&lt;/p&gt;
&lt;h2 id=&quot;a-practical-review-checklist-i-now-treat-as-mandatory&quot;&gt;A practical review checklist I now treat as mandatory&lt;/h2&gt;
&lt;p&gt;Before I trust an AI-assisted pass on a precision board, I manually review:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Return current continuity under each critical signal path.&lt;/li&gt;
&lt;li&gt;Analog/digital ground interaction at the exact stitch points, not just net names.&lt;/li&gt;
&lt;li&gt;Decoupling loop geometry (pin, cap, via topology), not just nearest-component distance.&lt;/li&gt;
&lt;li&gt;Clock and fast digital net proximity to high-impedance analog channels.&lt;/li&gt;
&lt;li&gt;Creepage and clearance across real isolation boundaries and along surfaces.&lt;/li&gt;
&lt;li&gt;Testpoint access and assembly risks (reworkability, tombstoning, awkward probe points).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If any of those rely on “the model probably understood that”, I assume it did not.&lt;/p&gt;
&lt;h2 id=&quot;what-ai-is-genuinely-good-for-in-this-workflow&quot;&gt;What AI is genuinely good for in this workflow&lt;/h2&gt;
&lt;p&gt;After using it in anger, the wins are real:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Faster exploration of placement variants.&lt;/li&gt;
&lt;li&gt;Deterministic scriptable edits to keep design intent reproducible.&lt;/li&gt;
&lt;li&gt;Constraint management that catches obvious misses early.&lt;/li&gt;
&lt;li&gt;Better ergonomics for repeated board evolutions.&lt;/li&gt;
&lt;li&gt;Mechanical and export workflows, including STEP models, can be standardized, but they still need several passes to reconcile footprint libraries, connector variants, and CAD export paths.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is similar to CNC in machining. You still need a machinist mindset. You just get to fail faster and with better logs.&lt;/p&gt;
&lt;h2 id=&quot;the-part-that-still-needs-engineers&quot;&gt;The part that still needs engineers&lt;/h2&gt;
&lt;p&gt;The physics does not care whether a trace came from a human, an RL policy, or a nicely branded copilot.&lt;/p&gt;
&lt;p&gt;Energy metering boards live or die on the details that are hardest to encode as generic reward functions. The edge where analog integrity, EMC, and safety overlap is still mostly tacit knowledge earned through measurements, bring-up scars, and post-mortems.&lt;/p&gt;
&lt;p&gt;So yes, use AI aggressively for PCB work. I certainly am.&lt;/p&gt;
&lt;p&gt;Just keep the old sign above the bench.&lt;/p&gt;
&lt;p&gt;Don’t trust the autorouter.&lt;/p&gt;
&lt;p&gt;Now it applies to systems, not just traces.&lt;/p&gt;
&lt;p&gt;If you are building similar mixed-signal boards, I would love to compare review checklists and failure cases that escaped DRC but showed up on the bench.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/1512784206937436262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/1512784206937436262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1512784206937436262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1512784206937436262'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/05/ai-assisted-pcb-design-for-energy.html' title='AI-assisted PCB design for energy monitoring (and scaling up don&#39;t trust the autorouter)'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-5213432990477987567</id><published>2026-05-01T17:00:00.000-07:00</published><updated>2026-05-02T02:24:13.096-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="aluminium"/><category scheme="http://www.blogger.com/atom/ns#" term="australia"/><category scheme="http://www.blogger.com/atom/ns#" term="industrial policy"/><category scheme="http://www.blogger.com/atom/ns#" term="silicon"/><category scheme="http://www.blogger.com/atom/ns#" term="solar"/><title type='text'>Using Aluminium Instead of Carbon to Make Silicon</title><content type='html'>&lt;p&gt;I have been thinking a lot about sovereign capability lately, not in the abstract flag-waving sense, but in the boring physical sense of &lt;strong&gt;what materials sit near each other, what energy sources are nearby, what ports exist, and what loops can actually close&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That line of thought clicked into a more concrete shape after reading the paper &lt;a href=&quot;https://pmc.ncbi.nlm.nih.gov/articles/PMC12442225/&quot;&gt;Carbon-Neutral Silicon via Aluminothermic Reduction? Exploring Industrial Symbiosis through Life Cycle Assessment&lt;/a&gt;, the &lt;a href=&quot;https://www.csiro.au/-/media/Mineral-Resources/Files/Australian-Silicon-Action-Plan/Australian-Silicon-Action-Plan-2.pdf&quot;&gt;Australian Silicon Action Plan&lt;/a&gt;, and then updating &lt;a href=&quot;https://docs.google.com/presentation/d/1VZ_QKO3aC5w3UAulypfcDd6PX8S6y-6UnfMyCCFqjms/edit?slide=id.g3dec81b2c26_0_537#slide=id.g3dec81b2c26_0_537&quot;&gt;my Aluminium + Silicon Sovereign ecosystem slide deck&lt;/a&gt; to reflect it.&lt;/p&gt;
&lt;p&gt;The core idea is simple enough to explain to a high-school chemistry class: we normally reduce quartz to silicon with carbon. What if, in the right industrial setting, we used &lt;strong&gt;aluminium to reduce silicon instead of carbon&lt;/strong&gt;?&lt;/p&gt;
&lt;h2 id=&quot;the-conventional-route-uses-carbon&quot;&gt;The Conventional Route Uses Carbon&lt;/h2&gt;
&lt;p&gt;Silicon does not come out of the ground in neat shiny wafers. It starts as silica or quartz, and the conventional metallurgical route is carbothermic reduction: take quartz, add a carbon source, add a lot of heat, and accept a pile of carbon dioxide as part of the bargain.&lt;/p&gt;
&lt;p&gt;That bargain made sense when the objective function was mostly “make silicon cheaply”. It makes less sense when we also care about carbon intensity, geopolitical fragility, and whether a country with abundant ore, sunshine, and smelting know-how can turn those endowments into a durable manufacturing base.&lt;/p&gt;
&lt;h2 id=&quot;the-alternative-route-uses-aluminium&quot;&gt;The Alternative Route Uses Aluminium&lt;/h2&gt;
&lt;p&gt;The paper explores aluminothermic reduction, using an aluminium source as the reductant material instead of carbon. More specifically, it looks at &lt;strong&gt;aluminium dross&lt;/strong&gt; as an industrial symbiosis input rather than a pristine, purpose-made feedstock. That detail matters. This is not a fantasy process that assumes some magical zero-cost aluminium stream falls from the sky. It starts from a messy industrial byproduct and asks whether a better loop can be built around it.&lt;/p&gt;
&lt;p&gt;The headline result is strong enough to justify attention: the authors find that the aluminothermic route can reduce &lt;strong&gt;global warming impact and cumulative energy demand by up to 80%&lt;/strong&gt; relative to the reference route.&lt;/p&gt;
&lt;p&gt;That is the part that makes you sit up.&lt;/p&gt;
&lt;p&gt;The useful thing about the paper is that it does not stop at the good news. Some impacts get worse, especially if the aluminium scrap would otherwise have displaced something valuable elsewhere, and because this route still needs extra input materials. So this is not free decarbonisation. It is a real industrial trade-off.&lt;/p&gt;
&lt;p&gt;That makes the paper more useful, not less. Serious policy should be built on “this looks promising, but here are the hotspots” rather than on conference-hall hydrogen hallucinations.&lt;/p&gt;
&lt;h2 id=&quot;why-this-starts-to-look-real&quot;&gt;Why This Starts To Look Real&lt;/h2&gt;
&lt;p&gt;In updating that slide deck, I kept coming back to the same question: what happens if you stop treating aluminium, silicon, and solar panels as separate industries?&lt;/p&gt;
&lt;p&gt;That is the framing I find compelling, because it turns this from a chemistry curiosity into an engineering and logistics problem.&lt;/p&gt;
&lt;p&gt;Around 80% of a typical solar panel by mass is aluminium plus silicon. If a country is serious about energy sovereignty, it should be thinking not just about installing more panels, but about building the material loops that sit behind them. Solar farms are not merely generators. They are future material stockpiles sitting in the sun.&lt;/p&gt;
&lt;p&gt;Once you see that, a different policy picture appears:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;quartz becomes not just a mining input but a strategic silicon feedstock.&lt;/li&gt;
&lt;li&gt;bauxite and aluminium refining become adjacent to solar manufacturing rather than unrelated heavy industry.&lt;/li&gt;
&lt;li&gt;end-of-life panels become future reductant, frame stock, and silicon feed instead of landfill problems.&lt;/li&gt;
&lt;li&gt;smelters, ports, and renewable generation start to look like parts of the same machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where aluminium reducing silicon instead of carbon stops being an isolated chemistry trick and starts looking like something you could build an industry around.&lt;/p&gt;
&lt;h2 id=&quot;if-i-had-to-put-pins-on-a-map&quot;&gt;If I Had To Put Pins On A Map&lt;/h2&gt;
&lt;p&gt;The notebook I pulled together on domestic solar manufacturing helped sharpen this. Once you stop talking in continent-sized blobs and start naming actual places, a few candidates jump out.&lt;/p&gt;
&lt;h3 id=&quot;kemerton-and-south-west-wa&quot;&gt;1. Kemerton and south-west WA&lt;/h3&gt;
&lt;p&gt;This is the least speculative option because &lt;a href=&quot;https://apvi.org.au/wp-content/uploads/2024/02/Silicon-to-Solar-Study-Overview-Report_opt.pdf&quot;&gt;Simcoa at Kemerton&lt;/a&gt; already exists and is still Australia’s only operating silicon manufacturer. The &lt;a href=&quot;https://www.csiro.au/-/media/Mineral-Resources/Files/Australian-Silicon-Action-Plan/Australian-Silicon-Action-Plan-2.pdf&quot;&gt;Silicon Action Plan&lt;/a&gt; notes Simcoa is producing about 52,000 tonnes of metallurgical silicon a year, mining its own quartz and running an established smelter operation.&lt;/p&gt;
&lt;p&gt;That matters because south-west WA also has the Darling Range bauxite mines, alumina refineries at Wagerup, Pinjarra and Worsley, the SWIS grid, and Bunbury port infrastructure all in the same broad industrial neighborhood. If you wanted to trial aluminium-assisted silicon reduction somewhere in Australia, starting near the one place that already knows how to make silicon seems less heroic than starting from a blank paddock.&lt;/p&gt;
&lt;h3 id=&quot;townsville-and-the-lansdown-precinct&quot;&gt;2. Townsville and the Lansdown precinct&lt;/h3&gt;
&lt;p&gt;If Kemerton is the incumbent, Townsville is the “someone is actually trying to draw the whole supply chain in one industrial estate” option. The &lt;a href=&quot;https://www.pv-magazine-australia.com/2026/04/21/silicon-ingots-and-wafers-massive-solar-supply-chain-projects-given-priority-by-federal-government/&quot;&gt;major project write-up&lt;/a&gt; and &lt;a href=&quot;https://www.pv-magazine-australia.com/2025/10/24/solar-sunshot-shines-4-7-million-on-ingot-and-wafer-manufacturing/&quot;&gt;Solar Sunshot coverage&lt;/a&gt; point to the Lansdown Eco-Industrial Precinct near Townsville as the proposed site for a quartz-to-metallurgical-silicon campus plus silicon ingot and wafer manufacturing.&lt;/p&gt;
&lt;p&gt;What I like about Townsville is not that it is magically complete today. It is that the logic is visible. There is Queensland quartz, there are nearby solar resources, there is port access, and CopperString plus the Northern Queensland REZ story gives you a plausible path to much more electricity than the region has today. It is easier to imagine an aluminothermic pilot piggybacking on a place already trying to integrate quartz, silicon and wafer production than on a site that only knows one piece of the story.&lt;/p&gt;
&lt;h3 id=&quot;gladstone&quot;&gt;3. Gladstone&lt;/h3&gt;
&lt;p&gt;Gladstone feels like the heavy-industry answer. It already has alumina, aluminium-adjacent infrastructure, deep-water port capability, and a lot of people thinking about how to decarbonise industrial heat without hollowing out the place. The &lt;a href=&quot;https://www.climateworkscentre.org/resource/heat-power-and-flexibility-to-future-proof-gladstone/&quot;&gt;Climateworks work on Gladstone&lt;/a&gt; is interesting here because it frames the region not just as a load, but as a flexible industrial node that could soak up and shape renewable power.&lt;/p&gt;
&lt;p&gt;Gladstone is weaker than Kemerton on current silicon capability, but stronger on industrial mass. If you needed somewhere that already thinks in terms of furnaces, refineries, export terminals and gigawatts rather than artisan clean-tech vibes, Gladstone is on the shortlist.&lt;/p&gt;
&lt;h3 id=&quot;mourilyan-and-weipa-as-upstream-feedstock-pieces&quot;&gt;4. Mourilyan and Weipa as upstream feedstock pieces&lt;/h3&gt;
&lt;p&gt;I would not put the whole chain in one place just to satisfy a PowerPoint aesthetic. Sometimes the better answer is a linked corridor rather than one mega-site.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://silicaresources.com.au/silica-sands-project-mourilyan/&quot;&gt;Mourilyan silica sands project&lt;/a&gt; is interesting because it gives Far North Queensland a high-purity silica input close to road and port infrastructure. Pair that with Cape York bauxite and alumina flows coming through Weipa and Yarwun and you start to see a north-to-central Queensland materials story, even if the final smelting and wafering steps land further south.&lt;/p&gt;
&lt;p&gt;That sort of arrangement is less neat on a map, but a lot more believable in real life.&lt;/p&gt;
&lt;p&gt;I have spent enough time around electronics, energy monitoring, and hardware supply chains to be skeptical of national capability claims built on nothing more than a minister at a lectern. Sovereign capability usually comes from embracing the mess: furnaces, scrap streams, slag reprocessing, aging solar farms, logistics yards, and the boring people who know how to keep them running through summer.&lt;/p&gt;
&lt;p&gt;The paper explicitly highlights recirculating carbonation gases, reprocessing byproduct slags, and using surplus aluminium scrap as some of the most important improvement levers. Those are exactly the kinds of details that separate a sovereign ecosystem from a PowerPoint ecosystem.&lt;/p&gt;
&lt;h2 id=&quot;the-fallen-leaves-analogy-is-better-than-the-circular-economy-cliche&quot;&gt;The Fallen Leaves Analogy Is Better Than the Circular Economy Cliche&lt;/h2&gt;
&lt;p&gt;One line from the slides stuck with me: every 10 years or so, as panel efficiency degrades or silicon technology advances, you recycle the aluminium and silicon into a new panel. Build enough installed capacity and after 30-35 years you have not just electricity generation, but a meaningful stockpile of reusable material.&lt;/p&gt;
&lt;p&gt;That feels less like a recycling slogan and more like a forest floor. Fallen leaves are not waste. They are deferred structure. The same could be true of first-generation solar deployments if we design the industrial loop ahead of time rather than pretending recycling will somehow organize itself later.&lt;/p&gt;
&lt;p&gt;This is also where the sovereign-policy lens improves the climate-policy lens. A circular loop that produces domestic industrial feedstock, manufacturing resilience, export optionality, and lower carbon intensity is politically sturdier than one justified only as moral sacrifice.&lt;/p&gt;
&lt;h2 id=&quot;what-i-would-actually-like-to-see-next&quot;&gt;What I Would Actually Like To See Next&lt;/h2&gt;
&lt;p&gt;If this idea is to move from interesting paper to something testable, I would want to see a few things next:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a serious Australian material flow analysis for quartz, aluminium scrap, aluminium dross, solar panel retirements, and metallurgical silicon demand.&lt;/li&gt;
&lt;li&gt;a location-based study around Kemerton, Townsville-Lansdown and Gladstone rather than a placeless national average.&lt;/li&gt;
&lt;li&gt;explicit comparison against the alternative use of the aluminium scrap streams, because the paper shows this assumption drives a lot of the environmental trade-off.&lt;/li&gt;
&lt;li&gt;a pilot framed as industrial symbiosis infrastructure, not just as a decarbonisation demonstration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The real question is not “can we make a greener tonne of silicon?” It is “can we build a self-reinforcing aluminium-silicon-energy system that compounds capability over decades?”&lt;/p&gt;
&lt;h2 id=&quot;final-thought&quot;&gt;Final Thought&lt;/h2&gt;
&lt;p&gt;I like this idea because it is neither purely green-tech optimism nor old-school extractive nostalgia. It says something more interesting: a country with abundant sun, bauxite, quartz, and engineering talent should be able to turn one generation of solar build-out into the feedstock for the next.&lt;/p&gt;
&lt;p&gt;Using aluminium to reduce silicon instead of carbon will not solve everything. The paper is clear about the trade-offs, and that honesty is part of why it is worth reading. But as a way of connecting chemistry, recycling, heavy industry, solar deployment, and geography into one coherent story, it has teeth.&lt;/p&gt;
&lt;p&gt;That is usually a sign the idea deserves a prototype.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/5213432990477987567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/5213432990477987567' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5213432990477987567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5213432990477987567'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/05/using-aluminium-instead-of-carbon-to.html' title='Using Aluminium Instead of Carbon to Make Silicon'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-1788928931185438421</id><published>2026-04-03T15:00:00.000-07:00</published><updated>2026-04-03T18:23:56.122-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="cloud"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="maintenance"/><category scheme="http://www.blogger.com/atom/ns#" term="software architecture"/><title type='text'>From SaaS to Serviced Software -- the code was never the hard part</title><content type='html'>&lt;p&gt;Sometime in the last two years the bottleneck shifted. I used to
spend most of a greenfield week staring at an empty editor, scaffolding
routes, arguing with ORMs, and coaxing CSS into something that did not
look like a government form from 2004. Today I can prompt my way to a
working CRUD app with auth, a reasonable schema, and even half-decent
styling before lunch. The code, it turns out, was never the hard part.
The hard part was–and still is–keeping the thing alive once real users
touch it.&lt;/p&gt;
&lt;h2 id=&quot;the-saas-mental-model&quot;&gt;The SaaS mental model&lt;/h2&gt;
&lt;p&gt;“Software as a Service” trained an entire generation to think the
value lives in the application layer. Build a clever feature, wrap it in
a subscription, ship a landing page. The implicit promise: we write the
software, you pay monthly, everyone wins. That framing put the spotlight
squarely on &lt;strong&gt;creation&lt;/strong&gt;–new features, new integrations,
new UI polish.&lt;/p&gt;
&lt;p&gt;But anyone who has operated a SaaS product past the euphoric launch
week knows where the hours actually go:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rotating secrets and patching CVEs at 11pm on a Friday&lt;/li&gt;
&lt;li&gt;Chasing down why the invoice PDF lambda timed out in ap-southeast-2
but not us-east-1&lt;/li&gt;
&lt;li&gt;Fighting Terraform drift after someone clicked through the console
“just this once”&lt;/li&gt;
&lt;li&gt;Explaining to a customer why their data export is 48 hours stale
because the Celery worker OOM-killed itself&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The ratio of build-time to keep-it-running-time was already lopsided.
AI just made it more obvious.&lt;/p&gt;
&lt;h2 id=&quot;enter-the-vibe-coded-prototype&quot;&gt;Enter the vibe-coded
prototype&lt;/h2&gt;
&lt;p&gt;Large language models have compressed the “zero to working prototype”
phase from weeks to hours. Cursor, Copilot, Aider, v0, Bolt – pick your
weapon. The scaffolding phase that used to justify a two-pizza team for
a quarter now fits in a solo weekend sprint. I have experienced this
first-hand: prompting out a FastAPI backend with DynamoDB tables, an SPA
frontend, and a deployment pipeline that mostly works. The code is not
elegant. It does not need to be. It is structurally correct enough to
demo and iterate.&lt;/p&gt;
&lt;p&gt;This is genuinely magical. It is also genuinely dangerous, because it
creates an illusion of completeness. The prototype works on your laptop,
passes the happy path tests the LLM also generated, and looks great in
the demo. Then production happens.&lt;/p&gt;
&lt;h2 id=&quot;production-is-where-software-goes-to-get-serviced&quot;&gt;Production is
where software goes to get serviced&lt;/h2&gt;
&lt;p&gt;Here is where the mental model needs updating. We are not really
selling Software as a Service anymore. We are selling &lt;strong&gt;Serviced
Software&lt;/strong&gt; – and the distinction matters.&lt;/p&gt;
&lt;p&gt;In the SaaS framing, the software is the product and the service is
the delivery mechanism. In the Serviced Software framing, the
&lt;strong&gt;service&lt;/strong&gt; is the product and the software is just the
substrate it runs on. Customers do not care that your backend is FastAPI
or Express or Rails. They care that:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;It is up&lt;/strong&gt; when they need it (hosting, redundancy,
failover)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Their data is safe&lt;/strong&gt; (encryption at rest and in
transit, access controls, backups that actually restore)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It stays current&lt;/strong&gt; (dependency updates, OS patches,
framework migrations)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It costs a predictable amount&lt;/strong&gt; (no surprise egress
bills, no runaway autoscaling)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Someone answers the phone&lt;/strong&gt; when it breaks at
3am&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;None of those are code problems. They are operational problems. And
they are the problems that AI is worst at solving, because they require
sustained human judgement over months and years, not a one-shot
generation pass.&lt;/p&gt;
&lt;h2 id=&quot;the-maintenance-asymmetry&quot;&gt;The maintenance asymmetry&lt;/h2&gt;
&lt;p&gt;There is a well-known asymmetry in software engineering: building
version 1.0 is perhaps 20% of the total lifetime cost. The remaining 80%
is maintenance, evolution, and eventual decommissioning. AI has
dramatically reduced the cost of that first 20%. But it has done almost
nothing for the other 80%.&lt;/p&gt;
&lt;p&gt;If anything, AI makes the maintenance problem worse. When code is
cheap to produce, people produce more of it. More repos, more
microservices, more side projects that “just need a small server.” Each
one becomes a maintenance liability. Each one needs patching,
monitoring, log rotation, certificate renewal, database vacuuming. The
&lt;a
href=&quot;https://techcrunch.com/2018/06/23/open-source-sustainability/&quot;&gt;open-source
maintainer burnout&lt;/a&gt; problem I wrote about after PyConAU 2019 is now
everyone’s problem, because everyone is now a maintainer of their own
vibe-coded fleet.&lt;/p&gt;
&lt;p&gt;I keep thinking about the analogy to 3D printing. When desktop
printers got cheap, everyone printed trinkets for a month. Then the
printers gathered dust because the hard part was never fabrication–it
was &lt;strong&gt;design, finishing, and material science&lt;/strong&gt;. The
bottleneck moved upstream and downstream simultaneously, leaving the
newly-cheap middle step feeling oddly irrelevant.&lt;/p&gt;
&lt;h2 id=&quot;what-serviced-software-looks-like-in-practice&quot;&gt;What “Serviced
Software” looks like in practice&lt;/h2&gt;
&lt;p&gt;If you accept that the value has shifted from code creation to code
stewardship, a few things follow:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Platform engineering matters more than feature
engineering.&lt;/strong&gt; Internal developer platforms (Backstage, Port,
Humanitec) that abstract away infrastructure and enforce guardrails are
more valuable than another AI code assistant. The companies investing in
paved roads for deployment, observability, and incident response will
win over those investing in faster code generation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Managed services eat custom code.&lt;/strong&gt; Every line of
custom infrastructure code is a future maintenance burden. I learned
this the hard way running &lt;a
href=&quot;https://whatnicklife.blogspot.com/2020/07/microservices-hardway.html&quot;&gt;microservices
from folders on EC2&lt;/a&gt; – cron jobs, plain-text .env files, manual venv
management. It worked, but every operational incident was my problem.
The appeal of managed Postgres over self-hosted, or Vercel over
hand-rolled CI/CD, is not laziness. It is recognizing where your scarce
operational attention should go.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Security becomes the primary differentiator.&lt;/strong&gt; When
everyone can generate a working app, the ones that survive are the ones
that do not get breached. Supply chain attacks, dependency confusion,
credential leaks in AI-generated code that helpfully hardcoded an API
key – these are the failure modes of the vibe-coding era. Security is
not a feature you bolt on; it is the service layer that justifies the
subscription.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cost modeling is a core engineering skill.&lt;/strong&gt; I wrote
about &lt;a
href=&quot;https://whatnicklife.blogspot.com/2020/07/microservices-hardway.html&quot;&gt;EKS
baseline costs&lt;/a&gt; being $70/month for personal projects back in 2020.
That sensitivity to operational cost used to be a niche concern. Now
that anyone can spin up infrastructure with a prompt, understanding what
it costs to keep running is table stakes. Cloud bills are the new
technical debt – invisible until they are catastrophic.&lt;/p&gt;
&lt;h2 id=&quot;tactical-tornados-vs-strategic-maintainers&quot;&gt;Tactical tornados vs
strategic maintainers&lt;/h2&gt;
&lt;p&gt;Every engineering org has its archetypes. The &lt;strong&gt;tactical
tornado&lt;/strong&gt; is the superstar feature developer who can bang out a
new module in a weekend, leave a trail of impressed stakeholders, and
move on to the next shiny thing. They are celebrated in sprint reviews,
promoted quickly, and held up as the template for “10x engineers.”
Product managers love them because they turn roadmap dreams into
demo-able reality at terrifying speed. AI amplifies the tornado: give
them Copilot and a weekend and they will generate an entire product
surface.&lt;/p&gt;
&lt;p&gt;Then Monday arrives. The tornado has moved on to the next feature.
Someone else inherits the code–no tests beyond the happy path, no
runbooks, secrets in environment variables that nobody documented, an
autoscaling policy copied from a blog post that assumed a different
traffic shape. The tactical tornado created value in a burst. The
&lt;strong&gt;strategic maintainer&lt;/strong&gt; captures it over months.&lt;/p&gt;
&lt;p&gt;Strategic maintainers are the people who go deep on the two or three
features that actually drive revenue. They understand the edge cases
customers hit at 2am. They know which database index is holding the
query plan together and what happens when the table crosses 50 million
rows. They are the ones who turn a flashy demo into a reliable
product–incrementally tightening error handling, adding observability,
negotiating with product managers about which “small” feature requests
would actually require rewriting the payment flow.&lt;/p&gt;
&lt;p&gt;Product managers sit in the middle of this tension. A good PM dreams
up the features that will deliver the most value and sequences them so
the team can ship without drowning in maintenance debt. A less
experienced PM treats every sprint as a feature factory, stacking new
work on top of un-serviced foundations, because the roadmap rewards
visible output over invisible resilience. In the Serviced Software
framing, the PM’s job is not just “what should we build next?” but “what
is costing us the most to keep running, and is it worth it?”&lt;/p&gt;
&lt;p&gt;The industry has historically rewarded tornados and feature-shipping
PMs disproportionately. Promotions go to the person who launched the
thing, not the person who kept it alive for three years. AI will sharpen
this imbalance unless orgs explicitly revalue the strategic maintainer.
When code generation is cheap, the scarce skill is not writing new
software–it is understanding existing software deeply enough to keep it
healthy.&lt;/p&gt;
&lt;h2 id=&quot;the-human-layer&quot;&gt;The human layer&lt;/h2&gt;
&lt;p&gt;There is a deeper point here that goes beyond tooling. The shift from
SaaS to Serviced Software is really a shift from
&lt;strong&gt;building&lt;/strong&gt; to &lt;strong&gt;caring&lt;/strong&gt;. Building is
exciting, creative, dopamine-rich. Caring is routine, patient, often
invisible. Our industry has always undervalued the people who keep the
lights on relative to the people who ship new features. AI will widen
that gap unless we consciously correct for it.&lt;/p&gt;
&lt;p&gt;The sysadmin, the SRE, the on-call engineer, the person who actually
reads the CVE advisories and patches before the exploit drops – these
roles are becoming more important, not less. The code is becoming
commodity. The care is becoming scarce.&lt;/p&gt;
&lt;h2 id=&quot;where-this-goes&quot;&gt;Where this goes&lt;/h2&gt;
&lt;p&gt;I do not think SaaS as a business model disappears. But I think the
honest version of what customers are paying for will increasingly sound
like: “We run and maintain this software so you do not have to.” That is
not a new idea – managed hosting has existed forever. What is new is
that the software layer itself is becoming thin enough that the
operational layer dominates the value proposition.&lt;/p&gt;
&lt;p&gt;We are entering an era where the question is not “can you build it?”
but “can you keep it running, secure, updated, and affordable for the
next five years?” The answer to that question has never been a one-shot
prompt. It is a sustained commitment – and that, for now, remains
stubbornly human.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/1788928931185438421/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/1788928931185438421' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1788928931185438421'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1788928931185438421'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/04/from-saas-to-serviced-software-code-was.html' title='From SaaS to Serviced Software -- the code was never the hard part'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-604579248761733803</id><published>2026-03-07T16:00:00.000-08:00</published><updated>2026-03-08T00:02:48.833-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="acolite"/><category scheme="http://www.blogger.com/atom/ns#" term="acp"/><category scheme="http://www.blogger.com/atom/ns#" term="agents"/><category scheme="http://www.blogger.com/atom/ns#" term="ai"/><category scheme="http://www.blogger.com/atom/ns#" term="earth-observation"/><category scheme="http://www.blogger.com/atom/ns#" term="foss4g"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="performance"/><category scheme="http://www.blogger.com/atom/ns#" term="rust"/><title type='text'>Two Agents, One Codebase: An F1 Race Team Approach to Porting ACOLITE to Rust</title><content type='html'>&lt;p&gt;In Formula 1, every team fields two drivers. Not as a backup plan – as a strategy. One driver pushes the pace, forcing rivals to respond. The other holds position, manages tyres, and covers the alternative strategy. They share telemetry, they share a garage, but they are running different races on the same track. The team wins when both cars score points, not when one driver tries to do everything.&lt;/p&gt;
&lt;p&gt;Porting a scientific Python codebase to Rust feels remarkably similar. You need the aggressive driver – the one who charges into unfamiliar code and lays down fast laps of Rust implementation. And you need the calculating driver – the one who reads the data, watches for degradation, and calls out when the numerical precision is drifting. Two AI coding agents, paired like Norris and Piastri, sharing a codebase but operating on different parts of the problem.&lt;/p&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/F-dVCeV3_H8&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id=&quot;the-starting-grid-why-rust-for-acolite&quot;&gt;The Starting Grid: Why Rust for ACOLITE?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/acolite/acolite&quot;&gt;ACOLITE&lt;/a&gt; is RBINS’ atmospheric correction toolkit for aquatic remote sensing. It handles everything from Landsat and Sentinel-2 to hyperspectral sensors like PACE OCI (286 bands) and PRISMA (239 bands). The Dark Spectrum Fitting (DSF) algorithm is elegant – image-based, no external atmospheric inputs – but in Python, processing a full PACE scene involves reading 291 NetCDF variables, interpolating multi-dimensional LUTs, and correcting each pixel’s reflectance through a chain of gas transmittance, Rayleigh scattering, and aerosol models. On a decent machine, this takes around 230 seconds.&lt;/p&gt;
&lt;p&gt;The seed was planted at FOSS4G 2025 in Auckland when Leo Hardtke ran a tutorial on Earth Observation processing with Rust. It was plagued by Nix environment issues (as I noted in my &lt;a href=&quot;https://whatnicklife.blogspot.com/2025/11/foss4g-2025-auckland-hazy-hops-and.html&quot;&gt;conference write-up&lt;/a&gt;), but when the code ran, it was fast. Zero-cost abstractions and fearless concurrency are not just slogans at that point – they are wall-clock seconds you are not spending waiting for your atmospheric correction to finish.&lt;/p&gt;
&lt;p&gt;I had also been watching Rob Woodcock’s &lt;a href=&quot;https://github.com/woodcockr/acolite/blob/acolite-mp/README-ACOLITE-MP.md&quot;&gt;acolite-mp&lt;/a&gt; branch, which tackled the same performance problem from within Python. His approach was clever: per-band parallelism with memory budgets tuned to cloud CPU-to-RAM ratios (2, 4, or 8 GiB per core), replacing NumPy’s interpolation with the multithreaded &lt;code&gt;pyinterp&lt;/code&gt;, and carefully managing the GIL contention that Python’s threading model inflicts on you. He got Sentinel-2 from 791s down to 197s and Landsat from 312s to 99s on a 24-core i9 – roughly a 3-4x speedup.&lt;/p&gt;
&lt;p&gt;But the GIL is still there. The memory model is still Python’s. And as Rob himself noted, “further performance improvements are possible but require more extensive changes to the file handling” and “there is a fair amount of GIL contention which limits threading being caused by some structural choices in the implementation.” At some point, you are fighting the language rather than the problem.&lt;/p&gt;
&lt;p&gt;Rust sidesteps all of this. No GIL. No garbage collector. Rayon gives you data-parallel iterators that map across bands or tiles with work-stealing. Memory usage is deterministic and known at compile time – you can profile it statically before deploying, which is a sentence that makes no sense in Python-land but is table stakes in systems programming.&lt;/p&gt;
&lt;h2 id=&quot;the-pit-crew-two-agents-via-acp&quot;&gt;The Pit Crew: Two Agents via ACP&lt;/h2&gt;
&lt;p&gt;Here is where the teammate analogy really kicks in. In F1, a team with only one driver is not half a team – it is no team at all. You cannot run a split strategy with a single car. You cannot use one driver to hold up a rival while the other pulls a gap. The performance of the pair exceeds the sum of the individuals because they create options that a solo driver simply cannot.&lt;/p&gt;
&lt;p&gt;Porting 40,000+ lines of scientific Python to Rust is the same. A single AI agent writing Rust will drift – the implementation slowly diverging from Python’s numerical behaviour until your reflectance values are off by just enough to be scientifically useless. You need the second driver to keep it honest.&lt;/p&gt;
&lt;p&gt;The solution I landed on was a &lt;a href=&quot;https://github.com/whatnick/acolite/tree/feature/rust-port&quot;&gt;multi-agent orchestration harness&lt;/a&gt; using the &lt;a href=&quot;https://agentclientprotocol.com/&quot;&gt;Agent Client Protocol (ACP)&lt;/a&gt;, a JSON-RPC 2.0 protocol over NDJSON stdio that lets coding agents communicate in a structured way:&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 24%&quot; /&gt;
&lt;col style=&quot;width: 20%&quot; /&gt;
&lt;col style=&quot;width: 55%&quot; /&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;F1 Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;strong&gt;Kiro&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Executor – writes Rust code, runs tests, reads files&lt;/td&gt;
&lt;td&gt;Lead driver – pushes the pace, sets fast laps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;&lt;strong&gt;Copilot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proposer – reviews output, suggests next steps, cross-checks Python&lt;/td&gt;
&lt;td&gt;Second driver – covers the strategy, watches the gaps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;&lt;strong&gt;Human&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Approver – filters proposals before dispatch&lt;/td&gt;
&lt;td&gt;Team principal – makes the call on when to pit&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The workflow per sensor port looks like this:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Human provides &lt;code&gt;--task&lt;/code&gt; to the orchestrator (&lt;code&gt;tools/agent_harness.py&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Kiro receives the task via ACP &lt;code&gt;session/prompt&lt;/code&gt; and starts writing code&lt;/li&gt;
&lt;li&gt;Kiro streams output via &lt;code&gt;session/update&lt;/code&gt; chunks&lt;/li&gt;
&lt;li&gt;Output goes to Copilot for review against the Python source&lt;/li&gt;
&lt;li&gt;Copilot proposes &lt;code&gt;ACTION:&lt;/code&gt; lines – “fix the gas transmittance interpolation order”, “the Rayleigh LUT needs pressure stacking”&lt;/li&gt;
&lt;li&gt;Human approves or rejects&lt;/li&gt;
&lt;li&gt;Approved actions go back to Kiro&lt;/li&gt;
&lt;li&gt;Repeat until regression tests pass or maximum cycles reached&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is not vibe coding. This is a two-car team running a split strategy.&lt;/p&gt;
&lt;p&gt;Think about how McLaren or Red Bull operate. The lead driver qualifies on pole and sets the pace in clean air. The second driver starts on a different tyre compound, runs a longer first stint, and emerges from the pits into a different part of the field. They are solving complementary problems – one optimises for raw speed, the other for strategic coverage. Neither is redundant.&lt;/p&gt;
&lt;p&gt;Kiro is the lead driver. It attacks the Rust implementation aggressively – writing loaders, porting DSF algorithms, wiring up rayon parallelism. It sets fast laps. It also occasionally bins it into the gravel trap by hallucinating a NumPy broadcasting rule that does not exist in ndarray.&lt;/p&gt;
&lt;p&gt;Copilot is the second driver. It reads the Python source, cross-references the Rust output, and spots where the gap to parity is growing. “The gas transmittance interpolation order is wrong” is exactly the kind of radio call a second driver makes – not flashy, but it prevents a DNF.&lt;/p&gt;
&lt;p&gt;The human is the team principal. You do not override the drivers on every corner, but you make the strategic calls: do we pit now and fix this RMSE regression, or do we push on and address it in the next stint? Is a 0.002 RMSE difference in Sentinel-2 reflectance acceptable? (It is – that is within float32 precision.) When do we switch from tiled DSF to fixed DSF mode for this sensor?&lt;/p&gt;
&lt;p&gt;Together, they converge faster than either alone, for the same reason that two cars gathering tyre data in free practice gives the team more information than one car doing twice as many laps.&lt;/p&gt;
&lt;h2 id=&quot;the-telemetry-regression-tests-against-real-data&quot;&gt;The Telemetry: Regression Tests Against Real Data&lt;/h2&gt;
&lt;p&gt;In F1, both drivers generate telemetry. The team overlays their data – braking points, throttle application, cornering speed – to find where one is faster and why. The overlay is the truth. Not the driver’s feeling, not the engineer’s simulation, but what the car actually did on the track.&lt;/p&gt;
&lt;p&gt;Regression tests are our telemetry overlay. The Python ACOLITE output is Driver 1’s trace. The Rust output is Driver 2’s. We overlay them pixel-by-pixel, band-by-band, and look at the delta. When the traces diverge, something real has changed and we need to understand whether it is a genuine improvement or an error we need to correct.&lt;/p&gt;
&lt;p&gt;There are currently 141 Python regression tests that compare Rust output against Python output pixel-by-pixel across real satellite scenes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Landsat 8/9&lt;/strong&gt;: 13 regression + 13 Rust-vs-Python + 7 benchmark tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sentinel-2 A/B&lt;/strong&gt;: 19 regression + 15 Rust-vs-Python + 9 benchmark tests&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PACE OCI&lt;/strong&gt;: 17 regression + 14 Rust-vs-Python + 12 DSF comparison + 12 ROI + 10 full-scene tests&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The tolerances are tight. Sentinel-2 achieves RMSE &amp;lt; 0.002 (physics-equivalent). Landsat gets RMSE &amp;lt; 0.02. PACE full-scene (1710 x 1272 pixels x 291 bands) hits mean RMSE of 0.004 with 100% of pixels within 0.05 of Python. Correlation coefficients are R &amp;gt; 0.999 across all sensors.&lt;/p&gt;
&lt;p&gt;These are not toy tests on synthetic data. They run against actual L1 scenes downloaded from USGS and NASA. When the tests break, something real is wrong.&lt;/p&gt;
&lt;h2 id=&quot;the-performance-gap-where-the-seconds-go&quot;&gt;The Performance Gap: Where the Seconds Go&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Sensor&lt;/th&gt;
&lt;th&gt;Scene Size&lt;/th&gt;
&lt;th&gt;Rust&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Landsat 8&lt;/td&gt;
&lt;td&gt;62M px x 7 bands&lt;/td&gt;
&lt;td&gt;66s&lt;/td&gt;
&lt;td&gt;180s&lt;/td&gt;
&lt;td&gt;2.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Landsat 9&lt;/td&gt;
&lt;td&gt;62M px x 7 bands&lt;/td&gt;
&lt;td&gt;56s&lt;/td&gt;
&lt;td&gt;180s&lt;/td&gt;
&lt;td&gt;3.2x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Sentinel-2 A&lt;/td&gt;
&lt;td&gt;30M px x 11 bands&lt;/td&gt;
&lt;td&gt;52s&lt;/td&gt;
&lt;td&gt;182s&lt;/td&gt;
&lt;td&gt;3.5x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Sentinel-2 B&lt;/td&gt;
&lt;td&gt;30M px x 11 bands&lt;/td&gt;
&lt;td&gt;64s&lt;/td&gt;
&lt;td&gt;173s&lt;/td&gt;
&lt;td&gt;2.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;PACE OCI (full)&lt;/td&gt;
&lt;td&gt;1710 x 1272 x 291 bands&lt;/td&gt;
&lt;td&gt;84s&lt;/td&gt;
&lt;td&gt;230s&lt;/td&gt;
&lt;td&gt;2.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The PACE result is particularly satisfying. The key optimisation was switching from 291 per-band NetCDF reads to 3 bulk detector reads, then applying rayon-parallel atmospheric correction across tiles. Load is 12 seconds, AC is 34 seconds, write is 35 seconds. That write phase for a 291-band hyperspectral cube goes to GeoZarr V3 with gzip compression – try doing that in a Python event loop without your memory allocator throwing a tantrum.&lt;/p&gt;
&lt;h2 id=&quot;energy-efficiency-the-fuel-strategy-nobody-talks-about&quot;&gt;Energy Efficiency: The Fuel Strategy Nobody Talks About&lt;/h2&gt;
&lt;p&gt;Here is the part where I get philosophical – and where the F1 analogy turns from metaphor into mirror.&lt;/p&gt;
&lt;p&gt;Formula 1 underwent a &lt;a href=&quot;https://www.redbull.com/us-en/fuel-efficiency-strategies-in-formula-1-racing&quot;&gt;fuel efficiency revolution in 2014&lt;/a&gt;. The FIA introduced hybrid power units, capped fuel flow at 100 kg/hour (monitored 2,200 times per second), and forced teams to extract maximum performance from minimum fuel. The result was not slower cars – it was faster cars that used less. The 2026 regulations go further: fossil carbon is prohibited entirely, the MGU-K will deliver three times the electrical power (350kW vs today’s 120kW), producing up to 1,000 horsepower while burning sustainable fuel. Less fuel, more power. That is not a trade-off – it is an engineering constraint that drives innovation.&lt;/p&gt;
&lt;p&gt;The same constraint applies to scientific computing, we just pretend it does not. Cloud computing bills are denominated in dollars, but the underlying unit is energy. Every CPU cycle your atmospheric correction burns is a watt drawn from a power grid somewhere. When you are processing continental-scale Sentinel-2 archives or the full PACE ocean colour mission, those watts add up. Python is the V10 era of scientific computing – glorious, unrestricted, and profligate with resources.&lt;/p&gt;
&lt;p&gt;Rust is the hybrid power unit. Its advantage is not just speed – it is energy per unit of work. A 3x speedup roughly translates to using a third of the compute time, which means a third of the energy, a third of the carbon footprint, and a third of your AWS bill. The Rust Foundation and others have pointed to studies showing compiled languages like Rust and C using an order of magnitude less energy than interpreted languages for equivalent workloads. Just as F1 teams discovered that fuel efficiency constraints forced them to build fundamentally better engines, switching to Rust forces you to think about memory layout, allocation patterns, and data flow in ways that Python’s garbage collector lets you ignore – until the bill arrives.&lt;/p&gt;
&lt;p&gt;And here is the irony that would make an F1 sustainability officer wince: Earth observation processing is meant to monitor the planet’s health. Burning excess energy to do it is like running your emissions-monitoring car on leaded fuel. F1 recognised that the sport’s 20-car grid is only 1% of its total carbon footprint, but pursued fuel efficiency anyway because the technology trickles down. The same logic applies to EO processing pipelines. The individual savings per scene are modest, but at continental archive scale they compound – just like how F1’s hybrid innovations now power road cars from Ferrari’s SF90 to the electric components in every modern turbo engine.&lt;/p&gt;
&lt;p&gt;Static memory profiling makes this tangible. In Rust, I can tell you at compile time that a Sentinel-2 full-scene atmospheric correction will peak at approximately N gigabytes of memory, because the allocations are deterministic. In Python, you find out at runtime – usually when the OOM killer visits your pod. F1 teams know their fuel load to the gram before the formation lap. Rust gives you the same certainty for compute.&lt;/p&gt;
&lt;h2 id=&quot;kubernetes-1.35-and-vertical-pod-autoscaling&quot;&gt;Kubernetes 1.35 and Vertical Pod Autoscaling&lt;/h2&gt;
&lt;p&gt;This deterministic memory behaviour dovetails nicely with Kubernetes 1.35’s improvements to &lt;a href=&quot;https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler&quot;&gt;Vertical Pod Autoscaler (VPA)&lt;/a&gt;. VPA watches your pod’s actual resource usage and adjusts CPU and memory requests/limits accordingly. When your workload has predictable resource usage – as Rust workloads tend to – VPA converges quickly to the right allocation instead of oscillating between OOM kills and wasted headroom.&lt;/p&gt;
&lt;p&gt;For a processing pipeline that ingests satellite scenes of varying sizes (a Landsat scene is 62 million pixels across 7 bands; a PACE scene is 2.2 million pixels across 291 bands), VPA can right-size pods per sensor type. Rust’s static memory profile means the VPA recommendations stabilise fast, which means tighter bin-packing, which means more scenes processed per node, which means lower cost per scene.&lt;/p&gt;
&lt;p&gt;Compare this to Python pods where memory usage is non-deterministic, garbage collection spikes are unpredictable, and the VPA has to overprovision to avoid OOM. The 2 GiB/core cloud ratio that Rob’s acolite-mp was carefully designed around becomes less of a constraint when your language does not waste half of it on interpreter overhead.&lt;/p&gt;
&lt;h2 id=&quot;out-of-band-development-preventing-merge-conflicts-with-upstream&quot;&gt;Out-of-Band Development: Preventing Merge Conflicts with Upstream&lt;/h2&gt;
&lt;p&gt;One design decision I am particularly happy with is keeping the Rust port on a separate feature branch (&lt;code&gt;feature/rust-port&lt;/code&gt;) and treating it as out-of-band from the Python codebase. ACOLITE upstream is actively maintained by Quinten Vanhellemont at RBINS, with regular additions of new sensors, algorithm refinements, and bug fixes. A traditional “rewrite in Rust” approach would create an immediate fork that diverges with every upstream commit.&lt;/p&gt;
&lt;p&gt;Instead, the Rust code lives in &lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;benches/&lt;/code&gt;, and &lt;code&gt;tests/&lt;/code&gt; directories that do not exist in upstream Python ACOLITE. The Python code in &lt;code&gt;acolite/&lt;/code&gt; stays untouched. The regression tests are the synchronisation mechanism – they import both the Python ACOLITE modules and the compiled Rust binary, run the same scene through both, and compare outputs.&lt;/p&gt;
&lt;p&gt;When upstream adds a new sensor or changes a gas transmittance coefficient, the regression tests fail in the Rust port. That failure is the trigger: it goes into the agent harness as a &lt;code&gt;--task&lt;/code&gt;, Kiro investigates the numerical difference, Copilot cross-references the upstream commit, and the fix lands in Rust without touching a single Python file. No merge conflicts. No rebasing nightmares. Just tests that enforce parity.&lt;/p&gt;
&lt;p&gt;This is how you keep an acceleration layer in sync with a moving target – you do not try to merge them. You test them against each other.&lt;/p&gt;
&lt;h2 id=&quot;what-is-next-the-gap-to-full-sensor-parity&quot;&gt;What Is Next: The Gap to Full Sensor Parity&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/whatnick/acolite/blob/feature/rust-port/RUST_PORT_ROADMAP.md&quot;&gt;roadmap&lt;/a&gt; has the current state at 48 Rust tests, 141 Python regression tests, and three sensors fully validated (Landsat 8/9, Sentinel-2 A/B, PACE OCI). The architecture – loader, AC, writer – is clean and extensible. But three sensors out of 30+ is a qualifying lap, not a race win. Here is what closing the gap to full ACOLITE parity actually looks like.&lt;/p&gt;
&lt;h3 id=&quot;sensor-coverage-3-down-30-to-go&quot;&gt;Sensor Coverage: 3 down, 30+ to go&lt;/h3&gt;
&lt;p&gt;Python ACOLITE supports a sprawling constellation of sensors. The Rust port has ticked off the three highest-priority ones but the remaining fleet breaks into tiers:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tier 1 – Near-term (shared loader patterns exist):&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Sensor&lt;/th&gt;
&lt;th&gt;Bands&lt;/th&gt;
&lt;th&gt;Loader Type&lt;/th&gt;
&lt;th&gt;Blocker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Sentinel-3 OLCI&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;NetCDF&lt;/td&gt;
&lt;td&gt;Sensor def exists, needs full pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;PRISMA&lt;/td&gt;
&lt;td&gt;239&lt;/td&gt;
&lt;td&gt;HDF5&lt;/td&gt;
&lt;td&gt;Shares pattern with PACE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;DESIS&lt;/td&gt;
&lt;td&gt;235&lt;/td&gt;
&lt;td&gt;HDF5&lt;/td&gt;
&lt;td&gt;Shares pattern with PACE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;EnMAP&lt;/td&gt;
&lt;td&gt;224&lt;/td&gt;
&lt;td&gt;HDF5&lt;/td&gt;
&lt;td&gt;Shares pattern with PACE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;EMIT&lt;/td&gt;
&lt;td&gt;285&lt;/td&gt;
&lt;td&gt;NetCDF&lt;/td&gt;
&lt;td&gt;Similar to PACE OCI&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;These are the low-hanging fruit. The PACE port proved out the NetCDF and hyperspectral GeoZarr writer path; PRISMA/DESIS/EnMAP share the HDF5 loader pattern. Each is a well-scoped &lt;code&gt;--task&lt;/code&gt; for the agent harness – Kiro writes the loader and wires up the AC pipeline, Copilot validates against Python output on a reference scene.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tier 2 – Medium-term (new loader work required):&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Sensor&lt;/th&gt;
&lt;th&gt;Bands&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Landsat 5 TM / 7 ETM+&lt;/td&gt;
&lt;td&gt;7-8&lt;/td&gt;
&lt;td&gt;Older calibration metadata formats&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;PlanetScope (Dove/SuperDove)&lt;/td&gt;
&lt;td&gt;4-8&lt;/td&gt;
&lt;td&gt;Commercial format, GeoTIFF based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;WorldView-2/3&lt;/td&gt;
&lt;td&gt;6-29&lt;/td&gt;
&lt;td&gt;Multi-resolution, pan-sharpening&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;Pleiades&lt;/td&gt;
&lt;td&gt;5-7&lt;/td&gt;
&lt;td&gt;DIMAP format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;QuickBird-2&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Legacy but still used&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;VIIRS (NPP/J1/J2)&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Swath-based HDF5, three platforms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;Aqua/Terra MODIS&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;HDF4/HDF-EOS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;GOCI-2&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Korean ocean colour mission&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each of these needs a dedicated loader – different metadata formats, different calibration approaches, different file layouts. The atmospheric correction core (DSF, gas transmittance, Rayleigh, aerosol models) is shared, but getting the radiometrically calibrated top-of-atmosphere reflectance array into the pipeline is the per-sensor work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tier 3 – Geostationary and niche (lowest priority for aquatic applications):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;GOES ABI, Himawari AHI, MTG-I FCI, SEVIRI, Sentinel-3 SLSTR, AMAZONIA-1 WFI, CHRIS, HYPERION, HICO, HyperField, HYPSO, Tanager. Some of these (HYPERION, HICO) are decommissioned but their archives are still processed. Others (Tanager at 420 bands, HYPSO at 120) are newer hyperspectral missions that would benefit most from Rust’s performance advantage.&lt;/p&gt;
&lt;h3 id=&quot;beyond-loaders-the-algorithm-gap&quot;&gt;Beyond Loaders: The Algorithm Gap&lt;/h3&gt;
&lt;p&gt;Sensor parity is not just about reading files. Python ACOLITE has several processing features the Rust port does not yet implement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ROI subsetting&lt;/strong&gt;: Limit processing to a bounding box or polygon – critical for operational workflows that do not need a full scene&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ancillary data retrieval&lt;/strong&gt;: NCEP ozone, pressure, and wind speed from NASA OBPG; currently the Rust port uses default values&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DEM-derived pressure&lt;/strong&gt;: Copernicus DEM at 30/90m for surface pressure estimation in mountainous coastal regions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Glint correction&lt;/strong&gt;: Sun glint removal for low-latitude ocean scenes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RAdCor adjacency correction&lt;/strong&gt;: The physics-based adjacency effect correction developed under the STEREO program&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TACT thermal processing&lt;/strong&gt;: Surface temperature from Landsat thermal bands via libRadtran – this one is architecturally interesting because it requires calling an external Fortran radiative transfer code&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interface reflectance (rsky)&lt;/strong&gt;: Sky reflection correction at the air-water interface&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;L2W water products&lt;/strong&gt;: Chlorophyll-a (OC algorithms), TSS (Nechad, Dogliotti), turbidity, Secchi depth – the derived products that downstream scientists actually use&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The L2W gap is the most consequential. Most ACOLITE users do not care about surface reflectance per se; they want chlorophyll maps or turbidity time series. Until the Rust port can produce L2W outputs, it remains a fast atmospheric correction engine rather than a complete aquatic remote sensing toolkit.&lt;/p&gt;
&lt;h3 id=&quot;the-realistic-path&quot;&gt;The Realistic Path&lt;/h3&gt;
&lt;p&gt;Closing this gap is not a sprint, it is an endurance race – appropriately enough. The agent harness makes each sensor port a repeatable, testable unit of work. The pattern is established: write loader, wire to AC pipeline, run regression tests against Python, fix deltas, validate on real data. Each sensor port takes the agents a day or two of focused work plus human review.&lt;/p&gt;
&lt;p&gt;At the current pace, Tier 1 sensors are within reach in the near term. Tier 2 will follow as the loader library matures. The algorithm features (ancillary data, glint, TACT) are orthogonal to sensor coverage and can be developed in parallel. L2W is the final milestone – when the Rust port can ingest a Sentinel-2 scene and produce a chlorophyll-a map that matches Python to within measurement uncertainty, the port will be race-ready for production.&lt;/p&gt;
&lt;p&gt;Each of these is a &lt;code&gt;--task&lt;/code&gt; for the agent harness. Two drivers, one constructor’s championship. The lead driver pushes into unfamiliar sensor territory, the second driver validates against Python, and the telemetry overlay catches every divergence before it compounds into a retirement.&lt;/p&gt;
&lt;p&gt;If the intersection of Rust, Earth observation, and AI-assisted development interests you, the code is all on &lt;a href=&quot;https://github.com/whatnick/acolite/tree/feature/rust-port&quot;&gt;GitHub&lt;/a&gt;. Feel free to ping me with ideas, bug reports, or competing approaches – especially if you have a cleverer way to handle the N-dimensional LUT interpolation. That one was a fun 3 days of Rapid Rust Rewrite fuelled by AI Amphetamine Analogs.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/604579248761733803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/604579248761733803' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/604579248761733803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/604579248761733803'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/03/two-agents-one-codebase-f1-race-team.html' title='Two Agents, One Codebase: An F1 Race Team Approach to Porting ACOLITE to Rust'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/F-dVCeV3_H8/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-8038859141391912899</id><published>2026-02-27T16:00:00.000-08:00</published><updated>2026-02-28T14:37:38.221-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arduino"/><category scheme="http://www.blogger.com/atom/ns#" term="arduino-cli"/><category scheme="http://www.blogger.com/atom/ns#" term="embedded"/><category scheme="http://www.blogger.com/atom/ns#" term="energy-monitor"/><category scheme="http://www.blogger.com/atom/ns#" term="esp32"/><category scheme="http://www.blogger.com/atom/ns#" term="github-copilot"/><category scheme="http://www.blogger.com/atom/ns#" term="logic-analyzer"/><category scheme="http://www.blogger.com/atom/ns#" term="saleae"/><title type='text'>Copilot + Arduino CLI + Saleae: Driver Development for V93XX</title><content type='html'>&lt;p&gt;I have been spending time building out the &lt;a
href=&quot;https://github.com/whatnick/V93XX_Arduino&quot;&gt;V93XX_Arduino&lt;/a&gt;
library for Vangotech energy-monitoring ASICs, and this is one of those
projects where tooling makes or breaks momentum.&lt;/p&gt;
&lt;p&gt;The pairing that worked best for me was:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/features/copilot&quot;&gt;GitHub Copilot&lt;/a&gt; for
repetitive protocol code, tests, and workflow glue&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://arduino.github.io/arduino-cli/latest/&quot;&gt;arduino-cli&lt;/a&gt; for
deterministic compile and upload loops&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.saleae.com/&quot;&gt;Saleae Logic Analyzer&lt;/a&gt; captures
to confirm what is &lt;em&gt;actually&lt;/em&gt; on the wire&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The short version: Copilot gets you to a plausible driver quickly,
but the logic analyzer gets you to a &lt;em&gt;correct&lt;/em&gt; driver.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe src=&quot;https://www.youtube.com/embed/7EaPbl-LAnU&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;V93XX driver workflow walkthrough&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;why-this-trio-works&quot;&gt;Why this trio works&lt;/h2&gt;
&lt;p&gt;Developing protocol drivers is usually a game of “spec says one
thing, silicon does another thing”.&lt;/p&gt;
&lt;p&gt;If you rely only on serial logs, you can miss timing and framing
issues. If you rely only on captures, you can waste hours writing
boilerplate and one-off scripts. Using these three together gives a
tighter loop:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Copilot proposes code and tests from your intent&lt;/li&gt;
&lt;li&gt;Arduino CLI compiles and flashes quickly from scripts&lt;/li&gt;
&lt;li&gt;Saleae confirms framing, parity, baud behavior, and CRC bytes&lt;/li&gt;
&lt;li&gt;Copilot helps refactor after you learn what the bus is doing&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In practice, this turned the V9381 UART ChecksumMode and waveform/FFT
work from a stop-start activity into a repeatable pipeline.&lt;/p&gt;
&lt;h2 id=&quot;project-context-v93xx_arduino&quot;&gt;Project context:
V93XX_Arduino&lt;/h2&gt;
&lt;p&gt;Repository: &lt;a
href=&quot;https://github.com/whatnick/V93XX_Arduino&quot;&gt;whatnick/V93XX_Arduino&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The library currently covers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;V93XX_UART&lt;/code&gt; for V9360 and V9381 UART modes (including
address pins and checksum modes)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;V93XX_SPI&lt;/code&gt; for V9381 SPI paths (faster acquisition, up
to MHz clocks)&lt;/li&gt;
&lt;li&gt;Examples for baseline comms, waveform capture, and FFT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Useful docs in the repo:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/whatnick/V93XX_Arduino/blob/main/docs/GETTING_STARTED.md&quot;&gt;docs/GETTING_STARTED.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/whatnick/V93XX_Arduino/blob/main/docs/TESTING.md&quot;&gt;docs/TESTING.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a
href=&quot;https://github.com/whatnick/V93XX_Arduino/blob/main/docs/COPILOT.md&quot;&gt;docs/COPILOT.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;practical-workflow&quot;&gt;Practical workflow&lt;/h2&gt;
&lt;h3 id=&quot;start-with-a-machine-checkable-baseline&quot;&gt;1) Start with a
machine-checkable baseline&lt;/h3&gt;
&lt;p&gt;Before touching hardware, run the local CRC and framing tests.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre
class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;python&lt;/span&gt; tools/test_checksum_mode.py&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If this is red, do not flash anything yet.&lt;/p&gt;
&lt;h3 id=&quot;use-copilot-for-structured-implementation-work&quot;&gt;2) Use Copilot
for structured implementation work&lt;/h3&gt;
&lt;p&gt;I get better results when prompts are specific and constrained.
Example prompt:&lt;/p&gt;
&lt;pre class=&quot;text&quot;&gt;&lt;code&gt;Implement V9381 UART read path with explicit ChecksumMode behavior.
Keep Clean mode strict and Dirty mode permissive.
Add unit tests for CRC-8 edge cases and frame parsing.
Do not change public method names.&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copilot is strongest here at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building test scaffolding quickly&lt;/li&gt;
&lt;li&gt;Keeping repetitive register access code consistent&lt;/li&gt;
&lt;li&gt;Producing incremental refactors after captures reveal protocol edge
cases&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;consume-datasheets-with-pdf-mcp-and-keep-them-in-repo&quot;&gt;3)
Consume datasheets with PDF MCP and keep them in-repo&lt;/h3&gt;
&lt;p&gt;Before generating more driver code, I now ingest the vendor datasheet
with &lt;a
href=&quot;https://github.com/SylphxAI/pdf-reader-mcp&quot;&gt;pdf-reader-mcp&lt;/a&gt; so
Copilot can work from extracted register tables and command framing
notes.&lt;/p&gt;
&lt;p&gt;My workflow is:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Commit the original datasheet PDF to the repository, for example
under &lt;code&gt;docs/datasheets/v93xx/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use PDF MCP to extract the high-value sections (register map,
UART/SPI timing, checksum/CRC rules, waveform buffer details).&lt;/li&gt;
&lt;li&gt;Save extracted artifacts back into the repo as text or markdown
notes, for example
&lt;code&gt;docs/datasheets/v93xx/register_notes.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prompt Copilot using both code and extracted notes so generated
changes are tied to concrete datasheet language.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This gives you a versioned paper trail from silicon docs to driver
behavior, which is very useful when reconciling captures from the logic
analyzer.&lt;/p&gt;
&lt;h3 id=&quot;compile-and-flash-with-arduino-cli&quot;&gt;4) Compile and flash with
Arduino CLI&lt;/h3&gt;
&lt;p&gt;For ESP32-S3 targets, this keeps the build deterministic and
scriptable:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre
class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;arduino-cli&lt;/span&gt; board list&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;arduino-cli&lt;/span&gt; compile &lt;span class=&quot;at&quot;&gt;--fqbn&lt;/span&gt; esp32:esp32:esp32s3 examples/V9381_UART_DIRTY_MODE&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;arduino-cli&lt;/span&gt; upload &lt;span class=&quot;at&quot;&gt;--fqbn&lt;/span&gt; esp32:esp32:esp32s3 &lt;span class=&quot;at&quot;&gt;--port&lt;/span&gt; COM3 examples/V9381_UART_DIRTY_MODE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;PowerShell users can run the project helper script:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb4&quot;&gt;&lt;pre
class=&quot;sourceCode powershell&quot;&gt;&lt;code class=&quot;sourceCode powershell&quot;&gt;&lt;span id=&quot;cb4-1&quot;&gt;&lt;a href=&quot;#cb4-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;\tools\run_automated_tests&lt;span class=&quot;op&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fu&quot;&gt;ps1&lt;/span&gt; &lt;span class=&quot;op&quot;&gt;-&lt;/span&gt;Port COM3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That pipeline can run unit tests, compile, upload, serial
verification, and optional capture/analysis phases.&lt;/p&gt;
&lt;h3 id=&quot;validate-on-wire-behavior-with-saleae&quot;&gt;5) Validate on-wire
behavior with Saleae&lt;/h3&gt;
&lt;p&gt;The logic analyzer phase is where protocol assumptions get
tested.&lt;/p&gt;
&lt;p&gt;For UART work:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Confirm bus settings (baud, parity, stop bits) match the target
mode&lt;/li&gt;
&lt;li&gt;Verify frame boundaries and inter-frame timing&lt;/li&gt;
&lt;li&gt;Check CRC byte placement and value against expected payload
sum/complement logic&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If using the helper scripts in this repo:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre
class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;python&lt;/span&gt; tools/capture_v9381_uart.py&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;python&lt;/span&gt; tools/analyze_checksum_captures.py &lt;span class=&quot;pp&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;capture_dir&lt;/span&gt;&lt;span class=&quot;pp&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This gives a concrete report of expected vs observed CRC and whether
behaviour matches Clean vs Dirty semantics.&lt;/p&gt;
&lt;h2 id=&quot;what-changed-in-my-debugging-habits&quot;&gt;What changed in my
debugging habits&lt;/h2&gt;
&lt;h3 id=&quot;old-approach&quot;&gt;Old approach&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Edit sketch&lt;/li&gt;
&lt;li&gt;Upload&lt;/li&gt;
&lt;li&gt;Stare at serial output&lt;/li&gt;
&lt;li&gt;Guess&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;new-approach&quot;&gt;New approach&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ask Copilot for narrow, test-backed change&lt;/li&gt;
&lt;li&gt;Build and flash with Arduino CLI from script&lt;/li&gt;
&lt;li&gt;Capture with Saleae and compare against expected frame math&lt;/li&gt;
&lt;li&gt;Feed mismatch details back into Copilot for targeted fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It feels closer to hardware TDD than trial-and-error firmware
hacking.&lt;/p&gt;
&lt;h2 id=&quot;trade-offs-and-cost-notes&quot;&gt;Trade-offs and cost notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Arduino CLI is free and excellent for repeatable CI-style local
loops&lt;/li&gt;
&lt;li&gt;Copilot is a paid productivity tool, but pays for itself when
protocol code churn is high&lt;/li&gt;
&lt;li&gt;Saleae hardware is not cheap, but it can save days when
parity/timing/CRC bugs are subtle&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are doing serious serial or SPI driver work, a logic analyzer
is not optional for long.&lt;/p&gt;
&lt;h2 id=&quot;troubleshooting-notes-that-keep-coming-up&quot;&gt;Troubleshooting notes
that keep coming up&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Wrong serial configuration (especially parity) can look like random
CRC failure.&lt;/li&gt;
&lt;li&gt;Upload success does not imply runtime protocol correctness.&lt;/li&gt;
&lt;li&gt;Dirty mode can hide issues by design; keep a Clean mode path for
strict validation.&lt;/li&gt;
&lt;li&gt;Keep datasheet extracts in-repo so Copilot prompts reference real
tables, not memory.&lt;/li&gt;
&lt;li&gt;A scripted workflow (&lt;code&gt;pdf-reader-mcp&lt;/code&gt; +
&lt;code&gt;arduino-cli&lt;/code&gt; + capture + analysis) beats ad-hoc manual steps
every time.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;closing&quot;&gt;Closing&lt;/h2&gt;
&lt;p&gt;For this V93XX work, the winning combination was AI-assisted coding
plus old-school instrumentation.&lt;/p&gt;
&lt;p&gt;Copilot helps me move faster, Arduino CLI keeps the loop
reproducible, and Saleae captures keep me honest.&lt;/p&gt;
&lt;p&gt;If you are building protocol drivers, treat those as complementary
tools, not alternatives.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/8038859141391912899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/8038859141391912899' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8038859141391912899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8038859141391912899'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/02/copilot-arduino-cli-saleae-driver.html' title='Copilot + Arduino CLI + Saleae: Driver Development for V93XX'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/7EaPbl-LAnU/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-3902826425366259988</id><published>2026-01-27T16:00:00.000-08:00</published><updated>2026-02-01T14:55:15.971-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="artix-7"/><category scheme="http://www.blogger.com/atom/ns#" term="fpga"/><category scheme="http://www.blogger.com/atom/ns#" term="jtag"/><category scheme="http://www.blogger.com/atom/ns#" term="litex"/><category scheme="http://www.blogger.com/atom/ns#" term="netv2"/><category scheme="http://www.blogger.com/atom/ns#" term="openocd"/><category scheme="http://www.blogger.com/atom/ns#" term="pcileech"/><category scheme="http://www.blogger.com/atom/ns#" term="raspberry-pi"/><title type='text'>Loading FPGA Bitstreams with OpenOCD and Raspberry Pi - From Captain DMA to NeTV2</title><content type='html'>&lt;h2 id=&quot;a-hot-adelaide-afternoon-and-a-pile-of-fpgas&quot;&gt;A Hot Adelaide Afternoon and a Pile of FPGAs&lt;/h2&gt;
&lt;p&gt;I was recruited to wire together the NeTV2 to the Raspberry Pi 5 PCI bus by some means. &lt;a href=&quot;https://wafer.space/about.html&quot;&gt;Tim&lt;/a&gt; donated a bunch of hardware to make it work. I picked them up from his place, while he sorted through the contents of his container. The ultimate aim is to get them going as part of &lt;a href=&quot;https://ps1.fpgas.online/fpgas/&quot;&gt;fpgas.online&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The box contained a treasure trove: an NeTV2 boards from bunnie’s (Andrew Huang) video overlay project, and lots of Raspberry Pi’s. As I went down the rabbit hole I acquired some more hardware for myself, Captain DMA development boards, and various other Artix-7 based experiments (Acorn, LiteFury). These boards share a common trait – they’re designed to appear as network devices on a PCI Express bus, which makes them interesting for all sorts of applications from video processing to… let’s say “creative” system analysis and game hacking using auto-target features.&lt;/p&gt;
&lt;p&gt;The challenge with inheriting random FPGA boards is getting new gateware onto them. The original programming cables might be lost, proprietary software might be Windows-only and in Chinese, and documentation can be scarce. This is where OpenOCD and a humble Raspberry Pi come to the rescue. As long as you figure out which pins are the JTAG, and can get a &lt;a href=&quot;https://github.com/AlphamaxMedia/netv2mvp-scripts/pull/1&quot;&gt;PR merged&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczOoOvoR6l13ubi_mrwFfM_4AexAW6DQ67SRTvG84NPs9llZma4NHTbgRZddiWEIbVjv7ujPzQsXrDTlO-DuvTyCz--4eKXX42wxqpAh3HmPKIcq81SGyrK7f5IVY1fBRHh-byXhQxAUtYIBd3pMgwRUQQ=w623-h827-s-no-gm?authuser=0&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;Pi4 and Pi5 with NeTV2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-problem-dma-cards-and-their-programming-woes&quot;&gt;The Problem: DMA Cards and Their Programming Woes&lt;/h2&gt;
&lt;p&gt;Captain DMA cards (and similar Artix-7 based DMA devices) typically come with a CH347 USB JTAG interface. The vendor provides a GUI tool, but it’s entirely in Chinese and only runs on Windows. For those of us who prefer reproducible, scripted workflows on Linux – or want to program boards headless on a Raspberry Pi – this is less than ideal.&lt;/p&gt;
&lt;p&gt;The workflow the GUI implements is actually straightforward:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;Connect to the CH347 JTAG interface&lt;/li&gt;
&lt;li&gt;Detect the FPGA/JTAG chain&lt;/li&gt;
&lt;li&gt;Load a BSCAN SPI bitstream for JTAG-to-SPI access&lt;/li&gt;
&lt;li&gt;Program the SPI flash with the target FPGA image&lt;/li&gt;
&lt;li&gt;Refresh the FPGA to load the new bitstream&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key insight is that we’re not programming the FPGA directly – we’re using JTAG to access the SPI flash chip that stores the bitstream. The BSCAN primitive acts as a bridge between JTAG and the SPI flash.&lt;/p&gt;
&lt;h2 id=&quot;openocd-scripts-for-captain-dma&quot;&gt;OpenOCD Scripts for Captain DMA&lt;/h2&gt;
&lt;p&gt;I’ve put together a set of scripts at https://github.com/whatnick/fpga-dma-scripts that replicate the Chinese GUI’s functionality using pure OpenOCD commands. The scripts support Linux/macOS and Windows, and handle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatic BSCAN bitstream download from quartiq’s prebuilt collection&lt;/li&gt;
&lt;li&gt;CH347 interface configuration installation&lt;/li&gt;
&lt;li&gt;Version checking for OpenOCD (needs 0.12.0+dev for CH347 support)&lt;/li&gt;
&lt;li&gt;Cross-platform flashing with proper error handling&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczPqLlS0_Fq1p9r7yxBNHXH110BrGtYnbzos090yTkNh9eg_dLfoH4uCBVidZTUjEHbep07EJZ1xLxtyRg2cz_kSP5-T4r_m1hA3vvau9xRkNZamT8G6mIwK9vOE-0In1jeeLv6l_WCQzXHXy70ql4QjwQ=w1098-h827-s-no-gm?authuser=0&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;Captain DMA clone attached to Raspberry Pi&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;basic-usage&quot;&gt;Basic Usage&lt;/h3&gt;
&lt;p&gt;On Linux/macOS:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a href=&quot;#cb1-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;./flash.sh&lt;/span&gt; 75t /path/to/pcileech_75t484_x1.bin&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;On Windows:&lt;/p&gt;
&lt;pre class=&quot;cmd&quot;&gt;&lt;code&gt;flash.cmd 75t C:\path\to\pcileech_75t484_x1.bin&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The scripts support three Artix-7 variants: 35T, 75T, and 100T. The underlying OpenOCD command is:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb3&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb3-1&quot;&gt;&lt;a href=&quot;#cb3-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;openocd&lt;/span&gt; -c &lt;span class=&quot;st&quot;&gt;&amp;quot;set BSCAN_FILE bscan_spi_xc7a75t.bit&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-2&quot;&gt;&lt;a href=&quot;#cb3-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ex&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;set FPGAIMAGE pcileech_75t484_x1.bin&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb3-3&quot;&gt;&lt;a href=&quot;#cb3-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;ex&quot;&gt;-f&lt;/span&gt; flash.cfg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The flash.cfg orchestrates the JTAG chain detection, BSCAN loading, and SPI programming sequence.&lt;/p&gt;
&lt;h3 id=&quot;example-output&quot;&gt;Example Output&lt;/h3&gt;
&lt;p&gt;A successful flash looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Open On-Chip Debugger 0.12.0+dev-02377-gb9e401616 (2026-01-25-09:47)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
xc7_program
jtagspi_program
Info : CH347 USB To UART+JTAG from vendor wch.cn with serial number 0123456789 found. (Chip version=5.44, Firmware=0x45)
Info : clock speed 7500 kHz
Info : JTAG tap: xc7.tap tap/device found: 0x13632093 (mfg: 0x049 (Xilinx), part: 0x3632, ver: 0x1)
Info : [xc7.proxy] Examination succeed
Info : Found flash device &amp;#39;win w25q64fv/jv&amp;#39; (ID 0x1740ef)
Info : sector 0 took 234 ms
Info : sector 1 took 250 ms
...
Info : sector 32 took 259 ms
Info : sector 33 took 256 ms&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each sector takes about 230-260ms to program. A full 75T bitstream covers around 34 sectors, so expect 8-10 seconds for the flash operation.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczOWiH7EPsnYT2TNeojmmERC_bMaomprkOQTDBU2O01TtNoX2w5f-m1VA3dsmcNbFfQ9GEZ5TQ2BLBNAUeF-vajcSMzXwtf1lzdK7oFaN-77kjOEej52QDaqun4EdPgxVdxmeAPZbGm-nOePuLR3TAghcQ=w1098-h827-s-no-gm?authuser=0&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;NeTV2 Wired over PCI-e&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;netv2-bunnies-video-overlay-board&quot;&gt;NeTV2: Bunnie’s Video Overlay Board&lt;/h2&gt;
&lt;p&gt;The NeTV2 (Network Television version 2) is bunnie’s open-source HDMI video overlay board. It uses the same Xilinx Artix-7 family (XC7A35T or XC7A100T depending on variant) and was designed for real-time HDMI signal processing. The board features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Artix-7 FPGA (35T or 100T variant)&lt;/li&gt;
&lt;li&gt;DDR3 SDRAM (K4B2G1646F)&lt;/li&gt;
&lt;li&gt;PCIe x4 interface&lt;/li&gt;
&lt;li&gt;RMII Ethernet&lt;/li&gt;
&lt;li&gt;HDMI input and output&lt;/li&gt;
&lt;li&gt;SD card slot&lt;/li&gt;
&lt;li&gt;SPI flash for bitstream storage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The original NeTV2 scripts from bunnie’s repo (https://github.com/bunnie/netv2mvp-scripts) were designed for Raspberry Pi 2/3 using the older sysfs GPIO interface. I’ve submitted a PR (https://github.com/AlphamaxMedia/netv2mvp-scripts/pull/1) that updates these for Raspberry Pi 4 and upstream OpenOCD.&lt;/p&gt;
&lt;h3 id=&quot;raspberry-pi-4-gpio-jtag-configuration&quot;&gt;Raspberry Pi 4 GPIO JTAG Configuration&lt;/h3&gt;
&lt;p&gt;The key changes for RPi4 compatibility involve the &lt;code&gt;bcm2835gpio&lt;/code&gt; driver configuration:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb5&quot;&gt;&lt;pre class=&quot;sourceCode tcl&quot;&gt;&lt;code class=&quot;sourceCode tcl&quot;&gt;&lt;span id=&quot;cb5-1&quot;&gt;&lt;a href=&quot;#cb5-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Boilerplate setup for Rpi on Alphamax configuration&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-2&quot;&gt;&lt;a href=&quot;#cb5-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-3&quot;&gt;&lt;a href=&quot;#cb5-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter driver bcm2835gpio&lt;/span&gt;
&lt;span id=&quot;cb5-4&quot;&gt;&lt;a href=&quot;#cb5-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-5&quot;&gt;&lt;a href=&quot;#cb5-5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;transport &lt;span class=&quot;ot&quot;&gt;select&lt;/span&gt; jtag&lt;/span&gt;
&lt;span id=&quot;cb5-6&quot;&gt;&lt;a href=&quot;#cb5-6&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-7&quot;&gt;&lt;a href=&quot;#cb5-7&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;set&lt;/span&gt; _CHIPNAME xc7a35t&lt;/span&gt;
&lt;span id=&quot;cb5-8&quot;&gt;&lt;a href=&quot;#cb5-8&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-9&quot;&gt;&lt;a href=&quot;#cb5-9&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Raspi4 uses a different peripheral base address&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-10&quot;&gt;&lt;a href=&quot;#cb5-10&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# RPi 2/3: 0x3F000000&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-11&quot;&gt;&lt;a href=&quot;#cb5-11&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# RPi 4:   0xFE000000&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-12&quot;&gt;&lt;a href=&quot;#cb5-12&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;bcm2835gpio peripheral_base &lt;span class=&quot;dv&quot;&gt;0x3F000000&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-13&quot;&gt;&lt;a href=&quot;#cb5-13&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-14&quot;&gt;&lt;a href=&quot;#cb5-14&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Speed coefficients tuned for RPi 3B+&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-15&quot;&gt;&lt;a href=&quot;#cb5-15&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;bcm2835gpio speed_coeffs &lt;span class=&quot;dv&quot;&gt;100000&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-16&quot;&gt;&lt;a href=&quot;#cb5-16&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-17&quot;&gt;&lt;a href=&quot;#cb5-17&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# GPIO pin assignments for JTAG&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-18&quot;&gt;&lt;a href=&quot;#cb5-18&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter gpio tck &lt;span class=&quot;dv&quot;&gt;4&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-19&quot;&gt;&lt;a href=&quot;#cb5-19&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter gpio tms &lt;span class=&quot;dv&quot;&gt;17&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-20&quot;&gt;&lt;a href=&quot;#cb5-20&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter gpio tdi &lt;span class=&quot;dv&quot;&gt;27&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-21&quot;&gt;&lt;a href=&quot;#cb5-21&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter gpio tdo &lt;span class=&quot;dv&quot;&gt;22&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-22&quot;&gt;&lt;a href=&quot;#cb5-22&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter gpio srst &lt;span class=&quot;dv&quot;&gt;24&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-23&quot;&gt;&lt;a href=&quot;#cb5-23&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-24&quot;&gt;&lt;a href=&quot;#cb5-24&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;reset_config none&lt;/span&gt;
&lt;span id=&quot;cb5-25&quot;&gt;&lt;a href=&quot;#cb5-25&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb5-26&quot;&gt;&lt;a href=&quot;#cb5-26&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;adapter speed &lt;span class=&quot;dv&quot;&gt;10000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The GPIO pins map directly to the Raspberry Pi’s header:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr class=&quot;header&quot;&gt;
&lt;th&gt;Signal&lt;/th&gt;
&lt;th&gt;GPIO&lt;/th&gt;
&lt;th&gt;Physical Pin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;TCK&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;TMS&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;TDI&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;even&quot;&gt;
&lt;td&gt;TDO&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr class=&quot;odd&quot;&gt;
&lt;td&gt;SRST&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;spi-flash-programming-with-raspberry-pi&quot;&gt;SPI Flash Programming with Raspberry Pi&lt;/h3&gt;
&lt;p&gt;The cl-spifpga-rpi4.cfg config file handles the actual programming:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb6&quot;&gt;&lt;pre class=&quot;sourceCode tcl&quot;&gt;&lt;code class=&quot;sourceCode tcl&quot;&gt;&lt;span id=&quot;cb6-1&quot;&gt;&lt;a href=&quot;#cb6-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Burn an FPGA image onto the SPI ROM&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-2&quot;&gt;&lt;a href=&quot;#cb6-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-3&quot;&gt;&lt;a href=&quot;#cb6-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ot&quot;&gt;find&lt;/span&gt; interface/alphamax-rpi.cfg&lt;span class=&quot;kw&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-4&quot;&gt;&lt;a href=&quot;#cb6-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-5&quot;&gt;&lt;a href=&quot;#cb6-5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ot&quot;&gt;find&lt;/span&gt; cpld/xilinx-xc7.cfg&lt;span class=&quot;kw&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-6&quot;&gt;&lt;a href=&quot;#cb6-6&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ot&quot;&gt;find&lt;/span&gt; cpld/jtagspi.cfg&lt;span class=&quot;kw&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-7&quot;&gt;&lt;a href=&quot;#cb6-7&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-8&quot;&gt;&lt;a href=&quot;#cb6-8&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;init&lt;/span&gt;
&lt;span id=&quot;cb6-9&quot;&gt;&lt;a href=&quot;#cb6-9&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-10&quot;&gt;&lt;a href=&quot;#cb6-10&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;jtagspi_init xc7.pld &lt;span class=&quot;dt&quot;&gt;$BSCAN_FILE&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-11&quot;&gt;&lt;a href=&quot;#cb6-11&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;jtagspi_program &lt;span class=&quot;dt&quot;&gt;$FPGAIMAGE&lt;/span&gt; &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-12&quot;&gt;&lt;a href=&quot;#cb6-12&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-13&quot;&gt;&lt;a href=&quot;#cb6-13&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;virtex2 refresh xc7.pld&lt;/span&gt;
&lt;span id=&quot;cb6-14&quot;&gt;&lt;a href=&quot;#cb6-14&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb6-15&quot;&gt;&lt;a href=&quot;#cb6-15&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;exit&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The command to flash a NeTV2 from a Raspberry Pi:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb7&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb7-1&quot;&gt;&lt;a href=&quot;#cb7-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;/opt/openocd/src/openocd&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-2&quot;&gt;&lt;a href=&quot;#cb7-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;set BSCAN_FILE /home/k8s/netv2mvp-scripts/bscan_spi_xc7a100t.bit&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-3&quot;&gt;&lt;a href=&quot;#cb7-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;set FPGAIMAGE /home/k8s/pcileech_netv2_top.bin&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb7-4&quot;&gt;&lt;a href=&quot;#cb7-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;  &lt;span class=&quot;ex&quot;&gt;-f&lt;/span&gt; /home/k8s/netv2mvp-scripts/cl-spifpga-rpi4.cfg&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The output shows the Macronix SPI flash being programmed:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Info : BCM2835 GPIO JTAG/SWD bitbang driver
Info : clock speed 10000 kHz
Info : JTAG tap: xc7.tap tap/device found: 0x13631093 (mfg: 0x049 (Xilinx), part: 0x3631, ver: 0x1)
Info : [xc7.proxy] Examination succeed
Info : Found flash device &amp;#39;mac 25l6405&amp;#39; (ID 0x1720c2)
Info : sector 0 took 286 ms
Info : sector 1 took 282 ms
...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note the device ID difference: &lt;code&gt;0x13631093&lt;/code&gt; for the 100T part versus &lt;code&gt;0x13632093&lt;/code&gt; for the 75T. The flash chip is a Macronix MX25L6405 (ID 0x1720c2) versus the Winbond W25Q64FV (ID 0x1740ef) on the Captain DMA boards.&lt;/p&gt;
&lt;h2 id=&quot;litex-builds-for-netv2&quot;&gt;LiteX Builds for NeTV2&lt;/h2&gt;
&lt;p&gt;If you want to run something other than the original gateware, LiteX has excellent support for the NeTV2. The board definition lives at https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/kosagi_netv2.py.&lt;/p&gt;
&lt;h3 id=&quot;building-a-basic-litex-soc&quot;&gt;Building a Basic LiteX SoC&lt;/h3&gt;
&lt;p&gt;Install LiteX following the standard setup, then:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb9&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb9-1&quot;&gt;&lt;a href=&quot;#cb9-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;bu&quot;&gt;cd&lt;/span&gt; litex-boards/litex_boards/targets&lt;/span&gt;
&lt;span id=&quot;cb9-2&quot;&gt;&lt;a href=&quot;#cb9-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-3&quot;&gt;&lt;a href=&quot;#cb9-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Build for XC7A35T variant with Ethernet&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-4&quot;&gt;&lt;a href=&quot;#cb9-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;./kosagi_netv2.py&lt;/span&gt; --variant=a7-35 --with-ethernet --build&lt;/span&gt;
&lt;span id=&quot;cb9-5&quot;&gt;&lt;a href=&quot;#cb9-5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-6&quot;&gt;&lt;a href=&quot;#cb9-6&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Or for the 100T variant with PCIe&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb9-7&quot;&gt;&lt;a href=&quot;#cb9-7&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;./kosagi_netv2.py&lt;/span&gt; --variant=a7-100 --with-pcie --build&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The target supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DDR3 SDRAM&lt;/strong&gt;: Using the K4B2G1646F module with LiteDRAM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ethernet&lt;/strong&gt;: RMII PHY via LiteEth&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCIe&lt;/strong&gt;: x4 Gen2 via LitePCIe&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SD Card&lt;/strong&gt;: Both SPI mode and native SDIO&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LED Chaser&lt;/strong&gt;: For the obligatory blinky demo&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;platform-definition-highlights&quot;&gt;Platform Definition Highlights&lt;/h3&gt;
&lt;p&gt;The platform file defines the IO constraints:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb10&quot;&gt;&lt;pre class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb10-1&quot;&gt;&lt;a href=&quot;#cb10-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;_io &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; [&lt;/span&gt;
&lt;span id=&quot;cb10-2&quot;&gt;&lt;a href=&quot;#cb10-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;# 50 MHz clock input&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-3&quot;&gt;&lt;a href=&quot;#cb10-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;st&quot;&gt;&amp;quot;clk50&amp;quot;&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;J19&amp;quot;&lt;/span&gt;), IOStandard(&lt;span class=&quot;st&quot;&gt;&amp;quot;LVCMOS33&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-4&quot;&gt;&lt;a href=&quot;#cb10-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb10-5&quot;&gt;&lt;a href=&quot;#cb10-5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;# User LEDs&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-6&quot;&gt;&lt;a href=&quot;#cb10-6&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;st&quot;&gt;&amp;quot;user_led&amp;quot;&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;M21&amp;quot;&lt;/span&gt;),  IOStandard(&lt;span class=&quot;st&quot;&gt;&amp;quot;LVCMOS33&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-7&quot;&gt;&lt;a href=&quot;#cb10-7&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;st&quot;&gt;&amp;quot;user_led&amp;quot;&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;1&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;N20&amp;quot;&lt;/span&gt;),  IOStandard(&lt;span class=&quot;st&quot;&gt;&amp;quot;LVCMOS33&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-8&quot;&gt;&lt;a href=&quot;#cb10-8&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;# ...&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-9&quot;&gt;&lt;a href=&quot;#cb10-9&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;/span&gt;
&lt;span id=&quot;cb10-10&quot;&gt;&lt;a href=&quot;#cb10-10&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;co&quot;&gt;# SPI Flash for bitstream storage&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb10-11&quot;&gt;&lt;a href=&quot;#cb10-11&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    (&lt;span class=&quot;st&quot;&gt;&amp;quot;spiflash&amp;quot;&lt;/span&gt;, &lt;span class=&quot;dv&quot;&gt;0&lt;/span&gt;,&lt;/span&gt;
&lt;span id=&quot;cb10-12&quot;&gt;&lt;a href=&quot;#cb10-12&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        Subsignal(&lt;span class=&quot;st&quot;&gt;&amp;quot;cs_n&amp;quot;&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;T19&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-13&quot;&gt;&lt;a href=&quot;#cb10-13&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        Subsignal(&lt;span class=&quot;st&quot;&gt;&amp;quot;mosi&amp;quot;&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;P22&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-14&quot;&gt;&lt;a href=&quot;#cb10-14&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        Subsignal(&lt;span class=&quot;st&quot;&gt;&amp;quot;miso&amp;quot;&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;R22&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-15&quot;&gt;&lt;a href=&quot;#cb10-15&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        Subsignal(&lt;span class=&quot;st&quot;&gt;&amp;quot;wp&amp;quot;&lt;/span&gt;,   Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;P21&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-16&quot;&gt;&lt;a href=&quot;#cb10-16&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        Subsignal(&lt;span class=&quot;st&quot;&gt;&amp;quot;hold&amp;quot;&lt;/span&gt;, Pins(&lt;span class=&quot;st&quot;&gt;&amp;quot;R21&amp;quot;&lt;/span&gt;)),&lt;/span&gt;
&lt;span id=&quot;cb10-17&quot;&gt;&lt;a href=&quot;#cb10-17&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        IOStandard(&lt;span class=&quot;st&quot;&gt;&amp;quot;LVCMOS33&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb10-18&quot;&gt;&lt;a href=&quot;#cb10-18&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    ),&lt;/span&gt;
&lt;span id=&quot;cb10-19&quot;&gt;&lt;a href=&quot;#cb10-19&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The platform also defines the programmer configuration, which now supports both OpenOCD and OpenFPGALoader:&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb11&quot;&gt;&lt;pre class=&quot;sourceCode python&quot;&gt;&lt;code class=&quot;sourceCode python&quot;&gt;&lt;span id=&quot;cb11-1&quot;&gt;&lt;a href=&quot;#cb11-1&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;&lt;span class=&quot;kw&quot;&gt;def&lt;/span&gt; create_programmer(&lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;, programmer&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;openocd&amp;quot;&lt;/span&gt;):&lt;/span&gt;
&lt;span id=&quot;cb11-2&quot;&gt;&lt;a href=&quot;#cb11-2&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; programmer &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;openfpgaloader&amp;quot;&lt;/span&gt;:&lt;/span&gt;
&lt;span id=&quot;cb11-3&quot;&gt;&lt;a href=&quot;#cb11-3&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; OpenFPGALoader(cable&lt;span class=&quot;op&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;st&quot;&gt;&amp;quot;digilent_hs2&amp;quot;&lt;/span&gt;)&lt;/span&gt;
&lt;span id=&quot;cb11-4&quot;&gt;&lt;a href=&quot;#cb11-4&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;    &lt;span class=&quot;cf&quot;&gt;elif&lt;/span&gt; programmer &lt;span class=&quot;op&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;openocd&amp;quot;&lt;/span&gt;:&lt;/span&gt;
&lt;span id=&quot;cb11-5&quot;&gt;&lt;a href=&quot;#cb11-5&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        bscan_spi &lt;span class=&quot;op&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;bscan_spi_xc7a100t.bit&amp;quot;&lt;/span&gt; &lt;span class=&quot;cf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;xc7a100t&amp;quot;&lt;/span&gt; &lt;span class=&quot;kw&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;va&quot;&gt;self&lt;/span&gt;.device &lt;span class=&quot;cf&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&amp;quot;bscan_spi_xc7a35t.bit&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb11-6&quot;&gt;&lt;a href=&quot;#cb11-6&quot; aria-hidden=&quot;true&quot;&gt;&lt;/a&gt;        &lt;span class=&quot;cf&quot;&gt;return&lt;/span&gt; OpenOCD(&lt;span class=&quot;st&quot;&gt;&amp;quot;openocd_netv2_rpi.cfg&amp;quot;&lt;/span&gt;, bscan_spi)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id=&quot;provisioning-for-fpgas.online&quot;&gt;Provisioning for fpgas.online&lt;/h2&gt;
&lt;p&gt;The ultimate destination for these NeTV2 boards is &lt;a href=&quot;https://ps1.fpgas.online/fpgas/&quot;&gt;fpgas.online&lt;/a&gt; – a community project that provides free remote access to FPGA development boards. The service currently has around 10 FPGA boards connected, each with a webcam pointed at the LEDs so you can see your bitstream running in real-time.&lt;/p&gt;
&lt;p&gt;Each board is attached to a Raspberry Pi that handles:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JTAG programming via the GPIO bitbang interface&lt;/li&gt;
&lt;li&gt;Webcam streaming for visual feedback&lt;/li&gt;
&lt;li&gt;Web-based terminal access for interactive development&lt;/li&gt;
&lt;li&gt;Queue management so multiple users can share the hardware&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where the Raspberry Pi JTAG programming approach really shines – you can reflash gateware remotely without any physical access to the boards. Combined with LiteX’s rapid build cycle, it becomes practical to iterate on FPGA designs from anywhere in the world.&lt;/p&gt;
&lt;p&gt;If you want to try FPGA development without buying hardware, head over to https://ps1.fpgas.online/fpgas/ and claim a board. There’s usually one free and ready to use.&lt;/p&gt;
&lt;h2 id=&quot;why-this-matters&quot;&gt;Why This Matters&lt;/h2&gt;
&lt;p&gt;These techniques apply to any Artix-7 board with SPI flash storage:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;: Scripts in version control beat clicking through GUIs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt;: CI/CD pipelines can flash test firmware automatically&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Headless operation&lt;/strong&gt;: A Raspberry Pi in a lab can program boards remotely&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cross-platform&lt;/strong&gt;: The same OpenOCD configs work on Linux, macOS, and Windows&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool preservation&lt;/strong&gt;: When vendors disappear, open source tooling remains&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remote labs&lt;/strong&gt;: Services like fpgas.online can offer FPGA access to anyone&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The BSCAN SPI approach is particularly elegant – it uses a small “helper” bitstream that turns the FPGA’s JTAG interface into a SPI master, allowing you to program the flash chip that normally stores the FPGA configuration. Once programmed, a power cycle or refresh command loads the new bitstream.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;fpgas.online Remote Lab&lt;/strong&gt;: https://ps1.fpgas.online/fpgas/&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Captain DMA Scripts&lt;/strong&gt;: https://github.com/whatnick/fpga-dma-scripts&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NeTV2 RPi4 Scripts&lt;/strong&gt;: https://github.com/AlphamaxMedia/netv2mvp-scripts/pull/1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LiteX NeTV2 Target&lt;/strong&gt;: https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/kosagi_netv2.py&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BSCAN SPI Bitstreams&lt;/strong&gt;: https://github.com/quartiq/bscan_spi_bitstreams&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PCILeech FPGA Project&lt;/strong&gt;: https://github.com/ufrisk/pcileech-fpga&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Video Walkthrough&lt;/strong&gt;: https://youtu.be/CNQnafoOTCM&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next time you inherit a box of mystery FPGA boards, you’ll know what to do. OpenOCD and a Raspberry Pi can breathe new life into almost any Xilinx 7-series board – no proprietary tools, no Windows VM, no Chinese language skills required.&lt;/p&gt;
&lt;figure&gt;
&lt;img src=&quot;https://lh3.googleusercontent.com/pw/AP1GczPZTGeXPh0Ry_lgyPZ0yhLZl4BcrjvF-NaD50y8osBgnp2dtR0uZrm_r538wEhMsWBX8ep3OPvhO69x2tmD83rr8uks9dgh_zTgIKf87Ku_lVv-3gd2aPdeZgokvfRA3U1Rh7DyXFdMkq2EtfZN6O_YGw=w623-h827-s-no-gm?authuser=0&quot; alt=&quot;&quot; /&gt;&lt;figcaption&gt;SQRL Acorn boards&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Feel free to ping me with other interesting DMA or video processing boards you’ve encountered. There’s always more gateware to explore.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/3902826425366259988/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/3902826425366259988' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/3902826425366259988'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/3902826425366259988'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2026/01/loading-fpga-bitstreams-with-openocd.html' title='Loading FPGA Bitstreams with OpenOCD and Raspberry Pi - From Captain DMA to NeTV2'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/pw/AP1GczOoOvoR6l13ubi_mrwFfM_4AexAW6DQ67SRTvG84NPs9llZma4NHTbgRZddiWEIbVjv7ujPzQsXrDTlO-DuvTyCz--4eKXX42wxqpAh3HmPKIcq81SGyrK7f5IVY1fBRHh-byXhQxAUtYIBd3pMgwRUQQ=s72-w623-h827-s-c-no-gm?authuser=0" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-7017091486894311247</id><published>2025-12-24T16:00:00.000-08:00</published><updated>2025-12-28T19:12:26.399-08:00</updated><title type='text'>Seven Years to Kubernetes: A Turing Pi 1 Christmas Miracle</title><content type='html'>&lt;figure&gt;&lt;img alt=&quot;Turing Pi 1 Cluster Board&quot; src=&quot;https://lh3.googleusercontent.com/pw/AP1GczNgAdriNJGw8gK7NeudfKWQ0xZaDhEiSRbRf1I5rqddafhjWINTGRnSUMnaiMZlq3MlNdjY6BZa5hEN_TFpA9E4t1g67WWRx4zzQO4InPSb0YEISAeva-mmStspIGT0XuA3Q2flBDedhgUKiM0waiLz4A=w979-h1305-s-no-gm?authuser=0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Turing Pi 1 Cluster Board&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-seven-year-itch-for-hardware&quot;&gt;The Seven Year Itch (For
Hardware)&lt;/h2&gt;
&lt;p&gt;Often I buy more hardware than I need. &lt;del&gt;Actually, strike
that&lt;/del&gt; – I &lt;em&gt;always&lt;/em&gt; buy more hardware than I need. It’s a
disease, really. This particular affliction manifested in 2018 when I
pre-ordered a &lt;a href=&quot;https://turingpi.com/&quot;&gt;Turing Pi 1&lt;/a&gt; because I
had convinced myself that building a Raspberry Pi cluster would be the
&lt;em&gt;perfect&lt;/em&gt; way to learn Kubernetes.&lt;/p&gt;
&lt;p&gt;It was not the perfect way.&lt;/p&gt;
&lt;p&gt;Little did I realize that it would take me &lt;strong&gt;seven
years&lt;/strong&gt; to gather all seven &lt;a href=&quot;https://www.mouser.com/new/raspberry-pi/raspberry-pi-cm3plus-compute-modules/&quot;&gt;Raspberry
Pi Compute Module 3+&lt;/a&gt; boards and finally bootstrap a &lt;a href=&quot;https://k3s.io/&quot;&gt;k3s&lt;/a&gt; cluster. In that time:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Kubernetes went through approximately 47 major versions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Raspberry Pi 4 and 5 came out (and experienced their own chip
shortages)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I discovered my Turing Pi board had a faulty ethernet
switch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I aged visibly, just look at my github profile and videos from
recent conference presentations.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!--Image: Close-up of the faulty ethernet switch IC--&gt;
&lt;figure&gt;
&lt;img alt=&quot;The Ethernet Switch of Broken Dreams&quot; src=&quot;https://lh3.googleusercontent.com/pw/AP1GczPkgl5Y3sIwqYwnvloHPWnmbpOhT1GZsTpGlOvbYbDyw1vBK_Tzt3W00DC2TwcP76WwPqIusmtvnNh3CepfQdDCOSNaCmJ3dFqLQ_s5nv4CI5BSMtMJgnsopHPj27SBggWoAXJZuYw2VLsZ8jzTRIkL8g=w1733-h1305-s-no-gm?authuser=0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;The Ethernet Switch of Broken
Dreams&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-recipe-for-homelab-kubernetes-suffering&quot;&gt;The Recipe for
Homelab Kubernetes Suffering&lt;/h2&gt;
&lt;p&gt;In this write-up, I’ll outline what it &lt;em&gt;actually&lt;/em&gt; takes to set
up a Raspberry Pi 3+ cluster in 2025. Consider this a cautionary tale
wrapped in a tutorial. I’ll probably resell this now-functioning cluster
to another masochist – er, enthusiast – and use the recouped capital to
buy something newer that will sit on my shelf for another seven
years.&lt;/p&gt;
&lt;h3 id=&quot;step-1-acquire-the-base-board&quot;&gt;Step 1: Acquire the Base
Board&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://turingpi.com/&quot;&gt;Turing Pi 1&lt;/a&gt; was a great
option back in the day. It’s a mini-ITX form factor board that accepts
up to 7 Raspberry Pi Compute Modules in SODIMM slots. The on-board
gigabit ethernet switch was supposed to be the killer feature – no
external networking required!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Make sure the on-board switch actually
works. Test it &lt;em&gt;before&lt;/em&gt; you commit to this path. Mine didn’t,
which I discovered approximately 6 years too late.&lt;/p&gt;
&lt;!--Video: Quick overview of the Turing Pi 1 board layout--&gt;
&lt;h3 id=&quot;step-2-collect-your-compute-modules-like-pokemon-but-expensive&quot;&gt;Step
2: Collect Your Compute Modules (Like Pokemon, But Expensive)&lt;/h3&gt;
&lt;p&gt;You’ll need &lt;a href=&quot;https://www.mouser.com/c/embedded-solutions/computing/system-on-modules-som/?m=Raspberry%20Pi&amp;amp;series=Raspberry%20Pi%20CM3&quot;&gt;Raspberry
Pi Compute Module 3+&lt;/a&gt; boards. The Turing Pi 1 can handle up to 7 of
them. I sourced mine from &lt;a href=&quot;https://www.mouser.com/&quot;&gt;Mouser
Electronics&lt;/a&gt;, though availability has been… variable… over the
years.&lt;/p&gt;
&lt;p&gt;I really wish there were more alternatives in the SODIMM compute
module format. If you’re in the business of making one with a newer
processor and more RAM, let’s talk. Seriously. My DMs are open.&lt;/p&gt;
&lt;!--Image: All 7 compute modules laid out before installation--&gt;
&lt;figure&gt;
&lt;img alt=&quot;Seven Compute Modules Ready for Battle&quot; src=&quot;https://lh3.googleusercontent.com/pw/AP1GczPGChQz4ifz4urKNmdyqWAXq6iAyC_b9FiUxXpJqDfu9BKk-TPETVwa4LfGsJNvNB7v2baeTExC1c6-p2aF8FDo14__G2-rx_ToMTemDMSR26cwQeHBlj-SEQr_F6Mlj0ZWs30cazW8uNoLaWPX-HClzQ=w1733-h1305-s-no-gm?authuser=0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Seven Compute Modules Ready for
Battle&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;step-3-flash-the-os-the-easy-part-they-said&quot;&gt;Step 3: Flash the
OS (The Easy Part, They Said)&lt;/h3&gt;
&lt;p&gt;The Compute Modules have onboard eMMC storage, which is the preferred
boot device. Trying to use SD cards will lead to disappointment,
inconsistent boots, and existential questioning of your life
choices.&lt;/p&gt;
&lt;p&gt;Here’s the gear you’ll need:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A Compute Module IO Board&lt;/strong&gt; - Something like the
&lt;a href=&quot;https://www.waveshare.com/cm3-io-base-b.htm&quot;&gt;Waveshare CM3/CM3+
IO Board&lt;/a&gt; or the &lt;a href=&quot;https://www.raspberrypi.com/products/compute-module-io-board-v3/&quot;&gt;official
Raspberry Pi IO Board&lt;/a&gt; to put the module in USB mass storage
mode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/raspberrypi/usbboot&quot;&gt;rpiboot/usbboot&lt;/a&gt;&lt;/strong&gt;
- The tool that makes the eMMC appear as a USB drive&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://www.raspberrypi.com/software/&quot;&gt;Raspberry
Pi Imager&lt;/a&gt;&lt;/strong&gt; - The official tool for flashing OS
images&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Critical step&lt;/strong&gt;: Bake in your SSH public key during
the imaging process. This will save you from having to find 7 spare HDMI
cables and keyboards. The Pi Imager has a settings gear icon that lets
you configure hostname, SSH keys, and WiFi – use it.&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb1&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb1-1&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb1-1&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-2&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb1-2&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Generate an SSH key if you don&#39;t have one&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-3&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb1-3&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb1-4&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb1-4&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;ssh-keygen&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-t&lt;/span&gt; ed25519 &lt;span class=&quot;at&quot;&gt;-C&lt;/span&gt; &lt;span class=&quot;st&quot;&gt;&quot;kubernetes-cluster&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;!--Image: Compute module in the IO board, ready for flashing--&gt;
&lt;figure&gt;
&lt;img alt=&quot;Flashing Setup with IO Board&quot; src=&quot;https://lh3.googleusercontent.com/pw/AP1GczMGgzgkCJelT_sQGVEn5NoHlZ4Ja7A7ay4QDjt2Labml4e8884f-o2VeLAUwmpUG-fk8n2zRYVmwGMKMQdEYR6H_ItabmI4X4O866Avzv7jC6RY0jJsJYou_7Hn0ifUNpqVIlzwU86PNmB4kEIpsGQw1w=w960-h744-s-no-gm?authuser=0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Flashing Setup with IO Board&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;step-4-network-configuration-here-be-dragons&quot;&gt;Step 4: Network
Configuration (Here Be Dragons)&lt;/h3&gt;
&lt;p&gt;Plug in all the modules and fire up the on-board Turing Pi ethernet.
If you’re lucky, the on-board network works and you can access all the
nodes. Marvel at how easy this was.&lt;/p&gt;
&lt;p&gt;If you’re me, you’ll discover the switch is dead and enter the seven
stages of homelab grief:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Denial&lt;/strong&gt;: “It’s probably just a loose
connection”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anger&lt;/strong&gt;: Unprintable + emails to Turing Pi support
and learning that the board is End-of-Life and unsupported.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bargaining&lt;/strong&gt;: “Maybe I only need 4 nodes
anyway”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Depression&lt;/strong&gt;: &lt;em&gt;stares at pile of unused compute
modules&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Acceptance&lt;/strong&gt;: “I guess I’m buying USB ethernet
adapters”&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;The Workaround&lt;/strong&gt;: Get a bunch of USB-to-Ethernet
adapters like the &lt;a href=&quot;https://www.amazon.com/TP-Link-Foldable-Gigabit-Ethernet-Compatible/dp/B00YUU3KC6&quot;&gt;TP-Link
UE300&lt;/a&gt; and wire them into an external switch.&lt;/p&gt;
&lt;p&gt;Unfortunately, only 4 of the compute modules have their USB ports
exposed on the Turing Pi 1. For the other 3, you’ll need to do some
creative soldering to expose the USB D+/D- and power lines. That’s just
12 more flying wires on the board. What could go wrong?&lt;/p&gt;
&lt;!--Image: The magnificent spaghetti of USB ethernet adapters--&gt;
&lt;figure&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; src=&quot;https://www.youtube.com/embed/piBWttzrFEA&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;USB Ethernet Adapters and Working cluster&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;step-5-the-case-mod-optional-but-satisfying&quot;&gt;Step 5: The Case
Mod (Optional But Satisfying)&lt;/h3&gt;
&lt;p&gt;I got a nice acrylic case to put it all in. It has a fan connection
on top for cooling, which you’ll need because 7 Pi’s generate surprising
heat.&lt;/p&gt;
&lt;p&gt;There were no extra slots for the 3 additional USB connections I
needed. But I have a Dremel, two weeks of Christmas holidays, and
absolutely no fear of voiding warranties.&lt;/p&gt;
&lt;!--Image: The acrylic case with custom USB cutouts--&gt;
&lt;figure&gt;
&lt;img alt=&quot;Custom Dremel Work on Acrylic Case&quot; src=&quot;https://lh3.googleusercontent.com/pw/AP1GczO23WP7xUanX4BUTK0ksSsKq1aYG1xfjEElwC6AbSdDH3KWPek9k7PLhclnleIKFxz9nE_OVC3hOcZ1WE4Q0K6SFJDmgdD8Q4HRc66JfgqGD6z1u08Uf_RjGYZQzrqENKYpgvUJB0fC_ahoq_tqAGXcLA=w1024-h796-s-no-gm?authuser=0&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Custom Dremel Work on Acrylic
Case&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;step-6-actually-installing-kubernetes-the-easy-part-for-real-this-time&quot;&gt;Step
6: Actually Installing Kubernetes (The Easy Part, For Real This
Time)&lt;/h3&gt;
&lt;p&gt;With SSH keys baked in, installing &lt;a href=&quot;https://docs.k3s.io/&quot;&gt;k3s&lt;/a&gt; is delightfully straightforward
using &lt;a href=&quot;https://github.com/alexellis/k3sup&quot;&gt;k3sup&lt;/a&gt; (pronounced
“ketchup”, because of course it is).&lt;/p&gt;
&lt;div class=&quot;sourceCode&quot; id=&quot;cb2&quot;&gt;&lt;pre class=&quot;sourceCode bash&quot;&gt;&lt;code class=&quot;sourceCode bash&quot;&gt;&lt;span id=&quot;cb2-1&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-1&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-2&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-2&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Install k3sup&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-3&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-3&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-4&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-4&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;curl&lt;/span&gt; &lt;span class=&quot;at&quot;&gt;-sLS&lt;/span&gt; https://get.k3sup.dev &lt;span class=&quot;kw&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;sh&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-5&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-5&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-6&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-6&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;fu&quot;&gt;sudo&lt;/span&gt; install k3sup /usr/local/bin/&lt;/span&gt;
&lt;span id=&quot;cb2-7&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-7&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-8&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-8&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-9&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-9&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-10&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-10&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Bootstrap the first node as the server&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-11&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-11&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-12&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-12&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;k3sup&lt;/span&gt; install &lt;span class=&quot;at&quot;&gt;--ip&lt;/span&gt; 192.168.1.101 &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; k8s&lt;/span&gt;
&lt;span id=&quot;cb2-13&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-13&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-14&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-14&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-15&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-15&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-16&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-16&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# Join additional nodes as agents&lt;/span&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-17&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-17&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-18&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-18&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;k3sup&lt;/span&gt; join &lt;span class=&quot;at&quot;&gt;--ip&lt;/span&gt; 192.168.1.102 &lt;span class=&quot;at&quot;&gt;--server-ip&lt;/span&gt; 192.168.1.101 &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; k8s&lt;/span&gt;
&lt;span id=&quot;cb2-19&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-19&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-20&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-20&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;ex&quot;&gt;k3sup&lt;/span&gt; join &lt;span class=&quot;at&quot;&gt;--ip&lt;/span&gt; 192.168.1.103 &lt;span class=&quot;at&quot;&gt;--server-ip&lt;/span&gt; 192.168.1.101 &lt;span class=&quot;at&quot;&gt;--user&lt;/span&gt; k8s&lt;/span&gt;
&lt;span id=&quot;cb2-21&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-21&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;/span&gt;
&lt;span id=&quot;cb2-22&quot;&gt;&lt;a aria-hidden=&quot;true&quot; href=&quot;#cb2-22&quot; tabindex=&quot;-1&quot;&gt;&lt;/a&gt;&lt;span class=&quot;co&quot;&gt;# ... repeat for remaining nodes&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/alexellis/k3sup&quot;&gt;k3sup&lt;/a&gt; SSHes into
each machine, downloads the necessary bits, and bootstraps a
low-resource-friendly cluster with &lt;a href=&quot;https://etcd.io/&quot;&gt;etcd&lt;/a&gt;
(or SQLite) as the datastore. It’s genuinely magical compared to
kubeadm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reality check&lt;/strong&gt;: After the k3s install, the Pi 3
doesn’t have much headroom left for actually running applications. We’re
talking about 1GB of RAM shared between the OS, kubelet, and your
workloads. It’s a great testbed for learning the k3s API and running ARM
binaries natively, but don’t expect to run your company’s microservices
on it.&lt;/p&gt;
&lt;!--Video: k3sup installation process and kubectl get nodes--&gt;
&lt;figure&gt;
&lt;iframe allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; src=&quot;https://www.youtube.com/embed/oq7Lz8Mx1dI&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;K3Sup based cluster setup&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;the-final-result&quot;&gt;The Final Result&lt;/h2&gt;
&lt;p&gt;After seven years of procrastination, hardware hunting, debugging
dead ethernet switches, creative soldering, and Dremel work, I finally
have a working 7-node Kubernetes cluster.&lt;/p&gt;
&lt;p&gt;It also serves as a rather festive Christmas decoration with the
green PCB and red blinking LEDs. Very on-brand for the holidays.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What’s Next?&lt;/h2&gt;
&lt;p&gt;Hopefully I’ve been a good boy this year and Santa will bring me some
newer clustering hardware to play with. The &lt;a href=&quot;https://turingpi.com/product/turing-pi-2-5/&quot;&gt;Turing Pi 2.5&lt;/a&gt;
looks tempting with its support for CM4, Jetson, and the &lt;a href=&quot;https://turingpi.com/product/turing-rk1/&quot;&gt;Turing RK1&lt;/a&gt;
modules.&lt;/p&gt;
&lt;p&gt;But knowing me, I’ll buy it in 2025 and finally get it working by
2032.&lt;/p&gt;
&lt;h2 id=&quot;hardware-shopping-list&quot;&gt;Hardware Shopping List&lt;/h2&gt;
&lt;p&gt;For anyone brave enough to follow this path, here’s what you’ll
need:&lt;/p&gt;
&lt;table&gt;
&lt;colgroup&gt;
&lt;col style=&quot;width: 31%;&quot;&gt;&lt;/col&gt;
&lt;col style=&quot;width: 31%;&quot;&gt;&lt;/col&gt;
&lt;col style=&quot;width: 36%;&quot;&gt;&lt;/col&gt;
&lt;/colgroup&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Link&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Turing Pi 1 Board&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://turingpi.com/&quot;&gt;Turing Pi&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Check if ethernet works!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Raspberry Pi CM3+ (x7)&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.mouser.com/new/raspberry-pi/raspberry-pi-cm3plus-compute-modules/&quot;&gt;Mouser&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;8GB/16GB/32GB eMMC options&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CM IO Board for flashing&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.waveshare.com/&quot;&gt;Waveshare&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Or official RPi IO Board&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USB Ethernet Adapters&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;https://www.amazon.com/&quot;&gt;Amazon&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Just in case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ethernet Switch&lt;/td&gt;
&lt;td&gt;Your choice&lt;/td&gt;
&lt;td&gt;8+ ports recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acrylic Case&lt;/td&gt;
&lt;td&gt;Various&lt;/td&gt;
&lt;td&gt;With fan for cooling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&quot;software-tools&quot;&gt;Software &amp;amp; Tools&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://www.raspberrypi.com/software/&quot;&gt;Raspberry Pi
Imager&lt;/a&gt; - OS flashing tool&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/raspberrypi/usbboot&quot;&gt;rpiboot/usbboot&lt;/a&gt; - For
eMMC flashing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://k3s.io/&quot;&gt;k3s&lt;/a&gt; - Lightweight Kubernetes
distribution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/alexellis/k3sup&quot;&gt;k3sup&lt;/a&gt; - k3s
installer via SSH&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://etcd.io/&quot;&gt;etcd&lt;/a&gt; - Distributed key-value
store&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to ping me with your own homelab Kubernetes horror stories.
Misery loves company.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/7017091486894311247/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/7017091486894311247' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/7017091486894311247'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/7017091486894311247'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2025/12/seven-years-to-kubernetes-turing-pi-1.html' title='Seven Years to Kubernetes: A Turing Pi 1 Christmas Miracle'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/pw/AP1GczNgAdriNJGw8gK7NeudfKWQ0xZaDhEiSRbRf1I5rqddafhjWINTGRnSUMnaiMZlq3MlNdjY6BZa5hEN_TFpA9E4t1g67WWRx4zzQO4InPSb0YEISAeva-mmStspIGT0XuA3Q2flBDedhgUKiM0waiLz4A=s72-w979-h1305-s-c-no-gm?authuser=0" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-5561528550520861108</id><published>2025-12-12T00:53:47.054-08:00</published><updated>2025-12-12T00:53:47.054-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="austender"/><category scheme="http://www.blogger.com/atom/ns#" term="ducklake"/><category scheme="http://www.blogger.com/atom/ns#" term="go"/><category scheme="http://www.blogger.com/atom/ns#" term="ocds"/><category scheme="http://www.blogger.com/atom/ns#" term="scraping"/><title type='text'>Refactoring the Austender Scraper: From Colly to OCDS</title><content type='html'>&lt;p&gt;The AusTender analyser started life as a straight HTML scraper built
with &lt;a href=&quot;https://github.com/gocolly/colly&quot;&gt;Colly&lt;/a&gt;, walking the
procurement portal page by page. It worked, but it was always one
redesign away from a slow death: layout shifts, odd pagination edges,
and the constant need to throttle hard so I could sleep at night.&lt;/p&gt;
&lt;p&gt;Then the Australian Government exposed an &lt;a
href=&quot;https://standard.open-contracting.org/&quot;&gt;Open Contracting Data
Standard (OCDS)&lt;/a&gt; API. That changed the whole game. Instead of
scraping tables and div soup, I can treat the portal like a versioned
data feed.&lt;/p&gt;
&lt;p&gt;Part of why I care: I am kind of fascinated by government spending as
a system. Budgets read like a mixture of engineering constraints and
political storytelling, and I keep wanting to trace the thread from
“budget line item” to “actual contract award” without hand-waving. The
Treasurer’s Final Budget Outcome release (2022-23, “first surplus in 15
years”) is exactly the sort of headline that makes me want to drill down
into the mechanics: &lt;a
href=&quot;https://ministers.treasury.gov.au/ministers/jim-chalmers-2022/media-releases/final-budget-outcome-shows-first-surplus-15-years&quot;&gt;Final
Budget Outcome shows first surplus in 15 years&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So the redesign in &lt;a
href=&quot;https://github.com/whatnick/austender_analyser&quot;&gt;&lt;code&gt;austender_analyser&lt;/code&gt;&lt;/a&gt;
does three things differently:&lt;/p&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Fetch via OCDS, not HTML&lt;/strong&gt;: Reduce breakage by
consuming the API’s canonical JSON, not scraped pages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Persist to Ducklake&lt;/strong&gt;: Store releases, parties, and
contracts in &lt;a href=&quot;https://github.com/duckdb/ducklake&quot;&gt;Ducklake&lt;/a&gt;
so you can query locally without rerunning the whole pipeline. This does
not quite work yet; I am treating it as a learning exercise with
Ducklake. It is much easier to learn on a real problem than on toy demo
datasets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Treat caching as optional&lt;/strong&gt;: Counterintuitively, the
local cache is sometimes slower than pulling fresh data. Ducklake’s
startup and query overhead can outweigh a simple, parallelized upstream
call. The new design keeps the cache but makes it opt-in and
measurable.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you prefer Python, the upstream API team ships a reference
walkthrough in the &lt;a
href=&quot;https://github.com/austender/austender-ocds-api/blob/master/examples/python/README.md&quot;&gt;austender-ocds-api
repo&lt;/a&gt; (see also the &lt;a
href=&quot;https://app.swaggerhub.com/apis/austender/ocds-api/1.1#/&quot;&gt;SwaggerHub
docs&lt;/a&gt; and an example endpoint like &lt;a
href=&quot;https://api.tenders.gov.au/ocds/findById/CN1117592&quot;&gt;&lt;code&gt;findById&lt;/code&gt;&lt;/a&gt;).&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://raw.githubusercontent.com/whatnick/austender_analyser/main/docs/KPMG_result_2023_01_22.png&quot;
alt=&quot;Early KPMG scrape results (2023)&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Early KPMG scrape results
(2023)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;why-move-off-colly&quot;&gt;Why move off Colly?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scraping HTML is like doing accounting by screenshot. OCDS is the
ledger export.&lt;/li&gt;
&lt;li&gt;Less breakage: OCDS is documented and versioned; DOM scraping is
brittle.&lt;/li&gt;
&lt;li&gt;Faster iteration: You model on structured data immediately, not
after a fragile extraction layer.&lt;/li&gt;
&lt;li&gt;Clear rate behavior: You can respect API limits without guessing at
dynamic page loads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-keep-ducklake-in-the-loop&quot;&gt;Why keep Ducklake in the
loop?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/duckdb/ducklake&quot;&gt;Ducklake&lt;/a&gt; is the
reproducibility knob. It lets me freeze a snapshot, replay transforms,
and run offline queries when I am iterating on analysis (or when the
upstream is slow, or when I just do not want to be a bad citizen).&lt;/p&gt;
&lt;p&gt;But caches are not free. Ducklake has startup and query overhead, and
that can be slower than simply pulling fresh JSON in parallel. So the
pipeline treats Ducklake like a tool, not a religion: measure the
latency, pick the faster path, keep an escape hatch when you need
repeatability.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://raw.githubusercontent.com/whatnick/austender_analyser/main/docs/reindex_disk_usage.png&quot;
alt=&quot;Reindex disk usage&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Reindex disk usage&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;current-flow&quot;&gt;Current flow&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pull OCDS releases in batches, keyed by release date and procurement
identifiers.&lt;/li&gt;
&lt;li&gt;Normalize the JSON into &lt;a
href=&quot;https://github.com/duckdb/ducklake&quot;&gt;Ducklake&lt;/a&gt; tables (releases,
awards, suppliers, items).&lt;/li&gt;
&lt;li&gt;Emit lightweight summaries for quick diffing between runs.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://raw.githubusercontent.com/whatnick/austender_analyser/main/docs/KPMG_contracts_flood.png&quot;
alt=&quot;KPMG contracts flood view&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;KPMG contracts flood view&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;Lessons learned&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A stable API beats heroic HTML scraping almost every time. Even in
times of AI and (firecrawl)[https://www.firecrawl.dev/].&lt;/li&gt;
&lt;li&gt;Caches are not free; measure them. Sometimes stressing the upstream
lightly is faster and still acceptable within published rate
limits.&lt;/li&gt;
&lt;li&gt;Keep exit hatches: allow forcing cache use, bypassing it, and
snapshotting runs for reproducibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next steps: Going deeper : tighten validation against the OCDS
schema, add minimal observability (latency histograms for API vs cache),
and ship a “fast path” mode that only hydrates the fields needed for
high-level spend dashboards. Going broader : find sites and build API
and Web aggregators for Australian state tender sites (e.g. &lt;a
href=&quot;https://www.tenders.vic.gov.au/contract/search?keywords=datacom&amp;amp;title=&amp;amp;code=&amp;amp;buyerId=&amp;amp;supplierName=&amp;amp;minCost=&amp;amp;expiryDateFrom=&amp;amp;expiryDateTo=&amp;amp;startDateFrom=&amp;amp;startDateTo=&amp;amp;contractStatus=&amp;amp;awardedDateFrom=&amp;amp;page=1&amp;amp;preset=&amp;amp;browse=false&amp;amp;desc=true&amp;amp;orderBy=startDate&quot;&gt;VicTender&lt;/a&gt;
and international ones.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/5561528550520861108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/5561528550520861108' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5561528550520861108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5561528550520861108'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2025/12/refactoring-austender-scraper-from.html' title='Refactoring the Austender Scraper: From Colly to OCDS'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-5021821387650199920</id><published>2025-12-06T03:36:26.069-08:00</published><updated>2025-12-06T03:36:26.069-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="economics"/><category scheme="http://www.blogger.com/atom/ns#" term="energy"/><category scheme="http://www.blogger.com/atom/ns#" term="limits"/><category scheme="http://www.blogger.com/atom/ns#" term="solar"/><title type='text'>Solar Ceilings and Compounding Dreams</title><content type='html'>&lt;p&gt;It is fashionable to wave away physical constraints with vague
references to solar abundance and human ingenuity. Yet every balance
sheet eventually meets a balance of energy. Solar photons may shower
Earth with roughly 170,000 terawatts, but financial markets expect
growth that compounds on top of itself forever. The math linking those
stories rarely appears in the same paragraph—so let’s put them
together.&lt;/p&gt;
&lt;h2 id=&quot;setting-the-stage&quot;&gt;Setting the Stage&lt;/h2&gt;
&lt;p&gt;I keep coming back to Tom Murphy’s dialogue in &lt;a
href=&quot;https://dothemath.ucsd.edu/2012/04/economist-meets-physicist/&quot;&gt;&lt;em&gt;Exponential
Economist Meets Finite Physicist&lt;/em&gt;&lt;/a&gt;. In Act One, Murphy plots U.S.
energy use from 1650 onward and it traces a remarkably straight
exponential line at ~3% per year. Economists in the conversation shrug;
after all, 2–3% feels modest. But compounding at that pace means energy
demand multiplies by ten every century. Our economic models implicitly
assume something even more optimistic : &lt;strong&gt;8–10% returns&lt;/strong&gt;
in equity markets, pension targets, and venture decks; without asking
what energy supply function supports that.&lt;/p&gt;
&lt;h2 id=&quot;thermodynamic-guardrails&quot;&gt;Thermodynamic Guardrails&lt;/h2&gt;
&lt;p&gt;Murphy distills the second law of thermodynamics into plain
language:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“At a 2.3% growth rate (conveniently chosen to represent a 10×
increase every century), we would reach boiling temperature in about 400
years… Even if we don’t have a name for the energy source yet, as long
as it obeys thermodynamics, we cook ourselves with perpetual energy
increase.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That thought experiment matters less for the literal 400-year timer
and more because it shows energy growth must decelerate to avoid turning
Earth into a heat engine. Solar panels, fusion, space mirrors … pick
your technology. The waste heat still has to radiate away. We cannot
spreadsheet, app and AI our way around Stefan–Boltzmann and Black Body
radiation.&lt;/p&gt;
&lt;h2 id=&quot;solar-arithmetic-vs-demand-curves&quot;&gt;Solar Arithmetic vs Demand
Curves&lt;/h2&gt;
&lt;p&gt;Let’s grant the optimists a heroic build-out: cover 5% of Earth’s
land area with 20%-efficient photovoltaic arrays, assume a generous 200
W/m² average output, and we net roughly 20 TW—about the entire human
primary energy demand today. That is fantastic news for decarbonization,
but it is not a blank check for compounding GDP. If demand keeps growing
at 3%, we would need 20 TW × (1.03)ⁿ in perpetuity. Within 250 years
we’d be trying to harvest thousands of terawatts—orders of magnitude
more land, materials, storage, and transmission than our initial miracle
project. Solar abundance is real; solar infinity is fiction.&lt;/p&gt;
&lt;h2 id=&quot;finance-is-an-energy-iou&quot;&gt;Finance Is an Energy IOU&lt;/h2&gt;
&lt;p&gt;Money is a claim on future work, and work requires energy. When
pensions assume 7–8% annual returns, when startups pledge 10× growth,
and when national budgets bake in permanent productivity gains, they are
effectively promising that future societies will deliver 2–3 doublings
of net energy per century. If we instead hit a solar plateau—because
land, materials, or social license cap expansion—those financial
promises become unmoored. We can pretend that virtual goods, algorithmic
trading, or luxury desserts (to borrow Murphy’s Act Four anecdote)
deliver infinite utility without added energy, but the chefs, coders,
and data centers still eat, commute, and cool their CPU’s , GPU’s and
Tensor processors. The intangible economy rides on a very tangible
energy base.&lt;/p&gt;
&lt;h2 id=&quot;rewriting-the-business-plan&quot;&gt;Rewriting the Business Plan&lt;/h2&gt;
&lt;p&gt;Accepting a solar ceiling does not doom us to stagnation. It just
forces different design constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;grow quality, not quantity—prioritize outcomes per unit energy … do
proof of useful work rather that roll the dice and gamble.&lt;/li&gt;
&lt;li&gt;align finance with expected energy supply rather than mythical
exponentials … and I am not talking of wasting energy on crypto.&lt;/li&gt;
&lt;li&gt;treat efficiency gains as buying time, not as a perpetual motion
machine … if you learnt enough physics in high school to reject the
perpetual motion machine, but have been lulled into perpetual 8% returns
from the finance markets, there is a serious schizophrenia issue.&lt;/li&gt;
&lt;li&gt;embed thermodynamic literacy in economic education so debates start
from the same math.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Murphy ends his essay noting that growth is not a “good quantum
number.” It is not conserved. Our job is to craft institutions,
portfolios, and narratives that can thrive when net energy flattens,
because physics already told us that day will arrive long before our
spreadsheets hit overflow errors.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/5021821387650199920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/5021821387650199920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5021821387650199920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5021821387650199920'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2025/12/solar-ceilings-and-compounding-dreams.html' title='Solar Ceilings and Compounding Dreams'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-5715192484569103603</id><published>2025-12-06T03:05:00.000-08:00</published><updated>2025-12-06T03:05:24.173-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="darwin"/><category scheme="http://www.blogger.com/atom/ns#" term="evolution"/><category scheme="http://www.blogger.com/atom/ns#" term="management"/><category scheme="http://www.blogger.com/atom/ns#" term="travel"/><title type='text'>Darwin 2022 - Ruminations Compendium</title><content type='html'>&lt;p&gt;Collected reflections from the July 2022 Darwin trip, a narrative of
adaptation, organisational change, and expansion can live in a single
place.&lt;/p&gt;
&lt;h2 id=&quot;july-19-lemmings-and-launchpads&quot;&gt;July 19 – Lemmings And
Launchpads&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;There is no exception to the rule that every organic being
naturally increases at so high a rate, that if not destroyed the earth
would soon be covered by the progeny of a single pair. Even slow
breeding man has doubled in twenty five years, and at this rate in a few
thousand years there would literally be no standing room for his
progeny.&lt;/em&gt; – &lt;strong&gt;Charles Darwin&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Like the lemming marching and diving into the ocean to self‑regulate,
humanity plunges itself into vices of its own creation: alcohol, drugs,
violence, and greed. Perhaps the next plunge is into the real ocean or
into the vacuum of space, chasing more room in which to stand or float.
Failure in harsh environments creates room by removing weaker
individuals, or greater resilience by rewarding the most adaptable.
Colonial Australia itself was founded on such selection—the most
adaptable individuals and the strictest rule enforcers reshaped an
unforgiving frontier.&lt;/p&gt;
&lt;h2 id=&quot;july-20-organisational-evolution-in-flight&quot;&gt;July 20 –
Organisational Evolution In Flight&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Seeing that a few members of such water-breathing classes as the
Crustacea and Mollusca are adapted to live on the land, and seeing that
we have flying birds and mammals, flying insects of vast diversified
types, and formerly had flying reptiles. It is conceivable that flying
fish, which now glide far through air, slightly rising and falling by
the aid of their fluttering fins, might have been modified into
perfectly winged animals.&lt;/em&gt; – &lt;strong&gt;Charles Darwin&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The ability to skim over water for a few metres comes from external
tweaks, but the ability to cross the Pacific like a Godwin Tern comes
from internal rewiring: hollow bones, high metabolism, and a brain with
a built‑in compass. Organisations face the same distinction. A brief
digital-transformation spasm can bolt on an app or a website, yet
sustaining that flight demands internal metamorphosis and a sense of
direction from leadership. Caterpillars become butterflies through
wholesale change—so must companies that aspire to be more than flying
fish.&lt;/p&gt;
&lt;h2 id=&quot;july-23-questions-for-the-corporate-naturalist&quot;&gt;July 23 –
Questions For The Corporate Naturalist&lt;/h2&gt;
&lt;ol type=&quot;1&quot;&gt;
&lt;li&gt;&lt;strong&gt;Where are the transitional forms?&lt;/strong&gt;&lt;br /&gt;
Organisations with no lines on the org chart operate as pure adhocracy.
Hidden behind corporate veils, they are like pupae in cocoons, waiting
to emerge in a more defined shape.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How can specialised organs evolve?&lt;/strong&gt;&lt;br /&gt;
Marketing machines, technology muscle, sales teeth, enterprise-planning
backbone, analyst frontal lobes—each department is an organ honed for a
specific survival task.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is behaviour or instinct inheritable?&lt;/strong&gt;&lt;br /&gt;
Culture answers this. The rituals, stories, and incentives that survive
layoffs and leadership changes become the genetic code of the firm.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why are some species sterile when crossed, while others are
fertile?&lt;/strong&gt;&lt;br /&gt;
Some mergers and acquisitions thrive; others fail because the two
organisational genomes cannot integrate and diverge instead of
hybridising.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;july-24-conquering-new-lands&quot;&gt;July 24 – Conquering New
Lands&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;He who believes in the struggle for existence and in the
principle of natural selection, will acknowledge that every organic
being is constantly endeavouring to increase in numbers; and that if any
one being vary ever so little, either in habits or structure, and thus
gain an advantage over some of that inhabitant, however different it may
be from its own place, it will seize on the place of that
inhabitant.&lt;/em&gt; – &lt;strong&gt;Charles Darwin&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;International expansion is a contest for ecological niches. Bringing
hard‑won optimisations from one country to another is a bid to displace
incumbents. The organisations that vary—by process, by product, by
mindset—claim new ground first.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/5715192484569103603/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/5715192484569103603' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5715192484569103603'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5715192484569103603'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2025/12/darwin-2022-ruminations-compendium.html' title='Darwin 2022 - Ruminations Compendium'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-4282903695964131183</id><published>2025-11-24T16:00:00.000-08:00</published><updated>2025-12-30T04:13:55.938-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="auckland"/><category scheme="http://www.blogger.com/atom/ns#" term="foss4g"/><category scheme="http://www.blogger.com/atom/ns#" term="geospatial"/><category scheme="http://www.blogger.com/atom/ns#" term="open-source"/><category scheme="http://www.blogger.com/atom/ns#" term="re-earth"/><category scheme="http://www.blogger.com/atom/ns#" term="rust"/><category scheme="http://www.blogger.com/atom/ns#" term="stac"/><category scheme="http://www.blogger.com/atom/ns#" term="webgpu"/><category scheme="http://www.blogger.com/atom/ns#" term="zarr"/><title type='text'>FOSS4G 2025 Auckland: Hazy Hops and Geospatial Heavy Lifting</title><content type='html'>&lt;p&gt;Every year, there is an international gathering of geospatial
software geeks working in open source somewhere in the world. This has
become known as the FOSS4G conference–with the “F” preferentially
standing for “Freedom” rather than just “Free”. The last one of these I
attended in person was a long while ago in Sydney (2009!). Since then, I
have attended a couple of the local Oceania editions and even served on
the board of the non-profit that organizes them, but this was my first
global one in a long time.&lt;/p&gt;
&lt;p&gt;It was great to see the community still alive with a lot of energy,
attracting around 400 people from around the world to Tāmaki
Makaurau.&lt;/p&gt;
&lt;h2 id=&quot;travel-and-weather-the-metallica-tax&quot;&gt;Travel and Weather: The
Metallica Tax&lt;/h2&gt;
&lt;p&gt;November in Auckland is very pleasant. Perhaps that is what drew so
many events there at once. Accommodation was expensive to unaffordable
due to a Metallica concert and an Indigenous education conference
happening simultaneously. There were, of course, amazing shows and
entertainment on offer as a result, but my wallet definitely felt the
“Metallica Tax”. I ended up staying a 30-minute bus ride away from the
city centre in Takapuna, which gave me some nice morning views of the
Hauraki Gulf before diving into the windowless conference rooms.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczO4yfiFrntpFvWikQ7ctSPWjOFhxseHa1wt9CKdp5duB9G2xdNDDZYcs7TIrBDcNpaPbFhGCLxWu9jh0hRUFvUPbeytR_6114voHZF2c2eO1xakqVI2uYwFz0C2Daa1WMgV7HWf1OLT_YPBZ8xrJyobuw=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Samoan Dance at the Opening&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Samoan Dance at the Opening&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;tutorials-rust-ai-and-no-code-flows&quot;&gt;Tutorials: Rust, AI, and
No-Code Flows&lt;/h2&gt;
&lt;h3 id=&quot;eo-with-rust---leo-hardtke&quot;&gt;EO with Rust - Leo Hardtke&lt;/h3&gt;
&lt;p&gt;Leo Hardtke’s tutorial was all about making Earth Observation (EO)
processing faster with Rust and without the Python overhead. It was,
however, plagued by Nix vagaries and the classic environment
distribution issues that seem to follow “modern” build systems
everywhere. When it worked, it was blazing fast. The code is available
on GitHub for those brave enough to venture into the world of memory
safety and zero-cost abstractions.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczP77n9taSH3s-N5lyr-Nugu6ZAGVJwQ560vymSJwgrs2b6xM0aD9lm3zw9ekTenydlUXmNrg5it30aXbWo9XcLwA9JJQAW2FJ2O-PF3BTaEXbDkx_5N0x3VMEVek2Upjndnr_g52HaQMnRoEgQ9587AnA=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;ODC Stac in Rust&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;ODC Stac in Rust&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;ai-in-the-frontend---felix-palmer&quot;&gt;AI in the Frontend - Felix
Palmer&lt;/h3&gt;
&lt;p&gt;Felix Palmer showed off a cool Claude-enabled frontend to make
Deck.gl do things in response to free-text commands. Zooming and
searching is just the beginning; we can also do custom frontend
processing using the frontend equivalent of GEOS, Turf.js.&lt;/p&gt;
&lt;p&gt;I hit a snag here: I could not get my account activation SMS from
Claude while in NZ (roaming issues, I suspect). So, in true maker
fashion, I ported the code to work with AWS Bedrock instead. It’s a good
reminder that in the world of LLMs, being tied to a single API is a
recipe for frustration.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczMiWdmQu9i4M9hF9JNuCZ0MPQfI0EqrHAjCEY92igXB7JHCRUy5tG9EdUf1v0-dUzxvtXA8H1J1D39DGjzIBOQk3Xi0xmJc8LjErBJEPtd37LsBVuSFRWgtRrc7dXsew_aQWpi4IjGMviZ4-pmYP3IGSg=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Multi-lingual Map AI&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Multi-lingual Map AI&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;reearth-flow---kyle-waite&quot;&gt;Re:earth Flow - Kyle Waite&lt;/h3&gt;
&lt;p&gt;This was perhaps the most interesting tutorial from an open-source
and national policy perspective. I often insist that science developers
learn programming, but sometimes for adoption, this is simply not a
feasible change. This is what creates room for numerous commercial and
open-source tooling for GUIs and no-code/low-code workflow systems like
FME, ESRI, and even the QGIS toolbox.&lt;/p&gt;
&lt;p&gt;As part of the Plateau project, the Japanese government is putting
together the “Flow” framework for prefectures to process and convert
their own 3D models. The intro to the UI tools was amazing, and in time,
it seems like it can challenge FME. The state management is done by
y.js, and we had a fun time getting multiple users to modify the flow
until it broke in spectacular fashion.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczPFz1E0lx6ZjNs3biXR8u9R0Ft1aj5RN_VXN4W2sEdnMvwlitjfjjrPzac3ZYJ3vwZQ7KvzxlOQ1TuzeANUsYOO9XvAf3hqHbPwNOu5-1gaIA7_wGFDCMjkIFuAS3TBj-Hi8hXzIwU9LYL35-NZawI4zA=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Re:Earth Flow Intro&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Re:Earth Flow Intro&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2
id=&quot;presentations-the-ones-that-stuck-with-me-among-many-excellent-ones&quot;&gt;Presentations:
The ones that stuck with me among many excellent ones&lt;/h2&gt;
&lt;p&gt;For the full roll of presentations check out the 150+ &lt;a
href=&quot;https://www.youtube.com/playlist?list=PLlZzWSPAR5GYPAGSgs1Z6ydhoVgL7CAHd&quot;&gt;youtube
playlist&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-java-geospatial-ecosystem---jody-garnett&quot;&gt;The Java
Geospatial Ecosystem - Jody Garnett&lt;/h3&gt;
&lt;p&gt;Jody Garnett gave a deep dive into the state of the art behind the
libraries doing the heavy lifting in the Java Geospatial ecosystem: JTS,
GeoTools, and the long journey behind getting the Java Imaging library
ported to an open-source equivalent supported by the Eclipse foundation.
It’s a reminder that while Python gets the hype, a lot of the world’s
spatial data still moves through Java pipes. I ended up also going to
his talk on Geoserver, which keeps being a force to reckon with in
serving GIS data at scale.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczNtj9Fz6gOQZqKQ7T2pmE0-4mcpCyBhWQgXIo101v5oJFavoj5qLzoCD3OZQOyYRcqLue0AaXvTUwH7-_5gCOaz6nbQQoU_A-Uo3kK4KhU-zhNKY8CJ456qQMpUb0mb-c_xARI__90casLTtBYMJHxEUA=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;State of GeoTools, Geoserver and JTS&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;State of GeoTools, Geoserver and
JTS&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;gpu-accelerated-zarr-loading---wei-ji&quot;&gt;GPU Accelerated Zarr
Loading - Wei Ji&lt;/h3&gt;
&lt;p&gt;Wei Ji’s presentation on GPU-native Zarr was a highlight. Optimizing
data throughput for large-scale geospatial ML workflows is the new
frontier, and moving the bottleneck from the CPU to the GPU is where the
real gains are.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczNcOi8-mDuRtPPjVTsSwjq95KPqCA7VpT62RK7SG-26rdQi9hAxX-Rb_9jewiMyUOlGwZ0LjEoZvrkSlzPxgERMYqcFTNjTBG_nXdTRv2fSz5AmL3Fkuk_pXZcqRvowdioxJ69W_5g8Ub6bWooqF0DGdQ=w983-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Zarr Accelerated by GPU&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Zarr Accelerated by GPU&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;is-zarr-the-new-cog---jarrett-keifer-and-julia-signell&quot;&gt;Is Zarr
the new COG? - Jarrett Keifer and Julia Signell&lt;/h3&gt;
&lt;p&gt;An excellent presentation dispelling the hype around Zarr. The
takeaway? Given the same input and compression, the resulting content is
the same size. It’s the usage pattern and the “tyranny of chunking” that
really affects performance, along with the fine points about using
multiple files, shards, and inodes.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczMr5Ceg5gRzzaLHmzQoje6kPWYv_0-q4dSkpSg8aQeM8a4GSRPECjN2eCkfRzQl4npxW6Sb6aO-DCH6ELLqbw4PztxCl0MVswxkFA055l-KMGvppSzRfu01LedKW4c0krKnuEOz3jx2Ta_ynX4smI1a9w=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Zarr vs COG&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Zarr vs COG&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;navara-web3d-engine---keiya-higuchi&quot;&gt;Navara Web3D Engine - Keiya
Higuchi&lt;/h3&gt;
&lt;p&gt;The Re:Earth folks returned with Navara, a re-imagined 3D engine for
the web using a modern stack including WebGPU. It aims to create more
options for realistic rendering and a functional separation between GIS
functions and visualization functions–which are often messily
intertwined in current offerings.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczNccStdUfMhrk7dStuv2fujA4OiDB4-hSB5DbxuXIUgnQPB1PavtqRfo8wfyMvueZkhtx7iO0UZzcaWqjDtMXsMjbCg1SLW52x-B4e9Bge2TQU6gCwHx63pZ0CD3uEeZ63wvVkS-58i3oE2bzc3Kga32g=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Navara 3D Web Viz&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Navara 3D Web Viz&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;stac-adventures-with-matt-hanson&quot;&gt;STAC Adventures with Matt
Hanson&lt;/h3&gt;
&lt;p&gt;One of the most fun presentations was Matt Hanson’s “Choose Your Own
Adventure” session. He let the audience pick the path in D&amp;amp;D fashion
to learn more about the STAC ecosystem. I threw in my two cents on the
fact that “not all STAC is made equal” and the desperate need for
conformance checks on hosting services that claim to be STAC compliant
but fail in subtle ways that break downstream libraries.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczP5rZfyQ_IhssnazaSWSfyBoVBziKYDG17bEcmjt4GO_rUmy4Qi9rviKP5Gw6SNKZEEp2e7cY9ucZVVv40yK9I3pvNKvt89mJVFqTiKl2AT3hM4YePpACjSz_RnRr_e0FyjIrBqphiugxrvNwEQGZYFIA=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;STAC Catalog&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;STAC Catalog&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id=&quot;esas-zarr-foray---james-banting-sparkgeo&quot;&gt;ESA’s Zarr Foray -
James Banting (SparkGeo)&lt;/h3&gt;
&lt;p&gt;ESA is restructuring the Sentinel satellite imagery archive into DGGS
/ Healpix Zarr format and publishing the EOPF toolkit. The SparkGeo
presentation showed the state of implementation of the user-facing
libraries and how they are being integrated into various tools.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczM21hc7L_88T7CXCJ-LAgkCkQGRtbR8KKrHrj89a3na1hvVTUAu0YML6dU3YqwkdW1bVGPv_qLByLoILv12YHHsUysmMrG8WogwTMtqzEJxIWhbquEfCF65Q50xFjNEMOYOCI_XlT6_YatdI6_FYKBIow=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Zarr in Action&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Zarr in Action&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id=&quot;after-parties-hazy-hops-and-community&quot;&gt;After Parties: Hazy Hops
and Community&lt;/h2&gt;
&lt;p&gt;The conference after-parties at the pub are where most of the real
action happens. I spent my evenings hanging out with a mix of old
friends and new faces, trying the famous New Zealand hazy hops. There’s
something about a good IPA that makes discussing coordinate reference
systems much more bearable.&lt;/p&gt;
&lt;figure&gt;
&lt;img
src=&quot;https://lh3.googleusercontent.com/pw/AP1GczMqFeZBl0yV4OOkmH4seYUaQmTQJ5KafmeGJNuJKte8UpVIx_YHyIQdC2fAtZd1MzvDN3QG1ti_WRLkx3cjT57b_xvOzUbr1P2J1Dzh75vlEHQz4SJ70-N1lYS3XV3zUZMvvvYB7GEhaRvDMW7zg5EyFg=w1733-h1305-s-no-gm?authuser=0&quot;
alt=&quot;Beer offerings - NZ Hazy Hops&quot; /&gt;
&lt;figcaption aria-hidden=&quot;true&quot;&gt;Beer offerings - NZ Hazy
Hops&lt;/figcaption&gt;
&lt;/figure&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/4282903695964131183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/4282903695964131183' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/4282903695964131183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/4282903695964131183'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2025/11/foss4g-2025-auckland-hazy-hops-and.html' title='FOSS4G 2025 Auckland: Hazy Hops and Geospatial Heavy Lifting'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://lh3.googleusercontent.com/pw/AP1GczO4yfiFrntpFvWikQ7ctSPWjOFhxseHa1wt9CKdp5duB9G2xdNDDZYcs7TIrBDcNpaPbFhGCLxWu9jh0hRUFvUPbeytR_6114voHZF2c2eO1xakqVI2uYwFz0C2Daa1WMgV7HWf1OLT_YPBZ8xrJyobuw=s72-w1733-h1305-s-c-no-gm?authuser=0" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-322668621403864527</id><published>2022-11-05T06:23:00.006-07:00</published><updated>2022-11-05T06:27:54.703-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="community"/><category scheme="http://www.blogger.com/atom/ns#" term="electronics"/><category scheme="http://www.blogger.com/atom/ns#" term="pcb assembly"/><category scheme="http://www.blogger.com/atom/ns#" term="promotion"/><title type='text'>Drop shipping products from PCBWay</title><content type='html'>&lt;h1 id=&quot;drop-shipping-products-from-pcbway&quot;&gt;Drop shipping products from PCBWay&lt;/h1&gt;
&lt;p&gt;For a while I have been ordering PCB’s from &lt;a href=&quot;https://www.pcbway.com/project/shareproject/ATM90E36_Breakout_a7d8bccf.html&quot;&gt;PCBWay&lt;/a&gt; and parts from &lt;a href=&quot;https://au.mouser.com/&quot;&gt;Mouser&lt;/a&gt; and &lt;a href=&quot;https://www.digikey.com.au/&quot;&gt;Digikey&lt;/a&gt;, then hand assembling them at home. These have been very small scale cottage industry style runs and ultimately time consuming as I focus more on design and evaluation of new energy monitor ASIC’s such as the &lt;a href=&quot;&quot;&gt;V9261F&lt;/a&gt;. When PCBWay started offering to stock and drop ship my PCB’s directly from the factory using their extensive clout with DHL, I promptly signed up for the service.&lt;/p&gt;
&lt;p&gt;Recently I have been getting my &lt;a href=&quot;https://github.com/whatnick/ATM90E36_Breakout_KiCAD&quot;&gt;ATM90E36 Devkit&lt;/a&gt; PCB’s assembled there. The service has been excellent with concierge like parts choice and purchase. Followed by extremely helpful consultation on assembly progress and correctness.&lt;/p&gt;
&lt;p&gt;I received the following images after the first stage and confirmed the crystal and LED’s.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNEY2otpCpvnRxLZn1ncbbgyeYG_vYzoyhFkhmeuszriHHgPmKGoPB-Obc7dVBd2UOy1B1amtHn6G4CczpNmh_kjPfuq1pFqEWwzVKTPOyYVIUHZBXNQN5ejFRygz2vcTfqHs62kUXQI5ROSdeLSUbroUzMX20QtUcyNMNq9lTzezSZMRwv1vzWDk2/s756/Q1-orientation%20confirmation.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;588&quot; data-original-width=&quot;756&quot; height=&quot;249&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNEY2otpCpvnRxLZn1ncbbgyeYG_vYzoyhFkhmeuszriHHgPmKGoPB-Obc7dVBd2UOy1B1amtHn6G4CczpNmh_kjPfuq1pFqEWwzVKTPOyYVIUHZBXNQN5ejFRygz2vcTfqHs62kUXQI5ROSdeLSUbroUzMX20QtUcyNMNq9lTzezSZMRwv1vzWDk2/s320/Q1-orientation%20confirmation.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr0WFpmPB_hAMPU-LAaF9tI7vj5fXukcuMV1kHA8Wmt0s0paVi8DXw_bnyUablpp-s4CKky0eALKeV8MbGnppu7wCjps2qDAU2HRpxN82womh5jsvIhVhmR_kW2A0HY3xEXFoBTDtItx1Zu2_iMNhg89DUKkpa3jzqEldMlnS3jxh8QB-EjcMs82Iv/s4608/T-U137W51580A-01.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;3456&quot; data-original-width=&quot;4608&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr0WFpmPB_hAMPU-LAaF9tI7vj5fXukcuMV1kHA8Wmt0s0paVi8DXw_bnyUablpp-s4CKky0eALKeV8MbGnppu7wCjps2qDAU2HRpxN82womh5jsvIhVhmR_kW2A0HY3xEXFoBTDtItx1Zu2_iMNhg89DUKkpa3jzqEldMlnS3jxh8QB-EjcMs82Iv/s320/T-U137W51580A-01.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtTLEC_IIN7goJ-8qe-oW19of6SG2wGNKLsTohXeU33LP6G3ONawgaFCc-29YHHU8wUeGCy4t-_bGh2-bZl6b90NzZoSkdCecba2XN3YzbPaPK4BZQMky4Tlmjqwz9g1dRDz-tns8YB9kc_UmTc14-D8tKw_3fUBLwW5eIvpCmROKGBkprmOC57Pc8/s4608/T-U137W51580A-02.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;3456&quot; data-original-width=&quot;4608&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjtTLEC_IIN7goJ-8qe-oW19of6SG2wGNKLsTohXeU33LP6G3ONawgaFCc-29YHHU8wUeGCy4t-_bGh2-bZl6b90NzZoSkdCecba2XN3YzbPaPK4BZQMky4Tlmjqwz9g1dRDz-tns8YB9kc_UmTc14-D8tKw_3fUBLwW5eIvpCmROKGBkprmOC57Pc8/s320/T-U137W51580A-02.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXqXVbWMlGTlX_dnRcX8GMw9TusoGBZNk7OAILeNQB7FfPOcGVinDssJPwiQbLeAOSCb8zqy7Bu86s4YBliw_himCMkiUWYqgpRVG8gm5fwXh5mcltnEStU-wvmOJRl6xETiB1ix1WFpnHW19qu0ADWZr9guSksU62KjkBQSk79Z4f0WLN8V2oKiPZ/s876/The%20arrow%20indicates%20cathode%20.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;542&quot; data-original-width=&quot;876&quot; height=&quot;198&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXqXVbWMlGTlX_dnRcX8GMw9TusoGBZNk7OAILeNQB7FfPOcGVinDssJPwiQbLeAOSCb8zqy7Bu86s4YBliw_himCMkiUWYqgpRVG8gm5fwXh5mcltnEStU-wvmOJRl6xETiB1ix1WFpnHW19qu0ADWZr9guSksU62KjkBQSk79Z4f0WLN8V2oKiPZ/s320/The%20arrow%20indicates%20cathode%20.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Then I received some more inspection photos to allay any doubts.&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Z0nJ7s3SrPC1HJ_5M1LupeAIDz_FQB2ilhKbZcwgjKtgUUVxOL48JjfhaFWpJmdM0rGYxwYqNEQ3N37CU0bJi3XDiJE3ALYd5ycIm2_KsVTn0rEJ94lWGdKJqkoIxkdw2uXAtz2Fkv8sDb38t3I-OwXzIYvxxi25g_8KJu5Brn88-2zzRH29mEcL/s1052/T-U137W51580A-the%20arrow%20indicates%20cathode%20.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;835&quot; data-original-width=&quot;1052&quot; height=&quot;254&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4Z0nJ7s3SrPC1HJ_5M1LupeAIDz_FQB2ilhKbZcwgjKtgUUVxOL48JjfhaFWpJmdM0rGYxwYqNEQ3N37CU0bJi3XDiJE3ALYd5ycIm2_KsVTn0rEJ94lWGdKJqkoIxkdw2uXAtz2Fkv8sDb38t3I-OwXzIYvxxi25g_8KJu5Brn88-2zzRH29mEcL/s320/T-U137W51580A-the%20arrow%20indicates%20cathode%20.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfd_H5I90aNo-VAsTkuAzyxHQGZ_18AKuHTG2wKCXN3uyFh6eEti9p4UWawtqZ4UD6mzGnxUHffVVvR5nECOL4jOqFsh27BOlH4eHFWLyIYjLwZE4fNQEUnuPqmrTCx14tJpqtkrg6YkbHFP7jp0vs1Wlh4S35zD5pigFuQCutHRMbQsGFUC9jZXXh/s4624/Updated%20T-U137W51580A-01.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;3472&quot; data-original-width=&quot;4624&quot; height=&quot;240&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfd_H5I90aNo-VAsTkuAzyxHQGZ_18AKuHTG2wKCXN3uyFh6eEti9p4UWawtqZ4UD6mzGnxUHffVVvR5nECOL4jOqFsh27BOlH4eHFWLyIYjLwZE4fNQEUnuPqmrTCx14tJpqtkrg6YkbHFP7jp0vs1Wlh4S35zD5pigFuQCutHRMbQsGFUC9jZXXh/s320/Updated%20T-U137W51580A-01.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Looking forward to the stock appearing on the &lt;a href=&quot;https://www.pcbway.com/project/gifts_detail/ATM90E26_FeatherWing.html&quot;&gt;shop front&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: This is a paid promotion of PCBWay services&lt;/strong&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/322668621403864527/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/322668621403864527' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/322668621403864527'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/322668621403864527'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2022/11/drop-shipping-products-from-pcbway.html' title='Drop shipping products from PCBWay'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNEY2otpCpvnRxLZn1ncbbgyeYG_vYzoyhFkhmeuszriHHgPmKGoPB-Obc7dVBd2UOy1B1amtHn6G4CczpNmh_kjPfuq1pFqEWwzVKTPOyYVIUHZBXNQN5ejFRygz2vcTfqHs62kUXQI5ROSdeLSUbroUzMX20QtUcyNMNq9lTzezSZMRwv1vzWDk2/s72-c/Q1-orientation%20confirmation.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-6189276971715771251</id><published>2020-12-27T13:51:00.002-08:00</published><updated>2020-12-31T05:28:56.985-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Code Logistics"/><category scheme="http://www.blogger.com/atom/ns#" term="Design patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Software Architecture"/><title type='text'>Trucks vs Trains as an analogy for Microservices vs Monoliths</title><content type='html'>&lt;p&gt;2018 and 2019 was mostly spent obsessing over containers, trucks, trailers and hand written paper invoices for me. I was helping build out the technology stack and engineering team for &lt;a href=&quot;https://www.lorisystems.com/&quot;&gt;Lori Systems&lt;/a&gt;. Early in 2019 we made our first DevOps hire, getting &lt;a href=&quot;https://www.linkedin.com/in/cmakamara/&quot;&gt;Clive&lt;/a&gt; from Safaricom and getting started on migrating our handrolled Django monolith from EC2 to EKS. We would make jokes around shipping containers using containers. Clive even had a container shaped stressball with the EKS logo on it. This set me thinking on the parallels between shipping code and shipping goods, perhaps also led to the foundations of this post.&lt;/p&gt;
&lt;h2 id=&quot;intermodal-shipping-in-the-real-world-and-in-software&quot;&gt;Intermodal Shipping in the real-world and in software&lt;/h2&gt;
&lt;p&gt;Over the almost 2-years of work in Logistics I learnt a lot about how the global logistics system works. Almost like the life-blood of the planet. Large container ships abstract away contents and ship things from Taiwan to Timbukutu. The seminal book on this topic is perhaps, &lt;a href=&quot;https://doi.org/10.1515/9781400880751&quot;&gt;The BOX&lt;/a&gt;. Watching global shipping lanes in &lt;a href=&quot;https://www.marinetraffic.com/en/ais/home/centerx:-12.0/centery:25.0/zoom:4&quot;&gt;Marine Traffic&lt;/a&gt; and scraping &lt;a href=&quot;https://www.kpa.co.ke/Pages/14DaysList.aspx&quot;&gt;ships arriving in Mombasa&lt;/a&gt; from the KPA Sharepoint became a daily ritual. I digress, back to the original point on the importance for containerization in shipping code or machinery.&lt;/p&gt;
&lt;p&gt;Docker uses the ubiquitous whale/ship logo, most containers arrive at ports this way from the oceans of developers. I don&#39;t quite have an analogy here for the massive ships that land the containers at ports, some &lt;a href=&quot;https://en.wikipedia.org/wiki/Twenty-foot_equivalent_unit&quot;&gt;500 or 1000 TEU&#39;s&lt;/a&gt; at a time. The analogy here covers land transport aspects, somewhat related to how code runs in production and is typically served via datacenters / public clouds to users.&lt;/p&gt;
&lt;p&gt;Containers themselves make transfer of goods/code from development (ships) to production (trains/trucks) easy. However even containerized applications can demonstrate tight coupling similar to what a train has, in effect being a distributed monolith, instead of a true suite of microservices. In my opinion, any system that requires a release train approach for new features is most likely to be a distributed monolith masquarding as microservices. The real flexibility comes from the low coupling between containers and the freedom to release each clearly delineated service at its own cadence on the roads.&lt;/p&gt;
&lt;h2 id=&quot;trains-are-awesome&quot;&gt;Trains are awesome&lt;/h2&gt;
&lt;p&gt;My 5yo is currently obsessed with steam engines, even though they are from an era long gone. There is something magical about a powerful engine pulling everything along smoothly on a set of constraints (rails). It works nicely as long as no quick changes are needed in the carriages and everyone wants to get to the same destination. Trouble arises when something in the closely coupled chain of components goes awry and requires a quick change. I still don&#39;t understand the &lt;a href=&quot;https://www.denofgeek.com/tv/snowpiercer-episode-6-review-trouble-comes-sideways/&quot;&gt;scene in snow piercer&lt;/a&gt; where a few wagons were dumped in a siding at speed. If we can do that one neat trick perhaps monoliths would become much more maintainable. In early stages of a product monoliths are a &lt;a href=&quot;https://www.infoq.com/news/2019/04/monolith-vs-microservices/&quot;&gt;nice simple entry point&lt;/a&gt;, especially if the features are narrowly scoped and well coupled. On the reverse the monolith may be a very good idea for a mature product which is not changing rapidly and perhaps needs to be optimised for performance instead by reducing communication overhead between components by introducing tight coupling. In both cases a modular approach and service-oriented designs are still feasible, as long as the implementation and maintenance team is aware of the implications. People are still driving around in classic cars from the 1900&#39;s, where as steam locomotives from that era are languishing in museums.&lt;/p&gt;
&lt;h2 id=&quot;trucks-are-flexible&quot;&gt;Trucks are flexible&lt;/h2&gt;
&lt;p&gt;One of the killer advantages of trucks in the logistics business is their ability to deliver right to the factory or warehouse loading bay. It is simply not feasible to build train tracks to serve every address. Even in areas with great railway infrastructure, buffers (known as Inland container depots) have to be placed to cover the last few miles of transport from the rail to the industrial areas. This sort of mode can sometimes be seen in Microservices being layered on older monoliths to provide user facing services, especially in banking systems. The other great advantage trucks have is the ability overtake each other gradually along the road, this manifests itself in software systems as rolling deployment of new features. Such an approach requires careful management of the stateful parts of the system such as storage and database schemas. Otherwise it turns into a Fast and Furious game of stealing a container from a moving platform, aka the &lt;a href=&quot;https://www.eurogamer.net/articles/2020-12-07-gangs-are-hitting-lorries-on-the-run-to-steal-ps5s&quot;&gt;Romanian Rollover&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;this-analogy-is-not-new&quot;&gt;This analogy is not new&lt;/h2&gt;
&lt;p&gt;The logistics analogies are rife in software engineering, we &lt;code&gt;ship&lt;/code&gt; code, we &lt;code&gt;package&lt;/code&gt; things, we have &lt;code&gt;release trains&lt;/code&gt;. The largest real world container orchestration organization &lt;a href=&quot;https://www.maersk.com/&quot;&gt;Maersk&lt;/a&gt; uses a 7-point logo surprisingly similar to the most popular software container orchestration platform &lt;a href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt;. I will continue updating this post as more ideas and links come together.&lt;/p&gt;
&lt;p&gt;You can engage with article via comments or the twitter thread.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Random Roadtrip Rumination : Microservices vs Monotliths is Trucks vs Trains for shipping features.
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1342654642736353281?ref_src=twsrc%5Etfw&quot;&gt;December 26, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/6189276971715771251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/6189276971715771251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/6189276971715771251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/6189276971715771251'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/12/trucks-vs-trains-as-analogy-for.html' title='Trucks vs Trains as an analogy for Microservices vs Monoliths'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-2570676582312627632</id><published>2020-10-04T15:19:00.004-07:00</published><updated>2020-10-24T04:23:36.775-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="blender"/><category scheme="http://www.blogger.com/atom/ns#" term="FreeCAD"/><category scheme="http://www.blogger.com/atom/ns#" term="KiCAD"/><category scheme="http://www.blogger.com/atom/ns#" term="Open-Source"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="qgis"/><title type='text'>Desktop Software API&#39;s in Python (KiCAD, FreeCAD, Blender, QGIS)</title><content type='html'>&lt;h1 id=&quot;python-wraps-around-everything&quot;&gt;Python wraps around everything&lt;/h1&gt;
&lt;p&gt;For the last couple of years I have mostly written &lt;a href=&quot;https://github.com/GeoscienceAustralia/dea-notebooks&quot;&gt;Satellite Data Processing code&lt;/a&gt; in Python and plenty of &lt;a href=&quot;https://github.com/opendatacube/datacube-ows&quot;&gt;Flask/Django web services&lt;/a&gt;. However Python is also an excellent automation tool for GUI based applications allowing custom plugins to be written and functionality provided out of the box extended by users.&lt;/p&gt;
&lt;p&gt;The first desktop application I seriously looked at Python plugins for was QGIS. It was early days of learning how to wrap C++ code using &lt;a href=&quot;http://osgeo-org.1560.x6.nabble.com/GDAL-Python-Bindings-td4157607.html#a4157610&quot;&gt;SWIG/SIP&lt;/a&gt; etc. In the old mailing list you can find a much younger me making inane comments about mixing wrapper metaphors in QGIS with SWIG + SIP. We have come a long way since then and SIP based bindings are the mainstay of QGIS plugins.&lt;/p&gt;
&lt;h2 id=&quot;qgis&quot;&gt;QGIS&lt;/h2&gt;
&lt;p&gt;QGIS has so many Python plugins that they need &lt;a href=&quot;https://plugins.qgis.org/&quot;&gt;a registry&lt;/a&gt; of their own. Occasionally QGIS Python gets twisted around itself due to &lt;a href=&quot;https://github.com/qgis/QGIS/issues/37783&quot;&gt;multiple Pythons in the user enviroment&lt;/a&gt;. You can also flip the python API around and instead of building a plugin you can turn QGIS into a custom desktop application. Which is what I have done with my basic &lt;a href=&quot;https://github.com/whatnick/demo_qgis_app&quot;&gt;Airport Viewer&lt;/a&gt; demo.&lt;/p&gt;
&lt;p&gt;QGIS being a fairly extensive and complex C++ application which takes &lt;a href=&quot;https://whatnicklife.blogspot.com/2020/08/compiling-qgis-in-msvc-in-2020.html&quot;&gt;hours to compile&lt;/a&gt;, being able to make small quick changes in python is invaluable.&lt;/p&gt;
&lt;h2 id=&quot;kicad&quot;&gt;KiCAD&lt;/h2&gt;
&lt;p&gt;At the time of writing KiCAD has an extensive Python API for processing the automating the PCB layout part of the workflow and this has lead to many innovations in automating traditionally laborious hand layout or even performing complex simulations / optimization to set trace lengths. For example &lt;a href=&quot;https://twitter.com/_joshajohnson&quot;&gt;Josh Johnson&lt;/a&gt; has one for &lt;a href=&quot;https://github.com/joshajohnson/ecp5-mini/blob/master/breakouts/clock-test/circle-placement.py&quot;&gt;laying parts out in a circle&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/gregdavill&quot;&gt;Greg Davill&lt;/a&gt; has several for &lt;a href=&quot;https://github.com/gregdavill/ButterStick/blob/main/lib/bus_aware_length_matching_verification.py&quot;&gt;length matching&lt;/a&gt; and &lt;a href=&quot;https://github.com/gregdavill/kicadScripts&quot;&gt;rendering file generation&lt;/a&gt;. My personal favourite among the KiCAD scripts is the one for generation of &lt;a href=&quot;https://github.com/openscopeproject/InteractiveHtmlBom&quot;&gt;Interactive BOM&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I am really looking forward to Python script support in the &lt;a href=&quot;https://forum.kicad.info/t/plans-for-the-python-api-for-eeschema/1776&quot;&gt;Schematic Editor&lt;/a&gt;. Meanwhile programmatic Schematic generation tools like &lt;a href=&quot;https://github.com/xesscorp/skidl&quot;&gt;Skidl&lt;/a&gt; provide schematic oriented Python fun.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://github.com/pcbarts/stylized-blender-setup&quot;&gt;rendering&lt;/a&gt; of the PCB&#39;s is often done in Blender. Which has its own set of Python nicities.&lt;/p&gt;
&lt;h2 id=&quot;blender&quot;&gt;Blender&lt;/h2&gt;
&lt;p&gt;My first foray in creating a &lt;a href=&quot;https://docs.blender.org/api/current/index.html#&quot;&gt;Blender API&lt;/a&gt; based application was during the Kinect USB protocol hacking days. The data stream had just been decoded and I wanted an easy pipeline to a commonly installed / open-source 3D display software. The Python API is mature enough for people these days to quickly put together &lt;a href=&quot;https://github.com/moraell/KinectMocap4Blender&quot;&gt;motion capture plugins&lt;/a&gt; for Blender. This plugin however demonstrates the challenges for creating native plugins for blender, the &lt;a href=&quot;https://docs.python.org/3/faq/windows.html#is-a-pyd-file-the-same-as-a-dll&quot;&gt;.pyd&lt;/a&gt; files for Python have to be recreated for different versions of Blender for ABI compaitibility.&lt;/p&gt;
&lt;p&gt;Getting the binaries working has had me thrashing about and posting in &lt;a href=&quot;https://blenderartists.org/t/python-as-a-module-msvc2010-win64/552870&quot;&gt;forums&lt;/a&gt;, then sticking to a working Blender build with Python 2.7 for about 5 years since I did not want to touch it and break it. My integration actually reversed the &lt;a href=&quot;https://wiki.blender.org/wiki/Building_Blender/Other/BlenderAsPyModule&quot;&gt;embedding process&lt;/a&gt;, i.e. instead of using additional modules in the Blender embedded python I embedded Blender in a 3D GIS automation.&lt;/p&gt;
&lt;p&gt;Native plugin weirdness aside, Blender Python API is a really powerful tool for creating procedural objects from waves / &lt;a href=&quot;https://b3d.interplanety.org/en/fluid-simulation-in-blender-2-80/&quot;&gt;fluid simulation&lt;/a&gt; to astrophysics with &lt;a href=&quot;https://amuse.readthedocs.io/en/latest/tutorial/blender.html&quot;&gt;amuse&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;freecad&quot;&gt;FreeCAD&lt;/h2&gt;
&lt;p&gt;FreeCAD is sort of the third part of my physical electrical / mechnical design triumvirate. I occasionally design parts for KiCAD in FreeCAD, or bring multiple boards together to &lt;a href=&quot;https://archive.org/details/kicon_2019-MCAD_ECAD_For_DIN_Rail_Energy_Monitors&quot;&gt;test enclosure fit&lt;/a&gt;. FreeCAD also has an extensive python library which is leveraged by KiCAD part library maintainers to &lt;a href=&quot;https://github.com/easyw/kicad-3d-models-in-freecad&quot;&gt;parametrically generate parts&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The scripting in FreeCAD can be used much like the PCB layout scripts in KiCAD to create this with circular symmetry, like &lt;a href=&quot;https://wiki.freecadweb.org/Scripted_Parts:_Ball_Bearing_-_Part_1&quot;&gt;ball bearings&lt;/a&gt; which are difficult and repetitive to do by hand.&lt;/p&gt;
&lt;h1 id=&quot;final-words&quot;&gt;Final words&lt;/h1&gt;
&lt;p&gt;There are lots of other pieces of desktop software I have used that have started shipping with Python API&#39;s to address the never ending demand from users to easily automate repeated tasks. The live process for making this blogpost in somewhat recursive fashion can be found here.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Started a new blog post around &lt;a href=&quot;https://twitter.com/hashtag/python?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#python&lt;/a&gt; wrapping around a bunch of desktop applications to ease automation / extension. Live updates here as I collate material to flesh it out. &lt;a href=&quot;https://t.co/zz8b29kHcO&quot;&gt;pic.twitter.com/zz8b29kHcO&lt;/a&gt;
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1312880481470349312?ref_src=twsrc%5Etfw&quot;&gt;October 4, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p&gt;I have even made videos withs a proprietary one, I will live that here for anyone interested in my attempts at a voiceover.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/YnppaRLpLWc&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;
&lt;/iframe&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/2570676582312627632/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/2570676582312627632' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2570676582312627632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/2570676582312627632'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/10/desktop-software-apis-in-python-kicad.html' title='Desktop Software API&#39;s in Python (KiCAD, FreeCAD, Blender, QGIS)'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/YnppaRLpLWc/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-53285416367457152</id><published>2020-08-30T00:12:00.004-07:00</published><updated>2020-10-02T02:27:15.389-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="c++"/><category scheme="http://www.blogger.com/atom/ns#" term="MSVC"/><category scheme="http://www.blogger.com/atom/ns#" term="Open-Source"/><category scheme="http://www.blogger.com/atom/ns#" term="qgis"/><title type='text'>Compiling QGIS in MSVC in 2020</title><content type='html'>&lt;h1 id=&quot;compiling-qgis-on-windows-in-200x&quot;&gt;Compiling QGIS on Windows in 200x&lt;/h1&gt;
&lt;p&gt;I don&#39;t quite remember when I decided to help compile QGIS on Windows. It was somewhere between compiling GDAL with ECW support for Photoshop on Windows and getting carried into Direct3D and C# land with NASA WorldWind. It was sometime in the 2000&#39;s while still working at Apogee Imaging in Lobethal.&lt;/p&gt;
&lt;p&gt;At that point I was manually building a database of the footprints of satellite imagery that filled up a wall cabinet with CD&#39;s and DVD&#39;s. The technique was something like open up the image, go around edges and trace a polygon. This was days before mature boolean thresholding and reliable/easy raster-to-vector logic.&lt;/p&gt;
&lt;p&gt;I hopped on IRC on #qgis in Freenode and chatted with luminaries like timlinux, frankw and gsherman. Listened to the automated notifications from &lt;strong&gt;sigq&lt;/strong&gt;, the commits bot. Things were heating up and instead of a Linux cross-compile to windows using MingW, something native to windows say using MSyS+MingW instead of Cygwin was desired. A lot of GDAL and Qt worked in MingW, so presumably QGIS would too. So I set myself to put together an MSYS environment with all the third-party dependencies that could be used to happily build QGIS. Eventually I built a release in NSIS as well.&lt;/p&gt;
&lt;p&gt;My MSYS environment got packed in a zip and shared via FTP/HTTP on a VPS I had back then to the rest of the community. I earned myself a pin in the QGIS core contributor map in Adelaide. Something I am very proud of to this day. Eventually the MingW build got deprecated and native MSVC builds were supported. That&#39;s how contributions work, nothing lasts forever. In my IRC days, I helped on-board Nathan Woodrow to QGIS, who in turn I believe helped on-board Nyall Dawson. Nyall has surpassed us all in feature contributions and work on QGIS.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Getting started on QGIS on MSVC blog article. Trying to add some historical perspective on my involvement. Found this acknowledgement in the docs. Thanks to &lt;a href=&quot;https://twitter.com/timlinux?ref_src=twsrc%5Etfw&quot;&gt;&lt;span class=&quot;citation&quot;&gt;@timlinux&lt;/span&gt;&lt;/a&gt; . Back in the days of sharing mingw zip files via FTP. &lt;a href=&quot;https://t.co/NTkQgU5ibN&quot;&gt;pic.twitter.com/NTkQgU5ibN&lt;/a&gt;
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1299858242311315456?ref_src=twsrc%5Etfw&quot;&gt;August 29, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;h1 id=&quot;fast-forward-to-2020-compiling-qgis-in-msvc&quot;&gt;Fast forward to 2020, compiling QGIS in MSVC&lt;/h1&gt;
&lt;p&gt;I am getting back into doing lots of Open-source work after long hiatus in private industry with &lt;a href=&quot;https://twitter.com/aerometrex&quot;&gt;Aerometrex&lt;/a&gt; and start-up land with &lt;a href=&quot;https://twitter.com/lorisystems&quot;&gt;Lorisystems&lt;/a&gt;. It is great fun working on mostly in the open at &lt;a href=&quot;https://twitter.com/GeoscienceAus&quot;&gt;Geoscience Australia&lt;/a&gt;. There is actually a recently archived opendatacube + qgis repository &lt;a href=&quot;https://github.com/opendatacube/datacube-qgis&quot;&gt;here&lt;/a&gt;. Seeing that repo and speaking to &lt;a href=&quot;https://twitter.com/madmanwoo&quot;&gt;Nathan&lt;/a&gt; and LinuxConfAu inspired me to have a go and getting back into actively working on the Qgis code base. It has sprawled out, with lots and lots of new features. The build system is still familiar via CMake and actually much easier now with MSVC. I cast around for a recent guide and found &lt;a href=&quot;https://www.shaeffer.co/compiling-qgis-on-windows/&quot;&gt;this&lt;/a&gt;. The guide mostly works, however I made some refinements.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ditched &lt;code&gt;bison&lt;/code&gt; and &lt;code&gt;flex&lt;/code&gt; via Cygwin to using the one available via Msys2. These can be found &lt;a href=&quot;https://packages.msys2.org/package/bison&quot;&gt;here&lt;/a&gt;. Not needing the while Cygwin system helps in keeping the windows build system light. Simply download the binaries and add them to the Osgeo4W binaries directory.&lt;/li&gt;
&lt;li&gt;Captured my &lt;a href=&quot;https://gist.github.com/whatnick/6008597bffa427a733b7ccf6ba0f8fca&quot;&gt;CMakeCache.txt&lt;/a&gt; to make it easier to reproduce and debug the build environment for others.&lt;/li&gt;
&lt;li&gt;Used &lt;a href=&quot;https://www.incredibuild.com/&quot;&gt;Incredibuild&lt;/a&gt; in demo mode to use a few NUC&#39;s I have lying around to speed up the build. Recording while building failed the first time and worked the next. The whole build from scratch still tooks around 35minutes overall.&lt;/li&gt;
&lt;/ul&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/zTW5DmO06b0&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;
&lt;/iframe&gt;
&lt;p&gt;I am planning to throw some of my day to day DevOps skills towards the QGIS project and start helping again with Raster enhancements and windows release management. Perhaps getting Incredibuild in the hands of the windows maintainers will help tighten up the iteration cycle and make testing easier.&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/R8wq6D_kEjA&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;
&lt;/iframe&gt;
&lt;p&gt;The twitter thread/ stream of consciousness edition of this is available as well.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Moving from babun to msys2 to get flex and bison required for compiling QGIS from source. &lt;a href=&quot;https://t.co/W866AOM9Kt&quot;&gt;https://t.co/W866AOM9Kt&lt;/a&gt; &lt;a href=&quot;https://t.co/fUmqpa9YHY&quot;&gt;pic.twitter.com/fUmqpa9YHY&lt;/a&gt;
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1276482732621565952?ref_src=twsrc%5Etfw&quot;&gt;June 26, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/53285416367457152/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/53285416367457152' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/53285416367457152'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/53285416367457152'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/08/compiling-qgis-in-msvc-in-2020.html' title='Compiling QGIS in MSVC in 2020'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img.youtube.com/vi/zTW5DmO06b0/default.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-8558429505813908133</id><published>2020-07-22T00:12:00.006-07:00</published><updated>2020-08-02T04:29:35.741-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="Design patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Microservices the hard way - folders in EC2 Instance</title><content type='html'>&lt;p&gt;For day to day work I wrangle containers in EKS these days. However when doing personal projects EKS is a luxury (baseline cost being $70 or so per month). So I decided to do microservice development for the rain radar project using no Docker, no Kubernetes but using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;multiple venvs&lt;/li&gt;
&lt;li&gt;multiple service folders&lt;/li&gt;
&lt;li&gt;environments in .env files (secrets in plain text)&lt;/li&gt;
&lt;li&gt;web service start using &lt;span class=&quot;citation&quot;&gt;@reboot&lt;/span&gt; in Cron&lt;/li&gt;
&lt;li&gt;scheduled services using ... ya Cron&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The whole thing started with noble intentions to use lambda&#39;s all the way however I got stuck in using S3-SNS to trigger the lambda and decided to scan the S3 bucket using timestamps to find latest files to process. More on the pitfalls of that later.&lt;/p&gt;
&lt;p&gt;The major microservices handle are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Raw radar data preparation using custom hand crafted algorithm, being ported to Rust &lt;a href=&quot;https://github.com/whatnick/crop_circle&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Inserting prepared data to DynamoDB as a &lt;a href=&quot;https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-indexes-general-sparse-indexes.html&quot;&gt;sparse array&lt;/a&gt; and serving this via Flask.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/pySTEPS/pysteps&quot;&gt;Nowcasting&lt;/a&gt; using the timeseries of sparse array of rain observations also serving results via Flask.&lt;/li&gt;
&lt;li&gt;Capturing rain events and nowcasts and creating text and gif to send to &lt;a href=&quot;https://python-twitter.readthedocs.io/en/latest/&quot;&gt;twitter&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these applications consumes the other to some extent and is sort of separated in responsibility. I decided to deploy them with basic a folder per application on the &lt;code&gt;/home/ubuntu&lt;/code&gt; directory, with a venv per folder.&lt;/p&gt;
&lt;p&gt;I had it like this for a while. Then I got tired for sshing into the box and git pulling in each folder. So I decided to write a fabfile per application which would do this for me and created deployment keys which would be used to pull the code to this folder. Then I got tired of running multiple fabfiles and decided to setup a polled process which run the fabfiles and git synced the code from a &lt;a href=&quot;https://support.atlassian.com/bitbucket-cloud/docs/schedule-pipelines/&quot;&gt;master pipeline&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Eventually I got around to bootstrapping the whole VM using &lt;a href=&quot;https://www.packer.io/&quot;&gt;Packer&lt;/a&gt; + &lt;a href=&quot;https://www.packer.io/docs/provisioners/ansible.html&quot;&gt;Ansible&lt;/a&gt; playbooks. The development work for it was done locally using &lt;a href=&quot;https://www.vagrantup.com/&quot;&gt;Vagrant&lt;/a&gt; with Hyper-V as the VM provide to test the same &lt;a href=&quot;https://www.vagrantup.com/docs/provisioning/ansible&quot;&gt;Ansible&lt;/a&gt; playbooks. I will follow up on this with a few characters on twitter.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Wrangling VM&#39;s with Packer, Vagrant and Ansible all at the same time. Helped me figure out issues in Ansible docs and divergence between bento ubuntu box and AWS AMI. One calls ntp ntpd, the other ntp.service. &lt;a href=&quot;https://t.co/tSbaPuKtVB&quot;&gt;pic.twitter.com/tSbaPuKtVB&lt;/a&gt;
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1284412192255733765?ref_src=twsrc%5Etfw&quot;&gt;July 18, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p&gt;Once the initial Packer AMI is established the choice is to either keep building this image or to move away from the whole VM based old-school stuff to a more modern/fun Kubernetes way.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/8558429505813908133/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/8558429505813908133' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8558429505813908133'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8558429505813908133'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/07/microservices-hard-way-folders-in-ec2.html' title='Microservices the hard way - folders in EC2 Instance'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-9038146343419407232</id><published>2020-06-01T06:59:00.005-07:00</published><updated>2020-06-06T02:40:49.675-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="RDS"/><category scheme="http://www.blogger.com/atom/ns#" term="Replication"/><category scheme="http://www.blogger.com/atom/ns#" term="Workarounds"/><title type='text'>Replicating Databases in RDS</title><content type='html'>&lt;p&gt;One Sunday in 2018 I sat for a whole day in Art Caffe at the ground floor of Yaya Centre in Nairobi on the phone to Norman at AWS Support in Cape Town discussing DMS for MSSQL servers. After a whole day of screen sharing and being on call we decided what we were trying to do was no achievable, but AWS was working on it. The next day AWS sent me an NDA (since expired).&lt;/p&gt;
&lt;p&gt;Data replication from on-prem Database instances or between cloud database instances is an issue that comes up all the time. I have hands on experience doing this a couple of times now. This post summarizes my 3 or so attempts at doing this with different sources and targets and lessons learnt.&lt;/p&gt;
&lt;h2 id=&quot;mssql-to-mssql-using-aws-dms&quot;&gt;MSSQL to MSSQL using AWS DMS&lt;/h2&gt;
&lt;p&gt;At the start-up I was working at we adopted a pre-built mini ERP, it covered logistics workflows and finance / billing aspects. It was built in the 2000&#39;s in .NET Classic and ran on IIS and MSSQL server. Quickly the MSSQL became the single point of lack of scalability in the system. Since AWS does not natively support read-replicas for MSSQL RDS instances I looked at DMS to create these replicas. DMS did not quite work as expected and led to the conversation alluded to above with Norman. I ended up performing replication using &lt;a href=&quot;https://cloudbasic.net/&quot;&gt;CloudBasic&lt;/a&gt; as the SaaS provider for managing the Change Tracking and handling schema changes in the source tables and propagating them to the target replicas. The replication was fine for single replicas, but quickly bogged the source database down as I added more replicas.&lt;/p&gt;
&lt;p&gt;As aside the same database was also being replicated to a Redshift cluster for BI usage using tooling provided by &lt;a href=&quot;https://www.sisense.com/product/data-teams/&quot;&gt;Periscope Data&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As part of this excercise I came to appreciate the advantage to write-only / append-only schemas in improving no-lock replication performance (at the cost of storage), also the need for timestamp columns such as &lt;code&gt;update_time&lt;/code&gt; to perform incremental data transfer. I spent a lot of time reading the &lt;a href=&quot;https://eng.uber.com/schemaless-part-one-mysql-datastore/&quot;&gt;Schemaless articles&lt;/a&gt; by Uber Eng around building Schemaless DB&#39;s on top of RDBMS&#39;s like MySQL. I don&#39;t 100% agree with their design choices but it adds interesting perspective. The bottomline &lt;strong&gt;CRUD at scale is HARD&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id=&quot;rds-postgresql-to-postgresql-using-dms&quot;&gt;RDS PostgreSQL to PostgreSQL using DMS&lt;/h2&gt;
&lt;p&gt;Fast forward a year or so, I am now working at Geoscience Australia, with the &lt;a href=&quot;http://www.ga.gov.au/dea&quot;&gt;Digital Earth Australia&lt;/a&gt;. Everything runs on Kubernetes and is highly scalable. Single point of lack of scalability is again the database. A pattern seems to be emerging here. We were performing cluster migration in Kubernetes and I offered to investigate DMS again.&lt;/p&gt;
&lt;p&gt;In the MSSQL scenario there is a small prologue, I had previously migrated around 1million cells from a massive Google Sheet to the MSSQL database at the start of my tenure at the startup, by the time we hit scalability issues in the single instance MSSQL we were at 10million rows in the largest append-only table. The PostgreSQL migration of the &lt;a href=&quot;https://www.opendatacube.org/&quot;&gt;datacube tables&lt;/a&gt; featured 8-9 million rows in the largest table. However the database also has lots of indexes and uses PostGIS for some applications, particularly &lt;a href=&quot;https://github.com/opendatacube/datacube-explorer&quot;&gt;Datacube Explorer&lt;/a&gt;. DMS fell down in support for the Geometry columns, however I learnt a lot in setting up DMS using Terraform IAC and fine tuning for JSON Blob columns, which in &lt;a href=&quot;https://github.com/opendatacube/datacube-core/releases/tag/datacube-1.8.0&quot;&gt;Datacube design in 1.8.x&lt;/a&gt; series can be upto 2MB in size. DMS migrates standard columns separately from LOB columns.&lt;/p&gt;
&lt;p&gt;Ultimately DMS was not feasible for datacube DB migration to a new RDS instance. However I believe core datacube can be migrated next time I try with applications depending on Materialized views and PostGIS setup afresh on new DB. Also by the time I try again Amazon may have better PostGIS support. For the cluster migration we ended up using a &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_RestoreFromSnapshot.html&quot;&gt;snaphot&lt;/a&gt; of the last DB.&lt;/p&gt;
&lt;h2 id=&quot;on-prem-postgresql-to-rds-postgresql&quot;&gt;On-prem PostgreSQL to RDS PostgreSQL&lt;/h2&gt;
&lt;p&gt;There is a Datacube PostgreSQL DB instance at the NCI which needs to be regularly replicated to RDS. It powers the &lt;a href=&quot;https://explorer.dea.ga.gov.au/ls5_fc_albers&quot;&gt;Explorer Datacube&lt;/a&gt; application. However DB migration from one server without direct disk access to RDS where we also don&#39;t have disk access using &lt;a href=&quot;https://www.postgresql.org/docs/11/app-pgrestore.html&quot;&gt;pg_dump / pg_restore&lt;/a&gt; for a DB with largest tables being around 22 million rows and the compressed dump being around 11GB is a long running task. Ideally we sort something out that is &lt;a href=&quot;https://github.com/opendatacube/datacube-core/pull/951&quot;&gt;incremental&lt;/a&gt; using &lt;code&gt;update_time&lt;/code&gt; generated using triggers. The options explored so far are :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using an &lt;a href=&quot;https://github.com/GeoscienceAustralia/dea-airflow/blob/develop/dags/k8s_db_sync.py&quot;&gt;Airflow DAG&lt;/a&gt; with Kubernetes Executors wrapped around pg_dump/restore with some application specific details.&lt;/li&gt;
&lt;li&gt;Using &lt;a href=&quot;https://aws.amazon.com/about-aws/whats-new/2019/06/amazon-aurora-with-postgresql-compatibility-supports-data-import-from-amazon-s3/&quot;&gt;COPY from S3&lt;/a&gt; support for Aurora PostgreSQL, CSV&#39;s restored using the COPY command are generated incrementally.&lt;/li&gt;
&lt;li&gt;Using PostgreSQL publish / subscribe and &lt;a href=&quot;https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication&quot;&gt;Logical Replication&lt;/a&gt;. Networking over the internet to maintain connectivity securely to the on-prem instance via &lt;a href=&quot;https://www.postgresql.org/docs/11/ssh-tunnels.html&quot;&gt;SSH Tunnels&lt;/a&gt; and to the RDS instance via &lt;a href=&quot;https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/&quot;&gt;EKS port-forwarding&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/9038146343419407232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/9038146343419407232' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/9038146343419407232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/9038146343419407232'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/06/replicating-databases-in-rds.html' title='Replicating Databases in RDS'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-8580824782511599889</id><published>2020-05-07T15:11:00.002-07:00</published><updated>2020-05-09T00:39:47.381-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Analog Devices"/><category scheme="http://www.blogger.com/atom/ns#" term="electronics"/><category scheme="http://www.blogger.com/atom/ns#" term="energy monitor"/><title type='text'>ADE7816 Energy Monitor</title><content type='html'>&lt;p&gt;I have been meaning to try out the &lt;a href=&quot;https://www.analog.com/en/products/ade7816.html&quot;&gt;ADE7816&lt;/a&gt; Single-phase 6 current channels energy monitor for a while. However time has been lacking for the last couple of years. Finally I have a working version with successful board bring-up and a semi-working &lt;a href=&quot;https://github.com/whatnick/ADE7816_Micropython&quot;&gt;Micropython driver&lt;/a&gt;, with an &lt;a href=&quot;https://github.com/whatnick/ADE7816_Arduino&quot;&gt;Arduino driver&lt;/a&gt; in the works.&lt;/p&gt;
&lt;h2 id=&quot;pcb-design&quot;&gt;PCB Design&lt;/h2&gt;
&lt;p&gt;The PCB design process for this was not easy mostly due to a footprint choice mistake on my part. I had placed the 5x5mm QFN part instead of the 6x6mm QFN part in KiCAD. This made the DRC fail everywhere in standard settings. However it ended up being a collaboration opportunity with Greg Davill who loves to practice and photograph bodging stuff. So I now have a work of art at hand instead of a non-functional board.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
Practising my bodge skills&lt;br&gt;&lt;br&gt;This is a QFN where the footprint on the PCB was incorrect.&lt;br&gt;&lt;br&gt;Just a couple more bodge wires to add. &lt;a href=&quot;https://t.co/AmZ1CsWqC3&quot;&gt;pic.twitter.com/AmZ1CsWqC3&lt;/a&gt;
&lt;/p&gt;
— Greg (&lt;span class=&quot;citation&quot;&gt;@GregDavill&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/GregDavill/status/1252870227584356352?ref_src=twsrc%5Etfw&quot;&gt;April 22, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p&gt;I am even debating whether to place the rest of the parts and possibly take away from the dead-bug awesomeness. Next time need to order parts in advance and make sure I do &lt;a href=&quot;https://forum.kicad.info/t/how-to-print-a-pcb-from-pcbnew-in-kicad-5-0/11924/5&quot;&gt;1-1 prints&lt;/a&gt; to verify footprints before pulling the trigger on PCB&#39;s.&lt;/p&gt;
&lt;h2 id=&quot;energy-montor-details&quot;&gt;Energy Montor Details&lt;/h2&gt;
&lt;p&gt;Now to more about the energy monitor. This ASIC features 3 single-ended and 3 differential current inputs and a single-phase voltage input, all in very compact 40-pin &lt;strong&gt;6x6mm&lt;/strong&gt; QFN package. In fact the PCB is large on purpose to accomodate ease of use with stereo-jack type current clamps. The main usage would be in standard households where there are typically 3-4 lighting circuits, 1-2 socket circuits and dedicated Air Conditioning circuit. A single energy monitor could be built to monitor all channels using a single-ASIC and leave out fancy NILM stuff from worrying about the lights. The socket circuits could have anything plugged into them and can potentially have point-of-load monitoring instead of breaker board based monitoring. All this translates to more data being generated for IoT platforms and some sensible firmware work needs to be done to handle that.&lt;/p&gt;
&lt;h2 id=&quot;ade7816-driver-development&quot;&gt;ADE7816 Driver Development&lt;/h2&gt;
&lt;p&gt;This is still work in progress. I have done some initial exploration to find prior art. Nothing exists yet from Arduino however there is some register lists from a &lt;a href=&quot;https://github.com/tadakado/smart-meter/tree/master/Soft&quot;&gt;Javascript driver&lt;/a&gt; written for the now defunct Intel Edison.&lt;/p&gt;
&lt;p&gt;Intel never quite had the maker market pinned right to market that board, it makes me sad to think of all the engineering ours sunk into a now defunct platform. Open-source software / hardware helps us salvage some of that. I also sped up the register listing by copy-pasting the ubquitous table from the ADE7816 datasheet and dropping it into a Jupyter notebook to parse all the registers, not as fancy as the Pdf parser I had built before, but much more reliable.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot;&gt;
&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;
My &lt;a href=&quot;https://twitter.com/adafruit?ref_src=twsrc%5Etfw&quot;&gt;&lt;span class=&quot;citation&quot;&gt;@adafruit&lt;/span&gt;&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/ESP32?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#ESP32&lt;/a&gt; + Logic Analyzer test rig. Due in the background is just to keep cables tidy. The ESP32 runs micropython so that I can iterate on SPI modes quickly and use the excellent struct functions to pack/unpack bytes. &lt;a href=&quot;https://t.co/0pQgAO1Cgl&quot;&gt;https://t.co/0pQgAO1Cgl&lt;/a&gt; &lt;a href=&quot;https://t.co/R2imRukrpT&quot;&gt;pic.twitter.com/R2imRukrpT&lt;/a&gt;
&lt;/p&gt;
— Tisham Dhar (&lt;span class=&quot;citation&quot;&gt;@whatnick&lt;/span&gt;) &lt;a href=&quot;https://twitter.com/whatnick/status/1250199028828008448?ref_src=twsrc%5Etfw&quot;&gt;April 14, 2020&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src=&quot;https://platform.twitter.com/widgets.js&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;
&lt;p&gt;My driver development follwed the now tried and tested Micropython + Jupyter Notebook + Logic Analyzer path. I used an ESP32 feather as host processor with standard micropython loaded and probed the SPI bus with read-write packets for known registers until the protocol gave in and started responding with some values. The ASIC is super versatile in supported protocols - I2C Slave, SPI Master and SPI Slave modes are all viable. So developing a fully functional driver supporting all the possible modes will take a while. The initial work so far is on the SPI slave mode since all my other work in DIN rail and Featherwing formats is linked to the SPI bus, however the I2C mode can be really interesting for host-processors with fewer pins and flaky SPI support (while having solid I2C support - like the Onion).&lt;/p&gt;
&lt;p&gt;If anyone is interested in driver development I am happy to send you a board or you can get one yourself from &lt;a href=&quot;https://oshpark.com/shared_projects/oovHySXk&quot;&gt;Oshpark&lt;/a&gt;, &lt;a href=&quot;https://aisler.net/whatnick/playground/ade7816-breakout&quot;&gt;Aisler&lt;/a&gt; or &lt;a href=&quot;https://www.pcbway.com/project/shareproject/Breakout_Board_for_ADE7816_6_Channel_Energy_Monitor_ASIC.html&quot;&gt;PCBWay&lt;/a&gt;. Once the drivers mature I will list it for a wider audience on Tindie.&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/8580824782511599889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/8580824782511599889' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8580824782511599889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/8580824782511599889'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/05/ade7816-energy-monitor.html' title='ADE7816 Energy Monitor'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-1021191518707358530</id><published>2020-04-04T00:12:00.006-07:00</published><updated>2020-04-04T06:02:14.704-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="Design patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Distributed Locking from Python while running on AWS</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
In the day and age of eventually consistent web-scale applications the concept of locking may seem very archaic. However in some instances attempting to obtain a lock and failing to do so within a limited window can prevent dogpile effects for expensive server side operations or prevent over-write of already executing long running tasks such as ETL processes.&lt;br /&gt;
I have used 3-basic approaches to create distributed locks on AWS with the help of built-in services and accessed them via Python which is what I build most of my sofware in.&lt;br /&gt;
&lt;h2 id=&quot;file-locks-upgraded-to-efs&quot;&gt;
File locks upgraded to EFS&lt;/h2&gt;
File based locks in UNIX file-systems are very common. They are typically created using the flock command, avalaible in Python under os-specific &lt;a href=&quot;https://docs.python.org/3/library/fcntl.html#fcntl.flock&quot;&gt;flock&lt;/a&gt; API. Also checkout the platform independent &lt;a href=&quot;https://pypi.org/project/filelock/&quot;&gt;filelock&lt;/a&gt;. This is well and good for a VM or single application instance. For distributed locking, we will need &lt;a href=&quot;https://aws.amazon.com/efs/&quot;&gt;EFS&lt;/a&gt; as the filesystem on which these locks are held, Linux-Kernel and NFS will use &lt;a href=&quot;https://github.com/torvalds/linux/commit/55725513b5ef9d462aa3e18527658a0362aaae83&quot;&gt;byte-range locks&lt;/a&gt; to help simulate locally attached file system type locks. However if the client loses connectivity the NFS lock-state cannot be determined, better run that EFS with enough replicas to ensure connectivity.&lt;br /&gt;
File locking this way is very useful if we are using EFS for holding large file and processing data anyway.&lt;br /&gt;
&lt;h2 id=&quot;redis-locks-upgraded-to-elasticache&quot;&gt;
Redis locks upgraded to ElastiCache&lt;/h2&gt;
Another popular pattern for holding locks in Python is using Redis. This can be upgraded in the cloud-hosted scenario to &lt;a href=&quot;https://aws.amazon.com/elasticache/redis/&quot;&gt;Redis-Elasticache&lt;/a&gt;, This pairs well with the &lt;a href=&quot;https://pypi.org/project/python-redis-lock/&quot;&gt;redis-lock&lt;/a&gt; library.&lt;br /&gt;
Using redis requires a bit of setup and is subject to similar network vagaries and EFS. It makes sense when using Redis already as an in-memory cache for accelration or as a broker/results mechanism for &lt;a href=&quot;https://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html&quot;&gt;Celery&lt;/a&gt;. Having data encrypted at rest and transit may require running an &lt;a href=&quot;https://www.stunnel.org/&quot;&gt;Stunnel Proxy&lt;/a&gt;.&lt;br /&gt;
&lt;h2 id=&quot;an-aws-only-method---dynamodb&quot;&gt;
An AWS only Method - DynamoDB&lt;/h2&gt;
A while ago AWS published &lt;a href=&quot;https://aws.amazon.com/blogs/database/building-distributed-locks-with-the-dynamodb-lock-client/&quot;&gt;an article&lt;/a&gt; for creating and holding locks on DynamoDB using a Java lock client. This client creates the lock and holds it live using heart-beats while the relevant code section executes. Since then it has been ported to &lt;a href=&quot;https://pypi.org/project/python-dynamodb-lock/&quot;&gt;Python&lt;/a&gt; and I am maintaining my own &lt;a href=&quot;https://github.com/whatnick/python_dynamodb_lock&quot;&gt;fork&lt;/a&gt;.&lt;br /&gt;
It works well and helps scale-out singleton processes run as Lambdas to multiple lambdas in a serverless fashion, with a given lambda quickly skipping over a task another lambda is holding a lock on. I have also used it on EC2 based stuff where I was already using DynamoDB for other purposes. This is possibly the easiest and cheapest method for achieving distributed locking. Locally testing this technique is also quite easy using &lt;a href=&quot;https://hub.docker.com/r/amazon/dynamodb-local/&quot;&gt;local-dynamodb&lt;/a&gt; in a docker container.&lt;br /&gt;
Feel free to ping me other distributed locking solutions that work well on AWS and I will try them out.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/1021191518707358530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/1021191518707358530' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1021191518707358530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/1021191518707358530'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/04/distributed-locking-from-python-while.html' title='Distributed Locking from Python while running on AWS'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3220006345447041404.post-5946366589254569308</id><published>2020-01-24T05:48:00.001-08:00</published><updated>2020-01-24T06:35:58.289-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="ecp5"/><category scheme="http://www.blogger.com/atom/ns#" term="electronics"/><category scheme="http://www.blogger.com/atom/ns#" term="fpga"/><category scheme="http://www.blogger.com/atom/ns#" term="open hardware"/><title type='text'>Testing the OrangeCrab r0.1</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
After hassling &lt;a href=&quot;https://twitter.com/GregDavill&quot;&gt;Greg Davill&lt;/a&gt; for a while on twitter and admiring his OrangeCrab hardware I managed to catch up with him in person in Adelaide. I have been away in Nairobi till October last year, then I spent a brief few days in Adelaide before coming over to Canberra to take up a position in Geoscience Australia. The new gig is much less time commitment than the start-up world and hopefully will allow more time for blogging and board bring-ups like this one.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtvrvNVcFg-ZvLpiSwNMcmTSTlHfzBRV-SSi87hoCt7ry1AhRbXUaCpuDgj-dc8Ml7K-ouPznJAxKEM0Q0zXTLHVjfNtHTOqSbyXCEKZDYDamZgLy8Qo3U7wdYeLzz3lYTSsXGxAMVjA/s1600/PANO_20191015_182101.vr.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;698&quot; data-original-width=&quot;1600&quot; height=&quot;173&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtvrvNVcFg-ZvLpiSwNMcmTSTlHfzBRV-SSi87hoCt7ry1AhRbXUaCpuDgj-dc8Ml7K-ouPznJAxKEM0Q0zXTLHVjfNtHTOqSbyXCEKZDYDamZgLy8Qo3U7wdYeLzz3lYTSsXGxAMVjA/s400/PANO_20191015_182101.vr.jpg&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
I caught up with Greg at a Japanese restaurant in Rundle mall and was treated to his now trademark led cube and led icosahedron. They are insanely detailed pieces of work and deserve staring at. However I am most grateful for the care package he left me, an OrangeCrab v0.1. This is an ECP5 board in feather form factor with an ADC built in to respect the Analog In pins on the feather. My aim for this board is to host some energy monitoring code on the FPGA with a fast 4mbps or so ADC and perform power/energy calculation on some parts of LUT&#39;s/DSP and have a &lt;a href=&quot;https://github.com/riscv/riscv-cores-list&quot;&gt;softcpu&lt;/a&gt; push data out.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmWDzWZ_ImBjAsDSHnUdkRS_q-inNApnz8_mUXO6O7gG5tRQCPl7LCvubKfq5wgOaDt050vBGhfw2cMSeQvFnIpuk9ZxHdPIhO8GaxtxH9fjor9KYVkQQcQGvasGccM4GP7ulygBZIaA0/s1600/IMG_20191205_203704.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;1600&quot; data-original-width=&quot;1200&quot; height=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmWDzWZ_ImBjAsDSHnUdkRS_q-inNApnz8_mUXO6O7gG5tRQCPl7LCvubKfq5wgOaDt050vBGhfw2cMSeQvFnIpuk9ZxHdPIhO8GaxtxH9fjor9KYVkQQcQGvasGccM4GP7ulygBZIaA0/s320/IMG_20191205_203704.jpg&quot; width=&quot;240&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
Greg also left me a home-made FTDI based board to use a JTAG programmer. The whole setup requires 3 USB cables:&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&amp;nbsp;To plugin and power the FPGA board (eventually it should be alos programmable via this port)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To attach a USB-Serial converter and watch the console when the gateware comes up&amp;nbsp;&lt;/li&gt;
&lt;li&gt;To program the board over JTAG using an FTDI chip&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
Getting firmware compiled these days is getting easier, but Greg had done his initial testing with &lt;a href=&quot;https://ycnrg.org/lattice-diamond-on-ubuntu-16-04/&quot;&gt;Lattice Diamond&lt;/a&gt;. I managed to installed it in WSL and promptly ran into a tonne of issues. The weirdest being close coupling to bash, Ubuntu actually uses &lt;a href=&quot;https://askubuntu.com/questions/976485/what-is-the-point-of-sh-being-linked-to-dash&quot;&gt;dash&lt;/a&gt; as its default shell. You can get a Diamond &lt;a href=&quot;http://www.latticesemi.com/Support/Licensing/&quot;&gt;licence&lt;/a&gt; and help support integration of diamond in &lt;a href=&quot;https://github.com/timvideos/litex-buildenv&quot;&gt;litex-buildenv&lt;/a&gt;.&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQScjLeWw8mV3m6PJMrGpi11_qhyBSNEIPvblvqwDS2Lvn3-6T5L5vpGEosuy2_-bFsNaaFHmysFAR_mrsrl2u5UjZH85aTxjLo-0FLa-Roz0In1xvXcGrUYe5XtUvqjgs0xAZ0E0h_94/s1600/RAM_Test_pass.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;834&quot; data-original-width=&quot;1600&quot; height=&quot;166&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQScjLeWw8mV3m6PJMrGpi11_qhyBSNEIPvblvqwDS2Lvn3-6T5L5vpGEosuy2_-bFsNaaFHmysFAR_mrsrl2u5UjZH85aTxjLo-0FLa-Roz0In1xvXcGrUYe5XtUvqjgs0xAZ0E0h_94/s320/RAM_Test_pass.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
I was about to give up then Greg got it working with the opensource toolchain and [NextPNR-ECP5&lt;a href=&quot;https://github.com/YosysHQ/nextpnr/tree/master/ecp5&quot;&gt;&lt;/a&gt;. I had by then setup litex-buildenv to support the orangecrab. So getting some gateware on was relatively easy. Then I got stuck on &lt;a href=&quot;https://github.com/enjoy-digital/litedram/issues/103&quot;&gt;RAM timing bug&lt;/a&gt; in Litex till a few hours ago when I tested out some &lt;a href=&quot;https://gist.github.com/gregdavill/e7644319dcc3b8015758171067d37b98&quot;&gt;new gateware&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Also Checkout out Greg&#39;s &lt;a href=&quot;https://github.com/gregdavill/foboot/tree/OrangeCrab-ECP5&quot;&gt;foboot fork&lt;/a&gt; and help make programming over the USB possible and reduce 1 USB cable. More work on this including getting &lt;a href=&quot;https://github.com/antonblanchard/microwatt&quot;&gt;MicroWatt&lt;/a&gt; running coming soon.&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://whatnicklife.blogspot.com/feeds/5946366589254569308/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/3220006345447041404/5946366589254569308' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5946366589254569308'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3220006345447041404/posts/default/5946366589254569308'/><link rel='alternate' type='text/html' href='http://whatnicklife.blogspot.com/2020/01/testing-orangecrab-r01.html' title='Testing the OrangeCrab r0.1'/><author><name>Tisham Dhar</name><uri>http://www.blogger.com/profile/15154154153085427197</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHtvrvNVcFg-ZvLpiSwNMcmTSTlHfzBRV-SSi87hoCt7ry1AhRbXUaCpuDgj-dc8Ml7K-ouPznJAxKEM0Q0zXTLHVjfNtHTOqSbyXCEKZDYDamZgLy8Qo3U7wdYeLzz3lYTSsXGxAMVjA/s72-c/PANO_20191015_182101.vr.jpg" height="72" width="72"/><thr:total>0</thr:total></entry></feed>