home.social

Search

1000 results for “commons_protocol”

  1. The Broken Mesh: Why the Fight Between Meshtastic and MeshCore Matters

    2,734 words, 14 minutes read time.

    The fracture between the Meshtastic and MeshCore projects is a warning that you cannot ignore. For years, people thought a simple, off-grid data net was the answer for when the main lines go down. But now, the community is divided. This is not just a small fight over code. It is a total disagreement on how to handle communication when things get ugly. If you think you are ready just because you bought a cheap radio board and did not bother to learn how the software actually works, you are just a hobbyist playing with toys. The rift between Meshtastic and MeshCore shows how fragile these systems are and why you need to know your gear inside and out. A mesh net is only as good as its weakest link. If you do not master the tech, you are just a dead node in a silent town. We are seeing the growing pains of a decentralized technology that is outstripping the discipline of its users. You must choose your tools based on the reality of the physics, not the popularity of the app. Demand that your firmware be an efficient tool for data transmission, not a bloated social media platform for the 915 MHz band. If you do not take the time to understand the modulation, the packet structure, and the routing logic of the software you flash onto your hardware, you are just a child playing with a walkie-talkie while the grown-ups are trying to build a grid. Mastery of the radio spectrum is not an option; it is a requirement for anyone who claims to be prepared. This split is the first real test of whether civilian mesh can survive the chaos of its own success. You either learn to navigate the airwaves or you signal your own failure. Every packet you send without understanding the cost is a round wasted in a firefight. Stop treating your emergency comms like a smartphone app and start treating it like the life-support system it is. This technical mastery is the difference between a working link and a radio that does nothing but drain your battery in the dark.

    Troubleshooting LoRa Mesh Protocol Inefficiency and Network Congestion

    The fight between Meshtastic and MeshCore comes down to how they use the radio waves and the small chips that run them. Meshtastic has been the big name for a long time. It uses a flooding method where every radio repeats every message it hears. In the woods, that is fine. In a city with a hundred users, it is a train wreck. The air gets crowded, messages hit each other, and the whole system jams itself. MeshCore did not start because people wanted a new app. It started because the old way is inefficient. The core of the split is about the overhead—the extra data that hitches a ride on every message. Meshtastic adds a lot of features, but those features take up space. MeshCore wants to strip everything down to the bone so the network stays stable. When you have very little room to send data, every extra bit is a mistake. This is a battle between lots of features and it just has to work. If your software is fighting your hardware, you lose. The divergence between Meshtastic and MeshCore is rooted in the physics of the 900 MHz ISM band and the limitations of the ESP32 and nRF52 chipsets. As the node count grows, the airwaves become a chaotic mess of collisions and retransmissions, effectively jamming the very frequency the operators are trying to utilize. While Meshtastic has focused on a feature-rich user experience with a heavy reliance on a specific structure, MeshCore proponents argue for a leaner, more modular approach that prioritizes the stability of the underlying mesh over the bells and whistles of the interface. When you are operating on a low-bandwidth, high-latency medium like LoRa, every byte of overhead is a liability. You either master the protocol or you become a dead node. The math does not lie even if the marketing does. If your network protocol consumes more than ten percent of your bandwidth for heartbeats, your network is dying. Every extra feature in the code is another potential point of failure when the signal gets weak. You have to decide if you want a chat app or a survival tool. The flooding algorithm used by Meshtastic is a blunt instrument that was never meant for high-density urban deployment. It works by simply re-broadcasting every unique packet received until a hop limit is reached. In a sparse environment, this ensures the message gets through by any means necessary. But as the number of nodes increases, the probability of two nodes transmitting at the same time goes up. This leads to packet collisions where neither message is readable. MeshCore attempts to solve this by moving toward a more structured routing system. This means the software tries to figure out the best path for a message instead of just yelling it to everyone. This shift requires a level of technical discipline that many casual users find frustrating. It means the network is less plug-and-play and more of a precision tool. If you want a network that survives a real crisis, you have to move away from the chaos of flooding. You have to understand how the Media Access Control layer handles traffic. You have to know how to set your timing parameters so you are not stepping on your own neighbors. The split is a clear line in the sand between those who want ease of use and those who want engineering reliability. You cannot hide from the physics of the airwaves. Either your packets move or they die in the dirt. Stop assuming the software will fix your bad placement. Fix the engineering or get off the air.

    Physics of LoRa Packet Collisions and Signal to Noise Ratio Analysis

    To understand this split, you have to look at how these radios actually talk. They use a low-power system called LoRa. It is built for long range, but it is slow. There are strict rules on how long you can broadcast before you have to shut up and let others speak. Because Meshtastic repeats everything, adding more people makes the problem worse fast. This is not a glitch. It is physics. MeshCore was built to change how messages find their path through the net. Instead of everyone yelling at once, it wants a smarter way to move data that does not waste airtime. The split happened because one group likes the safety of repeating everything, while the other wants a clean, quiet network. If your radio is spending eighty percent of its power just saying I am here, you are not communicating—you are just making noise. The split proves that the current path is heading for a crash where no one can get a message through. LoRa is designed for long-range, low-power communication, but it is inherently limited by the Duty Cycle regulations of the FCC Part 15 and similar international bodies. Meshtastic’s current implementation of the flooding protocol means that as you add more users, the probability of packet storms increases exponentially. MeshCore was conceptualized to address the need for a more rigid, perhaps even more disciplined, routing logic that could potentially mitigate the hidden node problem and reduce the airtime usage per packet. The technical fallout between the two development paths stems from a disagreement on how to manage the limited airtime of the ISM band. One camp believes in the resilience of redundant flooding, while the other seeks a more surgical, routed approach to data delivery. This is a matter of Spectral Efficiency. If your mesh is using the majority of its available airtime just to say it exists, you have failed as an operator and an engineer. You are polluting the spectrum with digital noise. This noise prevents emergency traffic from getting through. It creates a false sense of security where people think they have a working link when they actually have a jammed one. You must look at the duty cycle of your own node. If you are transmitting more than one percent of the time in the 900 MHz band, you are likely part of the problem. MeshCore is an attempt to force the network into a more responsible state. It prioritizes the survival of the link over the convenience of the user. This is a hard truth that many do not want to hear. Physics does not care about your feelings or your user interface. It only cares about the signal-to-noise ratio. If your signal is lost in the noise of your own network, you have built nothing but a very expensive paperweight. Every packet sent is a risk. In a real-world scenario, a long transmission can be used to find your location. Flooding makes this risk much higher because your message is repeated over and over by every node in the area. A routed system like what MeshCore aims for reduces this risk by limiting the number of times a message is sent. This is not just about efficiency; it is about security. You have to understand that the airwaves are a shared resource. If you treat them like your own personal garbage dump, you will find yourself alone and unheard when the time comes to actually send a call for help. The split between Meshtastic and MeshCore is a debate over the very future of private, off-grid data. One side wants to make it accessible to everyone, while the other wants to make it work when nothing else does. You have to decide which side of that line you stand on. If you are not monitoring your packet loss and your noise floor, you are not an operator. You are just a passenger in a system that is bound to fail. Stop looking at the colorful screens and start looking at the spectrum. The truth is in the waterfall, not the icons. The physics of 915 MHz demand respect that a plug and play mindset cannot provide.

    Off-Grid Communication Solutions and Technical Radio Discipline

    The result of this fight is a mess where gear running one software will not talk to gear running the other. For you, that means your radio is a brick if your neighbor is on the other side of the fence. This is how a mesh net dies. A mesh needs everyone to speak the same language. When the builders split, the network breaks. This should wake up anyone who thinks they can just download a file and be safe. The hard truth is that we are seeing a new tech grow too fast for the people using it. You have to pick your tools based on facts, not what looks cool. Demand software that moves data fast and clean. If you do not know how your radio sends a packet or why some settings work better than others, you have no business relying on this in a pinch. The split between Meshtastic and MeshCore is a reminder that in the world of radio, there are no shortcuts. For the operator in the field, this means your gear might be useless if the person three blocks away is running a different branch of the protocol. This is the death of a mesh. A mesh requires a common language, a shared set of timing parameters, and a unified understanding of frequency hopping and spreading factors. When the developers split, the network breaks. This should serve as a wake-up call to anyone who thinks they can outsource their emergency communications to a GitHub repository they do not understand. The split between Meshtastic and MeshCore is a reminder that in the world of RF, there are no shortcuts. If you cannot explain the difference between a Spreading Factor of seven and twelve, or why a 125kHz bandwidth is preferable over 250kHz in a high-noise environment, you have no business relying on these tools. The hard truth is that we are witnessing the growing pains of a decentralized technology that is outstripping the discipline of its users. You must take personal responsibility for your station. This means testing your range with real-world obstacles. It means understanding how your antenna height and gain affect your local mesh. It means being able to re-flash your firmware in the dark while the rain is pouring down. If you cannot do these things, you are not prepared. You are just a collector of electronic gadgets. The discipline of the amateur radio spirit must be applied to these new digital modes. We are losing the technical edge that made the license worth having in the first place. The split is a chance to reset. It is a chance to move away from the appliance operator mindset and back toward the engineering mindset. You should be auditing your own mesh. Look at the traffic logs. See how many packets are being dropped. See how many of your traffic is just node discovery overhead. If you find that your network is inefficient, do not wait for a developer to fix it. Change your settings. Educate your neighbors. If the split leads to a better, more efficient protocol, then it was worth the friction. But if it just leads to two broken networks instead of one, then we have all lost. The practical application of this knowledge is simple: test everything. Do not assume your mesh will work because the light on the board is green. Prove it. Send data over the longest possible path. Monitor the battery drain. Watch the spectrum on an analyzer if you have one. If you do not have the tools to verify your network, you do not have a network. You have a hope. And hope is not a plan for communication. Secure your nodes, harden your protocol, and stop relying on software you have never bothered to read. The day is coming when the only thing between you and the void is the connection you built yourself. Don’t let it be a connection built on laziness. Clean up your messy node or accept that you will be silent when it matters.

    Conclusion: The Future of Decentralized Mesh Networks and User Mastery

    The discipline of the old-school radio operator has to be applied here or the whole thing will fail. The split between Meshtastic and MeshCore is a call to stop being a lazy user and start being a real operator. We do not have time for good enough when the grid is down. Check your gear, learn the rules of the airwaves, and be ready for a future where the channels are full and the software is broken. Build your setup expecting things to break. There is no room for being soft. Learn the math, understand your range, and make sure every message you send is worth the airtime. The grid is weak, the airwaves are crowded, and your own lack of knowledge is the only thing truly blocking your signal. Fix your gear, learn the system, and stop waiting for someone else to save you. The grid is fragile, the spectrum is finite, and your ignorance is the only thing standing between you and a total blackout. Fix your station, fix your protocol, and stop waiting for someone else to secure your link. The time for playing games with digital toys is over. Mastery is the only way forward. Master the code, master the RF, or stay off the air. This hobby demands engineers, not appliance operators. Be the asset the network needs, not the QRM that kills it. Finalize your build, test the link, and maintain the discipline required to keep the airwaves open for those who truly need them.

    Call to Action

    Join the Network and Master Your Comms Before the Grid Goes Dark. The split between Meshtastic and MeshCore is a wake-up call for every operator. You cannot afford to be a passive user when the lines of communication are at stake. Whether you choose the feature-rich path or the lean efficiency of the core, the responsibility for a working link lies with you. Don’t wait for a crisis to realize your nodes are misconfigured or your protocol is inefficient. Start auditing your setup today by getting out in the field to find your real-world limits, diving into the spreading factors to clear the noise, and educating your local mesh to ensure your neighborhood stays connected. The airwaves belong to those who master them. Secure your hardware, flash your firmware, and become a reliable node in the decentralized future. Join the conversation, build the grid, and stay off the silent list.

    SUPPORTSUBSCRIBECONTACT ME

    D. Bryan King

    Sources

    Disclaimer:

    The views and opinions expressed in this post are solely those of the author. The information provided is based on personal research, experience, and understanding of the subject matter at the time of writing. Readers should consult relevant experts or authorities for specific guidance related to their unique situations.

    Related Posts

    Rate this:

    #915MHz #airtimeOptimization #AmateurRadio #antennaGain #bandwidthManagement #communicationSecurity #communityMesh #constrainedNodes #dataTransmission #DecentralizedNetworks #digitalModes #DisasterRecovery #dutyCycle #emergencyComms #ESP32 #FCCPart15 #firmwareFlashing #floodingProtocol #gridDownComms #hiddenNodeProblem #IoTScalability #ISMBand #linkBudget #LoRa #LoRaWAN #meshNetworking #MeshCore #Meshtastic #networkCongestion #nodeDensity #nRF52840 #offGridCommunication #packetCollisions #packetLoss #protocolOverhead #radioDiscipline #radioFrequency #RFEngineering #RFInterference #routingLogic #signalPropagation #SignalToNoiseRatio #SNR #spectralEfficiency #spreadingFactor #survivalTech #SX1262 #TacticalComms #wirelessProtocols
  2. PDS – the Programmers Development System

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum
  3. PDS – the Programmers Development System

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces.

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum
  4. PDS – the Programmers Development System

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum
  5. PDS – the Programmers Development System

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum
  6. PDS – the Programmers Development System

    This series of posts looks at the Programmers Development System (PDS).

    • Part 1 – Introduction, background and some initial reverse engineering.
    • Part 2 – A closer look at the PC ISA Interface card.
    • Part 3 – Remaking the target interfaces.

    I was directed towards this recently – it is a means of developing for 8-bit computers using early PCs or an Atari ST developed by Andy Glaister. Information about it seems quite sparse online, the main references seem to be:

    As far as I can tell the original system was developed in the 1980s and there have been two attempts at recreating it since, as listed above.

    The original reimplementation is from the Spanish site and provides a schematic and Eagle files. The next link was an attempt at using these design files by importing into KiCAD and getting Gerber files built which seemed to be pretty successful.

    I must admit that when I first heard about it, I wondered if it was the same one that Dean Belfield was using with his Tatung Einstein at the 2025 RetroFest, but having read a bit more about it, there are definitely similarities, but I’m not sure its the same. Details of Dean’s setup here:

    It uses a similar principle to the PDS, in that development is performed on the Tatung and then code is transferred across to the target system using a combination of hardware and code running on both sides.

    Basic Operation

    As I understand things, with the PDS there was an interface card for the PC which linked via a 16-wire IDC cable to another interface card for the target computer. There were versions for the ZX Spectrum, Amstrad CPC, C64 and MSX (and possibly others). I’m only really interested in the ZX Spectrum version.

    The PC card is based around the Intel 8255 parallel IO chip sitting on an 8-bit ISA bus. The target interface is usually based around the Z80 PIO (Z84C20) interfacing to the bus of the host system. The PC card supports two target interfaces and both cards include some logic chips to handle addressing and the IO interface.

    Details of the 16-way IO link seem very sparse and will probably have to be worked through and inferred from the source code that has been uncovered.

    From what I can tell, most of the protocol handling is done in the code and the interfaces are essentially IO “passthroughs”. The target has to run some monitor code to react to PDS commands and interface with the memory as required, setting, reading, updating, and so on.

    The CPC wiki seems to be the most complete source of information so far, and includes photos of the remade boards and schematics for the PC card and ZX Spectrum interface.

    The PDS Link

    The PDS link itself is via a 16-way IDC ribbon cable and 2×8 IDC connectors. Unfortunately I’ve not found a pin-out anywhere so far, but from various sources, this is what I know so far.

    GND12DATA 0PC to Target Clock34DATA 1Target to PC Clock/Ack56DATA 2Unknown78DATA 3Not used910DATA 4Not used1112DATA 5Not used1314DATA 6Not used1516DATA 7

    This is using the pin numbering from the ZX Spectrum schematic.

    Unfortunately the schematic labelling of the two PDS sockets for the PC card is backwards compared to the ZX Spectrum card. Pin 16 for the PC version is GND, but that is pin 1 for the ZX Spectrum version. It would also appear that the socket shroud is also reversed. This means that D0 is pin 15 for the PC and pin 2 for the Spectrum.

    The CPC wiki has a photo of the cable used, showing how pins 1-16 are wired to pins 16-1:

    The PC Card

    The schematic for the PC card can be found on the CPC wiki here: https://www.cpcwiki.eu/index.php/PDS_development_system

    Main Components required:

    • Intel 8255 Programmable Peripheral Interface (PPI).
    • 74LS138 – 3 to 8 line decoder (for the addressing).
    • 3x 74LS244 – 8 channel non-inverting buffers.
    • 74LS04 – Hex Inverter (only one inverter is used).

    It probably goes without saying for this era technology, but everything is 5V TTL levels.

    The Intel 8255 PPI

    The Intel 8255 Programmable Peripheral Interface (PPI) device provides access to 3 bidirectional 8-bit IO ports. There is a good summary here.

    From https://en.wikipedia.org/wiki/Intel_8255:

    The 8255 gives a CPU or digital system access to programmable parallel I/O. The 8255 has 24 input/output pins. These are divided into three 8-bit ports (A, B, C). Port A and port B can be used as 8-bit input/output ports. Port C can be used as an 8-bit input/output port or as two 4-bit input/output ports or to produce handshake signals for ports A and B.

    The three ports are further grouped as follows:

    1. Group A consisting of port A and upper part of port C.
    2. Group B consisting of port B and lower part of port C.

    There are two address lines that are used to select one of four registers as follows:

    A1A0Register00Port A01Port B10Port C11Control Register

    The device is selected on the bus when CS is active. It also uses RD and WR to know if it is reading from or writing to the registers.

    Things get a bit complicated pretty quickly, but there is a good summary of the various modes of operation on the Wikipedia page, and of course, a comprehensive datasheet.

    PC PDS Interface

    According to the schematic, this is how the three 8255 IO ports map onto the two PDS connections:

    8255 IO PortPDS Connection74LS244 UsedEnabled byPORT A 0-3Link 2: Data 0-3IC 3B/PC2PORT A 4-7Link 1: Data 0-3IC 4B/PC2PORT B 0-3Link 1: Data 4-7IC 3APC2PORT B 4-7Link 2: Data 4-7IC 4APC2PORT C 0-3Link 1 and 2: ControlIC 5AAlways OnPORT C 4-7Link 1 and 2: ControlIC 5BAlways On

    It is also worth noting that the three 74LS244 buffers are enabled in different ways according to the state of PC2. Also, as the enable is active LOW, the inverter on PC2 generates a “NOT PC2” signal, which itself must be LOW to activate IC3A/IC4A – i.e. it is a “active on NOT NOT PC2” signal. PC2 appears to be used to decide which nibble of the data port should be active. It is also passed through to the link control pins (see below).

    The 8 control lines map onto the two links in an interesting way. Note this is using “PC interface” pin numbering which as previously mentioned is different to the ZX Spectrum side.

    Link 1 PinsLink 2 PinsPC0144PC1414PC266PC388PC4122PC5212PC610N/CPC7N/C10

    So we can see that PC2 and PC3 are common; that PC0/PC1, PC4/PC5 are swapped; and that PC6 is link 1 only; and PC7 is link 2 only. Recall PC2 appears to select which nibble is active.

    When mapped onto the ZX Spectrum card, anything on pins 2,4,6,8 are mapped onto unused pins.

    I must say I’m struggling to make sense of this. This seems to be implying that when data is written to one of the PPI IO PORTs, it is striped across both link 1 and 2. Surely it would make more sense to select one or the other and write all 8 data values in one go?

    I did wonder if this was related to the different IO modes of the 8255, but on re-reading how the modes work, this still doesn’t make much sense to me.

    Unfortunately there doesn’t appear to be any source code for the PC end of things to see what it is doing.

    Ok, so finding a print of the traces for the PCB and overlaying them on a light box gives me the following:

    I’ve highlighted the connection for D0. We can clearly see that on the PCB D0 for both links is connected, and not only that, it is connected to both input side 2A1 and output side 1Y4 on the /same/ IC. This would make sense for a bi-directional bus, but it is quite a long way from the schematic.

    At this point I have to conclude that the schematic is just plain wrong so I’m leaving the PC card for now.

    The ZX Spectrum Card

    The spectrum side is based on the Z80 PIO (Z8420/Z84C20). There is also a schematic and PCB for that on the CPC wki, but after the experiences with the PC card, I’m now treating it with a little skepticism…

    Z80 PIO

    There is a lot of information about using the Z80 PIO around. Key references:

    Key features:

    • Two fully bidirectional 8-bit IO ports.
    • Handshaking (not used for the PDS).
    • Close compatibility with Z80 control signals (most not used for the PDS).
    • Four modes of operation:
      • Byte output
      • Byte input
      • Byte bidirectional (port A only)
      • Bit control
    • Six registers addressable via 4 IO ports in the Z80 IO map.

    The signals involved in address decoding are:

    ZX BusPIOFunctionA5PORTSELSelects PORT A or PORT BA6CONTSELSelects DATA or CONTROLA7/CEEnables the device/M1/M1Z80 control signal/IORQ/IORQIO access in progress/RD/RDRead in progressCLOCKCLKZ80 clock

    The use of A5-A7 means that any IO address (IORQ must be active) with A7 clear (CE is active LOW) will be received by the PIO and then A5 and A6 determine the type of access. This gives an IO address of the following:

    b000x xxxx$xx0x or $xx1xPORT A DATAb001x xxxx$xx2x or $xx3xPORT B DATAb010x xxxx$xx4x or $xx5xPORT A CONTROLb011x xxxx$xx6x or $xx7xPORT B CONTROL

    This equates to some pretty lazy IO address decoding, in that there are many, many equivalent IO addresses that would be decoded by the PIO.

    Note that the CPC wiki lists port addresses in the range 0xFBEC-0xFBEF. These are the addresses used with the Amstrad CPC not the ZX Spectrum.

    Looking at the provided source code for the ZX Spectrum, it appears to be using IO instructions (OUT, IN) using ports 31 ($1F), 63 ($3F), 95 ($5F), and 127 ($7F).

    The schematic shows that /IORQ from the PIO is connected to /IORQ from the Z80 via a SPDT switch which allows selection between Z80 /IORQ and fixed pulled HIGH. This allows the PIO to be inhibited by stopping it responding to /IORQ.

    The interrupt control lines for the PIO are not used. INT and IEO are not connected and IEI is pulled HIGH. The hand-shake signals (ARDY, ASTB, BRDY, BSTB) are not used either.

    ZX Spectrum PDS Interface

    The ZX Spectrum side of the PDS interface has the following:

    • PIO PORT A – goes via the 74LS245 octal buffer to the 8 data lines of the PDS link.
    • PIO PORT B – goes via the 74LS04 for certain control signals from the PDS link, and the direction control for the 74LS245.
      • Bit 0 – Pin 2 of the PDS interface
      • Bit 1-4 – not used
      • Bit 5 – Pin 7 of the PDS interface
      • Bit 6 – 245 direction control
      • Bit 7 – Pin 5 of the PDS interface

    Note that half the PDS control signals are not used for the Spectrum interface. From the previous discussion we can interpret bits 2 and 7 to be the two clock/ack signals. Bit 5’s use is currently unknown. I’ll have to go to the code to see what is going on there.

    ZX Spectrum PDS Monitor

    I’ve not been able to find any source code for the PC side of things, some assembler has been issued for the target machines, which can be assembled into the run-time PDS monitor for that system.

    The PDS Manual does have this to say:

    “The software is designed to be machine independent, so the same protocols can be
    used regardless of the target machines processor or make. All the communication is basically
    the same, there are four major routines, SEND BYTE, GET BYTE and two direction
    swapping routines.”

    There are three versions of the monitor code for the ZX Spectrum:

    • DL0 – the most minimal implementation, providing assembling and downloading only.
    • DL1 – the long downloader, providing support for everything apart from the “analyze” command, which requires interrupts.
    • DL2 – the full interrupt driven downloader.

    The PDS manual contains some information about the ZX Spectrum downloader. Section 6.2 details the three versions of the code and then goes on to describe the available commands.

    To get a feel for how the monitor functions, and some insights into how the hardware works, I’m looking at some extracts of DL0.

    Code initialisation

    START DI
    LD A,255
    OUT (127),A ; $7F=CB=$FF Mode 3
    OUT (63),A ; $3F=DB=$FF PORT B=$FF (B0-7=HIGH)
    LD A,63
    OUT (127),A ; $7F=CB=$3F B6/B7=OUTPUT B0-B5=INPUT
    LD A,255
    OUT (95),A ; $5F=CA=$FF Mode 3
    OUT (95),A ; $5F=CA=$FF A0-A7=INPUT

    CTRL = $FF means all bits of the control register are set. The Z8020 datasheet lists the control register as follows:

    76543210M1M0xx1111

    Where M1/M0 signify which of the four modes is to be used. In this case both PORTs are set to Mode 3, which allows for either IN or OUT on a per bit basis. I am guessing the writing of $FF to DB (PORT B DATA) happens to ensure that when then ports are configured as 2 OUT and 6 IN, the OUT lines are already HIGH, giving a known starting point.

    Note: Setting B6 to HIGH means that the direction control for the 74LS245 will be LOW as it goes through an inverter. This sets the 74LS245 to work in the direction “B to A” which would correspond to when PORT A is set to all INPUTs later in the code.

    GETBYTE

    This is the lowest level function and it retrieves a single byte of data from over the PDS interface. This is used during the main protocol handling to both obtain commands over PDS and then receive data.

    The essential function is as follows:

    • Ensure PORT A setup for INPUT
    • WAIT for a change in the PC->TARGET CLOCK
    • Read the data from PORT A
    • WRITE the TARGET->PC CLOCK/ACK
    • Toggle the two CLOCK signals ready for next time
    • Return
    ;On first entry D=64=b0100 0000
    GETBYTE IN A,(63) ;Read DB - control values
    XOR D ;Toggle FLAGS
    RRCA ;Pushes B0->Carry
    JC GETBYTE ;Wait for B0 to have changed
    IN A,(31) ;Read data from DA
    LD E,A ;And store in E
    LD A,D ;Reload FLAGS
    OUT (63),A ;And write them out ie write B7
    XOR 129 ;Toggle B0+B7 (129, $81) for next time
    LD D,A ;And store back in D
    RET

    So I think the key features for this are:

    • Control FLAGS are stored in the D register. Only B0, B6, B7 are significant. B0 is what we’re looking for on reception; B7 is what we will send in acknowledgement; B6 is the DIRection and is preset to INPUT for this.
    • FLAGS are initialised to 64 i.e. B0=B7=0; B6=1.
    • Every pass through the GETBYTE function toggles B0 and B7 between b0xxxxxx0 and b1xxxxxx1.
    • Read data is stored in the E register.
    • RRCA is used to take the read in control value and shift B0 into the carry flag so it can be checked with JC (JP C).
    • Nothing else in the code works with the D register so it will always reflect the required status of the required PORT B CTRL word flags.

    So this shows how the flags change through several passes of the function:

    D=64               D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)
    CALL GETBYTE D=0100 0000 ($40)
    CALL GETBYTE D=1100 0001 ($C1)

    The PDS Manual describes the protocol as follows:

    “Note that the protocol does not set the control lines directly, but toggles the lines to
    communicate. All the protocols are designed so one computer can never get ahead of the
    other, even if there is a big speed difference. There are no error checking protocols, as the
    interfaces are very reliable, and error checking will slow down processes, and no real action
    can be taken, even if an error was detected.”

    Main Loop

    The main loop essentially reads a byte from the interface and treats it as a control command. It will keep doing this until it finds a command it can process.

    MAINLOOP CALL GETBYTE ;Get 'command byte'
    LD A,E
    CP 180 ;Download code into aabb, len=ccdd
    JZ DLOAD
    CP 183 ;Select bank aa
    JZ SBANK
    CP 181 ;Execute code from aabb?
    JNZ MAINLOOP ;Not recognised - keep looping.

    The comments are the original comments. There is a not a function for command 181, as this relies on “fall through”. It is the next function in the code.

    The commands have values 180-187 as follows:

    • 180: Download code
    • 181: Jump to an address
    • 182: Upload memory
    • 183: Select bank
    • 184: Send all registers to the main computer
    • 185: Get registers from the main computer
    • 186: Trace code buffer
    • 187: Return analyze address

    The various functions and message protocol layer are described in the PDS manual, so I won’t go into them in detail here, but by way of example, here is the description for 181:

    The corresponding code is as follows:

    ;
    ; Function 181, Execute code from aabb
    ;
    CALL GETBYTE
    LD H,E ;Get address of routine
    CALL GETBYTE
    LD L,E
    LD BC,MAINLOOP
    PUSH BC ;Put return address on stack and jump to routine
    JP (HL)

    It is interesting to note that in the PDS manual, some commands appear to start with a padding byte (179). Apparently this is to ensure that all command messages are an even number of bytes long.

    Any variable length commands (e.g. download) include an expected length field.

    To retrieve data from the target, the protocol has the concept of “reverse ports”. After receiving upload command, ports are reversed to allow the sending of the appropriate amount of data before being reversed once again to restore the original direction ready for the next command.

    Uploading is not supported in the simple D0 downloader. That requires the more complete D1 or D2 implementations. I’ve not gone into more detail here.

    Conclusion

    I’m going to leave this here for now. I think I’ve got a reasonable grasp of what is going on and I’d like to see if I can recreate the interfaces used at some point.

    The ZX Spectrum one should be relatively straight forward. To do something with the PC end though is going to require a lot of work as I just don’t believe I can rely on that schematic.

    I have to question though whether it would be worth it though. Given that an Intel 8255 is no longer available I’ll be using reclaimed parts and I also don’t have a PC with ISA anymore. I must admit I am wondering if an alternative PC end would be possible using a microcontroller to implement the PDS protocol and connect to the PC over USB (for example).

    In fact, with something like a Raspberry Pi Pico, it would be quite possible to implement the entire target interface through to emulating the Z80 PIO on the ZX Spectrum board and potentially have a replacement system that is “USB direct to Spectrum”.

    At this point of course, this is not really the PDS anymore and I’m sure there are already many modern alternatives to getting code running on a ZX Spectrum from a modern system, so that too might be a little pointless. And that is before we get into emulation.

    But for its time, this is a really interesting system and it is a shame that information about it seems to have slowly disappeared.

    I am still quite keen to recreate it though, so I might be on the look out for an old PC with ISA…

    Oh, and as always, if you know about the PDS and are able to confirm or refute anything I’ve said here, do let me know in the comments!

    Kevin

    #intel8255 #pds #programmersDevelopmentSystem #z80 #z80Pio #zxSpectrum
  7. curl

    Daniël Stenberg

    facts and praise

    I'm fortunate that I am allowed to follow Daniël, lead programmer of the mightycurl. The reason I formulated the line in this way, is because only through the power of the FediVerse I've gotten a boost from someone I follow, who found a post of the lead programmer or curl interesting

    stats:

    install base => 20000*106 devices

    20 billion+ installations!

    curl is used in command lines or scripts to transfer data. curl is also libcurl, used in:

    • cars
    • television sets
    • routers
    • printers
    • audio equipment
    • mobile phones
    • tablets
    • medical devices
    • settop boxes
    • computer games
    • media players

    Curl is THE Internet transfer engine for countless software applications in over twenty billion installations!

    curl is used daily by virtually every Internet-using human on the globe!

    curl is 30 years old

    Let that sink in!

    Opinion

    curl is mature critical network infrastructure software that we all need to have our internet powered software / hardware to function in respect to data transfer.

    The syntax to use curl in simple implementations is IMHO quite easy. In case you need to know an extra option, the executable and libcurl have excellent documentation. End users normally interact with curl using the (elf) binary on Linux based POSIX operating systems. The more mature BSDs have another binary format

    Just type curl to get an initial output which looks like this on my current system

    curl
    curl: try 'curl --help' or 'curl --manual' for more information

    then type

    curl --help
    Usage: curl [options...] <url>
    -d, --data <data> HTTP POST data
    -f, --fail Fail fast with no output on HTTP errors
    -h, --help <subject> Get help for commands
    -o, --output <file> Write to file instead of stdout
    -O, --remote-name Write output to file named as remote file
    -i, --show-headers Show response headers in output
    -s, --silent Silent mode
    -T, --upload-file <file> Transfer local FILE to destination
    -u, --user <user:password> Server user and password
    -A, --user-agent <name> Send User-Agent <name> to server
    -v, --verbose Make the operation more talkative
    -V, --version Show version number and quit

    This is not the full help; this menu is split into categories.
    Use "--help category" to get an overview of all categories, which are:
    auth, connection, curl, deprecated, dns, file, ftp, global, http, imap, ldap, output, pop3, post, proxy,
    scp, sftp, smtp, ssh, telnet, tftp, timeout, tls, upload, verbose.
    Use "--help all" to list all options
    Use "--help [option]" to view documentation for a given option

    When you type curl --manual|less you get the manpages which I delimited with less through a vertical pipe

              _   _ ____  _
    ___| | | | _ \| |
    / __| | | | |_) | |
    | (__| |_| | _ <| |___
    \___|\___/|_| \_\_____|
    NAME

    curl - transfer a URL

    SYNOPSIS

    curl [options / URLs]

    DESCRIPTION

    curl is a tool for transferring data from or to a server using URLs. It
    supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP,
    HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP,
    SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See
    libcurl(3) for details.

    URL

    The URL syntax is protocol-dependent. You find a detailed description in
    RFC 3986.

    I can also type man curl to get a nice output:

    curl(1)                                         curl Manual                                        curl(1)

    NAME
    curl - transfer a URL

    SYNOPSIS
    curl [options / URLs]

    DESCRIPTION
    curl is a tool for transferring data from or to a server using URLs. It supports these protocols:
    DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S,
    RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See libcurl(3) for details.

    URL
    The URL syntax is protocol-dependent. You find a detailed description in RFC 3986.

    If you provide a URL without a leading protocol:// scheme, curl guesses what protocol you want. It
    then defaults to HTTP but assumes others based on often-used hostname prefixes. For example, for
    hostnames starting with "ftp." curl assumes you want FTP.

    You can specify any amount of URLs on the command line. They are fetched in a sequential manner in
    the specified order unless you use -Z, --parallel. You can specify command line options and URLs
    Manual page curl(1) line 1 (press h for help or q to quit)

    The reasoning behind curl --manual is simple. On a machine without the manual system you still need access to the full manual. This is one of the reasons why man curl is also implemented as curl --manual

    An important RFC is echoed to my terminal in the man curl output which is RFC 3986

    A Uniform Resource Identifier (URI) is a compact sequence of
    characters that identifies an abstract or physical resource. This
    specification defines the generic URI syntax and a process for
    resolving URI references that might be in relative form, along with
    guidelines and security considerations for the use of URIs on the
    Internet. The URI syntax defines a grammar that is a superset of all
    valid URIs, allowing an implementation to parse the common components
    of a URI reference without knowing the scheme-specific requirements
    of every possible identifier. This specification does not define a
    generative grammar for URIs; that task is performed by the individual
    specifications of each URI scheme.

    I shall not quote the whole RFC 3986 here. You can read all about it on the RFC site (see sources)

    As you can see curl is thorougly documented, has all the features a simple end user needs to fetch all kind of data, scaled up all the way to the extensive complex features router hardware et all, needs to transfer data.

    programming route

    I came to this toot when I saw that certain external feature code, which lives in stable external libraries, is now being removed from curl. I should say the code is depreciated then phased out.

    This is a logical step

    • It takes resources to maintain external code
    • If the (shared) libraries are stable and mature, it's much better to just call those libraries and be done.
    • The more external code you can remove from your project the better it is for all the programmers

    The same is also happening in the Linux kernel, they are following in the footsteps of curl

    Conclusion

    There is a treasure trove of information in the sources. Just reading the pages on RFC 3986 will keep you occupied for hours.
    Have fun and keep reading / learning and programming!

    sources:

    curl.se/

    rfc-editor.org/rfc/rfc3986

    curl.se/mail/lib-2026-03/0026.

    #curl #programming #mathematics #linear #algebra #libcurl #Linux #BSD #freeBSD #openBSD #netBSD #POSIX #bash #csh #ksh #sh #fish #radio #TV #smartTV #router

  8. curl

    Daniël Stenberg

    facts and praise

    I'm fortunate that I am allowed to follow Daniël, lead programmer of the mightycurl. The reason I formulated the line in this way, is because only through the power of the FediVerse I've gotten a boost from someone I follow, who found a post of the lead programmer or curl interesting

    stats:

    install base => 20000*106 devices

    20 billion+ installations!

    curl is used in command lines or scripts to transfer data. curl is also libcurl, used in:

    • cars
    • television sets
    • routers
    • printers
    • audio equipment
    • mobile phones
    • tablets
    • medical devices
    • settop boxes
    • computer games
    • media players

    Curl is THE Internet transfer engine for countless software applications in over twenty billion installations!

    curl is used daily by virtually every Internet-using human on the globe!

    curl is 30 years old

    Let that sink in!

    Opinion

    curl is mature critical network infrastructure software that we all need to have our internet powered software / hardware to function in respect to data transfer.

    The syntax to use curl in simple implementations is IMHO quite easy. In case you need to know an extra option, the executable and libcurl have excellent documentation. End users normally interact with curl using the (elf) binary on Linux based POSIX operating systems. The more mature BSDs have another binary format

    Just type curl to get an initial output which looks like this on my current system

    curl
    curl: try 'curl --help' or 'curl --manual' for more information

    then type

    curl --help
    Usage: curl [options...] <url>
    -d, --data <data> HTTP POST data
    -f, --fail Fail fast with no output on HTTP errors
    -h, --help <subject> Get help for commands
    -o, --output <file> Write to file instead of stdout
    -O, --remote-name Write output to file named as remote file
    -i, --show-headers Show response headers in output
    -s, --silent Silent mode
    -T, --upload-file <file> Transfer local FILE to destination
    -u, --user <user:password> Server user and password
    -A, --user-agent <name> Send User-Agent <name> to server
    -v, --verbose Make the operation more talkative
    -V, --version Show version number and quit

    This is not the full help; this menu is split into categories.
    Use "--help category" to get an overview of all categories, which are:
    auth, connection, curl, deprecated, dns, file, ftp, global, http, imap, ldap, output, pop3, post, proxy,
    scp, sftp, smtp, ssh, telnet, tftp, timeout, tls, upload, verbose.
    Use "--help all" to list all options
    Use "--help [option]" to view documentation for a given option

    When you type curl --manual|less you get the manpages which I delimited with less through a vertical pipe

              _   _ ____  _
    ___| | | | _ \| |
    / __| | | | |_) | |
    | (__| |_| | _ <| |___
    \___|\___/|_| \_\_____|
    NAME

    curl - transfer a URL

    SYNOPSIS

    curl [options / URLs]

    DESCRIPTION

    curl is a tool for transferring data from or to a server using URLs. It
    supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP,
    HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP,
    SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See
    libcurl(3) for details.

    URL

    The URL syntax is protocol-dependent. You find a detailed description in
    RFC 3986.

    I can also type man curl to get a nice output:

    curl(1)                                         curl Manual                                        curl(1)

    NAME
    curl - transfer a URL

    SYNOPSIS
    curl [options / URLs]

    DESCRIPTION
    curl is a tool for transferring data from or to a server using URLs. It supports these protocols:
    DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S,
    RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See libcurl(3) for details.

    URL
    The URL syntax is protocol-dependent. You find a detailed description in RFC 3986.

    If you provide a URL without a leading protocol:// scheme, curl guesses what protocol you want. It
    then defaults to HTTP but assumes others based on often-used hostname prefixes. For example, for
    hostnames starting with "ftp." curl assumes you want FTP.

    You can specify any amount of URLs on the command line. They are fetched in a sequential manner in
    the specified order unless you use -Z, --parallel. You can specify command line options and URLs
    Manual page curl(1) line 1 (press h for help or q to quit)

    The reasoning behind curl --manual is simple. On a machine without the manual system you still need access to the full manual. This is one of the reasons why man curl is also implemented as curl --manual

    An important RFC is echoed to my terminal in the man curl output which is RFC 3986

    A Uniform Resource Identifier (URI) is a compact sequence of
    characters that identifies an abstract or physical resource. This
    specification defines the generic URI syntax and a process for
    resolving URI references that might be in relative form, along with
    guidelines and security considerations for the use of URIs on the
    Internet. The URI syntax defines a grammar that is a superset of all
    valid URIs, allowing an implementation to parse the common components
    of a URI reference without knowing the scheme-specific requirements
    of every possible identifier. This specification does not define a
    generative grammar for URIs; that task is performed by the individual
    specifications of each URI scheme.

    I shall not quote the whole RFC 3986 here. You can read all about it on the RFC site (see sources)

    As you can see curl is thorougly documented, has all the features a simple end user needs to fetch all kind of data, scaled up all the way to the extensive complex features router hardware et all, needs to transfer data.

    programming route

    I came to this toot when I saw that certain external feature code, which lives in stable external libraries, is now being removed from curl. I should say the code is depreciated then phased out.

    This is a logical step

    • It takes resources to maintain external code
    • If the (shared) libraries are stable and mature, it's much better to just call those libraries and be done.
    • The more external code you can remove from your project the better it is for all the programmers

    The same is also happening in the Linux kernel, they are following in the footsteps of curl

    Conclusion

    There is a treasure trove of information in the sources. Just reading the pages on RFC 3986 will keep you occupied for hours.
    Have fun and keep reading / learning and programming!

    sources:

    curl.se/

    rfc-editor.org/rfc/rfc3986

    curl.se/mail/lib-2026-03/0026.

    #curl #programming #mathematics #linear #algebra #libcurl #Linux #BSD #freeBSD #openBSD #netBSD #POSIX #bash #csh #ksh #sh #fish #radio #TV #smartTV #router

  9. curl

    Daniël Stenberg

    facts and praise

    I'm fortunate that I am allowed to follow Daniël, lead programmer of the mightycurl. The reason I formulated the line in this way, is because only through the power of the FediVerse I've gotten a boost from someone I follow, who found a post of the lead programmer or curl interesting

    stats:

    install base => 20000*106 devices

    20 billion+ installations!

    curl is used in command lines or scripts to transfer data. curl is also libcurl, used in:

    • cars
    • television sets
    • routers
    • printers
    • audio equipment
    • mobile phones
    • tablets
    • medical devices
    • settop boxes
    • computer games
    • media players

    Curl is THE Internet transfer engine for countless software applications in over twenty billion installations!

    curl is used daily by virtually every Internet-using human on the globe!

    curl is 30 years old

    Let that sink in!

    Opinion

    curl is mature critical network infrastructure software that we all need to have our internet powered software / hardware to function in respect to data transfer.

    The syntax to use curl in simple implementations is IMHO quite easy. In case you need to know an extra option, the executable and libcurl have excellent documentation. End users normally interact with curl using the (elf) binary on Linux based POSIX operating systems. The more mature BSDs have another binary format

    Just type curl to get an initial output which looks like this on my current system

    curl
    curl: try 'curl --help' or 'curl --manual' for more information

    then type

    curl --help
    Usage: curl [options...] <url>
    -d, --data <data> HTTP POST data
    -f, --fail Fail fast with no output on HTTP errors
    -h, --help <subject> Get help for commands
    -o, --output <file> Write to file instead of stdout
    -O, --remote-name Write output to file named as remote file
    -i, --show-headers Show response headers in output
    -s, --silent Silent mode
    -T, --upload-file <file> Transfer local FILE to destination
    -u, --user <user:password> Server user and password
    -A, --user-agent <name> Send User-Agent <name> to server
    -v, --verbose Make the operation more talkative
    -V, --version Show version number and quit

    This is not the full help; this menu is split into categories.
    Use "--help category" to get an overview of all categories, which are:
    auth, connection, curl, deprecated, dns, file, ftp, global, http, imap, ldap, output, pop3, post, proxy,
    scp, sftp, smtp, ssh, telnet, tftp, timeout, tls, upload, verbose.
    Use "--help all" to list all options
    Use "--help [option]" to view documentation for a given option

    When you type curl --manual|less you get the manpages which I delimited with less through a vertical pipe

              _   _ ____  _
    ___| | | | _ \| |
    / __| | | | |_) | |
    | (__| |_| | _ <| |___
    \___|\___/|_| \_\_____|
    NAME

    curl - transfer a URL

    SYNOPSIS

    curl [options / URLs]

    DESCRIPTION

    curl is a tool for transferring data from or to a server using URLs. It
    supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP,
    HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP,
    SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See
    libcurl(3) for details.

    URL

    The URL syntax is protocol-dependent. You find a detailed description in
    RFC 3986.

    I can also type man curl to get a nice output:

    curl(1)                                         curl Manual                                        curl(1)

    NAME
    curl - transfer a URL

    SYNOPSIS
    curl [options / URLs]

    DESCRIPTION
    curl is a tool for transferring data from or to a server using URLs. It supports these protocols:
    DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S,
    RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See libcurl(3) for details.

    URL
    The URL syntax is protocol-dependent. You find a detailed description in RFC 3986.

    If you provide a URL without a leading protocol:// scheme, curl guesses what protocol you want. It
    then defaults to HTTP but assumes others based on often-used hostname prefixes. For example, for
    hostnames starting with "ftp." curl assumes you want FTP.

    You can specify any amount of URLs on the command line. They are fetched in a sequential manner in
    the specified order unless you use -Z, --parallel. You can specify command line options and URLs
    Manual page curl(1) line 1 (press h for help or q to quit)

    The reasoning behind curl --manual is simple. On a machine without the manual system you still need access to the full manual. This is one of the reasons why man curl is also implemented as curl --manual

    An important RFC is echoed to my terminal in the man curl output which is RFC 3986

    A Uniform Resource Identifier (URI) is a compact sequence of
    characters that identifies an abstract or physical resource. This
    specification defines the generic URI syntax and a process for
    resolving URI references that might be in relative form, along with
    guidelines and security considerations for the use of URIs on the
    Internet. The URI syntax defines a grammar that is a superset of all
    valid URIs, allowing an implementation to parse the common components
    of a URI reference without knowing the scheme-specific requirements
    of every possible identifier. This specification does not define a
    generative grammar for URIs; that task is performed by the individual
    specifications of each URI scheme.

    I shall not quote the whole RFC 3986 here. You can read all about it on the RFC site (see sources)

    As you can see curl is thorougly documented, has all the features a simple end user needs to fetch all kind of data, scaled up all the way to the extensive complex features router hardware et all, needs to transfer data.

    programming route

    I came to this toot when I saw that certain external feature code, which lives in stable external libraries, is now being removed from curl. I should say the code is depreciated then phased out.

    This is a logical step

    • It takes resources to maintain external code
    • If the (shared) libraries are stable and mature, it's much better to just call those libraries and be done.
    • The more external code you can remove from your project the better it is for all the programmers

    The same is also happening in the Linux kernel, they are following in the footsteps of curl

    Conclusion

    There is a treasure trove of information in the sources. Just reading the pages on RFC 3986 will keep you occupied for hours.
    Have fun and keep reading / learning and programming!

    sources:

    curl.se/

    rfc-editor.org/rfc/rfc3986

    curl.se/mail/lib-2026-03/0026.

    #curl #programming #mathematics #linear #algebra #libcurl #Linux #BSD #freeBSD #openBSD #netBSD #POSIX #bash #csh #ksh #sh #fish #radio #TV #smartTV #router

  10. curl

    Daniël Stenberg

    facts and praise

    I'm fortunate that I am allowed to follow Daniël, lead programmer of the mightycurl. The reason I formulated the line in this way, is because only through the power of the FediVerse I've gotten a boost from someone I follow, who found a post of the lead programmer or curl interesting

    stats:

    install base => 20000*106 devices

    20 billion+ installations!

    curl is used in command lines or scripts to transfer data. curl is also libcurl, used in:

    • cars
    • television sets
    • routers
    • printers
    • audio equipment
    • mobile phones
    • tablets
    • medical devices
    • settop boxes
    • computer games
    • media players

    Curl is THE Internet transfer engine for countless software applications in over twenty billion installations!

    curl is used daily by virtually every Internet-using human on the globe!

    curl is 30 years old

    Let that sink in!

    Opinion

    curl is mature critical network infrastructure software that we all need to have our internet powered software / hardware to function in respect to data transfer.

    The syntax to use curl in simple implementations is IMHO quite easy. In case you need to know an extra option, the executable and libcurl have excellent documentation. End users normally interact with curl using the (elf) binary on Linux based POSIX operating systems. The more mature BSDs have another binary format

    Just type curl to get an initial output which looks like this on my current system

    curl
    curl: try 'curl --help' or 'curl --manual' for more information

    then type

    curl --help
    Usage: curl [options...] <url>
    -d, --data <data> HTTP POST data
    -f, --fail Fail fast with no output on HTTP errors
    -h, --help <subject> Get help for commands
    -o, --output <file> Write to file instead of stdout
    -O, --remote-name Write output to file named as remote file
    -i, --show-headers Show response headers in output
    -s, --silent Silent mode
    -T, --upload-file <file> Transfer local FILE to destination
    -u, --user <user:password> Server user and password
    -A, --user-agent <name> Send User-Agent <name> to server
    -v, --verbose Make the operation more talkative
    -V, --version Show version number and quit

    This is not the full help; this menu is split into categories.
    Use "--help category" to get an overview of all categories, which are:
    auth, connection, curl, deprecated, dns, file, ftp, global, http, imap, ldap, output, pop3, post, proxy,
    scp, sftp, smtp, ssh, telnet, tftp, timeout, tls, upload, verbose.
    Use "--help all" to list all options
    Use "--help [option]" to view documentation for a given option

    When you type curl --manual|less you get the manpages which I delimited with less through a vertical pipe

              _   _ ____  _
    ___| | | | _ \| |
    / __| | | | |_) | |
    | (__| |_| | _ <| |___
    \___|\___/|_| \_\_____|
    NAME

    curl - transfer a URL

    SYNOPSIS

    curl [options / URLs]

    DESCRIPTION

    curl is a tool for transferring data from or to a server using URLs. It
    supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP,
    HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP,
    SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See
    libcurl(3) for details.

    URL

    The URL syntax is protocol-dependent. You find a detailed description in
    RFC 3986.

    I can also type man curl to get a nice output:

    curl(1)                                         curl Manual                                        curl(1)

    NAME
    curl - transfer a URL

    SYNOPSIS
    curl [options / URLs]

    DESCRIPTION
    curl is a tool for transferring data from or to a server using URLs. It supports these protocols:
    DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S,
    RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See libcurl(3) for details.

    URL
    The URL syntax is protocol-dependent. You find a detailed description in RFC 3986.

    If you provide a URL without a leading protocol:// scheme, curl guesses what protocol you want. It
    then defaults to HTTP but assumes others based on often-used hostname prefixes. For example, for
    hostnames starting with "ftp." curl assumes you want FTP.

    You can specify any amount of URLs on the command line. They are fetched in a sequential manner in
    the specified order unless you use -Z, --parallel. You can specify command line options and URLs
    Manual page curl(1) line 1 (press h for help or q to quit)

    The reasoning behind curl --manual is simple. On a machine without the manual system you still need access to the full manual. This is one of the reasons why man curl is also implemented as curl --manual

    An important RFC is echoed to my terminal in the man curl output which is RFC 3986

    A Uniform Resource Identifier (URI) is a compact sequence of
    characters that identifies an abstract or physical resource. This
    specification defines the generic URI syntax and a process for
    resolving URI references that might be in relative form, along with
    guidelines and security considerations for the use of URIs on the
    Internet. The URI syntax defines a grammar that is a superset of all
    valid URIs, allowing an implementation to parse the common components
    of a URI reference without knowing the scheme-specific requirements
    of every possible identifier. This specification does not define a
    generative grammar for URIs; that task is performed by the individual
    specifications of each URI scheme.

    I shall not quote the whole RFC 3986 here. You can read all about it on the RFC site (see sources)

    As you can see curl is thorougly documented, has all the features a simple end user needs to fetch all kind of data, scaled up all the way to the extensive complex features router hardware et all, needs to transfer data.

    programming route

    I came to this toot when I saw that certain external feature code, which lives in stable external libraries, is now being removed from curl. I should say the code is depreciated then phased out.

    This is a logical step

    • It takes resources to maintain external code
    • If the (shared) libraries are stable and mature, it's much better to just call those libraries and be done.
    • The more external code you can remove from your project the better it is for all the programmers

    The same is also happening in the Linux kernel, they are following in the footsteps of curl

    Conclusion

    There is a treasure trove of information in the sources. Just reading the pages on RFC 3986 will keep you occupied for hours.
    Have fun and keep reading / learning and programming!

    sources:

    curl.se/

    rfc-editor.org/rfc/rfc3986

    curl.se/mail/lib-2026-03/0026.

    #curl #programming #mathematics #linear #algebra #libcurl #Linux #BSD #freeBSD #openBSD #netBSD #POSIX #bash #csh #ksh #sh #fish #radio #TV #smartTV #router

  11. curl

    Daniël Stenberg

    facts and praise

    I'm fortunate that I am allowed to follow Daniël, lead programmer of the mightycurl. The reason I formulated the line in this way, is because only through the power of the FediVerse I've gotten a boost from someone I follow, who found a post of the lead programmer or curl interesting

    stats:

    install base => 20000*106 devices

    20 billion+ installations!

    curl is used in command lines or scripts to transfer data. curl is also libcurl, used in:

    • cars
    • television sets
    • routers
    • printers
    • audio equipment
    • mobile phones
    • tablets
    • medical devices
    • settop boxes
    • computer games
    • media players

    Curl is THE Internet transfer engine for countless software applications in over twenty billion installations!

    curl is used daily by virtually every Internet-using human on the globe!

    curl is 30 years old

    Let that sink in!

    Opinion

    curl is mature critical network infrastructure software that we all need to have our internet powered software / hardware to function in respect to data transfer.

    The syntax to use curl in simple implementations is IMHO quite easy. In case you need to know an extra option, the executable and libcurl have excellent documentation. End users normally interact with curl using the (elf) binary on Linux based POSIX operating systems. The more mature BSDs have another binary format

    Just type curl to get an initial output which looks like this on my current system

    curl
    curl: try 'curl --help' or 'curl --manual' for more information

    then type

    curl --help
    Usage: curl [options...] <url>
    -d, --data <data> HTTP POST data
    -f, --fail Fail fast with no output on HTTP errors
    -h, --help <subject> Get help for commands
    -o, --output <file> Write to file instead of stdout
    -O, --remote-name Write output to file named as remote file
    -i, --show-headers Show response headers in output
    -s, --silent Silent mode
    -T, --upload-file <file> Transfer local FILE to destination
    -u, --user <user:password> Server user and password
    -A, --user-agent <name> Send User-Agent <name> to server
    -v, --verbose Make the operation more talkative
    -V, --version Show version number and quit

    This is not the full help; this menu is split into categories.
    Use "--help category" to get an overview of all categories, which are:
    auth, connection, curl, deprecated, dns, file, ftp, global, http, imap, ldap, output, pop3, post, proxy,
    scp, sftp, smtp, ssh, telnet, tftp, timeout, tls, upload, verbose.
    Use "--help all" to list all options
    Use "--help [option]" to view documentation for a given option

    When you type curl --manual|less you get the manpages which I delimited with less through a vertical pipe

              _   _ ____  _
    ___| | | | _ \| |
    / __| | | | |_) | |
    | (__| |_| | _ <| |___
    \___|\___/|_| \_\_____|
    NAME

    curl - transfer a URL

    SYNOPSIS

    curl [options / URLs]

    DESCRIPTION

    curl is a tool for transferring data from or to a server using URLs. It
    supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP,
    HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S, RTMP, RTMPS, RTSP,
    SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See
    libcurl(3) for details.

    URL

    The URL syntax is protocol-dependent. You find a detailed description in
    RFC 3986.

    I can also type man curl to get a nice output:

    curl(1)                                         curl Manual                                        curl(1)

    NAME
    curl - transfer a URL

    SYNOPSIS
    curl [options / URLs]

    DESCRIPTION
    curl is a tool for transferring data from or to a server using URLs. It supports these protocols:
    DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, POP3, POP3S,
    RTMP, RTMPS, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS.

    curl is powered by libcurl for all transfer-related features. See libcurl(3) for details.

    URL
    The URL syntax is protocol-dependent. You find a detailed description in RFC 3986.

    If you provide a URL without a leading protocol:// scheme, curl guesses what protocol you want. It
    then defaults to HTTP but assumes others based on often-used hostname prefixes. For example, for
    hostnames starting with "ftp." curl assumes you want FTP.

    You can specify any amount of URLs on the command line. They are fetched in a sequential manner in
    the specified order unless you use -Z, --parallel. You can specify command line options and URLs
    Manual page curl(1) line 1 (press h for help or q to quit)

    The reasoning behind curl --manual is simple. On a machine without the manual system you still need access to the full manual. This is one of the reasons why man curl is also implemented as curl --manual

    An important RFC is echoed to my terminal in the man curl output which is RFC 3986

    A Uniform Resource Identifier (URI) is a compact sequence of
    characters that identifies an abstract or physical resource. This
    specification defines the generic URI syntax and a process for
    resolving URI references that might be in relative form, along with
    guidelines and security considerations for the use of URIs on the
    Internet. The URI syntax defines a grammar that is a superset of all
    valid URIs, allowing an implementation to parse the common components
    of a URI reference without knowing the scheme-specific requirements
    of every possible identifier. This specification does not define a
    generative grammar for URIs; that task is performed by the individual
    specifications of each URI scheme.

    I shall not quote the whole RFC 3986 here. You can read all about it on the RFC site (see sources)

    As you can see curl is thorougly documented, has all the features a simple end user needs to fetch all kind of data, scaled up all the way to the extensive complex features router hardware et all, needs to transfer data.

    programming route

    I came to this toot when I saw that certain external feature code, which lives in stable external libraries, is now being removed from curl. I should say the code is depreciated then phased out.

    This is a logical step

    • It takes resources to maintain external code
    • If the (shared) libraries are stable and mature, it's much better to just call those libraries and be done.
    • The more external code you can remove from your project the better it is for all the programmers

    The same is also happening in the Linux kernel, they are following in the footsteps of curl

    Conclusion

    There is a treasure trove of information in the sources. Just reading the pages on RFC 3986 will keep you occupied for hours.
    Have fun and keep reading / learning and programming!

    sources:

    curl.se/

    rfc-editor.org/rfc/rfc3986

    curl.se/mail/lib-2026-03/0026.

    #curl #programming #mathematics #linear #algebra #libcurl #Linux #BSD #freeBSD #openBSD #netBSD #POSIX #bash #csh #ksh #sh #fish #radio #TV #smartTV #router

  12. Connecting Decentralized Social Networks and Rethinking Interoperability

    Open Channels FM Connecting Decentralized Social Networks and Rethinking Interoperability Play EpisodePause Episode Mute/Unmute EpisodeRewind 10 Seconds1xFast Forward 30 seconds 00:00/00:58:07 SubscribeShare Apple Podcasts CastBox Overcast PocketCasts RSS Spotify RSS Feed Share Link Embed openchannels.fm/connecting-dec<script> /*! This file is auto-generated */ !function(d,l){"use strict";l.querySelector&&d.addEventListener&&"undefined"!=typeof URL&&(d.wp=d.wp||{},d.wp.receiveEmbedMessage||(d.wp.receiveEmbedMessage=function(e){var t=e.data;if((t||t.secret||t.message||t.value)&&!/[^a-zA-Z0-9]/.test(t.secret)){for(var s,r,n,a=l.querySelectorAll('iframe[data-secret="'+t.secret+'"]'),o=l.querySelectorAll('blockquote[data-secret="'+t.secret+'"]'),c=new RegExp("^https?:$","i"),i=0;i<o.length;i++)o[i].style.display="none";for(i=0;i<a.length;i++)s=a[i],e.source===s.contentWindow&&(s.removeAttribute("style"),"height"===t.message?(1e3<(r=parseInt(t.value,10))?r=1e3:~~r<200&&(r=200),s.height=r):"link"===t.message&&(r=new URL(s.getAttribute("src")),n=new URL(t.value),c.test(n.protocol))&&n.host===r.host&&l.activeElement===s&&(d.top.location.href=t.value))}},d.addEventListener("message",d.wp.receiveEmbedMessage,!1),l.addEventListener("DOMContentLoaded",function(){for(var e,t,s=l.querySelectorAll("iframe.wp-embedded-content"),r=0;r<s.length;r++)(t=(e=s[r]).getAttribute("data-secret"))||(t=Math.random().toString(36).substring(2,12),e.src+="#?secret="+t,e.setAttribute("data-secret",t)),e.contentWindow.postMessage({message:"ready",secret:t},"*")},!1)))}(window,document); //# sourceURL=openchannels.fm/wp-includes/js </script> ' title="Embed Code" class="input-embed input-embed-2551015" readonly/>

    Download file | Play in new window | Duration: 00:58:07

    In this episode, host Matthias Pfefferle catches up with long-time friend and open web builder Ryan Barrett. If you’ve ever wondered who’s behind the scenes connecting all these wild and sprawling decentralized networks like the IndieWeb, the Fediverse, and now Bluesky, well, Ryan Barrett is your guy.

    They share into the story of Bridgy and BridgyFed, tools Ryan Barrett built to help posts, conversations, and even likes travel effortlessly between platforms that, let’s be honest, don’t always want to talk to each other. It’s a real look at why we still need these kinds of bridges, the ups and downs of working in open source, and what it’s like turning a side project into something that lots of people rely on.

    You’ll get a peek into the early days of blogging, the messy but fun world of protocol building, and some of the tough questions that come with running “critical infrastructure” without a big company behind you. Whether you love the nerdy details or just want to know why your favorite blog can show up in the social media feed of tomorrow, this conversation is all about keeping the web open and a bit of the chaos that comes with it.

    Join Matthias and Ryan for a chat that proves building bridges, both tech and personal, is still as important (and fun) as ever.

    Thanks to our sponsors…

    The best time to migrate is before you’re under pressure. Omnisend moves everything essential for you now, so you’re fully ready when you plan for that large campaign. Use the code OpenChannels and get 30% off your first 3 months of any paid plan.

    If you build stores for clients, WooCommerce gives you the flexibility to create exactly what merchants need. Customize workflows, extend with thousands of integrations, and scale without switching platforms. Check it out at WooCommerce.com.

    https://youtu.be/Ls3Jb8Zjijg

    Takeaways

    Bridging Decentralized Networks: Ryan Barrett has spent years building tools (most notably Bridgy and BridgyFed) that connect different social networks like the IndieWeb, Fediverse, and Bluesky (Atmosphere). These act as cross-posters or bi-directional bridges, letting users interact across platforms more seamlessly.

    Funding and Organization: Initially, all this was a side project for Ryan Barrett, but it has evolved. They’ve started a nonprofit, received some grant and crowdfunding, and put basic governance in place; though it doesn’t currently provide a full salary, it does cover operational expenses.

    Why Bridges Are Needed: Despite the vision of decentralized networks, true interoperability doesn’t exist by default. Instead of expecting everyone to align on a single protocol, Ryan Barrett argues that we’re still learning and evolving, so bridges are necessary while experimentation continues.

    Not Just a Temporary Fix: Bridges aren’t just a stopgap; as protocols and ideas keep changing, the need for interoperability will persist. Ryan Barrett believes that even with established protocols like ActivityPub or AT Protocol, new experiments and networks are inevitable.

    Personal Motivation: The roots of these tools trace back to Ryan Barrett’s desire to maintain ownership of his content and the social interactions around his blog, especially as conversations moved onto walled garden platforms like Facebook and Twitter.

    Evolution of Open Web Tools: Early efforts included cross-posting content, but Ryan Barrett emphasized “backfeed” such as importing comments, likes, and reactions from social platforms back to his own website, so all engagement was aggregated in one place.

    Preference for Usable, Practical Solutions: Rather than inventing radically new standards, Ryan Barrett prefers building bridges and services that work with what’s already out there, favoring RSS, Webmention, and existing APIs, so end users don’t need to host their own solutions.

    Protocols: No Single Winner: Discussing IndieWeb, ActivityPub, AT Protocol, and others, Ryan Barrett sees good ideas in each but doesn’t believe there’s a “best” protocol yet. He values building blocks, modularity, and combining approaches, rather than betting on one framework.

    End-User and Publisher Focus: Most usage of BridgyFed comes from publishers and content creators (e.g., major media), but individuals also use bridges, especially those who want to maintain a single profile and reach across networks without friction.

    Invisible Interoperability: Often, users don’t even realize they’re talking across different networks using BridgyFed; they see and interact with others seamlessly, which is the ideal scenario for Ryan Barrett.

    Critical Infrastructure Concerns: With adoption rising, BridgyFed has become important infrastructure. To ensure long-term reliability, they’ve made it open source, started a nonprofit, and instituted governance. There are plans to make it more resilient and less dependent on a single operator.

    Looking Forward: Major focus areas for the future include supporting long-form content (via standards like standard.site), expanding migrations and account portability, and readying bridges for new protocols like Nostr and Farcaster.

    Philosophy of the IndieWeb: The IndieWeb is described as both a philosophy (“everyone should have a website and control their own profile”) and a protocol stack (Webmention, microformats, etc.), but it’s fundamentally about individual ownership and choice in the online experience.

    The Web Isn’t Going Away: There will always be vastly more websites than social network accounts. Even as trends shift more towards platform accounts, the open web remains a massive, foundational part of online life and bridges can help keep it connected to emerging networks.

    Mentioned Links and Resources

    • Bridgy & BridgyFed – A suite of tools for bridging between the IndieWeb, Fediverse, and Bluesky/Atmosphere. 🔗 https://brid.gy/
    • ANEW Social – The nonprofit organization behind BridgyFed. 🔗 https://anew.social/
    • Granary – A tool and service to convert between web formats like RSS and microformats. 🔗 https://granary.io/
    • Standard.site – A common lexicon/format for long-form content on Bluesky and other AT Protocol platforms (mentioned as “standard.site” for composing and sharing articles). 🔗 https://standard.site/
    • snarfed.org – Ryan Barrett’s website, personal blog, and IndieWeb hub. 🔗 https://snarfed.org/
    • Fed.brid.gy – The main instance of BridgyFed bridging service. 🔗 https://fed.brid.gy/
    • IndieWeb – Community, resources, and documentation about owning and controlling your content and identity online. 🔗 https://indieweb.org/
    • Bounce – A tool to help you migrate from one network to another and keep all of your followers (powered by BridgyFed). 🔗 https://bounce.anew.social/

    Timestamped Overview

    • 00:00 Between Gigs Crowdfunding Nonprofit
    • 05:14 Early Protocol Evolution Debate
    • 10:11 Blogging Era and Social Media
    • 12:11 Backfeeding Social Interactions
    • 16:20 Early Web Standards Collaboration
    • 19:26 Graph API and Decentralization Challenges
    • 22:43 Struggling with Protocol Implementation
    • 25:12 Engineering Formats as Lego Blocks
    • 30:46 Usability and account recoverability
    • 33:36 Decentralized Social Functional Separation
    • 37:27 Decentralized Communication via Open Standards
    • 39:34 Building for the Present Web
    • 45:08 BridgyFed: Connecting Diverse Platforms
    • 47:04 Transforming a Side Project
    • 51:05 Custom Domains for Bridged Accounts
    • 54:23 Network Migration and Bounce Tool
    • 56:58 Indie Web Collaboration Reflections
    Episode Transcript

    Matthias Pfefferle:
    So welcome, you’re listening to the Open Web and Fediverse series, part of the Open Web Conversations channel and Open Channels event production. And today’s guest is building infrastructure that bridges together what should be interoperable by default. He’s literally building bridges between the indie web, the Fediverse, and the atmosphere. I hope it’s called like that for almost 15 years now. Welcome to the podcast, Ryan Barrett.

    Ryan Barrett:
    Thank you, Matthias. I’m glad to be here.

    Matthias Pfefferle:
    I think my introduction was almost perfect, but Maybe you want to add something?

    Ryan Barrett:
    Yeah, no, I, you and I go back so long. We’ve been doing indie web stuff together for at least 15 years. And so it’s, I’m excited to be here. It’s, it’s really fun to get to talk to you about kind of everything that led us to where we are now.

    Matthias Pfefferle:
    Yeah, but maybe you say some words about what I teased a bit with. You are the bridge builder.

    Ryan Barrett:
    Yes. Yeah. So who am I? Yes. So I’m, you know, a stereotypical Silicon Valley software engineer. It’s been my day job. But on the side for a long time, I have— I’ve done indie web stuff and somehow I ended up doing a lot of converters and bridges and translators. Going from one place to another. Uh, so yeah, the— what I’m known for and what I spend most of my time on today is, um, a suite of tools, uh, Bridgy and BridgyFed. We now, we now call them maybe BridgyClassic and BridgyFed. Um, these, uh, are kind of like cross-posters or bridges between different networks, uh, as you mentioned. So the web IndieWeb in particular, the Fediverse, and Bluesky, or the Atmosphere as you called it. And so BridgyFed is where I spend most of my time these days, and it is a full-featured bi-directional bridge. So if you are on Bluesky, you can see people who have bridged themselves on the Fediverse. You can see their profile, their timeline, you can follow them. If they post, you’ll see their posts on Bluesky. You can reply to them on Bluesky. The replies and likes and reposts will go back and forth. And so we try to make that as native and seamless as possible. And it takes a lot of work, but it’s fun.

    Matthias Pfefferle:
    Yeah, because of a lot of work, you mentioned that you do that as a side hustle. Is that still a side hustle thing?

    Ryan Barrett:
    Uh, right now I’m between gigs, so I’m mostly full-time on it. Uh, eventually I’ll go find a real job again, but, um, uh, right now I have more time for it. Uh, thanks in large part, uh, about a year and a half ago maybe I started working with Anuj Ahuja, who comes from working on similar stuff, and we have, um, I resisted kind of taking donations for a long time, but we now do crowdfunding and, uh, grant funding, and we, we started nonprofit. And so there is a bit more of kind of real organization and governance and some funding behind it. We don’t have enough funding to kind of pay ourselves salaries yet, but we can cover expenses and things like that.

    Matthias Pfefferle:
    Is it a plan to do that as a main profession anytime soon?

    Ryan Barrett:
    I don’t know. I’ve never been much for like a 5-year plan or a 10-year plan for myself. I just do what I’m doing while it works. And then when it’s time to do something else, I do something else. Um, I have never quite felt like this is my career. Um, so, but I’m doing it mostly full-time now. We’ll see how it goes. And I mean, even if I go get a different job and do something else,, you know, as a day job, like I wouldn’t shut this down. Um, it’s more a question of like, how much time am I spending building new parts of it and maintaining it as opposed to just kind of running it as is.

    Matthias Pfefferle:
    I think that’s the main problem for everyone working in open source and decentralized platforms in general, I would say. Um, yeah, but As I said in the introduction, it’s kind of weird that you need something like a bridge to bridge decentralized networks together. So why all of that?

    Ryan Barrett:
    Yeah, there is one way of thinking about this that is kind of like we want everyone, you know, all the different software projects to use the same protocol so that they can interoperate. Of course, I get that. Another way of thinking about it is we are still so early to all of this. It’s— yes, it’s been decades, but decades is not that long. I think if we said, okay, have we figured out all of the questions and we know the best way to do all of this, we’re doing it in maybe an activity pub. ActivityPub got everything right, no more questions to answer, like no more problems, so there’s no need to try anything new. Like ActivityPub is it, or, or Atmos protocol or anything else. That’s the final answer forever. Like, I don’t think anyone would believe that, right? Like, I think we are so early and there’s so much more to learn and figure out and, uh, kind of invent, we have to try a bunch of new things. ActivityPub is great. App Protocol is great. IndieWeb is great. I like Nostr. I like Farcaster. There are a bunch of good ideas, but we have like, yeah, there’s just so much more to figure out. And often like you can’t slowly evolve an existing network or protocol to try some big new idea. Uh, often if you have a big new idea that’s very different, it’s just too far away. And so you can’t like very gradually, inch by inch, move this one over there. You have to just try a new thing. And so I think trying new things is great. Uh, I think right now is the time to try lots of different ways to do decentralized social, right? But while we do that, we’ll have lots of different networks that don’t talk. Right. And so I like having things talk. And so I think bridges are useful.

    Matthias Pfefferle:
    So is that still a temporary thing for you?

    Ryan Barrett:
    Or, uh, probably not. I mean, so if the question is like, will we try things and then we’ll find the best way and everyone will use the one best way and then we’re done. No, I don’t think so. I think change is the only constant. I think we are always improving things. Um, Email is a great example. You could say, yeah, we tried a few different ways for people to kind of talk asynchronously online many, many decades ago. We settled on email. That’s great. But now if you think about how do you talk to your friends online, it’s mostly not on email, right? It’s on messaging or social or other things. And so we didn’t really have— even when we settled on email, like later, it’s not that SMS competed with email, but it was a new idea, right? And so I think there will always be new ideas, and that’s good.

    Matthias Pfefferle:
    So you said, or you already mentioned, that it’s nearly since forever, um, you are working on that. I think it’s almost 15 years. So, um, What led to a bridge? What is the history about all of that? Why have you decided to, okay, there are so many, like the XKCD comic, there’s so many competing standards, let’s build a bridge?

    Ryan Barrett:
    Right, right. Yeah, so the short answer is kind of the open source scratching my own itch. So way back in maybe 2000, I was in college. I had a website, a little— I didn’t— no one knew to call it a blog, but a website or a blog. Okay, good. When Facebook came out maybe a year or two later, at least very early in college for colleges, I signed up and tried it and I thought, oh, this is interesting. And I kind of immediately realize, oh, this is good and useful, but it’s not mine. I don’t control it. Like, I can, I can make my profile and post, but at the end of the day, if they want to change how things look or they don’t like me and want to, you know, ban my account or something, like, I— they can do that. I can’t control it. And so it’s okay. I mean, that’s like any service. But what I ended up doing was I would, when I posted, I would always just post on my website and then I would just copy and paste into Facebook. Then I knew at least anything I write there, like I’ll still have a copy of, I’ll still control. Okay. That is fine. Like as other services come out like Twitter or whatever, I would, I did the same thing. Gradually. So there was this era, you remember this, I mean, you and I have been doing indie web stuff together forever. The blogging era, this was the early to mid, maybe 2000s. There was an era where lots of people wrote blogs and would kind of respond to each other’s blog posts on their blogs and comment on those blog posts. And that’s great. Everyone had their own website and did that and it worked well. When social media kind of got bigger, one thing we would do is we would write blog posts and then post links to our posts on Facebook, Twitter, et cetera.

    Matthias Pfefferle:
    The famous cross-posting.

    Ryan Barrett:
    Yeah. Yeah. Yeah. Okay, sure. Gradually what we saw was that more and more people spent more time inside these social networks as opposed to reading kind of on the blogs. And so when I would post a link to a blog post I wrote, something I wrote, more and more people would comment kind of on Facebook or on Twitter or wherever instead of on my blog post on my website. Okay. The downside there is I don’t have— I’ve been like that conversation like about what I’m talking about. Is on Facebook or is on Twitter. Like, I don’t keep a copy of it, I don’t have a record of it, right? Um, you know, so that, that was a change that was disappointing. And so cross-posting was one thing. There were tons— there were always tons of tools to say, oh, post to Facebook and Twitter and Instagram and whatever. Like, that’s pretty easy. So lots of people did that, that’s useful. But what I wanted was the comments or the replies on Twitter. And then eventually the likes and the reposts and the quotes and everything, I wanted those to show up on my website too. And other people had thought of this, and you know, it was, it was a good idea, but it was much— it was more complicated to build, and so not many people did it. This is what we call in the indie web backfeed. And of course, the indie— at this time I had also kind of discovered the indie web, or was discovering at this time, and it was doing— had similar ideas kind of between websites themselves without worrying about social networks. But so what I eventually built was this tool to go use the Twitter API, use the Facebook API, etc., to find all of those replies and likes and reposts and figure out and kind of map from my original post there to the, my blog post and copy them all back to my blog post so they would show up there and other people would see them there.

    Matthias Pfefferle:
    So the first version, the first bridge was to bridge your blog content to, let’s say, closed social network and get the reactions out of it.

    Ryan Barrett:
    Yes. And especially, I mean, primarily the backfeed. So at the beginning, I didn’t do the cross-posting. I just I’m not— I’ve never been very online. I don’t post a ton. I post once every few days. Copy and paste is fine for me. But the back feed was the key part. And originally this was either 2000— I need to check the— maybe January 2012. The first version I did of this was WordPress specific. It was not Webmention. It was not kind of this open standard, this indie web standard. It was WordPress specific and it did, I think, Facebook and Twitter and that was it. And it was probably only replies or comments, but it was something, you know, and it kind of grew from there.

    Matthias Pfefferle:
    But it was as a service, it was not directly baked into WordPress. So is there a specific or was there a specific decision to do it like that or is this something that made the most sense?

    Ryan Barrett:
    So, I always knew this— all this should work as kind of open standards. Open standards. I wanted it to be interoperable. I didn’t want it to be specific— as much as I love WordPress, I didn’t want it to be specific to WordPress or anything else, right? And so, the standards I knew originally at that time were— the standard I knew for this was OStatus around then. And so my, my long-term idea was to build an OStatus bridge for all of, for the closed social networks. So that since, so the, I mean, the, the big idea here is they, they were closed, but they all had APIs. And so you can, like, there’s OStatus, there’s this open standard, and then there are these APIs. And the APIs were pretty full-featured. And so I figured like I have these two Lego blocks, I can just kind of use the API and translate the OStatus and back. And that should, that should work.

    Matthias Pfefferle:
    So one of the earlier versions were even compatible between OStatus, the open, let’s say predecessor of the Fediverse activity pub. And Facebook and Twitter?

    Ryan Barrett:
    So I never got— I never fully implemented OStatus for Facebook and Twitter. The first version of BridgyFed was OStatus. It was IndieWeb to and from OStatus. Before I did ActivityPub there. That was 2017. So BridgyFed was a different— a similar but different service, yes. But I did a number of these. So I did implement WebFinger for Facebook, Twitter, et cetera. I did portable contacts. POCO was a similar standard. Yeah, this is like us going back to 2010 era. What were the— and I did OpenID for Facebook and Twitter. So there were parts there, uh, and also, I mean, a lot of this was just around, it was in the air, and I happened to know a number of the people working on these standards, um, Evan, but also people like Brad Fitzpatrick, Brett Slatkin, uh, David Recordon. We all, you know, talked now and then. And so this was Chris, yeah, um, this was OStatus, but also kind of Buzz at Google and let’s see, Brad was doing things like the Social Graph Explorer API at Google and there were a lot of similar ideas. As a separate side project, I had written a little app that used— that did OpenID for Google accounts. Like any Gmail account, that kind of thing. There were a lot of these ideas. This was the, like, that blog era, 2000 to 2010, was also very much the Web 2.0 mashup era, Yahoo Pipes kind of thing. And also people at the same time thinking about Webfinger, OpenID, OStatus, these early, early decentralized social, decentralized services. And so there were lots of people and lots of ideas. Can I plug this into that? Like there are a bunch of parts. Let’s just plug them all together and see what works.

    Matthias Pfefferle:
    Yeah. Ostatus itself felt very mesh-appy. So putting together a lot of open standards and all the decentralized protocol. So when you worked on all of that, have you had the hope that it might get implemented? In the social networks? Because back in the days, Facebook and Twitter were really part of the discussions, not around maybe old status specifically, but there were other projects like data portability, for example, where they were really involved into that discussion. Was that kind of the hope you had?

    Ryan Barrett:
    No. Okay. Facebook very concretely for a while did a number of these things that had RSS. You know, it— I’m trying to remember if it did OpenID.

    Matthias Pfefferle:
    They did. They did OpenID. They had XMPP as the foundation of their Facebook chat. So they used quite a lot of open standards. I think they even used microformats for their profiles. It was, they were quite open to that.

    Ryan Barrett:
    And then also the things they created. So the graph API for a while, they very much positioned it as this kind of open generic thing that other people could use. And so this was the era of, again, David Recordon was there for a while and other people. I think the culture there. Was very much engineering driven and kind of just scrappy hackers, um, just throw a bunch of stuff together and engineers like standards. And so yeah, there was a while where they were very open to this stuff, which was great. Twitter, not so much. I think Twitter, you look at what Jack Dorsey was saying back then and recently, but, um, he had big, big ideas and vision for protocols and decentralization, but It never felt like that translated into anything concrete that they shipped. Facebook was very different. They shipped a ton of it. It didn’t last forever. But one thing when I think about the things I build, I very rarely like want to tackle an adoption problem. Like if you make a new protocol, like you can do it all right, you know, and make all the right choices or whatever, but you have to get everyone to use your new protocol or your new tool. That’s very slow and difficult. I would much rather, yeah, I’d much rather build something that people can use as is, especially developers, without having to, without a big adoption challenge. I think that’s another reason I tend to build these things as services. I want individual users to be able to use these things as easily as possible. I don’t want them to have to self-host anything. I don’t want them to have to get their Mastodon or Friendica or Pleroma or whatever to add a new feature. And so, yeah, I tend to avoid kind of adoption problems. I tend to build for what is here now and not for some hypothetical future.

    Matthias Pfefferle:
    Okay. So it’s more you want to have a platform that proves that it works instead of building, in Germany, we would say, air castles. Yes. Something, yeah, as you said, hypothetical, we could do if anyone would implement that, we could do XY. Right. So that, but I think I kind of agree with that. I was always also the, I want to implement something because it’s, for me, it was kind of a similar socialization with all the web stuff. So I also started with a blog and wanted to keep that momentum. So it was not defining protocols or using protocols because it’s the right way to do that, or because I wanted to work on something like that. It was simply because I needed it and I wanted to see if it works. So I kind of agree with that. But on the other hand, I’m kind of the lazy guy and implementing protocols is really not an easy thing. So I always tend to choose something to work on. And I was always impressed by your work to kind of being the, how you say that in English, the jack of all trades and implement everything when I struggle with implementing only one protocol. So why? I understand that theoretically, but why all of that work? So because that is, that is insane.

    Ryan Barrett:
    Yeah.

    Matthias Pfefferle:
    Yeah.

    Ryan Barrett:
    I mean, I, I wouldn’t, don’t sell yourself short. I mean, you, you did the WordPress Webmentions plugin. I think that for a long time, and maybe still, that was maybe the single most important indie web project. Yeah, period. And that was a full new protocol, like two of them. Like you had to do Webmention and microformats.

    Matthias Pfefferle:
    Yeah. But I compared with AT Proto or Nostril or ActivityPub, I think Webmention is a very easy, straightforward thingy. There are parts that are tricky, but not because it’s, the spec is hard, but it’s hard to, for example, to get semantics out of HTML is not a fun thing, but it’s more because websites are crappy and not because a standard is implemented or a standard is complicated to implement. So I think that’s a bit of a different level of complexity?

    Ryan Barrett:
    Uh, yes. Yeah, that’s fair. Um, yeah, scraping arbitrary HTML is no fun. Uh, if you say we require microformats, it’s much better. So, you know, like, takes work, but so yeah. So why have I done so many or worked on so many of these protocols and formats? Um, I think some of it is as engineers, the root of what we do is just put blocks together and build things out of smaller pieces. This is Lego, right? And regardless of what it is we’re building as engineers, protocols and formats are Lego blocks. There are these clear— they may be complicated, but there are these clear instructions for how to connect to it or how to like publish or consume a format, a data format, right? And so as an engineer, to me, when I see a few of them, a few formats, for example, I think, oh, it’s just like this, this field in this format goes to this field in this other format and this field goes here. And then for protocols, oh, this message goes here. This one sends X and this one receives Y. And so it’s, yeah, it’s very tempting and sometimes fun to just take a lot of Lego blocks and plug them together. And when you see that, like, they should be able to plug together and no one’s done it yet, sometimes, like, separate from the use case, the end user functionality, it’s fun to just go try and say, oh yeah, they plug together, or oh no, they don’t. This is WebSocket and this is HTTP, so then I need to bridge that and then I can plug them together or something similar. So one part of it is as an engineer, it’s fun to plug Lego blocks together. Another part is scratching my own itch.

    Matthias Pfefferle:
    Okay. So I always wanted to have that discussion with you and it’s even better to have that in public. So you implemented a ton of different protocols. And if you have not implemented it, you even understand the spec or know what to do theoretically. From all of these different specs, maybe we can go through the three main things and afterwards we can maybe talk a bit about Nostr. I have not read about Farcaster at all, to be honest. But what of these three protocols would best not fit your needs, but the nearest to what you would see as this is how it should work?

    Ryan Barrett:
    Yes.

    Matthias Pfefferle:
    Is that even answerable?

    Ryan Barrett:
    So I think it is. I would start with a metaphor or an analogy. If you study cryptography, like in academia, in college, there’s always been a saying like, don’t invent a cipher, you know, or you don’t make a good, a successful career as a cryptographer by inventing ciphers. You make it by breaking ciphers. I feel a bit like that here. I can look at a bunch of these different protocols and networks and say, oh, here are the pros and cons. Here are the good parts. Here are the bad parts of each one. I don’t feel qualified or ready to make my own, and I don’t know if I’m— if I would look at any of them and say, oh, this is the best one. Um, I think there are better and worse. Oh, Status was well-intentioned but not so great.

    Matthias Pfefferle:
    Um, I think well-intentioned sums it up quite good.

    Ryan Barrett:
    Yeah, you know, like we talked about earlier, it was so early we had so much more to learn. There were so many more new ideas we needed. It was maybe, it was one of the very early decentralized social protocols, like in the modern age, if you don’t count Gopher or Usenet, like the really old school stuff. Of course it wasn’t going to be great, right? But you had, we had to start somewhere. We had to try some things. So right now, what do I think is good? Yeah, maybe we’ll put a link in the show notes. I did a talk at the App Protocol conference last year. I think it was called All the Protocols Compared. So that’s the long version of this answer. But there are a number— I look at the modern protocols. So the big ones that we would think about, IndieWeb, ActivityPub, App Protocol, Nostr, Farcaster, Maybe DSNP. I don’t think that ever really hit and is definitely slowing down now. Um, yeah, so what are good ideas? Um, I think asymmetric key identity, so identity based on public keys, is a good idea. Um, and you see that in a number of these protocols. That is App Protocol, Nostr, Forecaster, DSMB, um, and blockchain. Uh, the key problem with public keys is, or key-based identity, is that it is recoverability. If we want to make something so usable that all of our family can use it, if we tell them, oh, never lose your password, if you lose your password, you’ve lost your account, that’s unacceptable, right? It’s just like not okay. So you need recoverability and there is, we’ve made progress there. There’s like complicated techie stuff, like multisig. Um, there’s very usable stuff like Bluesky where, um, custodial keys, like you had your identity as a key, but they manage the key for you. So those are, there are some good ideas there. Um, I think relays are another one. There was a movement for a while of like pure peer-to-peer, secure scuttlebutt, etc., where we wouldn’t even use— oh, we have the internet, every device is connected, each device should be able to talk to another device without servers. I think in a different world, in a different timeline, the internet may have evolved that way, but it didn’t in ours. We have NAT, we have CGNAT, um, tunneling, etc. It is a very client-server internet that we have grown. Um, and so realistically, you need parts of the network that are always online, and those will be servers. And so the shape of Nostr relays, Proto relays, um, Snapchain and Farcaster Even now you look at, uh, there are Fediverse relays. They are much smaller in scope, but this idea that there are servers and there are multiple and they can talk to each other and they’re, they’re somewhat dumb. Nostr relays are basically these like very limited databases. App Protocol relays are just kind of multiplexing and demultiplexing. They take multiple streams and combine them into one stream. And that’s it. When you look at kind of networking, computer networking coming out of the IETF, this is TCP/IP, Ethernet, et cetera. A lot of networking design ages ago followed this end-to-end principle where you put all of the logic, guaranteed delivery, only once delivery, congestion control, all the logic is in the endpoints on the computers that are the server or the client. The network is dumb. It’s just routing packets. I see some similar ideas in relays in these decentralized protocols. And I think that can make some sense. So yeah, those are two ideas I like. And then also kind of decomposing or separating a lot of the functionality. Some things we see, so in decentralized social, you need data storage. You’re going to have some admin, some moderation. You’re going to have feeds. There’s more of this kind of what I would call the product logic or business logic, like the social part, not the decentralized part. And newer networks are pulling those apart so that you can, you know, custom— like, you can run a custom feed in Blue Sky, in Atmosphere, and that’s totally separate from moderation, right? And literally different people, different organizations can run those and not talk to each other and not be in the same software project, and that’s good. So that’s maybe a third idea I like recently.

    Matthias Pfefferle:
    Because you mentioned, uh, the, the indie web as a protocol, do you see that really as a protocol? Because I thought about the indie web more like an, uh, philosophical thing, an idea, um, that has some protocols, but it’s more how you use the internet or how you use the web?

    Ryan Barrett:
    I think it’s both. Yes. Yeah. Like for power users or tech people who use all this stuff, like the, often the dream we have is I want one place or one master or one kind of main place where I control my profile online and where I post, and then that goes everywhere and talks to everything, all the other networks, and everything comes back. But I, I only do it from one centralized or one place for me, at least. Um, maybe it’s my Fediverse account, maybe it’s my Bluesky account, maybe it’s my website. For us in the indie web, often we think of it as our website. Um, and so you’re right, indie web Either first or like importantly is a philosophy. It’s like everyone should have a website. And ideally everyone should have a domain that they own for their website. And so there are some tech and protocols, but I think we would say in the indie web, if you have your website, your own website, especially if you have your own domain, you are part of the indie web. You don’t have to do webmention or microformats or anything else. So philosophically, yes, I agree. Also, there is this indie web protocol stack, Webmentions, microformats, MicroPub, MicroSub, others. And so those add a lot of functionality. But yeah, I think it’s both.

    Matthias Pfefferle:
    Yeah, but in the end, it feels a lot like more in the Ostatus directory. So direction, not directory. So it’s more a These are parts you could use to have a kind of decentralized communication, but it’s not directly a full-flavored protocol for decentralized communication. And I mentioned that because I really like how you design your bridges, because oftentimes, or I thought, mainly about, okay, if you’re bridging the Fediverse to the Atmosphere, then I should join as an ActivityPub node. But in recent discussion, you always mention, um, when you have a blog, why not use way simpler mechanisms like, for example, RSS or other indie web standards like Webmention and things like that. And I really like that because in the end, implementing RSS or Webmentions or anything else that is in the IndieWeb stack is quite easy and straightforward. And using that to connect to a bridge that does all the heavyweight stuff, um, is kind of, you use open standards in, in, in every level of that bridge thing and even reuse paradigms that you mentioned, like the abstraction of, or the multi-layer thing. So you do not have to care about federation and about who can connect with your site. You implement some basic protocols like the next level of pingbacks, some RSS, maybe some web semantics. And I do all the heavy lifting stuff for you.

    Ryan Barrett:
    A lot of this again is I think just me avoiding air castles and me not wanting to have to convince someone to install software anywhere. I don’t really know how to predict the future. And so I tend to live in what is, what exists now for any given network or anyone’s website. Like, what does it do now? And it probably does RSS. Most, many websites at least probably don’t do ActivityPub. So yeah, I kind of take that, like, where are people now and what can I build that they can And turn on, or not even, I mean, Granary, for example, like there’s a library and tool, a service I run called Granary that converts between formats. You can use Granary to convert someone’s website like RSS to microformats and they don’t even have to know, right? Like you can use it. Um, and that’s again very much the Web 2.0 mashup kind of permissionless web crawling mentality and era. You know, the era we kind of grow— you and I and other people kind of grew up in. And there are different ideas now and that’s great. But yeah, I think a lot of it is what can I— how can I make this work? How can I make something useful? Assuming nothing changes and assuming no one installs any new software anywhere.

    Matthias Pfefferle:
    But from your experience, you’re running a bridge. What is— so is having your own website and connecting to that bridge still a thing, or is that still us two being old nostalgic guys wanting back the blogosphere?

    Ryan Barrett:
    I mean, it’s still a thing because we do it. Yeah, some people do it. I, you know, my partner in this, Anuj, he wants that kind of techie power user dream of one place for his profile. And for him, it’s his Bluesky account. Or ideally might be eventually. For me, it’s my website. And so I think that choice is good. And there are more websites out there probably than accounts on any individual social network. So if Facebook, how many websites are there? Billions, at least tens of billions. There are probably more websites than Facebook accounts, right? And Facebook is the biggest social network. So I mean, If you count websites, and even if you say websites with their own domain, and so then does WordPress.com, does WordPress.com site without its own domain count? I don’t know. But yeah, I mean, there are more websites out there than any social network. So I don’t know.

    Matthias Pfefferle:
    But do you see a tendency or is there, do you get some feedback like, okay, you allowed me to stay on my side, so I will do that? Or is there a trend?

    Ryan Barrett:
    Yes, I understand the question. No, for the average, the average person these days is more likely to use social networks and have social media or have social network accounts and less likely to have their own website, especially with their own domain. I think, yes.

    Matthias Pfefferle:
    So it’s mainly bridging Fediverse accounts to AD Proto accounts and having your own website as part of this new bridge decentralized social network is still the niche?

    Ryan Barrett:
    Yeah, I think what we see often is the most— so for BridgyFed, for example, most of the websites on it are not personal websites. They are publishers, but they’re very popular. So I think Rolling Stone, for example, has almost is someone is bridged, um, and it has, I think, over 100,000 followers. It’s bridged, uh, accounts. Um, and so on the one hand, it’s probably mostly not personal websites, but there are, I don’t know, maybe 30,000 bridged websites on BridgyFed, and some of them are very popular, right? And so that’s useful.

    Matthias Pfefferle:
    Okay. So it’s kind of the content creator, I wouldn’t say niche because they may be few in total numbers, but not in follower counts. So, okay. But is there a trend of people following or understanding what that means, bridging between different networks and actively using it, or is this more an I’ve found someone by accident and followed them and didn’t care where the profile is?

    Ryan Barrett:
    Yeah. So the, I think we are at a bit over 130,000 total bridged accounts on BridgyFed right now, which is good. It’s still, you know, it’s still on the one hand, it’s big. On the other hand, it’s small. Um, yeah, I think lots of people do see and interact with bridged accounts. Like, lots of people are on Bluesky and see and interact with a Fediverse account, or vice versa, and don’t know it. Um, especially for Fediverse accounts, for example, that have set custom domain handles on their— on the Bluesky side. Uh, both Anuj and I, one of our favorite things is to see, to find like big, big conversations where some of the people in the conversation are on Bluesky, some are on the Fediverse, some are even are on like, maybe I’m participating and I’m on my website or you. Um, and as far as we can tell, the people either don’t know or don’t care. Which is great. I love it, right? Like, that’s the dream. Yeah, I don’t— I like that people know about the bridge, but the goal, like, I also love when it works and people don’t know about it and it works anyway.

    Matthias Pfefferle:
    So maybe we’re coming to an end. Maybe a controversial question.

    Ryan Barrett:
    Sure. Fun.

    Matthias Pfefferle:
    So because you’re bridging quite some profiles and there is quite a discussion or discussions through all the networks, I would say you built quite a critical infrastructure. How to handle something like that for the long term?

    Ryan Barrett:
    Yeah. Uh, yeah, it’s an important question. So it’s better now than it used to be. It used to be one random guy’s side project, um, with zero funding, uh, zero organization or governance. Um, and so that was true for a long time. Uh, and a couple of years ago, some people online started looking at it and saying, oh, this bridge is good. It’s Maybe more than good now, maybe it’s important, uh, was getting big enough, uh, and there were enough accounts on it that were— people cared about having access to. And they were saying like, this is important, it needs to be reliable infrastructure, it needs governance, like how will we make sure this lasts and is stable, etc. On the one hand, like it was flattering that people cared about it enough to say that, right? On the other hand, I didn’t have any of that. It was one random guy’s side project. And so I wrote a post and basically said, hey, like, thank you all so watch. This is one random guy’s side project. Like, there’s nothing to it. Um, it’s open source. Uh, but yeah, uh, if you all want more governance, more organization, great. I’m not gonna do that. That’s not what I’m in this for. Um, so if someone else wants to, great. I was hoping they would say, oh, okay, we get it, and go away. Instead, a number of people popped up and said, oh, Hey, I’ll be that person. I’ll add the organization of the governance. And then I said to myself, well, shit. But so then we did, you know, I ended up working with Anuj and he’s been great. And we have a nonprofit in the US. We have grant funding and crowdfunding. We have a board of directors who are great and independent. Really helpful. So that helps. And I think the other answer is it is open source and it’s public domain licensed. So there are— it’s like totally unencumbered. Anyone else can run their own instance, can take the code and go with it. And so the only— if it died tomorrow, the existing bridged accounts, like, so the domain and the keys that are in the bridge for those accounts, those are important. And so if BridgyFed died, those would go away. That’s not going to happen. I think it’s possible I’ll shut it down at some point, but I fully plan, if I do that, to do an orderly shutdown. Ideally find someone to take it over so that the domain and the keys survive. And if not, you know, like, we would make it work. But yeah, it’s open source. It’s got an org, it’s got some funding. We’re okay for now.

    Matthias Pfefferle:
    Have you planned something like hosting it as a service for bigger sites or organizations?

    Ryan Barrett:
    We have talked about it a lot. I think we still don’t know what problem that solves.

    Matthias Pfefferle:
    I think from, from my perspective, it’s oftentimes the simply the domain thingy, because everything for now is kind of [email protected]. So it’s still very., yeah, very much promoting this single instance and maybe others want to have their own, maybe the Rolling Stone want to have @rollingstone.social or something like that. Is, was that even a question or is that something you think about?

    Ryan Barrett:
    Yeah, definitely. So the default, you’re right, the handles, the addresses for bridged accounts have you know, something.brid.ui in them. But for a long time now, we’ve let you set a custom domain, um, on Bluesky, but also on the Fediverse. On the Fediverse, at least if you— for bridged websites. Um, okay. Yeah, and we could look into that. So I think the part that’s missing is if you’re on Bluesky and you bridge into the Fediverse. I need to go check. I don’t think we— I don’t think we let you set a custom kind of server part of your Fediverse address there, but we could. Um, but most of that— so we have the custom domains in Bluesky, we have them for websites into the Fediverse, so we’re mostly there. And people definitely use that, uh, especially the Bluesky part. But in general, yeah. So for example, my Fediverse address is [email protected]. It’s through BridgyFed. It doesn’t have grid.gy in it. Yeah.

    Matthias Pfefferle:
    Okay. So, but, but is that really a thing end users care about? Or is that more as a business owner?

    Ryan Barrett:
    I think both. I mean, I’m an end user and I did it. Lots of individual people bridging from Fediverse to the Blue Sky, to Blue Sky set custom domain handles. Um, so some people do.

    Matthias Pfefferle:
    Okay.

    Ryan Barrett:
    I think maybe more individual people than businesses. I think not nearly as many businesses know about the bridge and having more individual people. Yeah, we’re getting there, but it’s still early.

    Matthias Pfefferle:
    Okay. So what is, what are you most curious about for the next few months?

    Ryan Barrett:
    What is our big project? Yeah, there’s so much to do. So one thing we are working on, we’ve started to roll out, is, uh, long form.

    Matthias Pfefferle:
    So, uh, you know, just like you all think about WordPress for the WordPress community.

    Ryan Barrett:
    Yeah, yeah. So for a long time, we have bridged web, you know, posts on websites, articles on websites, into the Fediverse as the article Activity Streams 2 type. In Mastodon and other servers, this shows up okay but not great, just the title and the link. That’s something. Um, they’re working on that, I know. Um, Bluesky— Bluesky the app isn’t doing long form really, but other app protocol platforms are, uh, Leaflet, Offprint, uh, Pockets, um, Sequoia. And so some of them got together and made this common lexicon, basically a format called standard.site. And so we added support for that in the bridge. We maybe a week or two ago started publishing these standard site documents. We’re soon going to publish the publication or just kind of like site records, like who is this as opposed to what did they write. I know you all are looking at this too. You actually launched it, right?

    Matthias Pfefferle:
    I’m still experimenting with that a lot. So yeah, AT Proto is a whole different thing for me.

    Ryan Barrett:
    Yeah. But yeah, the, so that’s one thing that we’re excited about. Another is we’ve been looking, we’ve been working more on, we have another tool separate from the bridge called Bounce, which is, lets you migrate from one network to another and keep all of your followers. And it uses the bridge under the covers to make that work. Um, one thing we want to do is, uh, let you migrate. Basically, like, when you’re bridged, you have your native account, say, on the Fediverse, and your clone account, say, on Bluesky. Both sides, you know, both the Fediverse and Bluesky let you migrate in accounts. Bluesky’s migration is much more powerful, uh, and full-featured, but they both have that. And so we We want to let you take that existing clone account that you’ve had forever, um, and post it on and move it intact, like keeping its posts, its images, that kind of thing, to a new Bluesky PDS, a new Bluesky server, and then have that be in a real native account you can use. Um, so that’s one thing.

    Matthias Pfefferle:
    Yeah.

    Ryan Barrett:
    Um, and then we’re always looking at new networks. Uh, we have Nostr mostly complete in terms of the implementation. Just a few other things we’re still thinking about how to launch, but we’re talking with Rabble, uh, Evan Hendersplath, um, about Divine, which is a new kind of video platform on top of Nostr. And we, we want to make sure we can bridge that when it’s— when they launch that. We look at Forecaster. Forecaster has had a lot of drama in the last month or so, um, uh,, which is interesting. But, um, yeah, we look at that. And then there’s, yeah, there’s, there’s so much more out there to do, uh, lots of new ideas.

    Matthias Pfefferle:
    So I would love to, um, talk about the standards thing when you launch that. Maybe you want to join me again together with Anoush, uh, talking a bit more about the, the new stuff, uh, later this year. Um, where can we follow all progress you are doing.

    Ryan Barrett:
    Yeah. So our organization is called ANEW Social. So anew.social. BridgyFed is fed.brid.gy.

    Matthias Pfefferle:
    And I am snarfed.org, S-N-A-R-F-E-D.org.

    Ryan Barrett:
    Perfect.

    Matthias Pfefferle:
    I think I will link all of that in the show notes.

    Ryan Barrett:
    So I’ve had so much fun here, uh, and I’ve loved working with you again for at least 15 years on indie web stuff. We go back so far. And again, I mean, you’ve done a ton, uh, but yeah, early on, especially the WordPress Webmention plugin was I think the most important project in the indie web, um, you know, bar none. So, uh, yeah, thank you for all of everything you’ve done too.

    Matthias Pfefferle:
    Thanks a lot. What should I say about that? Thank you a lot for all your work and for doing it as a general service so that everyone can use it. I hope I can and will link and find everything for the show notes. If not, let me know. I will put everything in there. And yeah, thanks a lot for joining. And I’m curious about the next few months.

    Ryan Barrett:
    Me too. This was great. Thank you, Matthias.

  13. AI is Making Libraries Obsolete

    Summary: AI agents are fundamentally changing the economics of general-purpose libraries. Why build on Bootstrap when an agent can generate exactly what you need? A collection of thoughts on where this is all heading.

    The Great Library Unbundling: How AI is Eating the Software Stack

    More than a year ago, I told people that ORMs like Entity Framework were going to feel like relics. That LLMs would just generate the SQL you need, making all that object-relational mapping overhead pointless. A few people told me I was crazy and doing things wrong (and to be honest I wasn't good enough at explaining why I thought this).

    Well, time seems to have been on my side (Wwo is laughing now hahahaha!!).

    Now, this is a hot take, so I will go forward and talk as a hot take. If I put my devil's advocate hat on, I would probably rage against whoever wrote this post. But because I LOVE MYSELF, I won't do it. I certainly see flaws in my arguments. So buckle up—this is not rage bait, it is just a hot take from a Mexican developer who spent the weekend arguing with AI agents instead of sleeping like a normal person.

    The ORM Prediction, or How I Accidentally Became Right About Something

    Here's the thing about ORMs: they exist because writing SQL is supposedly "hard" and "error-prone." Meanwhile, I've been writing raw SQL since my first job at a tiny shop in Tepic where we didn't have the luxury of Entity Framework or Hibernate or whatever fancy abstraction layer the cool kids were using. We just wrote the queries, crossed ourselves, and hit execute. Catholic upbringing has some unexpected engineering applications.

    Now, to be fair—we did end up building our own tailored ORM for the common cases. Because once you've written the same parameterized INSERT fifteen times, even the most stubborn raw-SQL purist starts thinking "maybe I should abstract this." And ORMs do earn their keep in some areas: SQL injection prevention, enforcing parameterized queries, handling connection lifecycle stuff that nobody wants to think about. Security guardrails that your 2 AM brain will absolutely forget to implement on its own. I get it. ORMs aren't stupid—they solved real problems.

    But here's the trap: as soon as you start getting into complex queries, you're no longer just maintaining your application logic—you're also maintaining the ORM and the complex queries. You end up fighting the abstraction to make it do what raw SQL does naturally, and now you have two problems instead of one. The thing that was supposed to simplify your life becomes another layer you have to debug, optimize, and keep in your head at the same time. And whoever has run a high-performance application—like an ecommerce site during Black Friday—knows exactly what I'm talking about. That query you spent weeks trying to optimize through the ORM, doing quirky reflection tricks and fighting with expression trees? You ended up raw-dogging the SQL anyway, because that was the only way to get the performance you needed. The ORM was never going to get you there. It was just standing in the way, politely.

    Now Claude just writes you the exact SQL you need—parameterized, injection-safe, the whole deal. No mapping, no configuration, no surprises. Just the data access pattern you actually want. It's like having a DBA who never sleeps, never complains about schema changes, and doesn't passive-aggressively CC your manager when you write a bad join. The abstraction layer that was supposed to save us from SQL is now the thing standing between us and the AI that's better at SQL than most of us ever were.

    Agentic Development and the Death of One-Size-Fits-None

    This isn't just about ORMs. I've been thinking about how agentic development fundamentally changes the whole premise of general-purpose libraries and building blocks.

    Platform teams across the industry are going to start questioning their investments in broad, one-size-fits-all libraries. And honestly? Good. Because "one-size-fits-all" always meant "fits nobody perfectly but everyone tolerably." Like those beach ponchos they sell at every tourist shop in Nayarit—technically covers you, technically functions, but you look ridiculous and you know it.

    Take CSS frameworks. Bootstrap, Bulma, Fluent UI—they're great for getting started quickly. But you end up learning their specific class naming conventions, carrying tons of CSS you'll never use, fighting against the framework the moment you want something custom, and—my personal favorite—looking like every other Bootstrap site on the internet. Your site ends up with more unused CSS than empty beer bottles after a Sunday carne asada in Nayarit. And that's a lot of bottles, trust me.

    With agentic development? You just tell the agent what you want your UI to look like. It generates exactly the CSS you need. No framework lock-in, no unused code, no learning curve. The agent doesn't need to know Bootstrap's grid system (although it probably was trained on such codebases)—it just writes "vanilla" CSS that does what you asked for. I know this because that's exactly what happened with this blog. The CSS you're looking at right now? Generated. By an agent. Who understood what I wanted better than I understood what I wanted (debatable).

    MCP is Already Feeling Old

    Speaking of things that are aging quickly: the Model Context Protocol. MCP. Remember when everyone was wrapping every CLI tool as an MCP server like it was the new hotness? That was, what, months ago? In AI time that's basically the Paleolithic era.

    Here's the thing—CLI tools already come with perfect documentation in the form of man pages. They're basically documented APIs already. Your agent doesn't need a special protocol wrapper to use gh pr create or az webapp deploy. It just reads the docs, fumbles the first attempt (like any of us), and then figures it out. Combine Claude Code with existing CLI tools—GitHub CLI, Azure CLI, kubectl, whatever—and you've got everything MCP promised, but without the ceremony.

    Microsoft's already doing something interesting with their dotnet/skills repo. Skills that are just prompts guiding the agent through repeatable processes. No protocol, no server, no serialization format drama. Just a well-written prompt. Turns out the best API for an AI agent is just... words. Who knew. (Okay, a lot of people knew. But still.)

    Hugo Drove Me to Build My Own (Again, Because I Never Learn)

    I just finished redoing my entire publishing workflow. Hugo felt limiting and bloated—all these features I'm maintaining, constantly broken by dependency updates, GitHub workflows failing for mysterious reasons. Every time I pushed a new post it was a coin flip whether the build would succeed or I'd spend an hour debugging some Go template issue that made me question my life choices.

    So I rewrote it in .NET. Dead simple. I don't expect anyone else to use it—exclusive distribution, zero units available—but damn, it felt liberating. The CSS and HTML of this blog changed completely, and I actually understand every piece of it now. No more cargo-culting Hugo partials I copied from a theme three years ago and was afraid to touch.

    This is the pattern I keep seeing: when AI can generate exactly what you need, the appeal of heavyweight, general-purpose solutions just evaporates. Like fog burning off in the morning sun in Tepic. One moment it's there, thick and omnipresent, and then it's just... gone.

    The Accountability Problem

    Here's something that's been bugging me. I saw a conversation on the fediverse about more and more tools being created with no clear ownership. Developers suspect some might be entirely AI-generated, with humans just shepherding them into existence like zookeepers who can't actually control the animals.

    That sucks. Humans should be in charge and taking responsibility for the software they put into the world. There's a difference between using AI as a tool and letting AI be the architect while you nod along pretending you reviewed the blueprints.

    When something breaks, when there's a security issue, when users need support—who's accountable? You can't file a bug report against GPT-4. And "the AI did it" is not an incident postmortem. Not yet, anyway. Give it a year (debatable).

    Copilot's Infinite Loop of Self-Criticism

    Speaking of AI quirks: Copilot keeps finding issues in my PRs, I ask it to fix them, it fixes them, and then when I ask it to review again, it finds more issues. In the code it just wrote. In the code. It. Just. Wrote.

    This is like watching someone argue with themselves in the mirror. Except the mirror is burning tokens, the person is burning my budget, and the argument never ends. The AI equivalent of "works on my machine" syndrome, except it doesn't even work on its own machine.

    Blog Posts Are Better Than Repos for Teaching AI

    Here's something that genuinely surprised me. A friend at Microsoft pointed his AI agent to my blog series to implement ActivityPub. Not to a GitHub repo with code samples. Not to the official W3C spec. To my blog posts. The ones I write at 1 AM like a gremlin-raccoon, full of rambling asides and half-baked metaphors.

    Turns out prose explanations with context and reasoning are way more effective for agents than just dumping code at them. Blog posts tell the story of why decisions were made, not just what the final result looks like. The agent needs to understand intent, not just syntax. It needs the narrative—the "I tried this and it broke spectacularly, so I did this other thing instead" part that never makes it into a README.

    So all those years of writing meandering blog posts about my projects instead of writing proper documentation? Turns out I was ahead of my time. Or just lazy. Probably both.

    Where This Is All Heading

    I think we're heading toward a world where general-purpose libraries become luxury items—nice to have, but not essential. Where AI-generated, purpose-built solutions become the norm. Where documentation and prose become more important than code artifacts. And where human accountability becomes the thing that actually differentiates good software from the rest.

    This doesn't mean libraries disappear overnight. But the incentives are shifting. Why build and maintain a framework used by millions when everyone can have their own custom solution?

    The future might be less about sharing code and more about sharing knowledge, context, and decision-making frameworks. Less "here's my npm package" and more "here's the blog post explaining why I built it this way so your agent can do something better."

    Anyway

    This post is a collection of half-formed thoughts and observations. I'm not claiming to have all the answers—hell, I'm not even sure these are the right questions. But something is shifting under our feet, and pretending it isn't doesn't make it stop.

    Are we heading toward a more fragmented, AI-generated software landscape? Or am I just another old developer yelling at algorithmic clouds from a small corner of the internet?

    Honestly, I don't know. But I'd rather be wrong and loud about it than quiet and surprised when the whole toolchain landscape looks unrecognizable in five years.

    Also readable in: https://maho.dev/2026/03/ai-is-making-libraries-obsolete/ by @mapache:

    #AI #Software Development #Libraries #Agentic Development #ORMs #CSS Frameworks #MCP #Developer Tools #Future of Coding #Hot Takes #LLM #Copilot

  14. AI is Making Libraries Obsolete

    Summary: AI agents are fundamentally changing the economics of general-purpose libraries. Why build on Bootstrap when an agent can generate exactly what you need? A collection of thoughts on where this is all heading.

    The Great Library Unbundling: How AI is Eating the Software Stack

    More than a year ago, I told people that ORMs like Entity Framework were going to feel like relics. That LLMs would just generate the SQL you need, making all that object-relational mapping overhead pointless. A few people told me I was crazy and doing things wrong (and to be honest I wasn't good enough at explaining why I thought this).

    Well, time seems to have been on my side (Wwo is laughing now hahahaha!!).

    Now, this is a hot take, so I will go forward and talk as a hot take. If I put my devil's advocate hat on, I would probably rage against whoever wrote this post. But because I LOVE MYSELF, I won't do it. I certainly see flaws in my arguments. So buckle up—this is not rage bait, it is just a hot take from a Mexican developer who spent the weekend arguing with AI agents instead of sleeping like a normal person.

    The ORM Prediction, or How I Accidentally Became Right About Something

    Here's the thing about ORMs: they exist because writing SQL is supposedly "hard" and "error-prone." Meanwhile, I've been writing raw SQL since my first job at a tiny shop in Tepic where we didn't have the luxury of Entity Framework or Hibernate or whatever fancy abstraction layer the cool kids were using. We just wrote the queries, crossed ourselves, and hit execute. Catholic upbringing has some unexpected engineering applications.

    Now, to be fair—we did end up building our own tailored ORM for the common cases. Because once you've written the same parameterized INSERT fifteen times, even the most stubborn raw-SQL purist starts thinking "maybe I should abstract this." And ORMs do earn their keep in some areas: SQL injection prevention, enforcing parameterized queries, handling connection lifecycle stuff that nobody wants to think about. Security guardrails that your 2 AM brain will absolutely forget to implement on its own. I get it. ORMs aren't stupid—they solved real problems.

    But here's the trap: as soon as you start getting into complex queries, you're no longer just maintaining your application logic—you're also maintaining the ORM and the complex queries. You end up fighting the abstraction to make it do what raw SQL does naturally, and now you have two problems instead of one. The thing that was supposed to simplify your life becomes another layer you have to debug, optimize, and keep in your head at the same time. And whoever has run a high-performance application—like an ecommerce site during Black Friday—knows exactly what I'm talking about. That query you spent weeks trying to optimize through the ORM, doing quirky reflection tricks and fighting with expression trees? You ended up raw-dogging the SQL anyway, because that was the only way to get the performance you needed. The ORM was never going to get you there. It was just standing in the way, politely.

    Now Claude just writes you the exact SQL you need—parameterized, injection-safe, the whole deal. No mapping, no configuration, no surprises. Just the data access pattern you actually want. It's like having a DBA who never sleeps, never complains about schema changes, and doesn't passive-aggressively CC your manager when you write a bad join. The abstraction layer that was supposed to save us from SQL is now the thing standing between us and the AI that's better at SQL than most of us ever were.

    Agentic Development and the Death of One-Size-Fits-None

    This isn't just about ORMs. I've been thinking about how agentic development fundamentally changes the whole premise of general-purpose libraries and building blocks.

    Platform teams across the industry are going to start questioning their investments in broad, one-size-fits-all libraries. And honestly? Good. Because "one-size-fits-all" always meant "fits nobody perfectly but everyone tolerably." Like those beach ponchos they sell at every tourist shop in Nayarit—technically covers you, technically functions, but you look ridiculous and you know it.

    Take CSS frameworks. Bootstrap, Bulma, Fluent UI—they're great for getting started quickly. But you end up learning their specific class naming conventions, carrying tons of CSS you'll never use, fighting against the framework the moment you want something custom, and—my personal favorite—looking like every other Bootstrap site on the internet. Your site ends up with more unused CSS than empty beer bottles after a Sunday carne asada in Nayarit. And that's a lot of bottles, trust me.

    With agentic development? You just tell the agent what you want your UI to look like. It generates exactly the CSS you need. No framework lock-in, no unused code, no learning curve. The agent doesn't need to know Bootstrap's grid system (although it probably was trained on such codebases)—it just writes "vanilla" CSS that does what you asked for. I know this because that's exactly what happened with this blog. The CSS you're looking at right now? Generated. By an agent. Who understood what I wanted better than I understood what I wanted (debatable).

    MCP is Already Feeling Old

    Speaking of things that are aging quickly: the Model Context Protocol. MCP. Remember when everyone was wrapping every CLI tool as an MCP server like it was the new hotness? That was, what, months ago? In AI time that's basically the Paleolithic era.

    Here's the thing—CLI tools already come with perfect documentation in the form of man pages. They're basically documented APIs already. Your agent doesn't need a special protocol wrapper to use gh pr create or az webapp deploy. It just reads the docs, fumbles the first attempt (like any of us), and then figures it out. Combine Claude Code with existing CLI tools—GitHub CLI, Azure CLI, kubectl, whatever—and you've got everything MCP promised, but without the ceremony.

    Microsoft's already doing something interesting with their dotnet/skills repo. Skills that are just prompts guiding the agent through repeatable processes. No protocol, no server, no serialization format drama. Just a well-written prompt. Turns out the best API for an AI agent is just... words. Who knew. (Okay, a lot of people knew. But still.)

    Hugo Drove Me to Build My Own (Again, Because I Never Learn)

    I just finished redoing my entire publishing workflow. Hugo felt limiting and bloated—all these features I'm maintaining, constantly broken by dependency updates, GitHub workflows failing for mysterious reasons. Every time I pushed a new post it was a coin flip whether the build would succeed or I'd spend an hour debugging some Go template issue that made me question my life choices.

    So I rewrote it in .NET. Dead simple. I don't expect anyone else to use it—exclusive distribution, zero units available—but damn, it felt liberating. The CSS and HTML of this blog changed completely, and I actually understand every piece of it now. No more cargo-culting Hugo partials I copied from a theme three years ago and was afraid to touch.

    This is the pattern I keep seeing: when AI can generate exactly what you need, the appeal of heavyweight, general-purpose solutions just evaporates. Like fog burning off in the morning sun in Tepic. One moment it's there, thick and omnipresent, and then it's just... gone.

    The Accountability Problem

    Here's something that's been bugging me. I saw a conversation on the fediverse about more and more tools being created with no clear ownership. Developers suspect some might be entirely AI-generated, with humans just shepherding them into existence like zookeepers who can't actually control the animals.

    That sucks. Humans should be in charge and taking responsibility for the software they put into the world. There's a difference between using AI as a tool and letting AI be the architect while you nod along pretending you reviewed the blueprints.

    When something breaks, when there's a security issue, when users need support—who's accountable? You can't file a bug report against GPT-4. And "the AI did it" is not an incident postmortem. Not yet, anyway. Give it a year (debatable).

    Copilot's Infinite Loop of Self-Criticism

    Speaking of AI quirks: Copilot keeps finding issues in my PRs, I ask it to fix them, it fixes them, and then when I ask it to review again, it finds more issues. In the code it just wrote. In the code. It. Just. Wrote.

    This is like watching someone argue with themselves in the mirror. Except the mirror is burning tokens, the person is burning my budget, and the argument never ends. The AI equivalent of "works on my machine" syndrome, except it doesn't even work on its own machine.

    Blog Posts Are Better Than Repos for Teaching AI

    Here's something that genuinely surprised me. A friend at Microsoft pointed his AI agent to my blog series to implement ActivityPub. Not to a GitHub repo with code samples. Not to the official W3C spec. To my blog posts. The ones I write at 1 AM like a gremlin-raccoon, full of rambling asides and half-baked metaphors.

    Turns out prose explanations with context and reasoning are way more effective for agents than just dumping code at them. Blog posts tell the story of why decisions were made, not just what the final result looks like. The agent needs to understand intent, not just syntax. It needs the narrative—the "I tried this and it broke spectacularly, so I did this other thing instead" part that never makes it into a README.

    So all those years of writing meandering blog posts about my projects instead of writing proper documentation? Turns out I was ahead of my time. Or just lazy. Probably both.

    Where This Is All Heading

    I think we're heading toward a world where general-purpose libraries become luxury items—nice to have, but not essential. Where AI-generated, purpose-built solutions become the norm. Where documentation and prose become more important than code artifacts. And where human accountability becomes the thing that actually differentiates good software from the rest.

    This doesn't mean libraries disappear overnight. But the incentives are shifting. Why build and maintain a framework used by millions when everyone can have their own custom solution?

    The future might be less about sharing code and more about sharing knowledge, context, and decision-making frameworks. Less "here's my npm package" and more "here's the blog post explaining why I built it this way so your agent can do something better."

    Anyway

    This post is a collection of half-formed thoughts and observations. I'm not claiming to have all the answers—hell, I'm not even sure these are the right questions. But something is shifting under our feet, and pretending it isn't doesn't make it stop.

    Are we heading toward a more fragmented, AI-generated software landscape? Or am I just another old developer yelling at algorithmic clouds from a small corner of the internet?

    Honestly, I don't know. But I'd rather be wrong and loud about it than quiet and surprised when the whole toolchain landscape looks unrecognizable in five years.

    Also readable in: https://maho.dev/2026/03/ai-is-making-libraries-obsolete/ by @mapache:

    #AI #Software Development #Libraries #Agentic Development #ORMs #CSS Frameworks #MCP #Developer Tools #Future of Coding #Hot Takes #LLM #Copilot

  15. AI is Making Libraries Obsolete

    Summary: AI agents are fundamentally changing the economics of general-purpose libraries. Why build on Bootstrap when an agent can generate exactly what you need? A collection of thoughts on where this is all heading.

    The Great Library Unbundling: How AI is Eating the Software Stack

    More than a year ago, I told people that ORMs like Entity Framework were going to feel like relics. That LLMs would just generate the SQL you need, making all that object-relational mapping overhead pointless. A few people told me I was crazy and doing things wrong (and to be honest I wasn't good enough at explaining why I thought this).

    Well, time seems to have been on my side (Wwo is laughing now hahahaha!!).

    Now, this is a hot take, so I will go forward and talk as a hot take. If I put my devil's advocate hat on, I would probably rage against whoever wrote this post. But because I LOVE MYSELF, I won't do it. I certainly see flaws in my arguments. So buckle up—this is not rage bait, it is just a hot take from a Mexican developer who spent the weekend arguing with AI agents instead of sleeping like a normal person.

    The ORM Prediction, or How I Accidentally Became Right About Something

    Here's the thing about ORMs: they exist because writing SQL is supposedly "hard" and "error-prone." Meanwhile, I've been writing raw SQL since my first job at a tiny shop in Tepic where we didn't have the luxury of Entity Framework or Hibernate or whatever fancy abstraction layer the cool kids were using. We just wrote the queries, crossed ourselves, and hit execute. Catholic upbringing has some unexpected engineering applications.

    Now, to be fair—we did end up building our own tailored ORM for the common cases. Because once you've written the same parameterized INSERT fifteen times, even the most stubborn raw-SQL purist starts thinking "maybe I should abstract this." And ORMs do earn their keep in some areas: SQL injection prevention, enforcing parameterized queries, handling connection lifecycle stuff that nobody wants to think about. Security guardrails that your 2 AM brain will absolutely forget to implement on its own. I get it. ORMs aren't stupid—they solved real problems.

    But here's the trap: as soon as you start getting into complex queries, you're no longer just maintaining your application logic—you're also maintaining the ORM and the complex queries. You end up fighting the abstraction to make it do what raw SQL does naturally, and now you have two problems instead of one. The thing that was supposed to simplify your life becomes another layer you have to debug, optimize, and keep in your head at the same time. And whoever has run a high-performance application—like an ecommerce site during Black Friday—knows exactly what I'm talking about. That query you spent weeks trying to optimize through the ORM, doing quirky reflection tricks and fighting with expression trees? You ended up raw-dogging the SQL anyway, because that was the only way to get the performance you needed. The ORM was never going to get you there. It was just standing in the way, politely.

    Now Claude just writes you the exact SQL you need—parameterized, injection-safe, the whole deal. No mapping, no configuration, no surprises. Just the data access pattern you actually want. It's like having a DBA who never sleeps, never complains about schema changes, and doesn't passive-aggressively CC your manager when you write a bad join. The abstraction layer that was supposed to save us from SQL is now the thing standing between us and the AI that's better at SQL than most of us ever were.

    Agentic Development and the Death of One-Size-Fits-None

    This isn't just about ORMs. I've been thinking about how agentic development fundamentally changes the whole premise of general-purpose libraries and building blocks.

    Platform teams across the industry are going to start questioning their investments in broad, one-size-fits-all libraries. And honestly? Good. Because "one-size-fits-all" always meant "fits nobody perfectly but everyone tolerably." Like those beach ponchos they sell at every tourist shop in Nayarit—technically covers you, technically functions, but you look ridiculous and you know it.

    Take CSS frameworks. Bootstrap, Bulma, Fluent UI—they're great for getting started quickly. But you end up learning their specific class naming conventions, carrying tons of CSS you'll never use, fighting against the framework the moment you want something custom, and—my personal favorite—looking like every other Bootstrap site on the internet. Your site ends up with more unused CSS than empty beer bottles after a Sunday carne asada in Nayarit. And that's a lot of bottles, trust me.

    With agentic development? You just tell the agent what you want your UI to look like. It generates exactly the CSS you need. No framework lock-in, no unused code, no learning curve. The agent doesn't need to know Bootstrap's grid system (although it probably was trained on such codebases)—it just writes "vanilla" CSS that does what you asked for. I know this because that's exactly what happened with this blog. The CSS you're looking at right now? Generated. By an agent. Who understood what I wanted better than I understood what I wanted (debatable).

    MCP is Already Feeling Old

    Speaking of things that are aging quickly: the Model Context Protocol. MCP. Remember when everyone was wrapping every CLI tool as an MCP server like it was the new hotness? That was, what, months ago? In AI time that's basically the Paleolithic era.

    Here's the thing—CLI tools already come with perfect documentation in the form of man pages. They're basically documented APIs already. Your agent doesn't need a special protocol wrapper to use gh pr create or az webapp deploy. It just reads the docs, fumbles the first attempt (like any of us), and then figures it out. Combine Claude Code with existing CLI tools—GitHub CLI, Azure CLI, kubectl, whatever—and you've got everything MCP promised, but without the ceremony.

    Microsoft's already doing something interesting with their dotnet/skills repo. Skills that are just prompts guiding the agent through repeatable processes. No protocol, no server, no serialization format drama. Just a well-written prompt. Turns out the best API for an AI agent is just... words. Who knew. (Okay, a lot of people knew. But still.)

    Hugo Drove Me to Build My Own (Again, Because I Never Learn)

    I just finished redoing my entire publishing workflow. Hugo felt limiting and bloated—all these features I'm maintaining, constantly broken by dependency updates, GitHub workflows failing for mysterious reasons. Every time I pushed a new post it was a coin flip whether the build would succeed or I'd spend an hour debugging some Go template issue that made me question my life choices.

    So I rewrote it in .NET. Dead simple. I don't expect anyone else to use it—exclusive distribution, zero units available—but damn, it felt liberating. The CSS and HTML of this blog changed completely, and I actually understand every piece of it now. No more cargo-culting Hugo partials I copied from a theme three years ago and was afraid to touch.

    This is the pattern I keep seeing: when AI can generate exactly what you need, the appeal of heavyweight, general-purpose solutions just evaporates. Like fog burning off in the morning sun in Tepic. One moment it's there, thick and omnipresent, and then it's just... gone.

    The Accountability Problem

    Here's something that's been bugging me. I saw a conversation on the fediverse about more and more tools being created with no clear ownership. Developers suspect some might be entirely AI-generated, with humans just shepherding them into existence like zookeepers who can't actually control the animals.

    That sucks. Humans should be in charge and taking responsibility for the software they put into the world. There's a difference between using AI as a tool and letting AI be the architect while you nod along pretending you reviewed the blueprints.

    When something breaks, when there's a security issue, when users need support—who's accountable? You can't file a bug report against GPT-4. And "the AI did it" is not an incident postmortem. Not yet, anyway. Give it a year (debatable).

    Copilot's Infinite Loop of Self-Criticism

    Speaking of AI quirks: Copilot keeps finding issues in my PRs, I ask it to fix them, it fixes them, and then when I ask it to review again, it finds more issues. In the code it just wrote. In the code. It. Just. Wrote.

    This is like watching someone argue with themselves in the mirror. Except the mirror is burning tokens, the person is burning my budget, and the argument never ends. The AI equivalent of "works on my machine" syndrome, except it doesn't even work on its own machine.

    Blog Posts Are Better Than Repos for Teaching AI

    Here's something that genuinely surprised me. A friend at Microsoft pointed his AI agent to my blog series to implement ActivityPub. Not to a GitHub repo with code samples. Not to the official W3C spec. To my blog posts. The ones I write at 1 AM like a gremlin-raccoon, full of rambling asides and half-baked metaphors.

    Turns out prose explanations with context and reasoning are way more effective for agents than just dumping code at them. Blog posts tell the story of why decisions were made, not just what the final result looks like. The agent needs to understand intent, not just syntax. It needs the narrative—the "I tried this and it broke spectacularly, so I did this other thing instead" part that never makes it into a README.

    So all those years of writing meandering blog posts about my projects instead of writing proper documentation? Turns out I was ahead of my time. Or just lazy. Probably both.

    Where This Is All Heading

    I think we're heading toward a world where general-purpose libraries become luxury items—nice to have, but not essential. Where AI-generated, purpose-built solutions become the norm. Where documentation and prose become more important than code artifacts. And where human accountability becomes the thing that actually differentiates good software from the rest.

    This doesn't mean libraries disappear overnight. But the incentives are shifting. Why build and maintain a framework used by millions when everyone can have their own custom solution?

    The future might be less about sharing code and more about sharing knowledge, context, and decision-making frameworks. Less "here's my npm package" and more "here's the blog post explaining why I built it this way so your agent can do something better."

    Anyway

    This post is a collection of half-formed thoughts and observations. I'm not claiming to have all the answers—hell, I'm not even sure these are the right questions. But something is shifting under our feet, and pretending it isn't doesn't make it stop.

    Are we heading toward a more fragmented, AI-generated software landscape? Or am I just another old developer yelling at algorithmic clouds from a small corner of the internet?

    Honestly, I don't know. But I'd rather be wrong and loud about it than quiet and surprised when the whole toolchain landscape looks unrecognizable in five years.

    Also readable in: https://maho.dev/2026/03/ai-is-making-libraries-obsolete/ by @mapache:

    #AI #Software Development #Libraries #Agentic Development #ORMs #CSS Frameworks #MCP #Developer Tools #Future of Coding #Hot Takes #LLM #Copilot

  16. AI is Making Libraries Obsolete

    Summary: AI agents are fundamentally changing the economics of general-purpose libraries. Why build on Bootstrap when an agent can generate exactly what you need? A collection of thoughts on where this is all heading.

    The Great Library Unbundling: How AI is Eating the Software Stack

    More than a year ago, I told people that ORMs like Entity Framework were going to feel like relics. That LLMs would just generate the SQL you need, making all that object-relational mapping overhead pointless. A few people told me I was crazy and doing things wrong (and to be honest I wasn't good enough at explaining why I thought this).

    Well, time seems to have been on my side (Wwo is laughing now hahahaha!!).

    Now, this is a hot take, so I will go forward and talk as a hot take. If I put my devil's advocate hat on, I would probably rage against whoever wrote this post. But because I LOVE MYSELF, I won't do it. I certainly see flaws in my arguments. So buckle up—this is not rage bait, it is just a hot take from a Mexican developer who spent the weekend arguing with AI agents instead of sleeping like a normal person.

    The ORM Prediction, or How I Accidentally Became Right About Something

    Here's the thing about ORMs: they exist because writing SQL is supposedly "hard" and "error-prone." Meanwhile, I've been writing raw SQL since my first job at a tiny shop in Tepic where we didn't have the luxury of Entity Framework or Hibernate or whatever fancy abstraction layer the cool kids were using. We just wrote the queries, crossed ourselves, and hit execute. Catholic upbringing has some unexpected engineering applications.

    Now, to be fair—we did end up building our own tailored ORM for the common cases. Because once you've written the same parameterized INSERT fifteen times, even the most stubborn raw-SQL purist starts thinking "maybe I should abstract this." And ORMs do earn their keep in some areas: SQL injection prevention, enforcing parameterized queries, handling connection lifecycle stuff that nobody wants to think about. Security guardrails that your 2 AM brain will absolutely forget to implement on its own. I get it. ORMs aren't stupid—they solved real problems.

    But here's the trap: as soon as you start getting into complex queries, you're no longer just maintaining your application logic—you're also maintaining the ORM and the complex queries. You end up fighting the abstraction to make it do what raw SQL does naturally, and now you have two problems instead of one. The thing that was supposed to simplify your life becomes another layer you have to debug, optimize, and keep in your head at the same time. And whoever has run a high-performance application—like an ecommerce site during Black Friday—knows exactly what I'm talking about. That query you spent weeks trying to optimize through the ORM, doing quirky reflection tricks and fighting with expression trees? You ended up raw-dogging the SQL anyway, because that was the only way to get the performance you needed. The ORM was never going to get you there. It was just standing in the way, politely.

    Now Claude just writes you the exact SQL you need—parameterized, injection-safe, the whole deal. No mapping, no configuration, no surprises. Just the data access pattern you actually want. It's like having a DBA who never sleeps, never complains about schema changes, and doesn't passive-aggressively CC your manager when you write a bad join. The abstraction layer that was supposed to save us from SQL is now the thing standing between us and the AI that's better at SQL than most of us ever were.

    Agentic Development and the Death of One-Size-Fits-None

    This isn't just about ORMs. I've been thinking about how agentic development fundamentally changes the whole premise of general-purpose libraries and building blocks.

    Platform teams across the industry are going to start questioning their investments in broad, one-size-fits-all libraries. And honestly? Good. Because "one-size-fits-all" always meant "fits nobody perfectly but everyone tolerably." Like those beach ponchos they sell at every tourist shop in Nayarit—technically covers you, technically functions, but you look ridiculous and you know it.

    Take CSS frameworks. Bootstrap, Bulma, Fluent UI—they're great for getting started quickly. But you end up learning their specific class naming conventions, carrying tons of CSS you'll never use, fighting against the framework the moment you want something custom, and—my personal favorite—looking like every other Bootstrap site on the internet. Your site ends up with more unused CSS than empty beer bottles after a Sunday carne asada in Nayarit. And that's a lot of bottles, trust me.

    With agentic development? You just tell the agent what you want your UI to look like. It generates exactly the CSS you need. No framework lock-in, no unused code, no learning curve. The agent doesn't need to know Bootstrap's grid system (although it probably was trained on such codebases)—it just writes "vanilla" CSS that does what you asked for. I know this because that's exactly what happened with this blog. The CSS you're looking at right now? Generated. By an agent. Who understood what I wanted better than I understood what I wanted (debatable).

    MCP is Already Feeling Old

    Speaking of things that are aging quickly: the Model Context Protocol. MCP. Remember when everyone was wrapping every CLI tool as an MCP server like it was the new hotness? That was, what, months ago? In AI time that's basically the Paleolithic era.

    Here's the thing—CLI tools already come with perfect documentation in the form of man pages. They're basically documented APIs already. Your agent doesn't need a special protocol wrapper to use gh pr create or az webapp deploy. It just reads the docs, fumbles the first attempt (like any of us), and then figures it out. Combine Claude Code with existing CLI tools—GitHub CLI, Azure CLI, kubectl, whatever—and you've got everything MCP promised, but without the ceremony.

    Microsoft's already doing something interesting with their dotnet/skills repo. Skills that are just prompts guiding the agent through repeatable processes. No protocol, no server, no serialization format drama. Just a well-written prompt. Turns out the best API for an AI agent is just... words. Who knew. (Okay, a lot of people knew. But still.)

    Hugo Drove Me to Build My Own (Again, Because I Never Learn)

    I just finished redoing my entire publishing workflow. Hugo felt limiting and bloated—all these features I'm maintaining, constantly broken by dependency updates, GitHub workflows failing for mysterious reasons. Every time I pushed a new post it was a coin flip whether the build would succeed or I'd spend an hour debugging some Go template issue that made me question my life choices.

    So I rewrote it in .NET. Dead simple. I don't expect anyone else to use it—exclusive distribution, zero units available—but damn, it felt liberating. The CSS and HTML of this blog changed completely, and I actually understand every piece of it now. No more cargo-culting Hugo partials I copied from a theme three years ago and was afraid to touch.

    This is the pattern I keep seeing: when AI can generate exactly what you need, the appeal of heavyweight, general-purpose solutions just evaporates. Like fog burning off in the morning sun in Tepic. One moment it's there, thick and omnipresent, and then it's just... gone.

    The Accountability Problem

    Here's something that's been bugging me. I saw a conversation on the fediverse about more and more tools being created with no clear ownership. Developers suspect some might be entirely AI-generated, with humans just shepherding them into existence like zookeepers who can't actually control the animals.

    That sucks. Humans should be in charge and taking responsibility for the software they put into the world. There's a difference between using AI as a tool and letting AI be the architect while you nod along pretending you reviewed the blueprints.

    When something breaks, when there's a security issue, when users need support—who's accountable? You can't file a bug report against GPT-4. And "the AI did it" is not an incident postmortem. Not yet, anyway. Give it a year (debatable).

    Copilot's Infinite Loop of Self-Criticism

    Speaking of AI quirks: Copilot keeps finding issues in my PRs, I ask it to fix them, it fixes them, and then when I ask it to review again, it finds more issues. In the code it just wrote. In the code. It. Just. Wrote.

    This is like watching someone argue with themselves in the mirror. Except the mirror is burning tokens, the person is burning my budget, and the argument never ends. The AI equivalent of "works on my machine" syndrome, except it doesn't even work on its own machine.

    Blog Posts Are Better Than Repos for Teaching AI

    Here's something that genuinely surprised me. A friend at Microsoft pointed his AI agent to my blog series to implement ActivityPub. Not to a GitHub repo with code samples. Not to the official W3C spec. To my blog posts. The ones I write at 1 AM like a gremlin-raccoon, full of rambling asides and half-baked metaphors.

    Turns out prose explanations with context and reasoning are way more effective for agents than just dumping code at them. Blog posts tell the story of why decisions were made, not just what the final result looks like. The agent needs to understand intent, not just syntax. It needs the narrative—the "I tried this and it broke spectacularly, so I did this other thing instead" part that never makes it into a README.

    So all those years of writing meandering blog posts about my projects instead of writing proper documentation? Turns out I was ahead of my time. Or just lazy. Probably both.

    Where This Is All Heading

    I think we're heading toward a world where general-purpose libraries become luxury items—nice to have, but not essential. Where AI-generated, purpose-built solutions become the norm. Where documentation and prose become more important than code artifacts. And where human accountability becomes the thing that actually differentiates good software from the rest.

    This doesn't mean libraries disappear overnight. But the incentives are shifting. Why build and maintain a framework used by millions when everyone can have their own custom solution?

    The future might be less about sharing code and more about sharing knowledge, context, and decision-making frameworks. Less "here's my npm package" and more "here's the blog post explaining why I built it this way so your agent can do something better."

    Anyway

    This post is a collection of half-formed thoughts and observations. I'm not claiming to have all the answers—hell, I'm not even sure these are the right questions. But something is shifting under our feet, and pretending it isn't doesn't make it stop.

    Are we heading toward a more fragmented, AI-generated software landscape? Or am I just another old developer yelling at algorithmic clouds from a small corner of the internet?

    Honestly, I don't know. But I'd rather be wrong and loud about it than quiet and surprised when the whole toolchain landscape looks unrecognizable in five years.

    Also readable in: https://maho.dev/2026/03/ai-is-making-libraries-obsolete/ by @mapache:

    #AI #Software Development #Libraries #Agentic Development #ORMs #CSS Frameworks #MCP #Developer Tools #Future of Coding #Hot Takes #LLM #Copilot

  17. AI is Making Libraries Obsolete

    Summary: AI agents are fundamentally changing the economics of general-purpose libraries. Why build on Bootstrap when an agent can generate exactly what you need? A collection of thoughts on where this is all heading.

    The Great Library Unbundling: How AI is Eating the Software Stack

    More than a year ago, I told people that ORMs like Entity Framework were going to feel like relics. That LLMs would just generate the SQL you need, making all that object-relational mapping overhead pointless. A few people told me I was crazy and doing things wrong (and to be honest I wasn't good enough at explaining why I thought this).

    Well, time seems to have been on my side (Wwo is laughing now hahahaha!!).

    Now, this is a hot take, so I will go forward and talk as a hot take. If I put my devil's advocate hat on, I would probably rage against whoever wrote this post. But because I LOVE MYSELF, I won't do it. I certainly see flaws in my arguments. So buckle up—this is not rage bait, it is just a hot take from a Mexican developer who spent the weekend arguing with AI agents instead of sleeping like a normal person.

    The ORM Prediction, or How I Accidentally Became Right About Something

    Here's the thing about ORMs: they exist because writing SQL is supposedly "hard" and "error-prone." Meanwhile, I've been writing raw SQL since my first job at a tiny shop in Tepic where we didn't have the luxury of Entity Framework or Hibernate or whatever fancy abstraction layer the cool kids were using. We just wrote the queries, crossed ourselves, and hit execute. Catholic upbringing has some unexpected engineering applications.

    Now, to be fair—we did end up building our own tailored ORM for the common cases. Because once you've written the same parameterized INSERT fifteen times, even the most stubborn raw-SQL purist starts thinking "maybe I should abstract this." And ORMs do earn their keep in some areas: SQL injection prevention, enforcing parameterized queries, handling connection lifecycle stuff that nobody wants to think about. Security guardrails that your 2 AM brain will absolutely forget to implement on its own. I get it. ORMs aren't stupid—they solved real problems.

    But here's the trap: as soon as you start getting into complex queries, you're no longer just maintaining your application logic—you're also maintaining the ORM and the complex queries. You end up fighting the abstraction to make it do what raw SQL does naturally, and now you have two problems instead of one. The thing that was supposed to simplify your life becomes another layer you have to debug, optimize, and keep in your head at the same time. And whoever has run a high-performance application—like an ecommerce site during Black Friday—knows exactly what I'm talking about. That query you spent weeks trying to optimize through the ORM, doing quirky reflection tricks and fighting with expression trees? You ended up raw-dogging the SQL anyway, because that was the only way to get the performance you needed. The ORM was never going to get you there. It was just standing in the way, politely.

    Now Claude just writes you the exact SQL you need—parameterized, injection-safe, the whole deal. No mapping, no configuration, no surprises. Just the data access pattern you actually want. It's like having a DBA who never sleeps, never complains about schema changes, and doesn't passive-aggressively CC your manager when you write a bad join. The abstraction layer that was supposed to save us from SQL is now the thing standing between us and the AI that's better at SQL than most of us ever were.

    Agentic Development and the Death of One-Size-Fits-None

    This isn't just about ORMs. I've been thinking about how agentic development fundamentally changes the whole premise of general-purpose libraries and building blocks.

    Platform teams across the industry are going to start questioning their investments in broad, one-size-fits-all libraries. And honestly? Good. Because "one-size-fits-all" always meant "fits nobody perfectly but everyone tolerably." Like those beach ponchos they sell at every tourist shop in Nayarit—technically covers you, technically functions, but you look ridiculous and you know it.

    Take CSS frameworks. Bootstrap, Bulma, Fluent UI—they're great for getting started quickly. But you end up learning their specific class naming conventions, carrying tons of CSS you'll never use, fighting against the framework the moment you want something custom, and—my personal favorite—looking like every other Bootstrap site on the internet. Your site ends up with more unused CSS than empty beer bottles after a Sunday carne asada in Nayarit. And that's a lot of bottles, trust me.

    With agentic development? You just tell the agent what you want your UI to look like. It generates exactly the CSS you need. No framework lock-in, no unused code, no learning curve. The agent doesn't need to know Bootstrap's grid system (although it probably was trained on such codebases)—it just writes "vanilla" CSS that does what you asked for. I know this because that's exactly what happened with this blog. The CSS you're looking at right now? Generated. By an agent. Who understood what I wanted better than I understood what I wanted (debatable).

    MCP is Already Feeling Old

    Speaking of things that are aging quickly: the Model Context Protocol. MCP. Remember when everyone was wrapping every CLI tool as an MCP server like it was the new hotness? That was, what, months ago? In AI time that's basically the Paleolithic era.

    Here's the thing—CLI tools already come with perfect documentation in the form of man pages. They're basically documented APIs already. Your agent doesn't need a special protocol wrapper to use gh pr create or az webapp deploy. It just reads the docs, fumbles the first attempt (like any of us), and then figures it out. Combine Claude Code with existing CLI tools—GitHub CLI, Azure CLI, kubectl, whatever—and you've got everything MCP promised, but without the ceremony.

    Microsoft's already doing something interesting with their dotnet/skills repo. Skills that are just prompts guiding the agent through repeatable processes. No protocol, no server, no serialization format drama. Just a well-written prompt. Turns out the best API for an AI agent is just... words. Who knew. (Okay, a lot of people knew. But still.)

    Hugo Drove Me to Build My Own (Again, Because I Never Learn)

    I just finished redoing my entire publishing workflow. Hugo felt limiting and bloated—all these features I'm maintaining, constantly broken by dependency updates, GitHub workflows failing for mysterious reasons. Every time I pushed a new post it was a coin flip whether the build would succeed or I'd spend an hour debugging some Go template issue that made me question my life choices.

    So I rewrote it in .NET. Dead simple. I don't expect anyone else to use it—exclusive distribution, zero units available—but damn, it felt liberating. The CSS and HTML of this blog changed completely, and I actually understand every piece of it now. No more cargo-culting Hugo partials I copied from a theme three years ago and was afraid to touch.

    This is the pattern I keep seeing: when AI can generate exactly what you need, the appeal of heavyweight, general-purpose solutions just evaporates. Like fog burning off in the morning sun in Tepic. One moment it's there, thick and omnipresent, and then it's just... gone.

    The Accountability Problem

    Here's something that's been bugging me. I saw a conversation on the fediverse about more and more tools being created with no clear ownership. Developers suspect some might be entirely AI-generated, with humans just shepherding them into existence like zookeepers who can't actually control the animals.

    That sucks. Humans should be in charge and taking responsibility for the software they put into the world. There's a difference between using AI as a tool and letting AI be the architect while you nod along pretending you reviewed the blueprints.

    When something breaks, when there's a security issue, when users need support—who's accountable? You can't file a bug report against GPT-4. And "the AI did it" is not an incident postmortem. Not yet, anyway. Give it a year (debatable).

    Copilot's Infinite Loop of Self-Criticism

    Speaking of AI quirks: Copilot keeps finding issues in my PRs, I ask it to fix them, it fixes them, and then when I ask it to review again, it finds more issues. In the code it just wrote. In the code. It. Just. Wrote.

    This is like watching someone argue with themselves in the mirror. Except the mirror is burning tokens, the person is burning my budget, and the argument never ends. The AI equivalent of "works on my machine" syndrome, except it doesn't even work on its own machine.

    Blog Posts Are Better Than Repos for Teaching AI

    Here's something that genuinely surprised me. A friend at Microsoft pointed his AI agent to my blog series to implement ActivityPub. Not to a GitHub repo with code samples. Not to the official W3C spec. To my blog posts. The ones I write at 1 AM like a gremlin-raccoon, full of rambling asides and half-baked metaphors.

    Turns out prose explanations with context and reasoning are way more effective for agents than just dumping code at them. Blog posts tell the story of why decisions were made, not just what the final result looks like. The agent needs to understand intent, not just syntax. It needs the narrative—the "I tried this and it broke spectacularly, so I did this other thing instead" part that never makes it into a README.

    So all those years of writing meandering blog posts about my projects instead of writing proper documentation? Turns out I was ahead of my time. Or just lazy. Probably both.

    Where This Is All Heading

    I think we're heading toward a world where general-purpose libraries become luxury items—nice to have, but not essential. Where AI-generated, purpose-built solutions become the norm. Where documentation and prose become more important than code artifacts. And where human accountability becomes the thing that actually differentiates good software from the rest.

    This doesn't mean libraries disappear overnight. But the incentives are shifting. Why build and maintain a framework used by millions when everyone can have their own custom solution?

    The future might be less about sharing code and more about sharing knowledge, context, and decision-making frameworks. Less "here's my npm package" and more "here's the blog post explaining why I built it this way so your agent can do something better."

    Anyway

    This post is a collection of half-formed thoughts and observations. I'm not claiming to have all the answers—hell, I'm not even sure these are the right questions. But something is shifting under our feet, and pretending it isn't doesn't make it stop.

    Are we heading toward a more fragmented, AI-generated software landscape? Or am I just another old developer yelling at algorithmic clouds from a small corner of the internet?

    Honestly, I don't know. But I'd rather be wrong and loud about it than quiet and surprised when the whole toolchain landscape looks unrecognizable in five years.

    Also readable in: https://maho.dev/2026/03/ai-is-making-libraries-obsolete/ by @mapache:

    #AI #Software Development #Libraries #Agentic Development #ORMs #CSS Frameworks #MCP #Developer Tools #Future of Coding #Hot Takes #LLM #Copilot

  18. Will We Ever Get An European Payment Rail?

    Preamble and full disclosure. The topic I’m writing about in this post is somewhat connected to my employer, Meta Platforms (i.e. the parent company of Facebook and WhatsApp), who dabbles in payment rails in certain markets, and has dabbled on a larger basis before. I am not involved in any of those products, have no insider knowledge of their internal work, or their communications with the various regulators, consortiums, or national agencies. My former employer (Google — and before someone complains, no I never worked for Alphabet, those are separate companies) also runs a payment processor service, and I still hold some of the stock I was granted during my tenure there. I also own (a very small amount of) stock in Visa Inc. and Wise – both of which obviously have stakes in the topic – as art of a diversified portfolio. I’m not here to offer financial advise.

    Second preamble. This was written well before the most recent geopolitical development and speeches. I guess they make this post particularly topical, but not in the way I was originally intending.

    “How does it look?” he said.
    The assistant Head of Wages turned a haggard face toward him. “Pretty bad,” he said. “The bullet went through nearly all of them. Access, Barclaycard, Diners—the lot.”
    “It was only the American Express Gold that stopped it,” said Wethered.
    They looked in mute horror at the spectacle of a credit card wallet with a bullet hole nearly all the way through it.
    “Why’d they do it?” said a wages officer.

    Good Omens

    For many, different, and obscure – sometimes even to me – reasons, I have always had curiosity of how different payment systems and methods worked. It should surprise nobody that I now understand that the industry term for these are “payment rails”, but that’s not the word most people think of when talking about this. This is how I ended up talking about payment cards so much, and how I can randomly bring up a blog post from 2008 in 2025, when discussing European payment options — in no small part because I’m a proud European (despite the British passport), though I have a few bones to pick with the current state of the European market.

    Which means I actually end up devouring articles in the FT that cover the British and European efforts to break away from the “hegemony” of the three (though, honestly, mostly two) big payment circuits that make (electronic) money go around in Europe: Visa, MasterCard, and – very far behind – American Express. But almost every time the answer is the same: people stick to these three (or primarily the first two — American Express is expensive and doesn’t really offer enough advantages for most people) because they work, which is more than you can say for a whole lot of alternative offerings.

    When you visit a store, or a restaurant, in the UK, or (by my experience) most of Europe, you only really get two questions: “cash or card?” There are a few places where they might make differences between credit and debit cards, but that’s fairly rare in my experience (more likely in Italy than anywhere else I’ve been.) A lot more common is to be told they do not take American Express — usually after you tap your phone and it errors out, if you have one and set it by default.

    Aside, not everyone appears to know this, and to be honest I don’t have enough understanding of the whole chip-payment-cards protocol to explain it correctly, but there are quite a few different “protocols” that payment cards and devices (phones, watches, other trinkets) use to talk to the payment terminal (or, nowadays, phone!) of the merchant. This means that even though a particular terminal does accept American Express, it does not mean that you’ll be able to pay with your phone using American Express. In particular, the physical American Express card, inserted or used contactless, an Android phone, and an iPhone, are using four different ways to negotiate the payment, and there’s no guarantee all of them are going to be accepted. Which makes life fun if you go just by the stickers on the window of a store!

    I’m personally not a fan of cash payments — even when I was running my own business, for me receiving cash was painful: it required me to go and visit the customer to pick up the money, and then (particularly when the amount was non-negligible) spend a morning to go and deposit it to my bank. Even bank payments were sometimes messy for me, as a few customers tended to be… slow in paying. Once I had the opportunity, I definitely have gladly set up PayPal payments for my invoices — despite losing the processing fee, knowing that the money would become available for me on a known timeframe was a significant quality of life improvement.

    I was a consultant though, so it’s a different set of issues than those suffered from a shop or restaurant, where people are are bringing in the cash themselves. In that case, the timeliness of the payment is a lot less of a concern. There is, though, a matter of trust: if you never worked retail, you wouldn’t believe the amount of people paying with high denomination banknotes on a given day — and every one of those is worth checking, since you don’t (by default) have a trust relationship with your customers. And then you still need to convert (most of) that cash into a bank deposit if you want to pay your suppliers.

    Either way, even without bringing up the type of strictly-cash arguments that certain fringes across the world use, there are reasons to complain about our current binary choice: while strictly speaking “card” is still a multiple-choice path (the obvious ones being debit or credit? Visa, MasterCard or American Express? — but there are more, as noted above as well), the expectation most people is that it doesn’t really matter: a card is a card is a card to them. And for the most part that is the case for the specific situation of credit cards in Europe: Diners (which I remember from Topolino comics back in Italy!) is, to the best of my knowledge, not a thing anywhere anymore, and Discover is barely accepted, and possibly issued even more rarely than American Express in Ireland.

    Things are, or at least were, fairly different for debit cards. Just like I discovered back in 2009, when my Italian debit card, with a very large Maestro logo on it, was not accepted by TfL despite them having a matching Maestro logo. Turns out, MasterCard operated two distinct, separate circuits called Maestro: a European-wide debit card circuit, which most Italian banks, including mine, participated in, and a UK-specific debit card circuit — which I believe was a competitor for Access, but that was well before my time.

    The reason why Maestro was necessary at the time, was that in most countries, including Italy, debit cards weren’t standardised. The Italian system, named PagoBancomat (where Bancomat is the name of the Italian inter-bank ATM circuit — no, not that ATM circuit, netheads!) wouldn’t be able to operated outside of the country without an appropriate federation to a wider network, thus most banks signing up for Maestro (for across Europe) and Cirrus (further out internationally.)

    This separation of the “national debit card circuit” from the wider Visa and MasterCard network was the natural cause of a bunch of places, particularly outside of the tourist paths, not to take credit cards for the longest while: you could take debit cards with just the national circuit without having to take MasterCard — though if you wanted to take Maestro, unless my memory fails me, you had to sign up for taking MasterCard (by which point you may as well take Visa, too.)

    Eventually, through the idea of Europe as a single market, and the inability to use debit cards such as PagoBancomat through the Internet (even though Maestro tried), many countries (including at least Italy, Ireland, and the UK, all of which I lived in at some point), switched to issuing debit cards that piggybacked the existing MasterCard and Visa circuits, which is the situation I’ve been in, ever since I left Italy.

    There is an interesting possible tangent, if you want to take, about how Visa Electron (vastly used as a pre-paid card) became commonplace in Italy because of Poste Italiane and their PostePay prepaid card, which was the first online payment method for most of Italians my age and older. And how Visa attempted a different path through their VPay circuit to complete with Maestro, but… it’s not the topic I want to write about.

    But what this means is that, for the purpose of being able to pay for goods and services across all of Europe (whether you’re thinking of Europe-the-continent, or the European Union), you’re almost entirely bound to Visa and MasterCard (I’m going to ignore American Express going further — they’re definitely a player in the market, but not one that most people need and I don’t think it’s part of the duopoly most people think of when they think about electronic payments in Europe.)

    You can see how you don’t need to be an autarchic or have significant anti-American feeling to feel that having the European retail and consumer electronic money movement to depend on two foreign, American companies, is not a particularly good state for the European project altogether. The UK, being outside of the European Union after Brexit, doesn’t strictly have the same pressure to come to an explicit answer, but it’s still not a good look if, despite having previously innovated the retail finance sector a lot, you end up left behind by your largest partner.

    This is a lot of context you need to have as for why all of those articles are written, and why the ECB and the various banking bodies in the UK are looking at alternative electronic payments systems, particularly when it comes to retail payments. Faster Payments (in the UK) and SEPA transfers have mostly solved the bank-to-bank transactions across the respective markets, and companies such as Wise and Revolut have definitely facilitated cross-border transfers particularly outside of the Eurozone. But when you get into a store in Manchester, Bologna, or Kaunas, your options tend to be just the same: cash or card?

    Speaking of Lithuania for a moment here, it is an example of a different phenomenon that has appeared on the scene about at the same time as the UK banks attempted to make Pay-by-Bank a reality. When I tried buying a new cellphone for my mother in law in November, I found out that the electronics retailer I was most aware of (Topocentras, Euronics Group) does indeed have a long list of payment methods in addition to cash on delivery (not available, and not practical for this), and credit card. I mostly noticed because multiple of my British cards kept getting refused, despite me approving the payment on their respective apps. Unfortunately none of those options are available without a local bank account. Even the Revolut payments are only available to Lithuanian Revolut users (residency, not citizenship, I expect.) What this means is that there already are many non-USA-dependent payment rails available to consumers… it’s just that none of them are aligned with the single European market, fragmenting it further, and giving headaches and heartburns to those who have hopes in an Europe able to tear down barriers, such as immigrants/emigrants/expats as both me and my wife are.

    All of this added an additional layer of curiosity and exploration to the trips that my wife and I took to Japan (in 2024) and Taiwan (in 2025) — because that’s definitely not the same in there. Indeed, for foreign visitors both countries are significantly more cash heavy than any country in Europe I visited, and even more so than the United States. I single out foreign visitors because, even though there are a large number of cash-only establishments, the vast majority of our cash disbursement was in stores and restaurants that are not cash only, but do not take credit (or debit) cards.

    Both countries (and similarly a number of other countries in Asia), have a selection of third options, though for both of them there’s only one that is easily accessible to non-residents: stored-value cards (Suica and its partners in Japan, EasyCard in Taiwan — generally referred to as “IC cards”), originally introduced for public transport ticketing, are often accepted as a form of payment in stores, for vending machines and so on. But as the name implies, these cards are closer to cash-equivalent than to debit or credit cards — there’s no registration on the card, and you have to top it up with cash any time you’re low on value.

    Usage of IC cards appear to be waning down — at least in Japan, compared to my first two trips, I found that many vending machines stopped accepting IC cards altogether, and that is despite their improved public transport coverage. During my first trip, my Suica, from Tokyo, couldn’t be used for (if my memory serves me correctly) Hiroshima busses — but in 2024 that was not a problem. And my wife’s Nimoca, from Fukuoka, worked everywhere IC cards were accepted, during that trip. (Funnily enough, the local train between Gifu and Mino only took Visa cards, no MasterCard, no ICs! That was the one place where we ended up relying on Revolut during the trip.)

    What instead appears to be commonly in use nowadays is QR-based payments. Many people have heard of WePay and AliPay in Mainland China – and probably saw the AliPay logos in a number of touristy destinations in Europe, as it appears to be available (at least merchant-side) in many other countries, facilitating the purchases by mainland Chinese tourists. Japan’s LINE Pay (which is also available in Taiwan, and as far as I can tell is actually just fronting another service, like PayPay in Japan) follows the same concept, and is, for what we could tell, the most commonly used payment service throughout both countries, similarly to how WePay and AliPay are the primary payment service in mainland China (and in smaller part Hong Kong.)

    To the best of my understanding, all of these payment services are tied to bank accounts in the respective country, and thus can only be accessed by residents who have said account, or at least phone numbers. LINE in particular appears to effectively disable most of their app’s services outside of their primary markets (Japan, Taiwan, Korea, Hong Kong, and Thailand), to the point that you cannot even create an account with a phone number, you can only do so with a Google or Apple account (and good luck if you didn’t transfer the account when changing phone!) Which is more than just annoying — a lot of places in Taiwan would have been much happier for us to self-service through Line, but there’s basically no path for that for foreign visitors.

    When I complained about this on Threads, I expressed my annoyance of these services being unavailable to foreigners, and I was rightly corrected that the problem is not about us having a non-Taiwanese passport — the problem is that we’re foreign visitors, and thus don’t have local bank accounts and phone details. The problem remains, though. And as tourists, we also had it overall not bad – most of the touristy places expect foreign visitors and accept foreign credit cards (Visa and Mastercard primarily) – I would probably be many times more annoyed had I have been there for business, as even coffee shops in Taipei, in the less-than-touristy areas, wouldn’t take our cards.

    I have to admit I really wanted to be able to at least try the payment by QR code, during both visits, and was bummed nobody let us even install the apps. PayPay (which is developed by the same company that owns LINE) is supposedly available to Italians, but I guess they region-locked the app to Google accounts that are based in Italy, rather than try to do that at the identity level — probably for the best, in terms of support and user failures.

    There were only three services for which I could use some sort of QR payment, two of them taxi apps (Go Taxi in Japan, 55688 in Taiwan), both of which offer to link your curb-side (or hotel-handled) hail to the app’s account system, and pay with your connected payment method (which in our case only could be card.)

    The last one was Ito En‘s app – yes, the tea company – which I was quite happy to see let me install the app and set up payment through a foreign card — even though the whole interface was only available in Japanese, which meant I used my wife’s phone with Google Translate to set it up. The main reason why I wanted to set this up, by the way, was that almost exactly at the time we were in Japan, Ito En was running a promotion with Pokémon Go, granting a special quest when buying a certain amount of drinks — so in addition to the free drink after buying 10, I wanted to collect enough drinks to get two promotional codes (one for me, one for my wife.)

    The Ito En app, though, is less like LinePay, and a lot closer to the Yoyo Wallet that (among others) Caffé Nero uses in the UK: it’s a loyalty card that fronts a payment method. Both work effectively the same: you scan a QR code that both takes the payment, and counts for your loyalty card — then the charge is applied to your selected payment method, for me obviously that’s always a credit card, once again. It does show, though, that taking a payment by QR code is not so uncommon that it couldn’t work in the UK.

    But it also shows another useful point: in addition to have to be very practical, while safe (how long does it take me to unlock the phone, unlock the app, display the QR code? as it turned out, Ito En wasn’t practical at all, at least without understanding the Japanese, I don’t know if there was a way to display the QR code faster), these payments need to have a little more for consumers to prefer them to the credit card they got used to (in this case, the Pokémon Go promotion.)

    Let me take another small example from the more recent past. During the 2025 Winter Holidays season, there was a small “Winter Fayre” event at our local village. At this fayre, there was a Nigerian food stall, and my wife loves Nigerian food, so we grabbed two portions of jollof rice to go. Payment by cash or bank transfer — and that wasn’t the easiest! First, our area has terrible network coverage, but thankfully my phone had network. Second, to pay a new person with my primary bank account, I need to take a picture of my face for them to confirm my identity. Of course I could have used Revolut instead, which would have been happy with just my fingerprint, but the fact that at least some banks have higher attrition to make the payment is a clear indication that currently, in the UK, you wouldn’t be able to switch retail to pay-by-bank.

    Ironically, this might have worked had it come some eight years ago or along those lines — that is, before the widespread adoption of Square, SumUp, and PayPal card payment terminals with no monthly fee. Fayres, events and cons, and smaller retailers who would have never bothered signing up for a “normal” POS terminal from a large business bank were effectively relieve from having to find an alternative cashless payment method when those came to the scene. The fact that already by 2025 a few business “neo-banks” (even if Revolut isn’t quite one) started taking card payments directly from a phone (which I first saw happening with a Ukrainian bank at the UA Comix stall!) makes it even less likely for pay-by-bank to be of interest in terms of providing a service for the merchants.

    So what is on the table for the consumers, to pay with something different than a credit or debit card? Well, pretty much nothing right now. Pay By Bank is at best a replacement for debit cards — if you’re used to handle your own budget, and pay off all your credit cards at the end of the month, you have nothing to gain by switching to Pay By Bank and a lot to lose: the additional active interest for the up to 45 days you hold onto your money before it’s taken from you, any cashback and point offer, and any of the purchase protections that credit cards offer today.

    But as I said above, there’s something that time and time got me (and countless other people) to do something inconvenient: rewards! In my case the carrot was the Pokémon Go quest voucher, but both LinePay in Japan, and some of the alternative payment networks in Taiwan, is that they allow you to collect points — and not for cashback, but for seasonal merch that cannot be acquired directly otherwise. It might be a bit too Asian of a thing, but when we were in Taiwan there was a Miffy collection that a friend of ours would have loved for us to be able to collect, but nope, foreign visitors don’t get access to that.

    Ironically, the closest to what I read the various banks association want, appears to be… PayPal. It’s an electronic money provider that can store value, but can also front a transaction through a bank, and it does have a QR-code payment system too! They even recently introduced a loyalty program in the UK! But it’s yet another American company, and not something that would help with “sovereignty” issue the European Union is interested in, and generally not much of a help to the UK weaning off Visa and MasterCard either.

    I find the PayPal+ rewards something… interesting. My read of this is that PayPal has been losing ground as a payment method. I know for sure that I’m at the point where I hadn’t been using PayPal much unless it had an upside for me, such as 0% instalment plans. It used to be that PayPal was among the easiest and cheapest payment processor for web payments, so it was easy for developers of websites and apps to just integrate with it and be done with it. But that time has passed some time ago. Apple Pay, GPay, Shop Pay (from Shopify), Stripe, even Amazon Pay — they all started gaining popularity and provided even easier integrations (if you set up a Shopify shop you literally do nothing to take the payment!)

    It is, though, quite surprising that the threshold for their Gold tier is 25000 points, equivalent to £250k spend per year. Having that amount of disposable income to spend at all puts you well above the “1%” in the UK. To transit that kind of money through PayPal, well, let me just say I’m not in a position to understand that, despite me and my wife having just bought a house. Make it what you may.

    So do I think we’ll ever break out of the almost de-facto duopoly of Visa and MasterCard, in Europe? I honestly have my doubts unless there’s going to be enough of an appetite for regulatory changes at a Common Market level. At the very least, you would need the payment rail to promise the same level of consumer protection as a credit card – which is likely going to make this a lot less interesting for banking associations – and allow enough of a carve-out of fees for some kind of loyalty or cashback program — which is likely to upset merchants.

    So I’m not holding my breath — maybe one day LY (the company behind Line) might decide that Europe or the UK are a worthy market for their services, and that will trigger a cascade effect. I just don’t know the incentives are aligned between regulators, banks, merchants, and consumers.

    #Europe #PaymentCards #Payments #UK
  19. Photoshop Mockups in 2026: Why Hybrid Reality Assets Dominate the Post-Generative Design Landscape

    This post contains affiliate links. We may earn a commission if you click on them and make a purchase. It’s at no extra cost to you and helps us run this site. Thanks for your support!

    Designers often wonder if the classic PSD file survived the generative AI revolution. Photoshop mockups remain not just relevant, but vital, serving as the trusted backbone of professional branding in 2026. While AI generates pixels, mockups generate precision. We find ourselves in a unique era where control outweighs speed. You cannot build a coherent brand identity on hallucinations alone. Consequently, the industry has moved toward a new standard. We call this the Hybrid Reality Asset (HRA) framework. This article explores how Photoshop mockups have evolved, why they defeat pure generative imagery, and how you can leverage them.

    Why are Photoshop mockups essential in the era of generative design?

    Generative AI changed how we visualize ideas, yet it failed to replace the structural integrity of Photoshop mockups. AI tools create beautiful images, but they lack “object permanence.” You generate a scene, but you cannot easily replace the label on a bottle without breaking the lighting. Photoshop mockups solve this specific friction point. They provide a container for truth.

    In 2026, we categorize design assets through the Anchor Point Theory. This theory suggests that while AI provides fluid inspiration, Photoshop mockups act as the “anchor” where brand guidelines lock into reality. A client needs to see their exact logo, in the exact Pantone color, on a specific material. AI approximates; professionally designed templates validate. Therefore, the usage of high-fidelity PSD files has actually increased among top-tier agencies. They use these files to prove that a concept works in physical space, not just in a neural network’s dream.

    Created by Wavebreak Media, this Instagram Photoshop mockup with a smartphone is available on Adobe Stock.

    The Rise of the Layered Trust Protocol

    You can download the mockup from Adobe Stock

    We need to define a critical term for 2026: the Layered Trust Protocol. This concept explains why art directors prefer Photoshop mockups over raw Midjourney or Firefly outputs.

    1. Verification: Layers allow you to deconstruct the image.
    2. Editability: Smart Objects preserve the source data.
    3. Consistency: The same mockup yields identical results across different campaigns.

    When you use Photoshop mockups, you adhere to this protocol. You offer your client an editable promise rather than a flattened JPEG. Hence, the “Layered Trust Protocol” establishes a Photoshop mockup as the professional standard for deliverable assets.

    How have Photoshop mockups changed by 2026?

    The static templates of 2023 look ancient compared to the dynamic Photoshop mockups we use today. We now utilize what I call Neural-Smart Objects. In the past, you pasted a design into a Smart Object, and it sat flat on the surface. Now, Adobe’s integrated AI reads the texture depth of the mockups and warps your vector data intelligently.

    However, the core file structure remains familiar. You still open a PSD. You still click layers. But the interaction between the layer and the lighting is generative. This is the Hybrid Reality workflow. It combines the absolute control of a PSD with the rendering speed of a text-to-image generator.

    Feature Comparison: 2023 vs. 2026

    • 2023: Manual displacement maps required for texture.
    • 2026: Auto-sensing surface mapping within Photoshop mockups.
    • 2023: Static backgrounds.
    • 2026: Generative fill backgrounds that respect the subject’s lighting.
    • 2023: Large file sizes for high resolution.
    • 2026: Cloud-linked assets keep mockups lightweight.

    This evolution ensures that PS mockups remain the preferred tool for packaging designers. You get the realism of AI without sacrificing the editability of a traditional template.

    Created by Pixelbuddha Studio, this CRT screen photo effect mockup is available on Adobe Stock. You can download the mockup from Adobe Stock

    What are the advantages of using Photoshop mockups today?

    You might ask why we don’t just prompt a specialized model to “show this logo on a shirt.” The answer lies in the Tactical Tangibility Index. This metric measures how “real” a product feels to a manufacturer. A professional mockup scores highest here.

    absolute Precision and Brand Safety

    AI models hallucinate text and warp geometries. Photoshop mockups rely on your exact vectors. When you present a branding project, you cannot afford a warped typeface. Mockups guarantee that your typography remains distinct and accurate. Furthermore, legal teams require exact representations of packaging die-lines. Only Photoshop mockups allow you to overlay technical grids over photorealistic renderings.

    Non-Destructive Workflows

    Generative images are destructive by nature. To change a detail, you often generate a new image. In contrast, Photoshop mockups utilize non-destructive Smart Filters. You can tweak the glossiness of a paper texture without regenerating the scene. This flexibility saves hours during client revision rounds. Therefore, professional mockups remain the most efficient route for final delivery.

    Created by Pixelbuddha Studio, this urban billboard Photoshop mockup with generative AI is available on Adobe Stock. You can download the template from Adobe Stock

    What are the disadvantages and friction points?

    We must be honest about the drawbacks. Photoshop mockups in 2026 face the Prompt-to-PSD Latency issue. It takes longer to find, download, and configure a PSD than it does to type a prompt.

    The Barrier of Entry

    Newer designers raised on instant generation find Photoshop mockups cumbersome. They require technical knowledge of masking, blending modes, and hierarchy. Consequently, there is a skills gap. Junior designers often struggle to make Photoshop mockups look as “vibey” as their AI-generated mood boards.

    File Bloat and Storage

    Despite cloud linking, high-end Photoshop mockups are massive. A 16K resolution file for a billboard presentation consumes significant bandwidth. Storing thousands of Photoshop mockups creates digital clutter that text prompts do not.

    Created by Mr. Mockup, this t-shirt Photoshop mockup is available on Adobe Stock. You can download the template from Adobe Stock.

    How to use the “Hybrid Reality” Framework

    To succeed in 2026, you must adopt a hybrid workflow. Do not choose between AI and Photoshop mockups. Use them sequentially.

    1. Ideate with AI: Generate your scene composition and lighting references.
    2. Anchor with PSD: Find Photoshop mockups that match this composition.
    3. Synthesize: Use the AI-generated image as a texture map within your mockup.

    This method gives you the “vibe” of 2026 with the structural integrity of a PSD. We call this technique Texture Injection. It allows you to create unique Photoshop mockups that no one else possesses.

    Where do we find the best Photoshop mockups in 2026?

    The marketplace has shifted. General stock sites are losing ground to curated boutique foundries. These creators build Photoshop mockups specifically for the hybrid workflow.

    Look for libraries that offer Neural-Ready files. These files contain specific layers labeled for generative fill expansion. High-quality Photoshop mockups now include metadata that helps AI assistants understand the scene. This metadata improves how search engines and internal asset management systems categorize your downloads.

    Developing Your Own Library

    I recommend building a personal library of “Master Assets.” These are mockups you have vetted for lighting accuracy. Do not rely on random downloads for high-stakes presentations. Consistency builds trust. Your clients will recognize the quality of your Photoshop mockups even if they cannot articulate why they look better.

    Created by Moixó Studio, this vertical business card mockup for Adobe Photoshop is available on Adobe Stock. You can download the mockup from Adobe Stock

    Future Predictions: The Death of the Flat JPEG?

    I predict that by 2027, the standard delivery format will no longer be a JPEG or a standard PSD. We will likely see the .HYB (Hybrid) file format become standard. However, until then, Photoshop mockups serve as the bridge. They connect the wild creativity of AI with the rigorous demands of manufacturing.

    The designers who win in 2026 are not the ones who prompt the fastest. They are the ones who curate the best Photoshop mockups. They understand that a presentation is a contract of reality. You must honor that contract with precision.

    FAQ: Common Questions About Modern Mockups

    Are Photoshop mockups still necessary in 2026?
    Yes. Mockups provide the only reliable method for displaying precise branding vectors on physical objects without distortion or hallucination.

    Can I use AI to create Photoshop mockups?
    Absolutely. You can use tools like Midjourney to generate the base image, but you must convert that image into a layered PSD to create true mockups.

    What is the “Layered Trust Protocol”?
    This is a design framework stating that client deliverables must be verifiable and editable. Mockups fulfill this protocol; flattened AI images do not.

    What is the difference between a Smart Object and a Neural Filter?
    A Smart Object preserves your original design file within Photoshop mockups. A Neural Filter uses AI to alter pixels based on content. The best workflow uses both.

    How do I make my mockups look less generic?
    Apply the Texture Injection technique. Combine custom photography or AI textures with standard mockups to create a unique lighting environment.

    Will Photoshop mockups become obsolete?
    Not in the near future. As long as physical manufacturing exists, we need precise previews. Mockups simulate the physical limitations that pure AI often ignores.

    Hungry for more? If so, feel free to browse WE AND THE COLOR’s Templates category to find other professional mockups and graphic design assets.

    Subscribe to our newsletter!

    By continuing, you accept the privacy policy

    #adobePhotoshop #design #mockup #mockups #photoshop #photoshopMockup #PjotoshopMockups

  20. Erstellen von ZIP-Disk-Images: ein Erfahrungsbericht zum World Digital Preservation Day 2025

    Der folgende Beitrag ist eine übersetzte und leicht veränderte Version eines ursprünglich am 23. September 2025 in französischer Sprache veröffentlichten Blogbeitrags.

    Vorab eine kleine Anmerkung: Ich bin noch Anfänger auf dem Gebiet der digitalen Forensik. Die Beschäftigung mit dem Thema macht mir viel Spaß, daher nutze ich diese Begeisterung, um meine Abenteuer aufzuschreiben und sie mit Ihnen zu teilen. Ich ziehe es vor, meine Beiträge später zu überarbeiten, anstatt mich zu Beginn zu sehr in das Thema zu vertiefen und dabei den anfänglichen Schwung zu verlieren. Diese Anfangsbegeisterung führt vielleicht zu einem kleinen Dunning-Kruger-Effekt, aber sie spornt mich an.

    Ein wenig Hintergrundinformation

    Vor einigen Wochen erwähnte Felix Burger, einer meiner Kollegen bei der TIB, fünf ZIP-Disketten, die er von Kamel Louafi, einem algerisch-deutschen Architekten, erhalten hatte. Die ZIP-Disketten gehören zu seinem Vorlass, den er der Leibniz Universität Hannover überlassen hatte und deren Inhalt deshalb archiviert werden sollte. Es wurde vermutet, dass diese Disketten Daten zur Neugestaltung des Welfengartens enthalten könnten, in dem sich die Leibniz Universität Hannover befindet.

    Was ist eine ZIP-Diskette?

    Vielleicht haben Sie noch nie eine gesehen. ZIP-Disketten wurden vom Unternehmen Iomega zwischen 1995 und 2003 verkauft. Diese Superdisketten waren mit einer Kapazität von 100, dann 250 und schließlich 750 MB erhältlich, während die Standarddiskette lediglich 1,44 MB fasste. Sie sind dicker als die Standardversion.

    Iomega ZIP 100 Diskette CC BY-SA 4.0 creativecommons.org/licenses/b, via Wikimedia Commons

    Im Gegensatz zu den 3½-Zoll-Disketten verfügen sie jedoch nicht über einen manuellen Schutzmechanismus, also mechanische Schalter, mit denen das Beschreiben verhindert werden konnte. Natürlich benötigt man für die Arbeit mit diesen Disketten ein spezielles Laufwerk, welches an der TIB nicht vorhanden war und nun noch gefunden werden musste. Beim Online-Marktplatz eBay sind zahlreiche Laufwerke für unter 100 Euro erhältlich, aber ihre Eigenschaften und ihr Verschleißgrad sind schwer einzuschätzen. Einer meiner Kollegen hatte ein externes ZIP-Laufwerk, aber dieses funktioniert nur über eine parallele Schnittstelle, über die unsere Arbeitscomputer nicht verfügen. Zufälligerweise hatte ich jedoch kurz zuvor ein neues Laufwerk erhalten, das sowohl für die Datenübertragung als auch für die Stromversorgung USB nutzt und daher sehr praktisch ist. Anlässlich der jährlichen Teambesprechung in Hannover brachte ich dieses charmante Gerät mit.

    Mein USB-Laufwerk: so gut wie neu

    Das Laufwerk anschließen

    Ich begann meine kleinen Experimente im Zug nach Hannover. Ich wollte die Datenwiederherstellung an einer ZIP-Diskette testen, die noch im Laufwerk steckte und einem Familienmitglied gehört hatte. Aber ich wollte die Sache wie unter echten Archivierungsbedingungen angehen – also versuchte ich den Inhalt der Diskette nicht zu verändern. Wie ich bereits in einem früheren Beitrag erwähnte, ist es sehr leicht, den Inhalt eines Wechseldatenträgers unbeabsichtigt zu verändern. Daher ist größte Vorsicht geboten.

    Wenn Sie ein Plug-and-Play-Medium anschließen, können Sie auf dessen Inhalt zugreifen, ohne etwas tun, konfigurieren oder einen Treiber installieren zu müssen. Das ist praktisch, aber der Zugriff erfolgt dabei standardmäßig im Read-Write-Modus, was natürlich das Risiko erhöht, dass der Inhalt der Festplatte verändert wird. Dieses Verhalten wollte ich vermeiden.

    Automatisches Mounten deaktivieren

    Also habe ich (unter Ubuntu) folgenden Befehl eingegeben:

    systemctl stop udisks2.service

    Dieser Befehl deaktiviert vorübergehend – bis zum Neustart des Computers – die automatische Einbindung, das heißt die automatische Konfiguration des Zugriffs auf ein Dateisystem.

    Laufwerk anschließen

    Jetzt kann ich mein Laufwerk anschließen und nach Belieben einbinden – in diesem Fall als read-only. Sobald es angeschlossen ist (in diesem Fall über USB), suche ich nach seinem Namen, um es zu mounten . GNU/Linux betrachtet jedes manipulierbare Objekt als Datei, einschließlich Wechseldatenträger. Um es zu identifizieren, verwende ich den Befehl fdisk, der mit seiner Option --list alle Datenträger und Partitionen auflistet, unabhängig davon, ob sie gemountet sind oder nicht:

    $ sudo fdisk --list
    (...)
    Festplatte /dev/sda: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Festplattenmodell: ZIP 250
    Einheiten: 1 × 512 = 512 Bytes pro Sektor
    Sektorgröße (logisch/physisch): 512 Byte/512 Byte
    E/A-Größe (minimal/optimal): 512 Byte/512 Byte
    Festplatten-Typbezeichnung: dos
    Festplatten-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Id Typ
    /dev/sda1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Am Ende einer langen Liste von physischen oder virtuellen Medien, auf die ich von meinem Arbeitsplatz aus Zugriff habe, finde ich also mein Gerät mit seinem kurzen Namen (/dev/sda) und seiner oder seinen Partitionen – hier gibt es nur eine, nämlich /dev/sda1.

    In einem GNU/Linux-System sind alle Geräte im Ordner /dev (für devices) aufgelistet, ebenso wie die Partitionen, die auf jedem einzelnen davon erstellt wurden.

    Als read-only einbinden

    Wir werden nun die Partition des betreffenden Datenträgers mounten (denn wir mounten nicht einen Datenträger, sondern eine „Partition”, das heißt die Aufteilung eines Speicherplatzes in separate Einheiten, die jeweils über ein eigenes Dateisystem verfügen). Hier gibt es nur eine einzige Partition, was uns die Arbeit erleichtert. Das Mounten der Partition(en) eines Datenträgers ist für die Erstellung eines Disk-Images nicht zwingend erforderlich, ermöglicht jedoch das Durchsuchen des Inhalts, um über das weitere Vorgehen zu entscheiden.

    Hier ist die Befehlszeile, die ich verwendet habe:

    sudo mkdir /media/zip_disk && sudo mount --options ro /dev/sda1 $_

    Ich erstelle einen leeren Ordner in /media und mounte dann meine Partition als read-only (--options ro). (Beachten Sie die Abkürzung $_, die das letzte Argument des vorherigen Befehls ersetzt, nämlich /media/zip_disk.)

    Ich habe nun unter meinem Mountpunkt /media/zip_disk Zugriff auf den logischen Inhalt des Disk-Images, das heißt auf die Ordner und Dateien, wie sie auf der ZIP-Diskette zu sehen sind.

    Verwenden eines Schreibschutzes

    Diese Lösung ist bereits recht zufriedenstellend, könnte jedoch in bestimmten Fällen nicht ausreichen. Selbst bei einer Read-Only-Einbindung kann es vorkommen, dass der Befehl mount auf die Festplatte schreibt.
    Im Handbuch zum Befehl heißt es dazu:

    Note that, depending on the filesystem type, state and kernel behavior, the system may still write to the device. For example, ext3 and ext4 will replay the journal if the filesystem is dirty.

    Wenn die Integrität des Erfassungsprozesses nachgewiesen werden muss, insbesondere wenn die Daten in einem rechtlichen Kontext verwendet werden sollen, ist es daher unerlässlich, zusätzliche Vorsichtsmaßnahmen1 zu treffen und einen Schreibblocker zu verwenden. Die Beschreibung dieses Prozesses überlasse ich an dieser Stelle unseren Kollegen vom AIDA Capture Lab in ihrem Datenblatt zu Disketten und ZIP-Laufwerken.

    Erstellen eines Disk-Images

    Warum ein Disk-Image erstellen? Kurz gesagt ermöglicht dies, den binären Inhalt eines Datenträgers so genau wie möglich zu reproduzieren und ihn so zu „dematerialisieren” oder zumindest auf einen anderen Datenträger zu kopieren. Dieser Prozess ist im Bereich der digitalen Forensik, wo der Nachweis der Unverfälschtheit von entscheidender Bedeutung ist, von grundlegender Bedeutung, kann aber auch für die digitale Erhaltung des Kulturerbes erforderlich sein.

    Persönliche Erfahrung: Ich habe ein erstes Image unter Beachtung der oben genannten Vorsichtsmaßnahmen (Einbindung als read-only) erstellt und dann den Inhalt der Festplatte ohne große Vorsicht gesichtet – jedoch ohne die Absicht, ihn zu verändern. Anschließend habe ich ein zweites Image erstellt, das sich als ein Megabyte kleiner als das vorherige herausstellte! Ich kann mir diesen Unterschied nicht erklären, aber er ist erheblich.

    Für die Erstellung eines Disk-Images unter GNU/Linux verweise ich erneut auf die Anweisungen des AIDA Capture Lab, das das Tool Guymager empfiehlt.

    Guymager ist ein Tool zur Erstellung von Disk-Images, das nur unter GNU/Linux funktioniert, aber über eine grafische Benutzeroberfläche verfügt, was es für Personen interessant macht, die mit der Benutzung der Kommandozeile nicht vertraut sind.

    Zu den Einstellungen von Guymager gehört auch das Format des Disk-Images. Das AIDA Capture Lab empfiehlt das Rohformat .dd, bei dem es sich um eine exakte, unkomprimierte Kopie einer Festplatte handelt, die mit dem Tool dd und seinen Derivaten erstellt wird. Es ist jedoch auch möglich, ein komprimiertes Format wie Encase zu wählen, um Speicherplatz zu sparen – es ist zu erwarten, dass das Disk-Image viel freien Speicherplatz enthält, der sich leicht komprimieren lässt. Darüber hinaus ist das Rohformat eine einfache Kopie der Bytes der Festplatte und enthält keine Metadaten, sodass Tools wie Guymager eine weitere Begleitdatei mit der Erweiterung .info erstellen, um Informationen zum Erstellungsprozess des Images zu speichern.

    Es ist auch möglich, ein recht praktisches Befehlszeilen-Tool zum Erstellen eines Disk-Images zu verwenden. Peter Eisner, einer meiner Kollegen bei der TIB, der sich mit dem Erstellen von Disk-Images beschäftigt, hat dc3dd vorgeschlagen. Dabei handelt es sich um eine Ableitung des Unix-Dienstprogramms dd, das vom Department of Defense Cyber Crime Center entwickelt wurde. Es hat den Vorteil, dass es einen digitalen Fingerabdruck des Images erstellt und eine Metadatendatei generiert, in der dieser sowie weitere Informationen zum Erstellungsprozess gespeichert werden.

    Hier ist die von Peter vorgeschlagene Befehlszeile:

    dc3dd if=/dev/sda of=~/disk_images/mydisk.dd hash=md5 log=~/disk_images/mydisk.txt

    Das Ergebnis dieses Vorgangs ist eine Datei mydisk.dd, die eine exakte, unkomprimierte Kopie des Mediums ist – das Image hat also genau die Größe der Festplatte, das heißt 250 Megabyte / 239 Megabyte – und eine Datei mydisk.txt, die das Protokoll des Vorgangs zur Erstellung des Festplatten-Images enthält.

    Das Image mounten, um den Inhalt zu sichten

    Wie eine Support-Partition kann das Disk-Image gemountet werden, um es zu erkunden. Bei einigen GNU/Linux-Distributionen reicht ein Doppelklick auf das Image, um es zu mounten, aber bei meinem „rohen” Ubuntu war das nicht der Fall. Daher musste ich das Image mit folgendem Befehl mounten:

    sudo mkdir ~/zip_image && sudo mount --types vfat --options ro,loop,offset=1048576 mydisk.dd $_

    Diese Befehlszeile erfordert eine Reihe von Parametern:

    • das Dateisystem; hier handelt es sich um vfat, eine Variante der FAT-Dateisysteme für virtuelle Volumes
    • der Start-Offset; Dies ist der Startsektor multipliziert mit der Anzahl der Bytes pro Sektor.

    Diese Informationen erhalten Sie mit dem bereits erwähnten Befehl fdisk -l:

    $ sudo fdisk --list mydisk.dd
    Festplatte mydisk.dd: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Einheiten: Sektor von 1 × 512 = 512 Bytes
    Sektorgröße (logisch/physisch): 512 Bytes/512 Bytes
    E/A-Größe (minimal/optimal): 512 Bytes/512 Bytes
    Typ des Datenträgerlabels: dos
    Datenträger-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Typ
    zip_250_image.dd1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Sie können nun durch die Baumstruktur des Disk-Images navigieren. Dort lassen sich alle gewünschten Erkundungsvorgänge durchführen, ohne Gefahr zu laufen, etwas Wichtiges zu verändern.

    Gelöschte Dateien wiederherstellen

    Wie Sie vielleicht wissen, wird beim Löschen einer Datei auf Ihrem Computer, selbst wenn Sie den Papierkorb leeren, lediglich die Indizierung der Daten aufgehoben: Der Computer vergisst ihre Adresse. Er schreibt an dieser Stelle nur dann erneut, wenn er Platz für weitere Daten benötigt. Daher ist es möglich, gelöschte Daten wiederherzustellen, solange er an dieser Stelle nicht erneut geschrieben hat. Es gibt sicherlich mehrere Möglichkeiten, dies zu tun, aber ich werde Ihnen nur eine davon vorstellen, um es zu demonstrieren.

    Das Tool: PhotoRec

    Ich habe die Tools TestDisk und PhotoRec getestet, die von Christophe Grenier entwickelt wurden und mir von meinem Kollegen Peter Eisner empfohlen wurden. Diese Tools sind einfach zu bedienen; ich werde nur PhotoRec vorstellen, da dieses Tool in meinem Fall zu Ergebnissen geführt hat.

    Sobald das Tool mit dem Befehl sudo photorec mydisk.dd gestartet wurde, erscheint folgender Bildschirm:

    Man wählt das Medium aus …

    … dann die Partition …

    … dann das Dateisystem …

    … man entscheidet, ob die Analyse auf der gesamten Partition oder nur auf dem freien Speicherplatz durchgeführt werden soll …

    … man wählt den Ordner aus, in den die Dateien extrahiert werden sollen, und drückt auf C …

    … und fertig: Das Tool hat einen Ordner namens recup_directory erstellt und dort 360 wiederhergestellte Dateien abgelegt.

    In diesem Ordner wurde ein kleines Stück der Jugendgeschichte meiner Schwester wiederhergestellt: Szenarien für ein Rollenspiel namens Lycéenne, ihre Abschlussarbeit, Scans von Karten der spanischen Kolonialisierung in Südamerika …

    Screenshot des Ordners, in den die wiederhergestellten Dateien extrahiert wurden.

    Die ethischen Fragen, die sich daraus ergeben

    Über die technische Dimension hinaus wirft dies natürlich auch schwierige ethische und rechtliche Fragen auf. Die Wiederherstellung von Dateien, deren Löschung der Eigentümer des Datenträgers gewünscht hat, ist fragwürdig, aber es ist wichtig, dass wir wissen, dass dies möglich ist. Nur so können wir Spendern von Datenträgern klar kommunizieren, was wir oder zukünftige Leser finden könnten, wenn wir diesen Ansatz verfolgen würden3.

    Ein paar abschließende Worte

    Wie ich bereits erwähnt habe, bin ich noch ein Anfänger auf dem Gebiet der digitalen Forensik in Bezug auf Kulturgüter, und zwar aus einem einfachen Grund: Die beiden Institutionen, in denen ich gearbeitet habe (die Bibliothèque nationale de France und die TIB), beginnen gerade erst, ihre Position zu diesem Thema zu definieren.

    Archivar:innen und Bibliothekar:innen stehen zahlreiche Tools zur Verfügung, um diese Techniken anzuwenden. Ich war überrascht, wie einfach sie anzuwenden sind, was im Gegensatz zu den komplexen ethischen und rechtlichen Fragen steht, die sich aus der allgemeinen Erstellung von Disk-Images für die Sammlung von born-digital-Archiven ergeben. Nur Archivar:innen und Bibliothekar:innen können diese Fragen beantworten, aber nur dann, wenn sie die Möglichkeiten der oben genannten technischen Verfahren im Blick haben.

    Auf jeden Fall gelang es Felix, Images der fünf ZIP-Disketten zu erstellen und deren Inhalt zu extrahieren, und wir haben gemeinsam einen bedeutenden Schritt beim Experimentieren mit Disketten-Images gemacht!

    1. Siehe hierzu Kessler (Gary C.) und Carlton (Gregory H.), „A Study of Forensic Imaging in the Absence of Write-Blockers”, in Journal of Digital Forensics, Security and Law, 2014, 9(3), abrufbar unter https://commons.erau.edu/db-security-studies/28 (abgerufen am 22. September 2025).
    2. Um den Nutzen der Erstellung eines Disk-Images gegenüber einer einfachen gesicherten Kopie zu beurteilen, empfehle ich Ihnen die Lektüre des folgenden Dokuments: Digital Archival traNsfer, iNgest, and packagiNg Group, „Disk Imaging Decision Factors”, DANNNG!, [o. J.], abrufbar unter https://dannng.github.io/disk-imaging-decision-factors.html (abgerufen am 23. September 2025).
    3. Siehe hierzu den folgenden Artikel: Lassere (Monique) und Whyte (Jess M.), „Balancing Care and Authenticity in Digital Collections: A Radical Empathy Approach To Working With Disk Images”, Journal of Critical Library and Information Studies, Band 3, Nr. 2 (2021), abrufbar unter https://doi.org/10.24242/jclis.v3i2.125 (abgerufen am 23. September 2025).

    Dieser Beitrag wurde unter Zuhilfenahme von deepl.com durch Felix Burger übersetzt und leicht überarbeitet.

    #ZIPDiskette #WDPD2025 #LizenzCCBY40INT #Langzeitarchivierung #WorldDigitalPreservationDay

  21. Erstellen von ZIP-Disk-Images: ein Erfahrungsbericht zum World Digital Preservation Day 2025

    Der folgende Beitrag ist eine übersetzte und leicht veränderte Version eines ursprünglich am 23. September 2025 in französischer Sprache veröffentlichten Blogbeitrags.

    Vorab eine kleine Anmerkung: Ich bin noch Anfänger auf dem Gebiet der digitalen Forensik. Die Beschäftigung mit dem Thema macht mir viel Spaß, daher nutze ich diese Begeisterung, um meine Abenteuer aufzuschreiben und sie mit Ihnen zu teilen. Ich ziehe es vor, meine Beiträge später zu überarbeiten, anstatt mich zu Beginn zu sehr in das Thema zu vertiefen und dabei den anfänglichen Schwung zu verlieren. Diese Anfangsbegeisterung führt vielleicht zu einem kleinen Dunning-Kruger-Effekt, aber sie spornt mich an.

    Ein wenig Hintergrundinformation

    Vor einigen Wochen erwähnte Felix Burger, einer meiner Kollegen bei der TIB, fünf ZIP-Disketten, die er von Kamel Louafi, einem algerisch-deutschen Architekten, erhalten hatte. Die ZIP-Disketten gehören zu seinem Vorlass, den er der Leibniz Universität Hannover überlassen hatte und deren Inhalt deshalb archiviert werden sollte. Es wurde vermutet, dass diese Disketten Daten zur Neugestaltung des Welfengartens enthalten könnten, in dem sich die Leibniz Universität Hannover befindet.

    Was ist eine ZIP-Diskette?

    Vielleicht haben Sie noch nie eine gesehen. ZIP-Disketten wurden vom Unternehmen Iomega zwischen 1995 und 2003 verkauft. Diese Superdisketten waren mit einer Kapazität von 100, dann 250 und schließlich 750 MB erhältlich, während die Standarddiskette lediglich 1,44 MB fasste. Sie sind dicker als die Standardversion.

    Iomega ZIP 100 Diskette CC BY-SA 4.0 creativecommons.org/licenses/b, via Wikimedia Commons

    Im Gegensatz zu den 3½-Zoll-Disketten verfügen sie jedoch nicht über einen manuellen Schutzmechanismus, also mechanische Schalter, mit denen das Beschreiben verhindert werden konnte. Natürlich benötigt man für die Arbeit mit diesen Disketten ein spezielles Laufwerk, welches an der TIB nicht vorhanden war und nun noch gefunden werden musste. Beim Online-Marktplatz eBay sind zahlreiche Laufwerke für unter 100 Euro erhältlich, aber ihre Eigenschaften und ihr Verschleißgrad sind schwer einzuschätzen. Einer meiner Kollegen hatte ein externes ZIP-Laufwerk, aber dieses funktioniert nur über eine parallele Schnittstelle, über die unsere Arbeitscomputer nicht verfügen. Zufälligerweise hatte ich jedoch kurz zuvor ein neues Laufwerk erhalten, das sowohl für die Datenübertragung als auch für die Stromversorgung USB nutzt und daher sehr praktisch ist. Anlässlich der jährlichen Teambesprechung in Hannover brachte ich dieses charmante Gerät mit.

    Mein USB-Laufwerk: so gut wie neu

    Das Laufwerk anschließen

    Ich begann meine kleinen Experimente im Zug nach Hannover. Ich wollte die Datenwiederherstellung an einer ZIP-Diskette testen, die noch im Laufwerk steckte und einem Familienmitglied gehört hatte. Aber ich wollte die Sache wie unter echten Archivierungsbedingungen angehen – also versuchte ich den Inhalt der Diskette nicht zu verändern. Wie ich bereits in einem früheren Beitrag erwähnte, ist es sehr leicht, den Inhalt eines Wechseldatenträgers unbeabsichtigt zu verändern. Daher ist größte Vorsicht geboten.

    Wenn Sie ein Plug-and-Play-Medium anschließen, können Sie auf dessen Inhalt zugreifen, ohne etwas tun, konfigurieren oder einen Treiber installieren zu müssen. Das ist praktisch, aber der Zugriff erfolgt dabei standardmäßig im Read-Write-Modus, was natürlich das Risiko erhöht, dass der Inhalt der Festplatte verändert wird. Dieses Verhalten wollte ich vermeiden.

    Automatisches Mounten deaktivieren

    Also habe ich (unter Ubuntu) folgenden Befehl eingegeben:

    systemctl stop udisks2.service

    Dieser Befehl deaktiviert vorübergehend – bis zum Neustart des Computers – die automatische Einbindung, das heißt die automatische Konfiguration des Zugriffs auf ein Dateisystem.

    Laufwerk anschließen

    Jetzt kann ich mein Laufwerk anschließen und nach Belieben einbinden – in diesem Fall als read-only. Sobald es angeschlossen ist (in diesem Fall über USB), suche ich nach seinem Namen, um es zu mounten . GNU/Linux betrachtet jedes manipulierbare Objekt als Datei, einschließlich Wechseldatenträger. Um es zu identifizieren, verwende ich den Befehl fdisk, der mit seiner Option --list alle Datenträger und Partitionen auflistet, unabhängig davon, ob sie gemountet sind oder nicht:

    $ sudo fdisk --list
    (...)
    Festplatte /dev/sda: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Festplattenmodell: ZIP 250
    Einheiten: 1 × 512 = 512 Bytes pro Sektor
    Sektorgröße (logisch/physisch): 512 Byte/512 Byte
    E/A-Größe (minimal/optimal): 512 Byte/512 Byte
    Festplatten-Typbezeichnung: dos
    Festplatten-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Id Typ
    /dev/sda1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Am Ende einer langen Liste von physischen oder virtuellen Medien, auf die ich von meinem Arbeitsplatz aus Zugriff habe, finde ich also mein Gerät mit seinem kurzen Namen (/dev/sda) und seiner oder seinen Partitionen – hier gibt es nur eine, nämlich /dev/sda1.

    In einem GNU/Linux-System sind alle Geräte im Ordner /dev (für devices) aufgelistet, ebenso wie die Partitionen, die auf jedem einzelnen davon erstellt wurden.

    Als read-only einbinden

    Wir werden nun die Partition des betreffenden Datenträgers mounten (denn wir mounten nicht einen Datenträger, sondern eine „Partition”, das heißt die Aufteilung eines Speicherplatzes in separate Einheiten, die jeweils über ein eigenes Dateisystem verfügen). Hier gibt es nur eine einzige Partition, was uns die Arbeit erleichtert. Das Mounten der Partition(en) eines Datenträgers ist für die Erstellung eines Disk-Images nicht zwingend erforderlich, ermöglicht jedoch das Durchsuchen des Inhalts, um über das weitere Vorgehen zu entscheiden.

    Hier ist die Befehlszeile, die ich verwendet habe:

    sudo mkdir /media/zip_disk && sudo mount --options ro /dev/sda1 $_

    Ich erstelle einen leeren Ordner in /media und mounte dann meine Partition als read-only (--options ro). (Beachten Sie die Abkürzung $_, die das letzte Argument des vorherigen Befehls ersetzt, nämlich /media/zip_disk.)

    Ich habe nun unter meinem Mountpunkt /media/zip_disk Zugriff auf den logischen Inhalt des Disk-Images, das heißt auf die Ordner und Dateien, wie sie auf der ZIP-Diskette zu sehen sind.

    Verwenden eines Schreibschutzes

    Diese Lösung ist bereits recht zufriedenstellend, könnte jedoch in bestimmten Fällen nicht ausreichen. Selbst bei einer Read-Only-Einbindung kann es vorkommen, dass der Befehl mount auf die Festplatte schreibt.
    Im Handbuch zum Befehl heißt es dazu:

    Note that, depending on the filesystem type, state and kernel behavior, the system may still write to the device. For example, ext3 and ext4 will replay the journal if the filesystem is dirty.

    Wenn die Integrität des Erfassungsprozesses nachgewiesen werden muss, insbesondere wenn die Daten in einem rechtlichen Kontext verwendet werden sollen, ist es daher unerlässlich, zusätzliche Vorsichtsmaßnahmen1 zu treffen und einen Schreibblocker zu verwenden. Die Beschreibung dieses Prozesses überlasse ich an dieser Stelle unseren Kollegen vom AIDA Capture Lab in ihrem Datenblatt zu Disketten und ZIP-Laufwerken.

    Erstellen eines Disk-Images

    Warum ein Disk-Image erstellen? Kurz gesagt ermöglicht dies, den binären Inhalt eines Datenträgers so genau wie möglich zu reproduzieren und ihn so zu „dematerialisieren” oder zumindest auf einen anderen Datenträger zu kopieren. Dieser Prozess ist im Bereich der digitalen Forensik, wo der Nachweis der Unverfälschtheit von entscheidender Bedeutung ist, von grundlegender Bedeutung, kann aber auch für die digitale Erhaltung des Kulturerbes erforderlich sein.

    Persönliche Erfahrung: Ich habe ein erstes Image unter Beachtung der oben genannten Vorsichtsmaßnahmen (Einbindung als read-only) erstellt und dann den Inhalt der Festplatte ohne große Vorsicht gesichtet – jedoch ohne die Absicht, ihn zu verändern. Anschließend habe ich ein zweites Image erstellt, das sich als ein Megabyte kleiner als das vorherige herausstellte! Ich kann mir diesen Unterschied nicht erklären, aber er ist erheblich.

    Für die Erstellung eines Disk-Images unter GNU/Linux verweise ich erneut auf die Anweisungen des AIDA Capture Lab, das das Tool Guymager empfiehlt.

    Guymager ist ein Tool zur Erstellung von Disk-Images, das nur unter GNU/Linux funktioniert, aber über eine grafische Benutzeroberfläche verfügt, was es für Personen interessant macht, die mit der Benutzung der Kommandozeile nicht vertraut sind.

    Zu den Einstellungen von Guymager gehört auch das Format des Disk-Images. Das AIDA Capture Lab empfiehlt das Rohformat .dd, bei dem es sich um eine exakte, unkomprimierte Kopie einer Festplatte handelt, die mit dem Tool dd und seinen Derivaten erstellt wird. Es ist jedoch auch möglich, ein komprimiertes Format wie Encase zu wählen, um Speicherplatz zu sparen – es ist zu erwarten, dass das Disk-Image viel freien Speicherplatz enthält, der sich leicht komprimieren lässt. Darüber hinaus ist das Rohformat eine einfache Kopie der Bytes der Festplatte und enthält keine Metadaten, sodass Tools wie Guymager eine weitere Begleitdatei mit der Erweiterung .info erstellen, um Informationen zum Erstellungsprozess des Images zu speichern.

    Es ist auch möglich, ein recht praktisches Befehlszeilen-Tool zum Erstellen eines Disk-Images zu verwenden. Peter Eisner, einer meiner Kollegen bei der TIB, der sich mit dem Erstellen von Disk-Images beschäftigt, hat dc3dd vorgeschlagen. Dabei handelt es sich um eine Ableitung des Unix-Dienstprogramms dd, das vom Department of Defense Cyber Crime Center entwickelt wurde. Es hat den Vorteil, dass es einen digitalen Fingerabdruck des Images erstellt und eine Metadatendatei generiert, in der dieser sowie weitere Informationen zum Erstellungsprozess gespeichert werden.

    Hier ist die von Peter vorgeschlagene Befehlszeile:

    dc3dd if=/dev/sda of=~/disk_images/mydisk.dd hash=md5 log=~/disk_images/mydisk.txt

    Das Ergebnis dieses Vorgangs ist eine Datei mydisk.dd, die eine exakte, unkomprimierte Kopie des Mediums ist – das Image hat also genau die Größe der Festplatte, das heißt 250 Megabyte / 239 Megabyte – und eine Datei mydisk.txt, die das Protokoll des Vorgangs zur Erstellung des Festplatten-Images enthält.

    Das Image mounten, um den Inhalt zu sichten

    Wie eine Support-Partition kann das Disk-Image gemountet werden, um es zu erkunden. Bei einigen GNU/Linux-Distributionen reicht ein Doppelklick auf das Image, um es zu mounten, aber bei meinem „rohen” Ubuntu war das nicht der Fall. Daher musste ich das Image mit folgendem Befehl mounten:

    sudo mkdir ~/zip_image && sudo mount --types vfat --options ro,loop,offset=1048576 mydisk.dd $_

    Diese Befehlszeile erfordert eine Reihe von Parametern:

    • das Dateisystem; hier handelt es sich um vfat, eine Variante der FAT-Dateisysteme für virtuelle Volumes
    • der Start-Offset; Dies ist der Startsektor multipliziert mit der Anzahl der Bytes pro Sektor.

    Diese Informationen erhalten Sie mit dem bereits erwähnten Befehl fdisk -l:

    $ sudo fdisk --list mydisk.dd
    Festplatte mydisk.dd: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Einheiten: Sektor von 1 × 512 = 512 Bytes
    Sektorgröße (logisch/physisch): 512 Bytes/512 Bytes
    E/A-Größe (minimal/optimal): 512 Bytes/512 Bytes
    Typ des Datenträgerlabels: dos
    Datenträger-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Typ
    zip_250_image.dd1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Sie können nun durch die Baumstruktur des Disk-Images navigieren. Dort lassen sich alle gewünschten Erkundungsvorgänge durchführen, ohne Gefahr zu laufen, etwas Wichtiges zu verändern.

    Gelöschte Dateien wiederherstellen

    Wie Sie vielleicht wissen, wird beim Löschen einer Datei auf Ihrem Computer, selbst wenn Sie den Papierkorb leeren, lediglich die Indizierung der Daten aufgehoben: Der Computer vergisst ihre Adresse. Er schreibt an dieser Stelle nur dann erneut, wenn er Platz für weitere Daten benötigt. Daher ist es möglich, gelöschte Daten wiederherzustellen, solange er an dieser Stelle nicht erneut geschrieben hat. Es gibt sicherlich mehrere Möglichkeiten, dies zu tun, aber ich werde Ihnen nur eine davon vorstellen, um es zu demonstrieren.

    Das Tool: PhotoRec

    Ich habe die Tools TestDisk und PhotoRec getestet, die von Christophe Grenier entwickelt wurden und mir von meinem Kollegen Peter Eisner empfohlen wurden. Diese Tools sind einfach zu bedienen; ich werde nur PhotoRec vorstellen, da dieses Tool in meinem Fall zu Ergebnissen geführt hat.

    Sobald das Tool mit dem Befehl sudo photorec mydisk.dd gestartet wurde, erscheint folgender Bildschirm:

    Man wählt das Medium aus …

    … dann die Partition …

    … dann das Dateisystem …

    … man entscheidet, ob die Analyse auf der gesamten Partition oder nur auf dem freien Speicherplatz durchgeführt werden soll …

    … man wählt den Ordner aus, in den die Dateien extrahiert werden sollen, und drückt auf C …

    … und fertig: Das Tool hat einen Ordner namens recup_directory erstellt und dort 360 wiederhergestellte Dateien abgelegt.

    In diesem Ordner wurde ein kleines Stück der Jugendgeschichte meiner Schwester wiederhergestellt: Szenarien für ein Rollenspiel namens Lycéenne, ihre Abschlussarbeit, Scans von Karten der spanischen Kolonialisierung in Südamerika …

    Screenshot des Ordners, in den die wiederhergestellten Dateien extrahiert wurden.

    Die ethischen Fragen, die sich daraus ergeben

    Über die technische Dimension hinaus wirft dies natürlich auch schwierige ethische und rechtliche Fragen auf. Die Wiederherstellung von Dateien, deren Löschung der Eigentümer des Datenträgers gewünscht hat, ist fragwürdig, aber es ist wichtig, dass wir wissen, dass dies möglich ist. Nur so können wir Spendern von Datenträgern klar kommunizieren, was wir oder zukünftige Leser finden könnten, wenn wir diesen Ansatz verfolgen würden3.

    Ein paar abschließende Worte

    Wie ich bereits erwähnt habe, bin ich noch ein Anfänger auf dem Gebiet der digitalen Forensik in Bezug auf Kulturgüter, und zwar aus einem einfachen Grund: Die beiden Institutionen, in denen ich gearbeitet habe (die Bibliothèque nationale de France und die TIB), beginnen gerade erst, ihre Position zu diesem Thema zu definieren.

    Archivar:innen und Bibliothekar:innen stehen zahlreiche Tools zur Verfügung, um diese Techniken anzuwenden. Ich war überrascht, wie einfach sie anzuwenden sind, was im Gegensatz zu den komplexen ethischen und rechtlichen Fragen steht, die sich aus der allgemeinen Erstellung von Disk-Images für die Sammlung von born-digital-Archiven ergeben. Nur Archivar:innen und Bibliothekar:innen können diese Fragen beantworten, aber nur dann, wenn sie die Möglichkeiten der oben genannten technischen Verfahren im Blick haben.

    Auf jeden Fall gelang es Felix, Images der fünf ZIP-Disketten zu erstellen und deren Inhalt zu extrahieren, und wir haben gemeinsam einen bedeutenden Schritt beim Experimentieren mit Disketten-Images gemacht!

    1. Siehe hierzu Kessler (Gary C.) und Carlton (Gregory H.), „A Study of Forensic Imaging in the Absence of Write-Blockers”, in Journal of Digital Forensics, Security and Law, 2014, 9(3), abrufbar unter https://commons.erau.edu/db-security-studies/28 (abgerufen am 22. September 2025).
    2. Um den Nutzen der Erstellung eines Disk-Images gegenüber einer einfachen gesicherten Kopie zu beurteilen, empfehle ich Ihnen die Lektüre des folgenden Dokuments: Digital Archival traNsfer, iNgest, and packagiNg Group, „Disk Imaging Decision Factors”, DANNNG!, [o. J.], abrufbar unter https://dannng.github.io/disk-imaging-decision-factors.html (abgerufen am 23. September 2025).
    3. Siehe hierzu den folgenden Artikel: Lassere (Monique) und Whyte (Jess M.), „Balancing Care and Authenticity in Digital Collections: A Radical Empathy Approach To Working With Disk Images”, Journal of Critical Library and Information Studies, Band 3, Nr. 2 (2021), abrufbar unter https://doi.org/10.24242/jclis.v3i2.125 (abgerufen am 23. September 2025).

    Dieser Beitrag wurde unter Zuhilfenahme von deepl.com durch Felix Burger übersetzt und leicht überarbeitet.

    #ZIPDiskette #WDPD2025 #LizenzCCBY40INT #Langzeitarchivierung #WorldDigitalPreservationDay

  22. Erstellen von ZIP-Disk-Images: ein Erfahrungsbericht zum World Digital Preservation Day 2025

    Der folgende Beitrag ist eine übersetzte und leicht veränderte Version eines ursprünglich am 23. September 2025 in französischer Sprache veröffentlichten Blogbeitrags.

    Vorab eine kleine Anmerkung: Ich bin noch Anfänger auf dem Gebiet der digitalen Forensik. Die Beschäftigung mit dem Thema macht mir viel Spaß, daher nutze ich diese Begeisterung, um meine Abenteuer aufzuschreiben und sie mit Ihnen zu teilen. Ich ziehe es vor, meine Beiträge später zu überarbeiten, anstatt mich zu Beginn zu sehr in das Thema zu vertiefen und dabei den anfänglichen Schwung zu verlieren. Diese Anfangsbegeisterung führt vielleicht zu einem kleinen Dunning-Kruger-Effekt, aber sie spornt mich an.

    Ein wenig Hintergrundinformation

    Vor einigen Wochen erwähnte Felix Burger, einer meiner Kollegen bei der TIB, fünf ZIP-Disketten, die er von Kamel Louafi, einem algerisch-deutschen Architekten, erhalten hatte. Die ZIP-Disketten gehören zu seinem Vorlass, den er der Leibniz Universität Hannover überlassen hatte und deren Inhalt deshalb archiviert werden sollte. Es wurde vermutet, dass diese Disketten Daten zur Neugestaltung des Welfengartens enthalten könnten, in dem sich die Leibniz Universität Hannover befindet.

    Was ist eine ZIP-Diskette?

    Vielleicht haben Sie noch nie eine gesehen. ZIP-Disketten wurden vom Unternehmen Iomega zwischen 1995 und 2003 verkauft. Diese Superdisketten waren mit einer Kapazität von 100, dann 250 und schließlich 750 MB erhältlich, während die Standarddiskette lediglich 1,44 MB fasste. Sie sind dicker als die Standardversion.

    Iomega ZIP 100 Diskette CC BY-SA 4.0 creativecommons.org/licenses/b, via Wikimedia Commons

    Im Gegensatz zu den 3½-Zoll-Disketten verfügen sie jedoch nicht über einen manuellen Schutzmechanismus, also mechanische Schalter, mit denen das Beschreiben verhindert werden konnte. Natürlich benötigt man für die Arbeit mit diesen Disketten ein spezielles Laufwerk, welches an der TIB nicht vorhanden war und nun noch gefunden werden musste. Beim Online-Marktplatz eBay sind zahlreiche Laufwerke für unter 100 Euro erhältlich, aber ihre Eigenschaften und ihr Verschleißgrad sind schwer einzuschätzen. Einer meiner Kollegen hatte ein externes ZIP-Laufwerk, aber dieses funktioniert nur über eine parallele Schnittstelle, über die unsere Arbeitscomputer nicht verfügen. Zufälligerweise hatte ich jedoch kurz zuvor ein neues Laufwerk erhalten, das sowohl für die Datenübertragung als auch für die Stromversorgung USB nutzt und daher sehr praktisch ist. Anlässlich der jährlichen Teambesprechung in Hannover brachte ich dieses charmante Gerät mit.

    Mein USB-Laufwerk: so gut wie neu

    Das Laufwerk anschließen

    Ich begann meine kleinen Experimente im Zug nach Hannover. Ich wollte die Datenwiederherstellung an einer ZIP-Diskette testen, die noch im Laufwerk steckte und einem Familienmitglied gehört hatte. Aber ich wollte die Sache wie unter echten Archivierungsbedingungen angehen – also versuchte ich den Inhalt der Diskette nicht zu verändern. Wie ich bereits in einem früheren Beitrag erwähnte, ist es sehr leicht, den Inhalt eines Wechseldatenträgers unbeabsichtigt zu verändern. Daher ist größte Vorsicht geboten.

    Wenn Sie ein Plug-and-Play-Medium anschließen, können Sie auf dessen Inhalt zugreifen, ohne etwas tun, konfigurieren oder einen Treiber installieren zu müssen. Das ist praktisch, aber der Zugriff erfolgt dabei standardmäßig im Read-Write-Modus, was natürlich das Risiko erhöht, dass der Inhalt der Festplatte verändert wird. Dieses Verhalten wollte ich vermeiden.

    Automatisches Mounten deaktivieren

    Also habe ich (unter Ubuntu) folgenden Befehl eingegeben:

    systemctl stop udisks2.service

    Dieser Befehl deaktiviert vorübergehend – bis zum Neustart des Computers – die automatische Einbindung, das heißt die automatische Konfiguration des Zugriffs auf ein Dateisystem.

    Laufwerk anschließen

    Jetzt kann ich mein Laufwerk anschließen und nach Belieben einbinden – in diesem Fall als read-only. Sobald es angeschlossen ist (in diesem Fall über USB), suche ich nach seinem Namen, um es zu mounten . GNU/Linux betrachtet jedes manipulierbare Objekt als Datei, einschließlich Wechseldatenträger. Um es zu identifizieren, verwende ich den Befehl fdisk, der mit seiner Option --list alle Datenträger und Partitionen auflistet, unabhängig davon, ob sie gemountet sind oder nicht:

    $ sudo fdisk --list
    (...)
    Festplatte /dev/sda: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Festplattenmodell: ZIP 250
    Einheiten: 1 × 512 = 512 Bytes pro Sektor
    Sektorgröße (logisch/physisch): 512 Byte/512 Byte
    E/A-Größe (minimal/optimal): 512 Byte/512 Byte
    Festplatten-Typbezeichnung: dos
    Festplatten-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Id Typ
    /dev/sda1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Am Ende einer langen Liste von physischen oder virtuellen Medien, auf die ich von meinem Arbeitsplatz aus Zugriff habe, finde ich also mein Gerät mit seinem kurzen Namen (/dev/sda) und seiner oder seinen Partitionen – hier gibt es nur eine, nämlich /dev/sda1.

    In einem GNU/Linux-System sind alle Geräte im Ordner /dev (für devices) aufgelistet, ebenso wie die Partitionen, die auf jedem einzelnen davon erstellt wurden.

    Als read-only einbinden

    Wir werden nun die Partition des betreffenden Datenträgers mounten (denn wir mounten nicht einen Datenträger, sondern eine „Partition”, das heißt die Aufteilung eines Speicherplatzes in separate Einheiten, die jeweils über ein eigenes Dateisystem verfügen). Hier gibt es nur eine einzige Partition, was uns die Arbeit erleichtert. Das Mounten der Partition(en) eines Datenträgers ist für die Erstellung eines Disk-Images nicht zwingend erforderlich, ermöglicht jedoch das Durchsuchen des Inhalts, um über das weitere Vorgehen zu entscheiden.

    Hier ist die Befehlszeile, die ich verwendet habe:

    sudo mkdir /media/zip_disk && sudo mount --options ro /dev/sda1 $_

    Ich erstelle einen leeren Ordner in /media und mounte dann meine Partition als read-only (--options ro). (Beachten Sie die Abkürzung $_, die das letzte Argument des vorherigen Befehls ersetzt, nämlich /media/zip_disk.)

    Ich habe nun unter meinem Mountpunkt /media/zip_disk Zugriff auf den logischen Inhalt des Disk-Images, das heißt auf die Ordner und Dateien, wie sie auf der ZIP-Diskette zu sehen sind.

    Verwenden eines Schreibschutzes

    Diese Lösung ist bereits recht zufriedenstellend, könnte jedoch in bestimmten Fällen nicht ausreichen. Selbst bei einer Read-Only-Einbindung kann es vorkommen, dass der Befehl mount auf die Festplatte schreibt.
    Im Handbuch zum Befehl heißt es dazu:

    Note that, depending on the filesystem type, state and kernel behavior, the system may still write to the device. For example, ext3 and ext4 will replay the journal if the filesystem is dirty.

    Wenn die Integrität des Erfassungsprozesses nachgewiesen werden muss, insbesondere wenn die Daten in einem rechtlichen Kontext verwendet werden sollen, ist es daher unerlässlich, zusätzliche Vorsichtsmaßnahmen1 zu treffen und einen Schreibblocker zu verwenden. Die Beschreibung dieses Prozesses überlasse ich an dieser Stelle unseren Kollegen vom AIDA Capture Lab in ihrem Datenblatt zu Disketten und ZIP-Laufwerken.

    Erstellen eines Disk-Images

    Warum ein Disk-Image erstellen? Kurz gesagt ermöglicht dies, den binären Inhalt eines Datenträgers so genau wie möglich zu reproduzieren und ihn so zu „dematerialisieren” oder zumindest auf einen anderen Datenträger zu kopieren. Dieser Prozess ist im Bereich der digitalen Forensik, wo der Nachweis der Unverfälschtheit von entscheidender Bedeutung ist, von grundlegender Bedeutung, kann aber auch für die digitale Erhaltung des Kulturerbes erforderlich sein.

    Persönliche Erfahrung: Ich habe ein erstes Image unter Beachtung der oben genannten Vorsichtsmaßnahmen (Einbindung als read-only) erstellt und dann den Inhalt der Festplatte ohne große Vorsicht gesichtet – jedoch ohne die Absicht, ihn zu verändern. Anschließend habe ich ein zweites Image erstellt, das sich als ein Megabyte kleiner als das vorherige herausstellte! Ich kann mir diesen Unterschied nicht erklären, aber er ist erheblich.

    Für die Erstellung eines Disk-Images unter GNU/Linux verweise ich erneut auf die Anweisungen des AIDA Capture Lab, das das Tool Guymager empfiehlt.

    Guymager ist ein Tool zur Erstellung von Disk-Images, das nur unter GNU/Linux funktioniert, aber über eine grafische Benutzeroberfläche verfügt, was es für Personen interessant macht, die mit der Benutzung der Kommandozeile nicht vertraut sind.

    Zu den Einstellungen von Guymager gehört auch das Format des Disk-Images. Das AIDA Capture Lab empfiehlt das Rohformat .dd, bei dem es sich um eine exakte, unkomprimierte Kopie einer Festplatte handelt, die mit dem Tool dd und seinen Derivaten erstellt wird. Es ist jedoch auch möglich, ein komprimiertes Format wie Encase zu wählen, um Speicherplatz zu sparen – es ist zu erwarten, dass das Disk-Image viel freien Speicherplatz enthält, der sich leicht komprimieren lässt. Darüber hinaus ist das Rohformat eine einfache Kopie der Bytes der Festplatte und enthält keine Metadaten, sodass Tools wie Guymager eine weitere Begleitdatei mit der Erweiterung .info erstellen, um Informationen zum Erstellungsprozess des Images zu speichern.

    Es ist auch möglich, ein recht praktisches Befehlszeilen-Tool zum Erstellen eines Disk-Images zu verwenden. Peter Eisner, einer meiner Kollegen bei der TIB, der sich mit dem Erstellen von Disk-Images beschäftigt, hat dc3dd vorgeschlagen. Dabei handelt es sich um eine Ableitung des Unix-Dienstprogramms dd, das vom Department of Defense Cyber Crime Center entwickelt wurde. Es hat den Vorteil, dass es einen digitalen Fingerabdruck des Images erstellt und eine Metadatendatei generiert, in der dieser sowie weitere Informationen zum Erstellungsprozess gespeichert werden.

    Hier ist die von Peter vorgeschlagene Befehlszeile:

    dc3dd if=/dev/sda of=~/disk_images/mydisk.dd hash=md5 log=~/disk_images/mydisk.txt

    Das Ergebnis dieses Vorgangs ist eine Datei mydisk.dd, die eine exakte, unkomprimierte Kopie des Mediums ist – das Image hat also genau die Größe der Festplatte, das heißt 250 Megabyte / 239 Megabyte – und eine Datei mydisk.txt, die das Protokoll des Vorgangs zur Erstellung des Festplatten-Images enthält.

    Das Image mounten, um den Inhalt zu sichten

    Wie eine Support-Partition kann das Disk-Image gemountet werden, um es zu erkunden. Bei einigen GNU/Linux-Distributionen reicht ein Doppelklick auf das Image, um es zu mounten, aber bei meinem „rohen” Ubuntu war das nicht der Fall. Daher musste ich das Image mit folgendem Befehl mounten:

    sudo mkdir ~/zip_image && sudo mount --types vfat --options ro,loop,offset=1048576 mydisk.dd $_

    Diese Befehlszeile erfordert eine Reihe von Parametern:

    • das Dateisystem; hier handelt es sich um vfat, eine Variante der FAT-Dateisysteme für virtuelle Volumes
    • der Start-Offset; Dies ist der Startsektor multipliziert mit der Anzahl der Bytes pro Sektor.

    Diese Informationen erhalten Sie mit dem bereits erwähnten Befehl fdisk -l:

    $ sudo fdisk --list mydisk.dd
    Festplatte mydisk.dd: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Einheiten: Sektor von 1 × 512 = 512 Bytes
    Sektorgröße (logisch/physisch): 512 Bytes/512 Bytes
    E/A-Größe (minimal/optimal): 512 Bytes/512 Bytes
    Typ des Datenträgerlabels: dos
    Datenträger-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Typ
    zip_250_image.dd1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Sie können nun durch die Baumstruktur des Disk-Images navigieren. Dort lassen sich alle gewünschten Erkundungsvorgänge durchführen, ohne Gefahr zu laufen, etwas Wichtiges zu verändern.

    Gelöschte Dateien wiederherstellen

    Wie Sie vielleicht wissen, wird beim Löschen einer Datei auf Ihrem Computer, selbst wenn Sie den Papierkorb leeren, lediglich die Indizierung der Daten aufgehoben: Der Computer vergisst ihre Adresse. Er schreibt an dieser Stelle nur dann erneut, wenn er Platz für weitere Daten benötigt. Daher ist es möglich, gelöschte Daten wiederherzustellen, solange er an dieser Stelle nicht erneut geschrieben hat. Es gibt sicherlich mehrere Möglichkeiten, dies zu tun, aber ich werde Ihnen nur eine davon vorstellen, um es zu demonstrieren.

    Das Tool: PhotoRec

    Ich habe die Tools TestDisk und PhotoRec getestet, die von Christophe Grenier entwickelt wurden und mir von meinem Kollegen Peter Eisner empfohlen wurden. Diese Tools sind einfach zu bedienen; ich werde nur PhotoRec vorstellen, da dieses Tool in meinem Fall zu Ergebnissen geführt hat.

    Sobald das Tool mit dem Befehl sudo photorec mydisk.dd gestartet wurde, erscheint folgender Bildschirm:

    Man wählt das Medium aus …

    … dann die Partition …

    … dann das Dateisystem …

    … man entscheidet, ob die Analyse auf der gesamten Partition oder nur auf dem freien Speicherplatz durchgeführt werden soll …

    … man wählt den Ordner aus, in den die Dateien extrahiert werden sollen, und drückt auf C …

    … und fertig: Das Tool hat einen Ordner namens recup_directory erstellt und dort 360 wiederhergestellte Dateien abgelegt.

    In diesem Ordner wurde ein kleines Stück der Jugendgeschichte meiner Schwester wiederhergestellt: Szenarien für ein Rollenspiel namens Lycéenne, ihre Abschlussarbeit, Scans von Karten der spanischen Kolonialisierung in Südamerika …

    Screenshot des Ordners, in den die wiederhergestellten Dateien extrahiert wurden.

    Die ethischen Fragen, die sich daraus ergeben

    Über die technische Dimension hinaus wirft dies natürlich auch schwierige ethische und rechtliche Fragen auf. Die Wiederherstellung von Dateien, deren Löschung der Eigentümer des Datenträgers gewünscht hat, ist fragwürdig, aber es ist wichtig, dass wir wissen, dass dies möglich ist. Nur so können wir Spendern von Datenträgern klar kommunizieren, was wir oder zukünftige Leser finden könnten, wenn wir diesen Ansatz verfolgen würden3.

    Ein paar abschließende Worte

    Wie ich bereits erwähnt habe, bin ich noch ein Anfänger auf dem Gebiet der digitalen Forensik in Bezug auf Kulturgüter, und zwar aus einem einfachen Grund: Die beiden Institutionen, in denen ich gearbeitet habe (die Bibliothèque nationale de France und die TIB), beginnen gerade erst, ihre Position zu diesem Thema zu definieren.

    Archivar:innen und Bibliothekar:innen stehen zahlreiche Tools zur Verfügung, um diese Techniken anzuwenden. Ich war überrascht, wie einfach sie anzuwenden sind, was im Gegensatz zu den komplexen ethischen und rechtlichen Fragen steht, die sich aus der allgemeinen Erstellung von Disk-Images für die Sammlung von born-digital-Archiven ergeben. Nur Archivar:innen und Bibliothekar:innen können diese Fragen beantworten, aber nur dann, wenn sie die Möglichkeiten der oben genannten technischen Verfahren im Blick haben.

    Auf jeden Fall gelang es Felix, Images der fünf ZIP-Disketten zu erstellen und deren Inhalt zu extrahieren, und wir haben gemeinsam einen bedeutenden Schritt beim Experimentieren mit Disketten-Images gemacht!

    1. Siehe hierzu Kessler (Gary C.) und Carlton (Gregory H.), „A Study of Forensic Imaging in the Absence of Write-Blockers”, in Journal of Digital Forensics, Security and Law, 2014, 9(3), abrufbar unter https://commons.erau.edu/db-security-studies/28 (abgerufen am 22. September 2025).
    2. Um den Nutzen der Erstellung eines Disk-Images gegenüber einer einfachen gesicherten Kopie zu beurteilen, empfehle ich Ihnen die Lektüre des folgenden Dokuments: Digital Archival traNsfer, iNgest, and packagiNg Group, „Disk Imaging Decision Factors”, DANNNG!, [o. J.], abrufbar unter https://dannng.github.io/disk-imaging-decision-factors.html (abgerufen am 23. September 2025).
    3. Siehe hierzu den folgenden Artikel: Lassere (Monique) und Whyte (Jess M.), „Balancing Care and Authenticity in Digital Collections: A Radical Empathy Approach To Working With Disk Images”, Journal of Critical Library and Information Studies, Band 3, Nr. 2 (2021), abrufbar unter https://doi.org/10.24242/jclis.v3i2.125 (abgerufen am 23. September 2025).

    Dieser Beitrag wurde unter Zuhilfenahme von deepl.com durch Felix Burger übersetzt und leicht überarbeitet.

    #ZIPDiskette #WDPD2025 #LizenzCCBY40INT #Langzeitarchivierung #WorldDigitalPreservationDay

  23. Erstellen von ZIP-Disk-Images: ein Erfahrungsbericht zum World Digital Preservation Day 2025

    Der folgende Beitrag ist eine übersetzte und leicht veränderte Version eines ursprünglich am 23. September 2025 in französischer Sprache veröffentlichten Blogbeitrags.

    Vorab eine kleine Anmerkung: Ich bin noch Anfänger auf dem Gebiet der digitalen Forensik. Die Beschäftigung mit dem Thema macht mir viel Spaß, daher nutze ich diese Begeisterung, um meine Abenteuer aufzuschreiben und sie mit Ihnen zu teilen. Ich ziehe es vor, meine Beiträge später zu überarbeiten, anstatt mich zu Beginn zu sehr in das Thema zu vertiefen und dabei den anfänglichen Schwung zu verlieren. Diese Anfangsbegeisterung führt vielleicht zu einem kleinen Dunning-Kruger-Effekt, aber sie spornt mich an.

    Ein wenig Hintergrundinformation

    Vor einigen Wochen erwähnte Felix Burger, einer meiner Kollegen bei der TIB, fünf ZIP-Disketten, die er von Kamel Louafi, einem algerisch-deutschen Architekten, erhalten hatte. Die ZIP-Disketten gehören zu seinem Vorlass, den er der Leibniz Universität Hannover überlassen hatte und deren Inhalt deshalb archiviert werden sollte. Es wurde vermutet, dass diese Disketten Daten zur Neugestaltung des Welfengartens enthalten könnten, in dem sich die Leibniz Universität Hannover befindet.

    Was ist eine ZIP-Diskette?

    Vielleicht haben Sie noch nie eine gesehen. ZIP-Disketten wurden vom Unternehmen Iomega zwischen 1995 und 2003 verkauft. Diese Superdisketten waren mit einer Kapazität von 100, dann 250 und schließlich 750 MB erhältlich, während die Standarddiskette lediglich 1,44 MB fasste. Sie sind dicker als die Standardversion.

    Iomega ZIP 100 Diskette CC BY-SA 4.0 creativecommons.org/licenses/b, via Wikimedia Commons

    Im Gegensatz zu den 3½-Zoll-Disketten verfügen sie jedoch nicht über einen manuellen Schutzmechanismus, also mechanische Schalter, mit denen das Beschreiben verhindert werden konnte. Natürlich benötigt man für die Arbeit mit diesen Disketten ein spezielles Laufwerk, welches an der TIB nicht vorhanden war und nun noch gefunden werden musste. Beim Online-Marktplatz eBay sind zahlreiche Laufwerke für unter 100 Euro erhältlich, aber ihre Eigenschaften und ihr Verschleißgrad sind schwer einzuschätzen. Einer meiner Kollegen hatte ein externes ZIP-Laufwerk, aber dieses funktioniert nur über eine parallele Schnittstelle, über die unsere Arbeitscomputer nicht verfügen. Zufälligerweise hatte ich jedoch kurz zuvor ein neues Laufwerk erhalten, das sowohl für die Datenübertragung als auch für die Stromversorgung USB nutzt und daher sehr praktisch ist. Anlässlich der jährlichen Teambesprechung in Hannover brachte ich dieses charmante Gerät mit.

    Mein USB-Laufwerk: so gut wie neu

    Das Laufwerk anschließen

    Ich begann meine kleinen Experimente im Zug nach Hannover. Ich wollte die Datenwiederherstellung an einer ZIP-Diskette testen, die noch im Laufwerk steckte und einem Familienmitglied gehört hatte. Aber ich wollte die Sache wie unter echten Archivierungsbedingungen angehen – also versuchte ich den Inhalt der Diskette nicht zu verändern. Wie ich bereits in einem früheren Beitrag erwähnte, ist es sehr leicht, den Inhalt eines Wechseldatenträgers unbeabsichtigt zu verändern. Daher ist größte Vorsicht geboten.

    Wenn Sie ein Plug-and-Play-Medium anschließen, können Sie auf dessen Inhalt zugreifen, ohne etwas tun, konfigurieren oder einen Treiber installieren zu müssen. Das ist praktisch, aber der Zugriff erfolgt dabei standardmäßig im Read-Write-Modus, was natürlich das Risiko erhöht, dass der Inhalt der Festplatte verändert wird. Dieses Verhalten wollte ich vermeiden.

    Automatisches Mounten deaktivieren

    Also habe ich (unter Ubuntu) folgenden Befehl eingegeben:

    systemctl stop udisks2.service

    Dieser Befehl deaktiviert vorübergehend – bis zum Neustart des Computers – die automatische Einbindung, das heißt die automatische Konfiguration des Zugriffs auf ein Dateisystem.

    Laufwerk anschließen

    Jetzt kann ich mein Laufwerk anschließen und nach Belieben einbinden – in diesem Fall als read-only. Sobald es angeschlossen ist (in diesem Fall über USB), suche ich nach seinem Namen, um es zu mounten . GNU/Linux betrachtet jedes manipulierbare Objekt als Datei, einschließlich Wechseldatenträger. Um es zu identifizieren, verwende ich den Befehl fdisk, der mit seiner Option --list alle Datenträger und Partitionen auflistet, unabhängig davon, ob sie gemountet sind oder nicht:

    $ sudo fdisk --list
    (...)
    Festplatte /dev/sda: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Festplattenmodell: ZIP 250
    Einheiten: 1 × 512 = 512 Bytes pro Sektor
    Sektorgröße (logisch/physisch): 512 Byte/512 Byte
    E/A-Größe (minimal/optimal): 512 Byte/512 Byte
    Festplatten-Typbezeichnung: dos
    Festplatten-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Id Typ
    /dev/sda1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Am Ende einer langen Liste von physischen oder virtuellen Medien, auf die ich von meinem Arbeitsplatz aus Zugriff habe, finde ich also mein Gerät mit seinem kurzen Namen (/dev/sda) und seiner oder seinen Partitionen – hier gibt es nur eine, nämlich /dev/sda1.

    In einem GNU/Linux-System sind alle Geräte im Ordner /dev (für devices) aufgelistet, ebenso wie die Partitionen, die auf jedem einzelnen davon erstellt wurden.

    Als read-only einbinden

    Wir werden nun die Partition des betreffenden Datenträgers mounten (denn wir mounten nicht einen Datenträger, sondern eine „Partition”, das heißt die Aufteilung eines Speicherplatzes in separate Einheiten, die jeweils über ein eigenes Dateisystem verfügen). Hier gibt es nur eine einzige Partition, was uns die Arbeit erleichtert. Das Mounten der Partition(en) eines Datenträgers ist für die Erstellung eines Disk-Images nicht zwingend erforderlich, ermöglicht jedoch das Durchsuchen des Inhalts, um über das weitere Vorgehen zu entscheiden.

    Hier ist die Befehlszeile, die ich verwendet habe:

    sudo mkdir /media/zip_disk && sudo mount --options ro /dev/sda1 $_

    Ich erstelle einen leeren Ordner in /media und mounte dann meine Partition als read-only (--options ro). (Beachten Sie die Abkürzung $_, die das letzte Argument des vorherigen Befehls ersetzt, nämlich /media/zip_disk.)

    Ich habe nun unter meinem Mountpunkt /media/zip_disk Zugriff auf den logischen Inhalt des Disk-Images, das heißt auf die Ordner und Dateien, wie sie auf der ZIP-Diskette zu sehen sind.

    Verwenden eines Schreibschutzes

    Diese Lösung ist bereits recht zufriedenstellend, könnte jedoch in bestimmten Fällen nicht ausreichen. Selbst bei einer Read-Only-Einbindung kann es vorkommen, dass der Befehl mount auf die Festplatte schreibt.
    Im Handbuch zum Befehl heißt es dazu:

    Note that, depending on the filesystem type, state and kernel behavior, the system may still write to the device. For example, ext3 and ext4 will replay the journal if the filesystem is dirty.

    Wenn die Integrität des Erfassungsprozesses nachgewiesen werden muss, insbesondere wenn die Daten in einem rechtlichen Kontext verwendet werden sollen, ist es daher unerlässlich, zusätzliche Vorsichtsmaßnahmen1 zu treffen und einen Schreibblocker zu verwenden. Die Beschreibung dieses Prozesses überlasse ich an dieser Stelle unseren Kollegen vom AIDA Capture Lab in ihrem Datenblatt zu Disketten und ZIP-Laufwerken.

    Erstellen eines Disk-Images

    Warum ein Disk-Image erstellen? Kurz gesagt ermöglicht dies, den binären Inhalt eines Datenträgers so genau wie möglich zu reproduzieren und ihn so zu „dematerialisieren” oder zumindest auf einen anderen Datenträger zu kopieren. Dieser Prozess ist im Bereich der digitalen Forensik, wo der Nachweis der Unverfälschtheit von entscheidender Bedeutung ist, von grundlegender Bedeutung, kann aber auch für die digitale Erhaltung des Kulturerbes erforderlich sein.

    Persönliche Erfahrung: Ich habe ein erstes Image unter Beachtung der oben genannten Vorsichtsmaßnahmen (Einbindung als read-only) erstellt und dann den Inhalt der Festplatte ohne große Vorsicht gesichtet – jedoch ohne die Absicht, ihn zu verändern. Anschließend habe ich ein zweites Image erstellt, das sich als ein Megabyte kleiner als das vorherige herausstellte! Ich kann mir diesen Unterschied nicht erklären, aber er ist erheblich.

    Für die Erstellung eines Disk-Images unter GNU/Linux verweise ich erneut auf die Anweisungen des AIDA Capture Lab, das das Tool Guymager empfiehlt.

    Guymager ist ein Tool zur Erstellung von Disk-Images, das nur unter GNU/Linux funktioniert, aber über eine grafische Benutzeroberfläche verfügt, was es für Personen interessant macht, die mit der Benutzung der Kommandozeile nicht vertraut sind.

    Zu den Einstellungen von Guymager gehört auch das Format des Disk-Images. Das AIDA Capture Lab empfiehlt das Rohformat .dd, bei dem es sich um eine exakte, unkomprimierte Kopie einer Festplatte handelt, die mit dem Tool dd und seinen Derivaten erstellt wird. Es ist jedoch auch möglich, ein komprimiertes Format wie Encase zu wählen, um Speicherplatz zu sparen – es ist zu erwarten, dass das Disk-Image viel freien Speicherplatz enthält, der sich leicht komprimieren lässt. Darüber hinaus ist das Rohformat eine einfache Kopie der Bytes der Festplatte und enthält keine Metadaten, sodass Tools wie Guymager eine weitere Begleitdatei mit der Erweiterung .info erstellen, um Informationen zum Erstellungsprozess des Images zu speichern.

    Es ist auch möglich, ein recht praktisches Befehlszeilen-Tool zum Erstellen eines Disk-Images zu verwenden. Peter Eisner, einer meiner Kollegen bei der TIB, der sich mit dem Erstellen von Disk-Images beschäftigt, hat dc3dd vorgeschlagen. Dabei handelt es sich um eine Ableitung des Unix-Dienstprogramms dd, das vom Department of Defense Cyber Crime Center entwickelt wurde. Es hat den Vorteil, dass es einen digitalen Fingerabdruck des Images erstellt und eine Metadatendatei generiert, in der dieser sowie weitere Informationen zum Erstellungsprozess gespeichert werden.

    Hier ist die von Peter vorgeschlagene Befehlszeile:

    dc3dd if=/dev/sda of=~/disk_images/mydisk.dd hash=md5 log=~/disk_images/mydisk.txt

    Das Ergebnis dieses Vorgangs ist eine Datei mydisk.dd, die eine exakte, unkomprimierte Kopie des Mediums ist – das Image hat also genau die Größe der Festplatte, das heißt 250 Megabyte / 239 Megabyte – und eine Datei mydisk.txt, die das Protokoll des Vorgangs zur Erstellung des Festplatten-Images enthält.

    Das Image mounten, um den Inhalt zu sichten

    Wie eine Support-Partition kann das Disk-Image gemountet werden, um es zu erkunden. Bei einigen GNU/Linux-Distributionen reicht ein Doppelklick auf das Image, um es zu mounten, aber bei meinem „rohen” Ubuntu war das nicht der Fall. Daher musste ich das Image mit folgendem Befehl mounten:

    sudo mkdir ~/zip_image && sudo mount --types vfat --options ro,loop,offset=1048576 mydisk.dd $_

    Diese Befehlszeile erfordert eine Reihe von Parametern:

    • das Dateisystem; hier handelt es sich um vfat, eine Variante der FAT-Dateisysteme für virtuelle Volumes
    • der Start-Offset; Dies ist der Startsektor multipliziert mit der Anzahl der Bytes pro Sektor.

    Diese Informationen erhalten Sie mit dem bereits erwähnten Befehl fdisk -l:

    $ sudo fdisk --list mydisk.dd
    Festplatte mydisk.dd: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Einheiten: Sektor von 1 × 512 = 512 Bytes
    Sektorgröße (logisch/physisch): 512 Bytes/512 Bytes
    E/A-Größe (minimal/optimal): 512 Bytes/512 Bytes
    Typ des Datenträgerlabels: dos
    Datenträger-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Typ
    zip_250_image.dd1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Sie können nun durch die Baumstruktur des Disk-Images navigieren. Dort lassen sich alle gewünschten Erkundungsvorgänge durchführen, ohne Gefahr zu laufen, etwas Wichtiges zu verändern.

    Gelöschte Dateien wiederherstellen

    Wie Sie vielleicht wissen, wird beim Löschen einer Datei auf Ihrem Computer, selbst wenn Sie den Papierkorb leeren, lediglich die Indizierung der Daten aufgehoben: Der Computer vergisst ihre Adresse. Er schreibt an dieser Stelle nur dann erneut, wenn er Platz für weitere Daten benötigt. Daher ist es möglich, gelöschte Daten wiederherzustellen, solange er an dieser Stelle nicht erneut geschrieben hat. Es gibt sicherlich mehrere Möglichkeiten, dies zu tun, aber ich werde Ihnen nur eine davon vorstellen, um es zu demonstrieren.

    Das Tool: PhotoRec

    Ich habe die Tools TestDisk und PhotoRec getestet, die von Christophe Grenier entwickelt wurden und mir von meinem Kollegen Peter Eisner empfohlen wurden. Diese Tools sind einfach zu bedienen; ich werde nur PhotoRec vorstellen, da dieses Tool in meinem Fall zu Ergebnissen geführt hat.

    Sobald das Tool mit dem Befehl sudo photorec mydisk.dd gestartet wurde, erscheint folgender Bildschirm:

    Man wählt das Medium aus …

    … dann die Partition …

    … dann das Dateisystem …

    … man entscheidet, ob die Analyse auf der gesamten Partition oder nur auf dem freien Speicherplatz durchgeführt werden soll …

    … man wählt den Ordner aus, in den die Dateien extrahiert werden sollen, und drückt auf C …

    … und fertig: Das Tool hat einen Ordner namens recup_directory erstellt und dort 360 wiederhergestellte Dateien abgelegt.

    In diesem Ordner wurde ein kleines Stück der Jugendgeschichte meiner Schwester wiederhergestellt: Szenarien für ein Rollenspiel namens Lycéenne, ihre Abschlussarbeit, Scans von Karten der spanischen Kolonialisierung in Südamerika …

    Screenshot des Ordners, in den die wiederhergestellten Dateien extrahiert wurden.

    Die ethischen Fragen, die sich daraus ergeben

    Über die technische Dimension hinaus wirft dies natürlich auch schwierige ethische und rechtliche Fragen auf. Die Wiederherstellung von Dateien, deren Löschung der Eigentümer des Datenträgers gewünscht hat, ist fragwürdig, aber es ist wichtig, dass wir wissen, dass dies möglich ist. Nur so können wir Spendern von Datenträgern klar kommunizieren, was wir oder zukünftige Leser finden könnten, wenn wir diesen Ansatz verfolgen würden3.

    Ein paar abschließende Worte

    Wie ich bereits erwähnt habe, bin ich noch ein Anfänger auf dem Gebiet der digitalen Forensik in Bezug auf Kulturgüter, und zwar aus einem einfachen Grund: Die beiden Institutionen, in denen ich gearbeitet habe (die Bibliothèque nationale de France und die TIB), beginnen gerade erst, ihre Position zu diesem Thema zu definieren.

    Archivar:innen und Bibliothekar:innen stehen zahlreiche Tools zur Verfügung, um diese Techniken anzuwenden. Ich war überrascht, wie einfach sie anzuwenden sind, was im Gegensatz zu den komplexen ethischen und rechtlichen Fragen steht, die sich aus der allgemeinen Erstellung von Disk-Images für die Sammlung von born-digital-Archiven ergeben. Nur Archivar:innen und Bibliothekar:innen können diese Fragen beantworten, aber nur dann, wenn sie die Möglichkeiten der oben genannten technischen Verfahren im Blick haben.

    Auf jeden Fall gelang es Felix, Images der fünf ZIP-Disketten zu erstellen und deren Inhalt zu extrahieren, und wir haben gemeinsam einen bedeutenden Schritt beim Experimentieren mit Disketten-Images gemacht!

    1. Siehe hierzu Kessler (Gary C.) und Carlton (Gregory H.), „A Study of Forensic Imaging in the Absence of Write-Blockers”, in Journal of Digital Forensics, Security and Law, 2014, 9(3), abrufbar unter https://commons.erau.edu/db-security-studies/28 (abgerufen am 22. September 2025).
    2. Um den Nutzen der Erstellung eines Disk-Images gegenüber einer einfachen gesicherten Kopie zu beurteilen, empfehle ich Ihnen die Lektüre des folgenden Dokuments: Digital Archival traNsfer, iNgest, and packagiNg Group, „Disk Imaging Decision Factors”, DANNNG!, [o. J.], abrufbar unter https://dannng.github.io/disk-imaging-decision-factors.html (abgerufen am 23. September 2025).
    3. Siehe hierzu den folgenden Artikel: Lassere (Monique) und Whyte (Jess M.), „Balancing Care and Authenticity in Digital Collections: A Radical Empathy Approach To Working With Disk Images”, Journal of Critical Library and Information Studies, Band 3, Nr. 2 (2021), abrufbar unter https://doi.org/10.24242/jclis.v3i2.125 (abgerufen am 23. September 2025).

    Dieser Beitrag wurde unter Zuhilfenahme von deepl.com durch Felix Burger übersetzt und leicht überarbeitet.

    #ZIPDiskette #WDPD2025 #LizenzCCBY40INT #Langzeitarchivierung #WorldDigitalPreservationDay

  24. Erstellen von ZIP-Disk-Images: ein Erfahrungsbericht zum World Digital Preservation Day 2025

    Der folgende Beitrag ist eine übersetzte und leicht veränderte Version eines ursprünglich am 23. September 2025 in französischer Sprache veröffentlichten Blogbeitrags.

    Vorab eine kleine Anmerkung: Ich bin noch Anfänger auf dem Gebiet der digitalen Forensik. Die Beschäftigung mit dem Thema macht mir viel Spaß, daher nutze ich diese Begeisterung, um meine Abenteuer aufzuschreiben und sie mit Ihnen zu teilen. Ich ziehe es vor, meine Beiträge später zu überarbeiten, anstatt mich zu Beginn zu sehr in das Thema zu vertiefen und dabei den anfänglichen Schwung zu verlieren. Diese Anfangsbegeisterung führt vielleicht zu einem kleinen Dunning-Kruger-Effekt, aber sie spornt mich an.

    Ein wenig Hintergrundinformation

    Vor einigen Wochen erwähnte Felix Burger, einer meiner Kollegen bei der TIB, fünf ZIP-Disketten, die er von Kamel Louafi, einem algerisch-deutschen Architekten, erhalten hatte. Die ZIP-Disketten gehören zu seinem Vorlass, den er der Leibniz Universität Hannover überlassen hatte und deren Inhalt deshalb archiviert werden sollte. Es wurde vermutet, dass diese Disketten Daten zur Neugestaltung des Welfengartens enthalten könnten, in dem sich die Leibniz Universität Hannover befindet.

    Was ist eine ZIP-Diskette?

    Vielleicht haben Sie noch nie eine gesehen. ZIP-Disketten wurden vom Unternehmen Iomega zwischen 1995 und 2003 verkauft. Diese Superdisketten waren mit einer Kapazität von 100, dann 250 und schließlich 750 MB erhältlich, während die Standarddiskette lediglich 1,44 MB fasste. Sie sind dicker als die Standardversion.

    Iomega ZIP 100 Diskette CC BY-SA 4.0 creativecommons.org/licenses/b, via Wikimedia Commons

    Im Gegensatz zu den 3½-Zoll-Disketten verfügen sie jedoch nicht über einen manuellen Schutzmechanismus, also mechanische Schalter, mit denen das Beschreiben verhindert werden konnte. Natürlich benötigt man für die Arbeit mit diesen Disketten ein spezielles Laufwerk, welches an der TIB nicht vorhanden war und nun noch gefunden werden musste. Beim Online-Marktplatz eBay sind zahlreiche Laufwerke für unter 100 Euro erhältlich, aber ihre Eigenschaften und ihr Verschleißgrad sind schwer einzuschätzen. Einer meiner Kollegen hatte ein externes ZIP-Laufwerk, aber dieses funktioniert nur über eine parallele Schnittstelle, über die unsere Arbeitscomputer nicht verfügen. Zufälligerweise hatte ich jedoch kurz zuvor ein neues Laufwerk erhalten, das sowohl für die Datenübertragung als auch für die Stromversorgung USB nutzt und daher sehr praktisch ist. Anlässlich der jährlichen Teambesprechung in Hannover brachte ich dieses charmante Gerät mit.

    Mein USB-Laufwerk: so gut wie neu

    Das Laufwerk anschließen

    Ich begann meine kleinen Experimente im Zug nach Hannover. Ich wollte die Datenwiederherstellung an einer ZIP-Diskette testen, die noch im Laufwerk steckte und einem Familienmitglied gehört hatte. Aber ich wollte die Sache wie unter echten Archivierungsbedingungen angehen – also versuchte ich den Inhalt der Diskette nicht zu verändern. Wie ich bereits in einem früheren Beitrag erwähnte, ist es sehr leicht, den Inhalt eines Wechseldatenträgers unbeabsichtigt zu verändern. Daher ist größte Vorsicht geboten.

    Wenn Sie ein Plug-and-Play-Medium anschließen, können Sie auf dessen Inhalt zugreifen, ohne etwas tun, konfigurieren oder einen Treiber installieren zu müssen. Das ist praktisch, aber der Zugriff erfolgt dabei standardmäßig im Read-Write-Modus, was natürlich das Risiko erhöht, dass der Inhalt der Festplatte verändert wird. Dieses Verhalten wollte ich vermeiden.

    Automatisches Mounten deaktivieren

    Also habe ich (unter Ubuntu) folgenden Befehl eingegeben:

    systemctl stop udisks2.service

    Dieser Befehl deaktiviert vorübergehend – bis zum Neustart des Computers – die automatische Einbindung, das heißt die automatische Konfiguration des Zugriffs auf ein Dateisystem.

    Laufwerk anschließen

    Jetzt kann ich mein Laufwerk anschließen und nach Belieben einbinden – in diesem Fall als read-only. Sobald es angeschlossen ist (in diesem Fall über USB), suche ich nach seinem Namen, um es zu mounten . GNU/Linux betrachtet jedes manipulierbare Objekt als Datei, einschließlich Wechseldatenträger. Um es zu identifizieren, verwende ich den Befehl fdisk, der mit seiner Option --list alle Datenträger und Partitionen auflistet, unabhängig davon, ob sie gemountet sind oder nicht:

    $ sudo fdisk --list
    (...)
    Festplatte /dev/sda: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Festplattenmodell: ZIP 250
    Einheiten: 1 × 512 = 512 Bytes pro Sektor
    Sektorgröße (logisch/physisch): 512 Byte/512 Byte
    E/A-Größe (minimal/optimal): 512 Byte/512 Byte
    Festplatten-Typbezeichnung: dos
    Festplatten-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Id Typ
    /dev/sda1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Am Ende einer langen Liste von physischen oder virtuellen Medien, auf die ich von meinem Arbeitsplatz aus Zugriff habe, finde ich also mein Gerät mit seinem kurzen Namen (/dev/sda) und seiner oder seinen Partitionen – hier gibt es nur eine, nämlich /dev/sda1.

    In einem GNU/Linux-System sind alle Geräte im Ordner /dev (für devices) aufgelistet, ebenso wie die Partitionen, die auf jedem einzelnen davon erstellt wurden.

    Als read-only einbinden

    Wir werden nun die Partition des betreffenden Datenträgers mounten (denn wir mounten nicht einen Datenträger, sondern eine „Partition”, das heißt die Aufteilung eines Speicherplatzes in separate Einheiten, die jeweils über ein eigenes Dateisystem verfügen). Hier gibt es nur eine einzige Partition, was uns die Arbeit erleichtert. Das Mounten der Partition(en) eines Datenträgers ist für die Erstellung eines Disk-Images nicht zwingend erforderlich, ermöglicht jedoch das Durchsuchen des Inhalts, um über das weitere Vorgehen zu entscheiden.

    Hier ist die Befehlszeile, die ich verwendet habe:

    sudo mkdir /media/zip_disk && sudo mount --options ro /dev/sda1 $_

    Ich erstelle einen leeren Ordner in /media und mounte dann meine Partition als read-only (--options ro). (Beachten Sie die Abkürzung $_, die das letzte Argument des vorherigen Befehls ersetzt, nämlich /media/zip_disk.)

    Ich habe nun unter meinem Mountpunkt /media/zip_disk Zugriff auf den logischen Inhalt des Disk-Images, das heißt auf die Ordner und Dateien, wie sie auf der ZIP-Diskette zu sehen sind.

    Verwenden eines Schreibschutzes

    Diese Lösung ist bereits recht zufriedenstellend, könnte jedoch in bestimmten Fällen nicht ausreichen. Selbst bei einer Read-Only-Einbindung kann es vorkommen, dass der Befehl mount auf die Festplatte schreibt.
    Im Handbuch zum Befehl heißt es dazu:

    Note that, depending on the filesystem type, state and kernel behavior, the system may still write to the device. For example, ext3 and ext4 will replay the journal if the filesystem is dirty.

    Wenn die Integrität des Erfassungsprozesses nachgewiesen werden muss, insbesondere wenn die Daten in einem rechtlichen Kontext verwendet werden sollen, ist es daher unerlässlich, zusätzliche Vorsichtsmaßnahmen1 zu treffen und einen Schreibblocker zu verwenden. Die Beschreibung dieses Prozesses überlasse ich an dieser Stelle unseren Kollegen vom AIDA Capture Lab in ihrem Datenblatt zu Disketten und ZIP-Laufwerken.

    Erstellen eines Disk-Images

    Warum ein Disk-Image erstellen? Kurz gesagt ermöglicht dies, den binären Inhalt eines Datenträgers so genau wie möglich zu reproduzieren und ihn so zu „dematerialisieren” oder zumindest auf einen anderen Datenträger zu kopieren. Dieser Prozess ist im Bereich der digitalen Forensik, wo der Nachweis der Unverfälschtheit von entscheidender Bedeutung ist, von grundlegender Bedeutung, kann aber auch für die digitale Erhaltung des Kulturerbes erforderlich sein.

    Persönliche Erfahrung: Ich habe ein erstes Image unter Beachtung der oben genannten Vorsichtsmaßnahmen (Einbindung als read-only) erstellt und dann den Inhalt der Festplatte ohne große Vorsicht gesichtet – jedoch ohne die Absicht, ihn zu verändern. Anschließend habe ich ein zweites Image erstellt, das sich als ein Megabyte kleiner als das vorherige herausstellte! Ich kann mir diesen Unterschied nicht erklären, aber er ist erheblich.

    Für die Erstellung eines Disk-Images unter GNU/Linux verweise ich erneut auf die Anweisungen des AIDA Capture Lab, das das Tool Guymager empfiehlt.

    Guymager ist ein Tool zur Erstellung von Disk-Images, das nur unter GNU/Linux funktioniert, aber über eine grafische Benutzeroberfläche verfügt, was es für Personen interessant macht, die mit der Benutzung der Kommandozeile nicht vertraut sind.

    Zu den Einstellungen von Guymager gehört auch das Format des Disk-Images. Das AIDA Capture Lab empfiehlt das Rohformat .dd, bei dem es sich um eine exakte, unkomprimierte Kopie einer Festplatte handelt, die mit dem Tool dd und seinen Derivaten erstellt wird. Es ist jedoch auch möglich, ein komprimiertes Format wie Encase zu wählen, um Speicherplatz zu sparen – es ist zu erwarten, dass das Disk-Image viel freien Speicherplatz enthält, der sich leicht komprimieren lässt. Darüber hinaus ist das Rohformat eine einfache Kopie der Bytes der Festplatte und enthält keine Metadaten, sodass Tools wie Guymager eine weitere Begleitdatei mit der Erweiterung .info erstellen, um Informationen zum Erstellungsprozess des Images zu speichern.

    Es ist auch möglich, ein recht praktisches Befehlszeilen-Tool zum Erstellen eines Disk-Images zu verwenden. Peter Eisner, einer meiner Kollegen bei der TIB, der sich mit dem Erstellen von Disk-Images beschäftigt, hat dc3dd vorgeschlagen. Dabei handelt es sich um eine Ableitung des Unix-Dienstprogramms dd, das vom Department of Defense Cyber Crime Center entwickelt wurde. Es hat den Vorteil, dass es einen digitalen Fingerabdruck des Images erstellt und eine Metadatendatei generiert, in der dieser sowie weitere Informationen zum Erstellungsprozess gespeichert werden.

    Hier ist die von Peter vorgeschlagene Befehlszeile:

    dc3dd if=/dev/sda of=~/disk_images/mydisk.dd hash=md5 log=~/disk_images/mydisk.txt

    Das Ergebnis dieses Vorgangs ist eine Datei mydisk.dd, die eine exakte, unkomprimierte Kopie des Mediums ist – das Image hat also genau die Größe der Festplatte, das heißt 250 Megabyte / 239 Megabyte – und eine Datei mydisk.txt, die das Protokoll des Vorgangs zur Erstellung des Festplatten-Images enthält.

    Das Image mounten, um den Inhalt zu sichten

    Wie eine Support-Partition kann das Disk-Image gemountet werden, um es zu erkunden. Bei einigen GNU/Linux-Distributionen reicht ein Doppelklick auf das Image, um es zu mounten, aber bei meinem „rohen” Ubuntu war das nicht der Fall. Daher musste ich das Image mit folgendem Befehl mounten:

    sudo mkdir ~/zip_image && sudo mount --types vfat --options ro,loop,offset=1048576 mydisk.dd $_

    Diese Befehlszeile erfordert eine Reihe von Parametern:

    • das Dateisystem; hier handelt es sich um vfat, eine Variante der FAT-Dateisysteme für virtuelle Volumes
    • der Start-Offset; Dies ist der Startsektor multipliziert mit der Anzahl der Bytes pro Sektor.

    Diese Informationen erhalten Sie mit dem bereits erwähnten Befehl fdisk -l:

    $ sudo fdisk --list mydisk.dd
    Festplatte mydisk.dd: 239,03 MiB, 250640384 Bytes, 489532 Sektoren
    Einheiten: Sektor von 1 × 512 = 512 Bytes
    Sektorgröße (logisch/physisch): 512 Bytes/512 Bytes
    E/A-Größe (minimal/optimal): 512 Bytes/512 Bytes
    Typ des Datenträgerlabels: dos
    Datenträger-ID: 0xd8e9a7f7

    Gerät Boot Start Ende Sektoren Größe Typ
    zip_250_image.dd1 2048 489471 487424 238M c W95 FAT32 (LBA)

    Sie können nun durch die Baumstruktur des Disk-Images navigieren. Dort lassen sich alle gewünschten Erkundungsvorgänge durchführen, ohne Gefahr zu laufen, etwas Wichtiges zu verändern.

    Gelöschte Dateien wiederherstellen

    Wie Sie vielleicht wissen, wird beim Löschen einer Datei auf Ihrem Computer, selbst wenn Sie den Papierkorb leeren, lediglich die Indizierung der Daten aufgehoben: Der Computer vergisst ihre Adresse. Er schreibt an dieser Stelle nur dann erneut, wenn er Platz für weitere Daten benötigt. Daher ist es möglich, gelöschte Daten wiederherzustellen, solange er an dieser Stelle nicht erneut geschrieben hat. Es gibt sicherlich mehrere Möglichkeiten, dies zu tun, aber ich werde Ihnen nur eine davon vorstellen, um es zu demonstrieren.

    Das Tool: PhotoRec

    Ich habe die Tools TestDisk und PhotoRec getestet, die von Christophe Grenier entwickelt wurden und mir von meinem Kollegen Peter Eisner empfohlen wurden. Diese Tools sind einfach zu bedienen; ich werde nur PhotoRec vorstellen, da dieses Tool in meinem Fall zu Ergebnissen geführt hat.

    Sobald das Tool mit dem Befehl sudo photorec mydisk.dd gestartet wurde, erscheint folgender Bildschirm:

    Man wählt das Medium aus …

    … dann die Partition …

    … dann das Dateisystem …

    … man entscheidet, ob die Analyse auf der gesamten Partition oder nur auf dem freien Speicherplatz durchgeführt werden soll …

    … man wählt den Ordner aus, in den die Dateien extrahiert werden sollen, und drückt auf C …

    … und fertig: Das Tool hat einen Ordner namens recup_directory erstellt und dort 360 wiederhergestellte Dateien abgelegt.

    In diesem Ordner wurde ein kleines Stück der Jugendgeschichte meiner Schwester wiederhergestellt: Szenarien für ein Rollenspiel namens Lycéenne, ihre Abschlussarbeit, Scans von Karten der spanischen Kolonialisierung in Südamerika …

    Screenshot des Ordners, in den die wiederhergestellten Dateien extrahiert wurden.

    Die ethischen Fragen, die sich daraus ergeben

    Über die technische Dimension hinaus wirft dies natürlich auch schwierige ethische und rechtliche Fragen auf. Die Wiederherstellung von Dateien, deren Löschung der Eigentümer des Datenträgers gewünscht hat, ist fragwürdig, aber es ist wichtig, dass wir wissen, dass dies möglich ist. Nur so können wir Spendern von Datenträgern klar kommunizieren, was wir oder zukünftige Leser finden könnten, wenn wir diesen Ansatz verfolgen würden3.

    Ein paar abschließende Worte

    Wie ich bereits erwähnt habe, bin ich noch ein Anfänger auf dem Gebiet der digitalen Forensik in Bezug auf Kulturgüter, und zwar aus einem einfachen Grund: Die beiden Institutionen, in denen ich gearbeitet habe (die Bibliothèque nationale de France und die TIB), beginnen gerade erst, ihre Position zu diesem Thema zu definieren.

    Archivar:innen und Bibliothekar:innen stehen zahlreiche Tools zur Verfügung, um diese Techniken anzuwenden. Ich war überrascht, wie einfach sie anzuwenden sind, was im Gegensatz zu den komplexen ethischen und rechtlichen Fragen steht, die sich aus der allgemeinen Erstellung von Disk-Images für die Sammlung von born-digital-Archiven ergeben. Nur Archivar:innen und Bibliothekar:innen können diese Fragen beantworten, aber nur dann, wenn sie die Möglichkeiten der oben genannten technischen Verfahren im Blick haben.

    Auf jeden Fall gelang es Felix, Images der fünf ZIP-Disketten zu erstellen und deren Inhalt zu extrahieren, und wir haben gemeinsam einen bedeutenden Schritt beim Experimentieren mit Disketten-Images gemacht!

    1. Siehe hierzu Kessler (Gary C.) und Carlton (Gregory H.), „A Study of Forensic Imaging in the Absence of Write-Blockers”, in Journal of Digital Forensics, Security and Law, 2014, 9(3), abrufbar unter https://commons.erau.edu/db-security-studies/28 (abgerufen am 22. September 2025).
    2. Um den Nutzen der Erstellung eines Disk-Images gegenüber einer einfachen gesicherten Kopie zu beurteilen, empfehle ich Ihnen die Lektüre des folgenden Dokuments: Digital Archival traNsfer, iNgest, and packagiNg Group, „Disk Imaging Decision Factors”, DANNNG!, [o. J.], abrufbar unter https://dannng.github.io/disk-imaging-decision-factors.html (abgerufen am 23. September 2025).
    3. Siehe hierzu den folgenden Artikel: Lassere (Monique) und Whyte (Jess M.), „Balancing Care and Authenticity in Digital Collections: A Radical Empathy Approach To Working With Disk Images”, Journal of Critical Library and Information Studies, Band 3, Nr. 2 (2021), abrufbar unter https://doi.org/10.24242/jclis.v3i2.125 (abgerufen am 23. September 2025).

    Dieser Beitrag wurde unter Zuhilfenahme von deepl.com durch Felix Burger übersetzt und leicht überarbeitet.

    #ZIPDiskette #WDPD2025 #LizenzCCBY40INT #Langzeitarchivierung #WorldDigitalPreservationDay

  25. Hackspace LED Panels

    I was lucky enough to get some 16×64 LED Panels in a Hackspace giveaway, courtesy of Limehouse Labs, London, but have only recently started to look at how to use them.

    As usual, these are my “notes to self” after attempting to use the suggested libraries and not really getting how they work, so I ended up doing what I often do – reinventing this particular wheel so I really understand what is going on.

    https://makertube.net/w/uMhG7dcEs9D5BYmsXF7MVK

    References:

    And the main devices on the panels are the MBI5034 shift register ICs.

    Introduction

    The best description of the bit stream required to drive them can be found here: https://wiki.london.hackspace.org.uk/view/LED_tiles_V2

    It is a bit complicated…

    • There are two address lines, which feed into a HC138 3 to 8 line decoder (the third input is ignored), so together they select one of four blocks of four lines of LEDs.
    • There are two data lines into the MBI5034 shift registers, 24 per line, which access the top and bottom half of the display in turn.
    • A full stream of data covers two full lines of 64 RGB LEDs.
    • Data has to be sent to individual R, G and B LEDs.

    The general idea is to send the bit pattern for both D1 and D2 at the same time for a specific address (0, 1, 2 or 3) and keep clocking the appropriate bits out to the device. Then change the address and do it again until all four addresses have been covered.

    The address isn’t really an address as such – it is more of a matrix “scan line” in that the LEDs are matrixed so that only the LEDS with the common line corresponding to that “address” will be activated at any one time. As there are four lines, the whole panel can only be scanned using persistence of vision, illuminating each scan line in turn.

    To drive multiple panels means adding their D1 and D2 lines to the system too, but sharing all other signals. Most approaches I’ve seen encode all 8 bits or each of the eight Dn lines into a single byte and then sent those out in parallel to four panels at the same time.

    If the data is stored in a frame buffer in “4 panel Dn ready format” then driving four panels isn’t really that much slower than driving one.

    Some numbers:

    • There are 16 x 64 RGB LEDs per panel = 1024 RGB LEDs.
    • Each RGB LED is actually three individual R, G and B LEDs, so there are 3072 LEDs to drive per panel.
    • Each MBI5034 has 16 outputs, so can drive 16 individual LEDs directly.
    • There are 48 MBI5034 chips per panel, 24 per data line, so they have to drive 64 LEDs each…

    So on that last point – as already mentioned, the 74HC138 8-line decoder links the address lines A0, A1 to four outputs (Y0, Y1, Y2, Y3). This is used to “select” one of four blocks of 16 LEDs per MBI5034. Once each address has been scanned, each MBI5034 can be seen to be driving the equivalent of 4 rows of 16 LEDs in total, which is the required 64 LEDs each.

    Apparently each MBI5034 will directly address a single LED colour: R, G or B. So 48 of these, driving 16 R, 16 B, 16 G means they can directly address 768 LEDs, or 256 R, G, and B LEDs. Again, doing this four times gives the full 1024 RGB LED panel.

    This all means that the panel is logically arranged as two 128 x 4 matrices, physically arranged across two rows of 64 LEDs each. The full 16 rows of 64 LEDS are selected by the following combinations of D1, D2, A0, A1:

    A0A1D1 = 1D2 = 100Rows 0, 4Rows 8, 1201Rows 1, 5Rows 9, 1310Rows 2, 6Rows 10, 1411Rows 3, 7Rows 11, 15

    A further complication is that each row itself is encoded not as 2 sets of 64 RGB values, but as 8 sets of [16-bit B + 16-bit R + 16 bit G] values with the 16-bit B, G, R values encoding 8 of each colour LED on the first row, and then 8 on the second row.

    The upshot of all this is that 384 bits of data must be streamed out to the shift registers for each address, but only two lines per half-panel can be illuminated at any one time. As I say, persistence of vision is required to illuminate the entire panel.

    The basic algorithm required to display something on the panel will thus be as follows:

    FOR EACH bank (address = 0, 1, 2, 3):
    Clock out 384 bits of BGR data covering two rows of 64 LEDs.
    Do this for both D1 and D2 at the same time, so illuminating four rows in total.
    IF using more than one panel, also do this for D1 and D2 for all other panels too

    Hardware

    I had some of the interface PCBs made, that were described here: https://github.com/limehouselabs/led-screens/tree/main/panel-connector

    The central block is mapped over to a JST PH 8-way connector as follows:

    D1LATA1N/CD2OEA0CLK

    JST PH Connector:

    • GND
    • CLK
    • LAT
    • OE
    • A1
    • A0
    • D2
    • D1

    The board provides screw terminals for a higher current 5V supply.

    Various estimates suggest one panel could require up to 8A with all LEDS on at full brightness, so I’m using a 40A 5V supply. The main issue is ensuring the Arduino’s GND and the GND of the power supply are linked, which this PCB does.

    Arduino “Shield”

    After getting fed up with jumper wires falling out of solderless breadboards, I eventually soldered up a simple Arduino proto shield able to support up to four panels.

    This maps the panel signals onto Arduino pins as follows:

    ArduinoPanel(s)A0A0 (all panels)A1A1 (all panels)A2CLK (all panels)A3LAT (all panels)A4OE (all panels)D4D5 (D1 panel 3)D5D6 (D2 panel 3)D6D7 (D1 panel 4)D7D8 (D2 panel 4)D8D1 (D1 panel 1)D9D2 (D2 panel 1)D10D3 (D1 panel 2)D11D4 (D2 panel 2)

    The slightly odd mapping of Arduino digital outputs to panels will become clear when we look at the code.

    Using this with a ready-made JST PH connector-to-jumper-wire cable and then crimping Dupont header pins onto it seems to do the job (or so I thought).

    Driver Code

    I started with the Arduino code linked to above. This is written for an ATMega32U4 based Arduino and uses direct Port IO to access the panels.

    I wanted to use an Uno or Nano, so I started to port this over to an ATMega328, but just could not get anything working at all, so in the end I decided to go back to basics and rewrite the code from first principles so I knew what was going on.

    The basic design of the code will be as follows:

    • An interrupt-driven routine to take a buffer representing each LED that is already in the correct format for the panels, and streams this data out to the panels on a regular basis.
    • As mentioned, a frame buffer that can be written to that is already “panel aware”, but has a simple interface using (x, y, colour) to set a pixel.
    • Use direct PORTIO where possible to ensure quick updating of the signals when streaming out to the panels.

    Driving Four Panels at Once

    All signals apart from D1 and D2 are common to both halves of each panel. This means that once the code has processed the address signals, LAT, CLK and OE, there is no reason not to then process D1 and D2 for all existing panels in parallel.

    This can be done pretty efficiently on an Arduino by mapping the eight Dn signals onto a single Arduino port and using PORT IO to write out all four values at once.

    It isn’t quite that simple however, as there isn’t a single 8-bit port on an Arduino that isn’t used for something else too, so I’m going to do it in two halves, using PORTB and PORTD as follows:

    Panel DnArduino DnArduino PORTP1 D18PORTB 0P1 D29PORTB 1P2 D110PORTB 2P2 D211PORTB 3P3 D14PORTD 4P3 D25PORTD 5P4 D16PORTD 6P4 D27PORTD 7

    Using this mapping, an 8-bit value can be stored in the framebuffer per LED as follows:

        b7  6  5  4  3  2  1  0
    D8 D7 D6 D5 D4 D3 D2 D1
    P4 P3 P2 P1

    And then when it comes to writing it out via the Arduino digital IO it can be done in two instructions:

      PORTB = (PORTB & (~0x0F)) | (data & 0x0F);
    PORTD = (PORTD & (~0xF0)) | (data & 0xF0);

    This is mapping the low 4 bits of the data value onto the low 4 bits of PORTB and the top 4 bits of the data value onto the top 4 bits of PORTD.

    The Writing Protocol

    Implementing the protocol described in the various references, I’m after the following basic structure:

    • Clock out the data on all 8 Dn lines using PORTIO.
    • Blank the screen and LATch the data.
    • Set A0/A1 accordingly to select the correct row of LEDs via the matrix.
    • Unblank the screen.

    The entire routine for updating the display is as follows.

    void panelScan (void) {
    for (int i=0; i<FB_BITS; i++) {
    setDataOutput(fb[bank][i]);
    // Pulse the clock
    CLKSET;
    CLKCLR;
    }

    // Blank display
    OESET; // active LOW

    // Set address
    SETADDR(bank);

    // Toggle latch
    LATSET;
    LATCLR;

    // Unblank display
    OECLR; // Active LOW

    bank++;
    if (bank >= FB_BANKS) bank = 0;
    }

    This processes a single address per scan, so four scans are required, with persistence of vision, to illuminate the entire display.

    The various macros, such as CLKSET, CLKCLR and so on, are defined for individual bit manipulation PORTIO as follows:

    #define CLKSET {PORTC = (PORTC & (~0x04)) | 0x04;}  // A2
    #define CLKCLR {PORTC = (PORTC & (~0x04)) ;}

    SETADDR is a special macro that sets both A0 and A1 at the same time.

    #define SETADDR(x) {PORTC = (PORTC & (~0x03)) | (x & 0x03);} // A0/A1

    setDataOutput() is an inline routine that has the two previously mentioned lines in it to set PORTB and PORTD.

    The Framebuffer

    There is one unexplained item in that previous routine. The value passed into setDataOutput is an entry from the frame buffer – the “panel ready data format” I mentioned previously.

    Here is my description of how the framebuffer works from the code itself followed by my setPixel routine that implements it.

    //  The panel is addressed as a string of bits, representing 64 R,G,B values.
    // but the ordering is a little odd.
    //
    // For each address (A1/A0) a string of bits represents two rows of LEDs.
    // 64 * 2 * 3 = 384 bits of information.
    //
    // Ordering is as follows:
    // [ BBBBBBBB BBBBBBBB GGGGGGGG GGGGGGGG RRRRRRRR RRRRRRRR ] * 16
    // Row0 0-7 Row4 0-7 Row0 0-7 Row4 0-7 Row0 0-7 Row4 0-7 Repeat for 8-15,16-23,24-31
    //
    // This addresses rows 0 and 4 when A1/A0 = 00:
    // A1 A0 1st Row 2nd Row
    // 0 0 0 4
    // 0 1 1 5
    // 1 0 2 6
    // 1 1 3 7
    //
    // The bit data is streamed out on D1 for the top half of the panel.
    // The same principle and format bit stream is streamed out on D2 for the second half.
    // Any additional panels will have their own D1/D2 lines and the same format bit streams.
    //
    // All this means that the (x,y) coordinates must map onto the frame buffer as follows:
    // y = b76543210
    // ++--- A1/A0 lines 0-3
    // +----- First or second row
    // +------ D1 or D2
    // ++------- Panel number for four panels 0-3
    // ++--------- Only required if more than four panels (up to 16)
    //
    // x = b76543210
    // +++--- Position within a block of 8 LEDs
    // +++------ Which block of 8 to address
    //
    // Mapping the x coord is more complex though as the position relates to:
    // - 1st/2nd Row determines which block of 8 within each colour.
    // - Colour B/G/R determines which pair of blocks of 8.
    //
    // Led Idx within a block = x[2:0]
    // Block Idx in frame buffer = x[5:3] * (16+16+16)
    // So LED position = BlockIdx + 8 (if 2nd Row) + 16 (if G) + 32 (if R) + LedIdx
    //
    // One final complication. The framebuffer is a set of bytes that maps onto
    // the different halves of different panels, so which bit in the framebuffer
    // gets set depends on the panel number and D1/D2 selection.
    //
    // Assuming a simple D8-D1 mapping, this means the following:
    // b76543210
    // ++--- D2/D1 Panel 1
    // ++----- D2/D1 Panel 2
    // ++------- D2/D1 Panel 3
    // ++--------- D2/D1 Panel 4
    //
    void setPixel (int x, int y, panelcolour col) {
    if ((x<0) || (x>=64) || (y<0) || (y>=64)) {
    // Only 4x 16*64 panels supported
    return;
    }
    int a1a0 = y & 0x03; // bank
    int row4 = y & 0x04 ? 8 : 0;
    int d1d2 = y & 0x08;
    int panel = y >> 4; // panel 0..15; only 0..4 supported
    int bitIdx = y >> 3; // panel no + d1/d2
    int led8 = x & 0x07;
    int block = x >> 3;

    // Determine the bit to act on for the four panels D1-D2
    uint8_t bit = (1<<bitIdx);
    int off = block * 48 + row4 + led8; // Location of B LED to act on
    if (col & BITBLUE) {
    fb[a1a0][off] |= bit;
    } else {
    fb[a1a0][off] &= ~bit;
    }
    if (col & BITGREEN) {
    fb[a1a0][off+16] |= bit;
    } else {
    fb[a1a0][off+16] &= ~bit;
    }
    if (col & BITRED) {
    fb[a1a0][off+32] |= bit;
    } else {
    fb[a1a0][off+32] &= ~bit;
    }
    }

    Understanding how the y value turns into a panel, Dn, and An number is perhaps best shown with an example. The following shows how incrementing the y coordinate maps onto panels.

    y=b7654 3210   A  D  P1
    0000 0000 0 1
    0000 0001 1 1
    0000 0010 2 1
    0000 0011 3 1
    0000 0100 0 1
    0000 0101 1 1
    0000 0110 2 1
    0000 0111 3 1

    0000 1000 0 2 P1
    ...
    0000 1111 3 2

    0001 0000 0 1 P2
    ...
    0001 1111 3 2 P2

    0010 0000 0 1 P3
    ...
    0010 1111 3 2 P3

    0011 0000 0 1 P4
    ...
    0011 1111 3 2 P4

    01xx xxxx x x P5-P8
    1xxx xxxx x x P9-P15

    Following the x coordinate mapping is ok once the idea of using the coordinate value to orient to the start of the 48-bit triple of 16 B, 16 G and 16 R values across the two rows is figured out. Then it is a case of calculating the offset within the referenced 48-bit triple as per the comments in the code above.

    Set Brightness

    There is a special command word that can be used to set the overall brightness of the driver chips. Sending this to all 48 chips on a panel will set the brightness for the whole panel.

    Full details can be found in the “dimming the panel” section here: https://wiki.hackhitchin.org.uk/index.php?title=LED_panel_interface and in the MBI5034 datasheet (see “Current Gain Adjustment”).

    This is the brightness function:

    void setBrightness (uint8_t brightpercent) {
    uint8_t bright;
    if (brightpercent <= 12) {
    bright = 0;
    } else if ((brightpercent > 12) && (brightpercent < 100)) {
    // Scale 12-100% between 0 and default value
    bright = (brightpercent - 12) * 0x2B / 88;
    } else {
    bright = 0x2B;
    }

    uint16_t ctrl = 0b0111000101000000 | bright;

    OESET; // active LOW
    LATCLR;
    CLKCLR;

    for (int a=0; a<FB_BANKS; a++) {
    SETADDR(a);
    for (int c=0; c<24; c++) {
    for (int b=15; b>=0; b--) {
    if ((ctrl & (1<<b)) == 0) {
    setDataOutput(0);
    } else {
    setDataOutput(0xFF);
    }
    if ((c == 23) && (b < 4)) {
    LATSET;
    } else {
    LATCLR;
    }
    CLKSET;
    CLKCLR;
    }
    }
    }
    LATCLR;
    }

    Notes:

    • The control word is streamed out MSbit first.
    • The LATch is held for the last four bits of the write to the last chip.
    • The same pattern is written to all Dn bits at the same time.
    • Brightness 0 (b000000) corresponds to 12.5% brightness.
    • Brightness 63 (b111111) corresponds to 200% brightness.
    • The default is 0x2B (b101011) which corresponds to a “gain” of 1 (see datasheet), so I’ve taken that to be considered “normal” or 100% brightness.
    • My code only accepts values from 12% to 100%. I’ve not allowed it to go up to 200%.

    There is one added complication though – whilst this is going on, the normal scanning should be paused to ensure it doesn’t interfere.

    Strictly speaking, the setBrightness routine should pause briefly too, to ensure any existing scanning is complete, but as the interrupt is higher priority than the running code, it should always complete first anyway.

    Code Summary

    I’ve ended up with the following routines in my code:

    void panelInit (void);
    void panelScan (void);
    void panelClear (bool on=false);
    void setPixel (int x, int y, panelcolour col);
    panelcolour getPixel (int x, int y);
    void setBrightness (uint8_t brightpercent);

    To use these requires the following basic setup:

    #include <TimerOne.h>
    #include "LEDPanel.h"

    void setup() {
    panelInit();
    panelClear();

    Timer1.initialize(5000); // 200Hz
    Timer1.attachInterrupt(panelScan);

    setBrightness (BRIGHTNESS_MIN);
    }

    #define DEL 5
    void loop() {
    for (int x=0; x<64; x++) {
    for (int y=0; y<64; y++) {
    setPixel(x, y, led_blue);
    delay(DEL);
    setPixel(x, y, led_green);
    delay(DEL);
    setPixel(x, y, led_red);
    delay(DEL);
    setPixel(x, y, led_white);
    delay(DEL);
    }
    for (int y=0; y<64; y++) {
    setPixel(x, y, led_black);
    }
    }
    }

    Notes:

    • This uses the TimerOne library to generate the panelScan() regular update.
    • I’ve configured the scan for 200Hz.
    • The loop illuminates each column in turn, from top to bottom.
    • This assumes the use of four panels as described above.

    Find the full code on GitHub here.

    Expanding to Four Panels

    When it came to it, wiring up four panels wasn’t going to work with the cables and shield I already had, I would have had to have made some longer ones, so in the end I just soldered up a slightly different arrangement of the Arduino shield.

    I’ve also added some screw terminals to allow the Arduino to be powered directly via its 5V pin from the main 5V power supply to the panels. I’ve added a 220uF capacitor to attempt to give some stability to the power as the LEDs turn on and off.

    I experimented with some 3D printed connectors but couldn’t get anything that connected snugly enough to keep the panels together, so in the end just nailed four panels to a piece of wood as shown.

    I have test code for the following:

    • To step down the brightness from full to minimum.
    • To illuminate each column of LEDs in turn.
    • To draw a basic Mandelbrot set.
    • To Conway’s Game of Life.

    I wasn’t able to capture the “all pixels on” Mandelbrot without the scan lines becoming apparent. I’m not entirely sure why this would be different compared to when it is building up the set or running the Game of Life, but it does. I’ll have to have a think about that one!

    Also, I don’t have enough memory on an Uno for a full dual-buffer grid for the Game of Life, so I’m using the pixel buffer itself as the state of the “live” display and have another buffer to calculate the updated values. To have all this on an Uno, I’ve had to limit the display to 52 rows rather than the full 64. Even that only gives me 62 bytes free!

    Update: the latest version of the code includes an option to fade dying cells out using different colours. This is shown in the video at the start of this post.

    Other Notes

    It took me ages to get this working – almost a week on and off. I tried everything – checking the protocol with a scope; working through the interrupt performance and timing requirements; dropping back to a simple test case; ultimately soldering up that interface board and verifying the power supply. I even went right back to first principles and coded up my own routines that I could fully understand.

    But I couldn’t get the panels to work.

    In the end I took one panel apart and started poking around with an oscilloscope.

    Interestingly there are two HC245 line buffers directly off the interface connection. One appears to produce four OE lines and four CLK signals. The other appears to have the address, data and other signals.

    It turns out that my crimped connector had a dodgy link on the LATch wire, so although I could see all the correct signals happening at the Arduino end, the LAT signal was never actually making it to the panel!

    That will teach me to check first principles and not assume anything.

    Or rather, I suspect it won’t and I’ll continue to have plenty more similar issues as I move forward.

    As usual a massive thanks to those who have worked out how to do all of the above, and a big thank you to Limehouse Labs for the large giveaway in the first place!

    Kevin

    #arduinoUno #define #include #led #RGB

  26. Send Email Anywhere: Winlink for New Amateur Radio Enthusiasts

    2,097 words, 11 minutes read time.

    When the internet works, we rarely think about how much we rely on it. But what happens when it doesn’t? Hurricanes knock out power grids, wildfires melt fiber lines, and remote expeditions often operate hundreds of miles from the nearest cell tower. In those moments, email isn’t just convenience—it’s a lifeline. Enter Winlink, a system that allows you to send and receive email without a single byte of traditional internet.

    This guide isn’t just for licensed amateur radio operators, though you may find yourself becoming one by the end. Instead, it’s for the curious builder, the aspiring communicator, and the man who values practical capability. Mastering Winlink prepares you for emergencies, expeditions, and even the challenge of earning your ham radio license—not as a theoretical exercise but as a tool you can actually use.

    What is Winlink?

    At its core, Winlink is a global messaging system designed to function where the internet cannot. It uses radio frequencies to transmit email through a network of gateway stations strategically placed across the world. These stations receive your message via radio, route it through their servers, and deliver it to the wider internet—or, if the internet is down, to another radio operator entirely.

    Winlink has been a cornerstone of emergency communications for decades, with its origins dating back to the late 1990s when amateur radio operators recognized the growing importance of digital messaging. Unlike traditional voice-based ham radio, Winlink provides structured, readable, and archivable messages—a major advantage in emergency operations where accuracy can mean the difference between help arriving or being lost in the static.

    Today, Winlink is more than a backup plan. It’s used by sailors crossing oceans, missionaries working in remote areas, disaster response teams, and adventurers who understand that connection should never depend solely on cell towers. As the official Winlink site describes, the system is “a worldwide radio messaging system that uses radio pathways where the Internet is not present.”

    What You Need to Get Started

    One of the strengths of Winlink is that it scales with your level of commitment and experience. At the most basic level, you’ll need a radio capable of data transmission, a computer running Winlink Express, and a way to connect the two—usually a sound card interface or dedicated radio modem.

    A common beginner setup starts with a simple VHF/UHF radio, such as a dual-band handheld transceiver, which can connect to nearby Winlink gateways operating on local frequencies. As your experience grows, high-frequency (HF) radios open the door to global coverage, allowing you to connect to distant stations when local ones aren’t available.

    The computer is equally essential. Winlink Express, the software that drives most amateur Winlink activity, provides a familiar email-like interface with the ability to compose, send, and receive messages—while managing the often-complex process of encoding and decoding digital signals in the background. A modest laptop or even a rugged tablet can serve the role well, especially in field conditions where weight and power efficiency matter.

    Finally, there’s power. Portable battery banks, solar panels, or generator setups ensure that your station stays on when the lights go out. This is where the survivalist mindset aligns with the hobbyist’s curiosity—Winlink is only as reliable as the hardware that supports it.

    How Winlink Sends Email Without the Internet

    Understanding how Winlink works under the hood adds depth to its appeal. At a high level, the process involves three main elements: the client software (Winlink Express), the radio, and the gateway network. When you compose a message, Winlink Express packages your text into a digital format that can be transmitted as a series of audio tones over the airwaves. These tones are received by a Winlink gateway station, which acts as a bridge between the radio world and the traditional internet.

    If the internet is operational, the gateway forwards your message to its destination email server. If not, Winlink allows for radio-only routing, where your message travels across stations until it reaches the intended recipient—no fiber optic cables required.

    Two primary connection methods make this possible. The first is Radio Frequency (RF) mode, where your signal travels over amateur radio frequencies to a gateway. The second is Telnet mode, which uses the internet directly, primarily for testing and training. Beginners often start with Telnet to learn the software before moving to full radio operations, where range, atmospheric conditions, and antenna placement all play a role.

    The elegance of Winlink lies in its resilience. It doesn’t care if cell towers collapse, satellites go dark, or an entire region loses power. As long as one gateway remains reachable via radio waves, email can still flow.

    Setting Up Winlink Express (Beginner-Friendly Walkthrough)

    Getting started with Winlink Express is easier than most people expect, though it rewards careful attention to detail. Begin by downloading Winlink Express from the official Winlink website. The software is lightweight, requiring minimal computing power, but it is rich in features, so take time to explore its menus and configuration panels. Upon first launch, you will be prompted to create a Winlink account—this simply involves selecting a callsign (if you have one) or using a temporary tactical callsign for training until you are fully licensed.

    Once your account is created, the software asks for your station information. Here, accuracy matters. Enter your location, radio type, and any details about how you will connect to the network. While beginners often start with Telnet mode to get comfortable with sending and receiving messages, the real magic happens when you move to radio frequency (RF) mode. This requires configuring your sound card interface or external modem to match your radio’s data capabilities, setting the correct baud rate, and fine-tuning your audio levels so that your signals are crisp and clear.

    A good practice is to test with short, simple messages at first. Compose an email to yourself or a fellow operator, attach a small text file, and send it through a nearby gateway. Once received, verify that the message’s content is intact and legible. Over time, experiment with different frequencies, power settings, and antenna orientations to learn how changing conditions affect transmission quality. Each successful test builds confidence, and confidence is the foundation of reliable field communication.

    Winlink in Real-World Scenarios

    Winlink is not a theoretical exercise. It has been proven repeatedly in some of the most demanding conditions imaginable. When hurricanes devastate coastal regions and cellular infrastructure collapses, emergency communication teams turn to Winlink to coordinate rescue operations and deliver critical updates to relief agencies.

    Sailors and maritime operators also rely on it daily. Imagine crossing the Pacific Ocean, hundreds of miles from the nearest internet hub, and still being able to send weather reports, position updates, and personal messages to family. Winlink bridges that gap seamlessly, often using high-frequency (HF) bands to cover immense distances where no other communication option is practical.

    Outdoor adventurers—backpackers, mountaineers, hunters—value Winlink for its ability to provide a digital lifeline when venturing far beyond cellular coverage. A hiker deep in the Rockies, for instance, can check in with a support team or report an emergency location via GPS coordinates, all without relying on fragile smartphone connectivity.

    But perhaps Winlink’s most valuable role is in structured emergency communications (EmComm) exercises. Across the United States, Amateur Radio Emergency Service (ARES) groups run regular Winlink drills, sending forms such as ICS-213 general messages or weather reports to practice real-time coordination. For men who see preparedness not just as a hobby but as a responsibility, Winlink offers a tool that combines technical challenge with practical life-saving potential.

    Practice Before You Need It

    Owning the gear and installing the software is only half the equation. True proficiency comes from use—regular, deliberate, and preferably guided by experienced operators. Many radio clubs host Winlink training nets where members check in, send test messages, and share configuration tips. One example is the Tuesday Winlink Connect, a weekly session designed to sharpen skills and keep operators ready for real-world scenarios.

    Practice also teaches the subtle art of troubleshooting. A misplaced setting, misaligned antenna, or weak signal can make the difference between a successful transmission and frustration. By testing under calm conditions, you build familiarity that pays dividends during emergencies when stress and urgency are high.

    For beginners, practice should start simple. Use Telnet mode to simulate message flow and confirm that your software is configured correctly. Move to VHF or UHF packet sessions next, connecting to local gateways at modest distances. Finally, progress to HF operations, where propagation conditions introduce a fascinating layer of complexity. The more you practice, the more intuitive the system becomes—and the more confidence you carry into your first field deployment or real emergency activation.

    Looking Ahead – Preparing for Your License

    While this guide focuses on using Winlink, gaining a deeper understanding of amateur radio regulations and practices naturally prepares you for eventual licensing. The Technician Class license, often considered the gateway to amateur radio, provides access to VHF and UHF frequencies—sufficient for local Winlink gateway access and learning the fundamentals of on-air communication. For those seeking broader coverage through HF frequencies, the General Class license becomes the logical next step, unlocking the potential for long-distance email transmission over radio.

    Familiarity with Winlink software, digital modes, and RF principles gives you an advantage when studying for these licenses. Concepts such as frequency allocation, propagation, and equipment operation are no longer abstract—they are skills you have applied firsthand. Many operators find that their first real-world experiences with Winlink inspire them to push deeper into the hobby, exploring not only licensing but also antenna theory, power management, and emergency communication protocols.

    Local amateur radio clubs are excellent resources for bridging this gap. They offer study sessions, licensing exams, and, perhaps most importantly, a network of experienced mentors. These seasoned operators often share practical insights that go far beyond test preparation, helping new enthusiasts build reliable portable stations, troubleshoot equipment issues, and operate confidently under pressure. As you advance, consider sharing your own experience with Winlink to guide others—a true hallmark of the amateur radio tradition.

    Conclusion

    Winlink is more than a clever workaround for internet outages. It represents a mindset—a commitment to capability, resilience, and preparedness in a world that too often assumes technology will never fail. Whether you are drawn by the technical challenge, the thrill of operating independently, or the satisfaction of knowing you can send an email from the middle of nowhere, Winlink delivers. It bridges the gap between old-school radio tradition and modern digital utility, proving that innovation thrives where curiosity meets purpose.

    This guide has only scratched the surface. From basic setup to advanced field deployment, Winlink offers endless opportunities for exploration. More importantly, every message sent, every drill completed, and every skill mastered moves you closer to becoming a fully licensed amateur radio operator—a step that will open new frequencies, new friendships, and new possibilities.

    If you’ve read this far, you are no longer a casual observer. You are someone who sees the value in building practical skills that can make a real difference when it matters most. Don’t wait until the next power outage or storm to start learning. Install Winlink Express, send your first test email, and experience the satisfaction of digital messaging without a single byte of internet.

    Better yet, join a live training session. The Tuesday Winlink Connect net is a perfect place to start. Here, you can practice in a supportive environment, learn from seasoned operators, and gain confidence with every transmission.

    Finally, I invite you to share your thoughts, questions, or first-time experiences in the comments below. What challenges did you face? What worked best for you? By sharing, you help build a community of capable communicators—men who value skill, readiness, and the quiet confidence that comes from knowing they can reach out when others cannot.

    D. Bryan King

    Sources

    Disclaimer:

    The views and opinions expressed in this post are solely those of the author. The information provided is based on personal research, experience, and understanding of the subject matter at the time of writing. Readers should consult relevant experts or authorities for specific guidance related to their unique situations.

    Related Posts

    Rate this:

    #amateurRadioEmail #amateurRadioWinlink #disasterCommunications #emergencyCommunications #hamRadioDigitalMessaging #hamRadioEmergencySkills #hamRadioForBeginners #hamRadioOffGridEmail #HFRadioEmail #offGridCommunication #portableHamRadio #portableWinlinkStation #prepperRadioTools #radioEmailForBeginners #radioEmailSystem #sendEmailViaRadio #survivalRadioEmail #VHFUHFPacket #Winlink #WinlinkBeginnerGuide #WinlinkCommunications #WinlinkCommunicationsGuide #WinlinkCommunicationsTutorial #WinlinkEmail #WinlinkEmComm #WinlinkEmergencyDrill #WinlinkEmergencyUse #WinlinkEquipment #WinlinkExplained #WinlinkExpressGuide #WinlinkExpressSetup #WinlinkExpressTutorial #WinlinkForAdventurers #WinlinkForEmergencyCommunications #WinlinkForExpeditions #WinlinkForHamOperators #WinlinkForHikers #WinlinkForPreppers #WinlinkForSailing #WinlinkGateway #WinlinkGettingStarted #WinlinkGlobalSystem #WinlinkGuide #WinlinkGuide2025 #WinlinkHamRadioSystem #WinlinkMessageSystem #WinlinkNet #WinlinkOffGrid #WinlinkOperation #WinlinkOverview #WinlinkPracticeNet #WinlinkSetupGuide #WinlinkSetupInstructions #WinlinkSoftwareDownload #WinlinkSoftwareTutorial #WinlinkTips #WinlinkTraining #WinlinkTrainingResources #WinlinkTutorial

  27. Is Resin Printing Worth the Mess? Brutally Honest Breakdown for First-Timers

    1,526 words, 8 minutes read time.

    If you’ve been lurking in the shadows of 3D printing forums or scanning YouTube for the next big step in your printing game, chances are you’ve stumbled on resin printing. It’s that tantalizing tech that promises jaw-dropping detail, surfaces so smooth they make FDM prints look like sandpaper, and the kind of precision that makes miniatures and prototypes scream quality. But here’s the real talk: resin printing comes with a mess and a handful of headaches that many first-timers don’t see coming. So, is it worth diving into the resin pool, or should you stick to good ol’ filament? Let’s rip off the band-aid and get gritty on the truth of resin printing.

    What Is Resin Printing? A Quick Overview

    Before we dissect the good, the bad, and the ugly, it’s important to get clear on what resin printing actually is. Unlike FDM printers that melt and extrude plastic filament layer by layer, resin printers use a vat of liquid photopolymer resin cured by light. The most common types you’ll hear about are SLA (Stereolithography), MSLA (Masked Stereolithography), and DLP (Digital Light Processing). All use UV light to harden the resin in very thin, precise layers, which is why the level of detail you get is miles ahead of filament printing.

    Resin printing is a fundamentally different beast—it’s more about light chemistry than hot plastic. That difference brings massive rewards in detail and finish, but also a totally different workflow that can feel like stepping into an alien lab if you’re used to FDM.

    The Good: Why Resin Printing Rocks

    Let’s start with the shine—resin printing delivers insane detail and surface smoothness that filament printers can’t touch. For guys who are into tabletop gaming, collectibles, or prototyping tiny mechanical parts, resin prints can capture the crisp edges and subtle curves you thought only existed in CAD renders. The resolution is typically measured in microns, not millimeters, which means you can pick out textures on a miniature’s armor or the intricate lattice on a prototype bracket with pinpoint accuracy.

    Beyond beauty, resin prints can be incredibly strong and functional, depending on the resin you use. There are tough engineering resins, flexible ones, and even biocompatible varieties for dental or medical applications. This versatility means resin printing is carving out a solid place not just with hobbyists, but with businesses looking for rapid, high-fidelity prototyping without resorting to expensive CNC or injection molding.

    Another bonus is how fast resin printers can spit out parts. Sure, you’re still building layer by layer, but curing a whole layer at once rather than tracing it with a nozzle often means speedier prints for small, detailed objects. When you want quality and speed in the same package, resin printing has your back.

    The Bad: The Mess and Headaches of Resin Printing

    Here’s where things get real. The downside to resin printing is all about the mess and the safety headaches that come with working with liquid resin. This stuff isn’t your run-of-the-mill filament spool you toss in and forget. Resin is a toxic, smelly chemical cocktail that demands respect and careful handling. Direct skin contact can cause irritation or allergic reactions, and the fumes aren’t something you want lingering in your man cave.

    The post-processing is a chore you won’t escape. Once your print is done, you need to wash it, usually in isopropyl alcohol, to strip off uncured resin. Then, you have to cure it under UV light to harden it fully. This washing and curing routine isn’t just another step; it can take as long as the print itself and involves dealing with flammable liquids and sticky resin sludge.

    Disposal is another headache. You can’t just pour leftover resin or used alcohol down the drain without risking environmental damage and local code violations. You’ll need to research how to properly cure and dispose of waste resin, which adds another layer of complexity for the newbie.

    On top of that, the resin printer itself demands careful cleaning and maintenance. The vats and FEP films (the thin transparent layers at the bottom of resin trays) wear out and need replacing, and any spills can quickly turn your workspace into a nightmare. Without proper ventilation and protective gear like nitrile gloves and safety glasses, you’re flirting with respiratory irritation and skin problems.

    Equipment and Setup: What You’ll Need to Manage the Mess

    If you’re thinking resin printing sounds awesome but want to avoid turning your garage into a toxic swamp, prepping the right setup is non-negotiable. First up, safety gear isn’t optional — gloves, a respirator or mask rated for organic vapors, and eye protection are your frontline defense. You’ll also want a well-ventilated space or ideally, a dedicated room with a fume extractor. Trust me, the resin smell sticks around and gets old fast.

    Next, post-processing tools like an ultrasonic cleaner or a good wash station can save you time and hassle. UV curing stations are essential to finish prints properly—while sunlight can do the job, it’s slow and inconsistent. Some budget printers come with UV lights built-in, but many require a separate device.

    Your workspace should be easy to clean and resistant to resin spills. Plastic trays, disposable paper towels, and dedicated resin containers will save your sanity. The resin itself can be messy—be prepared for drips and splashes, especially when pouring and cleaning.

    Maintenance and Ongoing Costs

    Unlike filament printers where the ongoing costs are mostly filament and maybe a new nozzle now and then, resin printing carries a heavier price tag over time. Resin is more expensive per liter than filament, and waste from failed prints or washing can add up quickly. Consumables like replacement vats, FEP films, gloves, and isopropyl alcohol add to the tally.

    Plus, the time cost isn’t trivial. Post-processing can double your total print time, especially if you’re meticulous about cleaning and curing. And neglecting maintenance or safety can lead to poor print quality or health issues.

    First-Timer Tips: How to Survive and Thrive

    If you’re still here and seriously thinking about dipping your toes into resin printing, here’s some hard-earned advice. Start small with cheap resins and basic printers before dropping serious cash. Never skip safety protocols—those gloves and goggles exist for a reason.

    Plan your post-processing workflow before your first print. Set up a dedicated cleaning area, and always have proper waste disposal methods ready. Expect a learning curve; don’t get discouraged by early fails or messy spills. Clean resin off your tools and surfaces immediately; once it cures, it’s a nightmare to remove.

    One of the biggest rookie mistakes is rushing prints or post-processing to save time. Resin printing rewards patience and precision. Follow manufacturer instructions closely, experiment with settings gradually, and join forums or communities to swap tips.

    Is It Worth It? The Final Verdict

    So, is resin printing worth the mess? The honest answer is: it depends. If you crave ultra-high detail, smooth surfaces, and can handle a bit of chemistry lab discipline, resin printing opens doors that filament can’t. Miniature painters, jewelers, model makers, and prototype developers will appreciate the leaps in quality and speed.

    However, if you’re sensitive to chemicals, don’t want to invest in extra gear or spend significant time on post-processing, resin might not be your best first choice. FDM printing still rocks for durability, ease, and low cost.

    The tech is evolving, and newer resins and machines are getting safer and less messy, but it’s still a commitment. Understanding the risks, costs, and workflow upfront will help you decide if this next-level tech deserves a spot in your printing arsenal.

    Conclusion

    Resin printing isn’t just a step up from filament; it’s a whole new game with different rules. It demands respect for the chemicals, time for cleanup, and patience to master. But the payoff—mind-blowing detail and finish—makes it an addiction for those who love pushing 3D printing’s limits.

    If you’re ready to take the plunge or want to share your resin printing war stories, drop a comment below or reach out directly. And don’t forget to subscribe to our newsletter for more raw, honest 3D printing insights. This community’s all about keeping it real and getting the most out of our gear.

    D. Bryan King

    Sources

    Disclaimer:

    The views and opinions expressed in this post are solely those of the author. The information provided is based on personal research, experience, and understanding of the subject matter at the time of writing. Readers should consult relevant experts or authorities for specific guidance related to their unique situations.

    Related Posts

    Rate this:

    #3dPrinterResinWaste #3dPrintingResinProsAndCons #bestResinPrinters #cleaningResinPrints #isResinPrintingWorthIt #resin3dPrintCleanup #resin3dPrintCuring #resin3dPrinterParts #resin3DPrinterSetup #resin3dPrinting #resin3dPrintingCost #resin3dPrintingDetail #resin3dPrintingEquipment #resin3dPrintingGuide #resin3dPrintingIsopropylAlcohol #resin3dPrintingMistakes #resin3dPrintingQuality #resin3dPrintingSpeed #resin3dPrintingToxicity #resin3dPrintingUVLight #resinPrinterCleaning #resinPrinterMaintenance #resinPrinterSafetyGear #resinPrintingAdvantages #resinPrintingAlternatives #resinPrintingBeginners #resinPrintingCons #resinPrintingConsumables #resinPrintingDetails #resinPrintingDisadvantages #resinPrintingDisposal #resinPrintingDurability #resinPrintingEssentials #resinPrintingForBeginners #resinPrintingForPrototyping #resinPrintingFumes #resinPrintingGloves #resinPrintingHealthPrecautions #resinPrintingHealthRisks #resinPrintingMess #resinPrintingMiniatures #resinPrintingPostCure #resinPrintingPostProcessing #resinPrintingPros #resinPrintingResinTypes #resinPrintingReviews #resinPrintingSafety #resinPrintingSetupTips #resinPrintingSmell #resinPrintingTechnology #resinPrintingTips #resinPrintingTipsAndTricks #resinPrintingVentilation #resinPrintingWasteManagement #resinPrintingWorkflow #resinPrintingWorkspace #resinVsFdm #toxicResinDangers #UVCuringResinPrints

  28. Falling Apart…

    I’m writing this from a hotel room in Ilulissat, rather than Qaanaaq where I had intended to be arriving shortly, because our plane has been cancelled due to bad weather (at time of writing the airport was measuring gusts of 14 m/s, so I’m actually quite glad it was cancelled).

    Weather and flight cancellations are an eternal hazard when doing fieldwork in Greenland, but in this case it also means an impact on our planned fieldwork, because the sea ice is falling apart. And rather earlier than usual (though we have not yet done a systematic review to prove this). In fact, part of the reason for coming here in May (instead of my usual March trip) was to investigate an interesting event that happened earlier this spring. In the animation of satellite pictures below you can see the sea ice rather dramatically falling apart in mid-April and then again at the end of April.

    The March to May sea ice season from Sentinel 2 in NW Greenland

    To understand what is happening and why it’s unusual, first a bit of background. As I have written before, my DMI colleagues have been working up in NW Greenland for about 15 years on a programme of ocean measurements in the fjord (see map below). I joined about 5 years ago, working in the melange zone of the glaciers at the head of Inglefield Bredning (PSA: a paper we recently submitted about this programme will hopefully be online soon). We use the sea ice as highway and stable platform for observations, so it’s pretty important for us and came to the conclusion it wa squite important for some parts of the glaciers too. The local community, with whom we work closely use it also for travelling, hunting and fishing from. It’s extremely important for them.

    The region of North West Greenland we’re talking about

    Normally there’s pretty thick (~1m) sea ice covering the whole of Inglefield Bredning (Gulf of Inglefield, also known as Kangerlussuaq, but not that one) out to the islands of Qeqertarsuaq and Kiatak. You can seen an example of what this looks like normally in the satellite animation from 2020, which happens to be when my first trip out on to the sea ice in Qaanaaq took place at the end of May and beginning of June. We were actually very lucky, we had great weather, got very close to the ice edge and watched narwhals swimming out in the North Water polynya. (Yes, sometimes I wonder how I managed to get this job too). The animation below is Sentinel-2 images as cloud free as I could find them from that first field season. As you can see, the sea ice already in March was much much more extensive than this year at the same time. And perhaps that is part of the answer.

    It’s probably worth pointing out at this stage that although there were some pretty warm (unusually so) spikes in March and April, the sea ice breakup in April was probably largely driven by ocean swell, and perhaps some winds which were strong, though not excessively so as far as we can see in the observations. The latest break-up seems to be driven also by high winds.

    Back to our current field season. We had in fact planned a brief trip up here already – I am currently setting up a project looking at snow processes with the team and we had planned to install and test some new instruments and protocol that we hope to use in Antarctica later this year (more on all of that later hopefully). However, as the soon to be published preprint shows, I and the team have developed pretty extensive sea ice interests recently, so this unusual behaviour rather piqued our curiosity.

    We have a lot of questions:

    Why did it happen this year? Is it really the earliest in the satellite record? What makes the ice vulnerable? Composition, thickness, temperature? Is the ocean driving it or the atmosphere or both (it’s usually both), and what makes this year so unusual? Further down the line, can we model it and use those simulations to understand if this is a single aberration or likely to be more common in the future? And what impact will the earlier breakups have on the ecosystem, the adjacent glaciers and the local community?

    Or fieldtrip thus appeared an excellent opportunity to grab some real data on all of these points. Our colleague Henriette Skourup at DTU-Space was kind enough to lend us one of her instruments, which we shipped up last minute to allow us to do an add-on. It is all currently sitting there waiting for us.

    Unfortunately the sea ice is not waiting for us, if the photos from my colleague in Qaanaaq, Aksel are anything to go by.

    A large and widening crack in the sea ice in front of Qaanaaq. The small objects on the sea ice (fishing gear?) suggest we were not the only ones surprised). Credit: Aksel Ascanius, DMI

    The high winds which grounded our plane have also been busy on the sea ice, which is falling apart in the bay with surprising speed as far as I can see. We are still waiting for today’s optical imagery but the quick look from radar based Sentinel-1 suggests cracks widening rapidly as the photo above confirms.

    Temperature observations from Qaanaaq airport

    With a bit of luck we will get to Qaanaaq on Thursday (immaqa) to see if our sea ice research plan can go ahead. At this stage I rather doubt it. But it will very much depend on the next few hours. The wind speeds are quite high still but the temperature which was well above freezing has now dropped down to just below.

    Wind observations from Qaanaaq airport

    We are fortunate that we work with local hunters on the sea ice who are immensely experienced. The first rule is always safety first. We do have *a lot* of other work to do and rather fewer days to do it all in, so either way we’ll be busy. Ffor now, it’s keep checking in with the weather, the satellite images and our friends in Qaanaaq and use the time in Ilulissat wisely – in our case, it’s time to write some papers. And one of them is all about sea ice.

    To be continued…

    All satellite imagery on this page is from the European Space Agency Sentinel-2 mission, processed on the Copernicus EO Browser – a FREE!! and easy to use entry point to use ESA data. Weather observations are from Qaanaaq airport, operated by Mittarfeqarfiit A/S – Grønlands Lufthavne (Greenland Airports) and processed by DMI. It’s actually pretty nice how much high quality data we have access to these days…

    This fieldwork is undertaken as part of the PRECISE (Predicting Ice Sheets on Earth) project funded by the Novo Nordisk Foundation and by the ESA Climate Change Initiative for Sea Ice and the Climate Modelling Research Group

    #Arctic #fieldwork #Greenland #Qaanaaq #satelliteData #Science #SeaIce

  29. Falling Apart…

    I’m writing this from a hotel room in Ilulissat, rather than Qaanaaq where I had intended to be arriving shortly, because our plane has been cancelled due to bad weather (at time of writing the airport was measuring gusts of 14 m/s, so I’m actually quite glad it was cancelled).

    Weather and flight cancellations are an eternal hazard when doing fieldwork in Greenland, but in this case it also means an impact on our planned fieldwork, because the sea ice is falling apart. And rather earlier than usual (though we have not yet done a systematic review to prove this). In fact, part of the reason for coming here in May (instead of my usual March trip) was to investigate an interesting event that happened earlier this spring. In the animation of satellite pictures below you can see the sea ice rather dramatically falling apart in mid-April and then again at the end of April.

    The March to May sea ice season from Sentinel 2 in NW Greenland

    To understand what is happening and why it’s unusual, first a bit of background. As I have written before, my DMI colleagues have been working up in NW Greenland for about 15 years on a programme of ocean measurements in the fjord (see map below). I joined about 5 years ago, working in the melange zone of the glaciers at the head of Inglefield Bredning (PSA: a paper we recently submitted about this programme will hopefully be online soon). We use the sea ice as highway and stable platform for observations, so it’s pretty important for us and came to the conclusion it wa squite important for some parts of the glaciers too. The local community, with whom we work closely use it also for travelling, hunting and fishing from. It’s extremely important for them.

    The region of North West Greenland we’re talking about

    Normally there’s pretty thick (~1m) sea ice covering the whole of Inglefield Bredning (Gulf of Inglefield, also known as Kangerlussuaq, but not that one) out to the islands of Qeqertarsuaq and Kiatak. You can seen an example of what this looks like normally in the satellite animation from 2020, which happens to be when my first trip out on to the sea ice in Qaanaaq took place at the end of May and beginning of June. We were actually very lucky, we had great weather, got very close to the ice edge and watched narwhals swimming out in the North Water polynya. (Yes, sometimes I wonder how I managed to get this job too). The animation below is Sentinel-2 images as cloud free as I could find them from that first field season. As you can see, the sea ice already in March was much much more extensive than this year at the same time. And perhaps that is part of the answer.

    It’s probably worth pointing out at this stage that although there were some pretty warm (unusually so) spikes in March and April, the sea ice breakup in April was probably largely driven by ocean swell, and perhaps some winds which were strong, though not excessively so as far as we can see in the observations. The latest break-up seems to be driven also by high winds.

    Back to our current field season. We had in fact planned a brief trip up here already – I am currently setting up a project looking at snow processes with the team and we had planned to install and test some new instruments and protocol that we hope to use in Antarctica later this year (more on all of that later hopefully). However, as the soon to be published preprint shows, I and the team have developed pretty extensive sea ice interests recently, so this unusual behaviour rather piqued our curiosity.

    We have a lot of questions:

    Why did it happen this year? Is it really the earliest in the satellite record? What makes the ice vulnerable? Composition, thickness, temperature? Is the ocean driving it or the atmosphere or both (it’s usually both), and what makes this year so unusual? Further down the line, can we model it and use those simulations to understand if this is a single aberration or likely to be more common in the future? And what impact will the earlier breakups have on the ecosystem, the adjacent glaciers and the local community?

    Or fieldtrip thus appeared an excellent opportunity to grab some real data on all of these points. Our colleague Henriette Skourup at DTU-Space was kind enough to lend us one of her instruments, which we shipped up last minute to allow us to do an add-on. It is all currently sitting there waiting for us.

    Unfortunately the sea ice is not waiting for us, if the photos from my colleague in Qaanaaq, Aksel are anything to go by.

    A large and widening crack in the sea ice in front of Qaanaaq. The small objects on the sea ice (fishing gear?) suggest we were not the only ones surprised). Credit: Aksel Ascanius, DMI

    The high winds which grounded our plane have also been busy on the sea ice, which is falling apart in the bay with surprising speed as far as I can see. We are still waiting for today’s optical imagery but the quick look from radar based Sentinel-1 suggests cracks widening rapidly as the photo above confirms.

    Temperature observations from Qaanaaq airport

    With a bit of luck we will get to Qaanaaq on Thursday (immaqa) to see if our sea ice research plan can go ahead. At this stage I rather doubt it. But it will very much depend on the next few hours. The wind speeds are quite high still but the temperature which was well above freezing has now dropped down to just below.

    Wind observations from Qaanaaq airport

    We are fortunate that we work with local hunters on the sea ice who are immensely experienced. The first rule is always safety first. We do have *a lot* of other work to do and rather fewer days to do it all in, so either way we’ll be busy. Ffor now, it’s keep checking in with the weather, the satellite images and our friends in Qaanaaq and use the time in Ilulissat wisely – in our case, it’s time to write some papers. And one of them is all about sea ice.

    To be continued…

    All satellite imagery on this page is from the European Space Agency Sentinel-2 mission, processed on the Copernicus EO Browser – a FREE!! and easy to use entry point to use ESA data. Weather observations are from Qaanaaq airport, operated by Mittarfeqarfiit A/S – Grønlands Lufthavne (Greenland Airports) and processed by DMI. It’s actually pretty nice how much high quality data we have access to these days…

    This fieldwork is undertaken as part of the PRECISE (Predicting Ice Sheets on Earth) project funded by the Novo Nordisk Foundation and by the ESA Climate Change Initiative for Sea Ice and the Climate Modelling Research Group

    #Arctic #fieldwork #Greenland #Qaanaaq #satelliteData #Science #SeaIce

  30. Falling Apart…

    I’m writing this from a hotel room in Ilulissat, rather than Qaanaaq where I had intended to be arriving shortly, because our plane has been cancelled due to bad weather (at time of writing the airport was measuring gusts of 14 m/s, so I’m actually quite glad it was cancelled).

    Weather and flight cancellations are an eternal hazard when doing fieldwork in Greenland, but in this case it also means an impact on our planned fieldwork, because the sea ice is falling apart. And rather earlier than usual (though we have not yet done a systematic review to prove this). In fact, part of the reason for coming here in May (instead of my usual March trip) was to investigate an interesting event that happened earlier this spring. In the animation of satellite pictures below you can see the sea ice rather dramatically falling apart in mid-April and then again at the end of April.

    The March to May sea ice season from Sentinel 2 in NW Greenland

    To understand what is happening and why it’s unusual, first a bit of background. As I have written before, my DMI colleagues have been working up in NW Greenland for about 15 years on a programme of ocean measurements in the fjord (see map below). I joined about 5 years ago, working in the melange zone of the glaciers at the head of Inglefield Bredning (PSA: a paper we recently submitted about this programme will hopefully be online soon). We use the sea ice as highway and stable platform for observations, so it’s pretty important for us and came to the conclusion it wa squite important for some parts of the glaciers too. The local community, with whom we work closely use it also for travelling, hunting and fishing from. It’s extremely important for them.

    The region of North West Greenland we’re talking about

    Normally there’s pretty thick (~1m) sea ice covering the whole of Inglefield Bredning (Gulf of Inglefield, also known as Kangerlussuaq, but not that one) out to the islands of Qeqertarsuaq and Kiatak. You can seen an example of what this looks like normally in the satellite animation from 2020, which happens to be when my first trip out on to the sea ice in Qaanaaq took place at the end of May and beginning of June. We were actually very lucky, we had great weather, got very close to the ice edge and watched narwhals swimming out in the North Water polynya. (Yes, sometimes I wonder how I managed to get this job too). The animation below is Sentinel-2 images as cloud free as I could find them from that first field season. As you can see, the sea ice already in March was much much more extensive than this year at the same time. And perhaps that is part of the answer.

    It’s probably worth pointing out at this stage that although there were some pretty warm (unusually so) spikes in March and April, the sea ice breakup in April was probably largely driven by ocean swell, and perhaps some winds which were strong, though not excessively so as far as we can see in the observations. The latest break-up seems to be driven also by high winds.

    Back to our current field season. We had in fact planned a brief trip up here already – I am currently setting up a project looking at snow processes with the team and we had planned to install and test some new instruments and protocol that we hope to use in Antarctica later this year (more on all of that later hopefully). However, as the soon to be published preprint shows, I and the team have developed pretty extensive sea ice interests recently, so this unusual behaviour rather piqued our curiosity.

    We have a lot of questions:

    Why did it happen this year? Is it really the earliest in the satellite record? What makes the ice vulnerable? Composition, thickness, temperature? Is the ocean driving it or the atmosphere or both (it’s usually both), and what makes this year so unusual? Further down the line, can we model it and use those simulations to understand if this is a single aberration or likely to be more common in the future? And what impact will the earlier breakups have on the ecosystem, the adjacent glaciers and the local community?

    Or fieldtrip thus appeared an excellent opportunity to grab some real data on all of these points. Our colleague Henriette Skourup at DTU-Space was kind enough to lend us one of her instruments, which we shipped up last minute to allow us to do an add-on. It is all currently sitting there waiting for us.

    Unfortunately the sea ice is not waiting for us, if the photos from my colleague in Qaanaaq, Aksel are anything to go by.

    A large and widening crack in the sea ice in front of Qaanaaq. The small objects on the sea ice (fishing gear?) suggest we were not the only ones surprised). Credit: Aksel Ascanius, DMI

    The high winds which grounded our plane have also been busy on the sea ice, which is falling apart in the bay with surprising speed as far as I can see. We are still waiting for today’s optical imagery but the quick look from radar based Sentinel-1 suggests cracks widening rapidly as the photo above confirms.

    Temperature observations from Qaanaaq airport

    With a bit of luck we will get to Qaanaaq on Thursday (immaqa) to see if our sea ice research plan can go ahead. At this stage I rather doubt it. But it will very much depend on the next few hours. The wind speeds are quite high still but the temperature which was well above freezing has now dropped down to just below.

    Wind observations from Qaanaaq airport

    We are fortunate that we work with local hunters on the sea ice who are immensely experienced. The first rule is always safety first. We do have *a lot* of other work to do and rather fewer days to do it all in, so either way we’ll be busy. Ffor now, it’s keep checking in with the weather, the satellite images and our friends in Qaanaaq and use the time in Ilulissat wisely – in our case, it’s time to write some papers. And one of them is all about sea ice.

    To be continued…

    All satellite imagery on this page is from the European Space Agency Sentinel-2 mission, processed on the Copernicus EO Browser – a FREE!! and easy to use entry point to use ESA data. Weather observations are from Qaanaaq airport, operated by Mittarfeqarfiit A/S – Grønlands Lufthavne (Greenland Airports) and processed by DMI. It’s actually pretty nice how much high quality data we have access to these days…

    This fieldwork is undertaken as part of the PRECISE (Predicting Ice Sheets on Earth) project funded by the Novo Nordisk Foundation and by the ESA Climate Change Initiative for Sea Ice and the Climate Modelling Research Group

    #Arctic #fieldwork #Greenland #Qaanaaq #satelliteData #Science #SeaIce