Blog

  • The Spreadsheet Part

    It can’t really be put off any longer: I’ve been writing the parameter and patch management part of OSCar.

    Most of the knobs that a musician can tweak are mapped somehow to software parameters that begin and end their lives in a small block of memory. Aside from responding to a tweaked knob, these parameters must do a lot of dull but essential work:

    • They must be constrained to sensible minimum and maximum values.
    • Whenever they are changed on the synthesiser, we must send unique MIDI control messages so that the player can record any changes they make during a performance.
    • Those control messages must then be mapped back to the controls, so that MIDI replay also works. This makes movements like filter sweeps and small changes in timbre easier to time, control, and edit.
    • Patch saving and loading functions need to move whole blocks of parameters between the current memory and some larger storage area.
    • Changes to the parameters, by whatever means, need to be tracked and relayed to the sound-producing parts of the synth, so that any numbers we use internally that are mathematically derived from the parameters are recalculated only when necessary.

    We end up essentially — in fact, literally — managing a spreadsheet row for every aspect of the synthesiser that the musician can control, and building something akin to a filing system in memory so that their values can be stored and recalled, one at a time or en masse.

    Original OSCar manual (WordStar for the win!), showing the internal parameter layout, laid bare by the advent of the MIDI retrofit. The first half of a 32-byte preset is shown. Hair loss is original and mine.

    There’s no escaping having to do all this, as almost the first piece of proper programming, or you have to go back and write all your control code again to wire such features in. Bringing control knobs into play last week made it inevitable that the time for this dull work is upon me, and it breaks one of my rules: none of these changes make the synth any more playable. Yet.

    And here is where I heave my second sigh, as I need to diverge, considerably, from the original OSCar code and the work I’ve done there.

    Diversion 1: Rethinking MIDI control

    The first OSCar was sold towards the end of 1983, and the world first heard about MIDI in early 1984. It was clearly going to be transformative, so OSC quickly made a MIDI retrofit board and some new firmware (clever bodges, both) so OSCar would support its most fundamental features. It must quickly have been incorporated into the stock unit: every OSCar I’ve seen for sale has this kit fitted.

    Chris with his own OSCar, in a publicity photo taken by Focusrite in the early 2010s. He’s holding the MIDI retrofit board in his left hand.

    The MIDI support was very rudimentary, though — control data could not be automated except for pitch bend and modulation. And there was a weird anomaly in the use of the ‘All Notes Off’ message whenever the last note on the synth was released: presumably, that’s a useful remedy for stuck notes, but it’s considered bad practice today because it doesn’t merge well.

    The new firmware did let you turn data on or off in a granular way that modern synthesisers don’t tend to support: note on/off messages could be suppressed while program change messages were sent and received, for example. This makes a kind of sense when you’re connecting two synths together, but when (as now) everything tends to be mediated through a digital audio workstation, those features are no longer needed.

    OSCar also lets you send and receive all presets, waveforms, and sequences from memory: a handy feature which entirely replaced the need for the cassette interface (in fact, the M2 firmware release appears accidentally to have broken the ability to reload waveforms from a cassette). It didn’t let you save or alter one preset at a time, though: it was an everything-or-nothing feature.

    (To send arbitrary data of this kind requires a company to embed its manufacturer number into the message. Until recently, developing new MIDI products therefore required payment of a small annual subscription to the MIDI Manufacturers Association. It was important enough to do this for Supperware and PWG independently to register their own numbers and pay separate subscriptions. The Oxford Synthesiser Company, though, squatted in Solid State Logic‘s manufacturer code. Pre-Internet and in the very early days of MIDI, it’s quite charming to see a little Socialist collective of Oxford-based companies registering and occupying a single manufacturer number.)

    There’s an aftermarket firmware upgrade by Tauntek that rethought OSCar’s MIDI support. Bob Grieb, who wrote this new ROM, did a remarkable amount of work, disassembling and emulating the OSCar code to reverse-engineer what he needed to.

    (Bob and I spoke about this over email: he was very forthcoming about the techniques he used. Of course I asked, very early on, if he’d let me look at any of the work he’d done, but he was understandably reluctant to give this away for free, and was so done with it that he didn’t want to know what I was up to.) Bob’s work involves a more extensive set of modifications than the original MIDI kit to accommodate a bigger EPROM and more RAM.

    Tauntek picked MIDI control values to make the software implementation as simple as possible (rather than making interoperability the main priority), so it features slightly peculiar choices of controller numbers. Reportedly it doesn’t take much automation before it starts to choke: you cannot escape the limitations of the Z80 unless you escape the Z80. I’m pleased to have a much faster processor in the new OSCar to manage this stuff.

    Diversion 2: Recollection varies

    OSCar uses static RAM, and a backup NiCad battery. Chris could write anything anywhere in RAM and trust that it’d still be there after the synth was turned off, put in a box for a month, and then switched on again. (Until the battery ran out or failed, that is, but that was the user’s problem.)

    Modern microcontrollers use FLASH memory for everything of a semi-permanent nature, including the firmware. Unlike RAM, it will preserve its state in the absence of power, so we can get rid of the battery. But the first big difference versus RAM is that you have to erase FLASH in pages of a few kilobytes at once. A save, then, is a lot more involved. It takes some data shuffling beforehand, and freezes up the processor for a few tens of milliseconds while the system memory is juggled.

    The second problem is that FLASH does wear out after a few thousand erase cycles, as its tiny logic gates become subject to irreversible physical changes. It’s up to the programmer to level the wear of FLASH, avoiding the case where (for example) a customer making a series of modifications to the same preset might hammer one small area of memory with erase-program cycles, and cause it to fail prematurely.

    We need to introduce something akin to a filing system: a largish block of memory reserved for presets that minimises the number of erase cycles applied to each page. We no longer save a certain preset in a certain allocated place in memory, but in the next available slot within a memory pool reserved for general use. We need to build a table of contents whenever the synth is powered on.

    Diversion 3: Mod cons

    OSCar lets you store 36 voice presets, along with a handful of waveforms and sequences. In fact, the first OSCar firmware let you store only 12 presets, which occupied about 20% of its 2K of RAM. We’ve got blasé about huge quantities of memory, so such small numbers feel very limiting today.

    Mantis, for example, sells with 100 factory presets and 100 other slots free, although it does a lot more so presets can sound more different. To break the barrier of 36 presets requires changes to the user interface as well as the underlying code. The balance to strike is not to make the changes to the load/save workflow so intrusive that they appear sacrilegious to people who love the original OSCar, but also not to be ashamed by them so they get lost in obscurity.

    The second thing that’s nice about synths like Mantis is compare and undo features. Compare mode allows you, for example, to listen to the preset you’re about to overwrite before you commit to saving your new one. I am not sure if there’s space for a similar feature in OSCar without changing too much about the way it works. OSCar uses the keybed to choose presets in load and save modes: being able to turn it back into a keyboard so you can play the preset you’re about to overwrite feels like it may involve too much interference with the original workflow, and we won’t know until we try it and argue about it. I carry Paul’s avatar in my head when I consider such decisions, and he tends to be a lot more conservative than I am.

    Undo is easier, though. This allows you a chance to retrieve your work in progress if you were careless enough to load a preset while you were deep into editing a sound. The principle here is that you shouldn’t ever be able to lose an hour’s work by pressing the wrong button (unless it’s the power button). It’d be courteous to find a place for this.

    Diversion 4: Tidying up, just because

    The memory map in OSCar, as you can glean from the section of manual above, is a bit of a mess. (They usually are.) Parameters were added as Chris designed the synth. They’re not arranged in logical sections, and the naming conventions aren’t that clear to a modern programmer’s eyes. Mod Wheel Pitch Amount versus Direct Pitch Mod Amount, for example? We can improve that. Backwards compatibility can be maintained by making the import program a little more complicated, so it recognises and remaps data from an original OSCar (complete with its Solid State Logic manufacturer ID).

    We end up with a spreadsheet a bit like this:

    It’s in Python because it feeds into C code generation routines, and it’s unfinished. All the refresh fields are zero, because I haven’t written anything that uses them yet. OSCar, without its MIDI controller support, didn’t need them. And, while OSCar’s parameter map was 8 bits all the way, the actual precision was limited by a series of operations before those numbers hit the synth engine. Not all bits are meaningful in practice, and 7-bit parameters are far simpler to control over MIDI, so I will probably revise most of these.

    But it’s a start. The comment numbers at the end are the Tauntek MIDI control numbers: I thought it’d be nice to preserve compatibility wherever it looked like it wouldn’t compromise other things. In the end, though, I went my own way for all but a few parameters. It’s not going to inconvenience many people: perhaps a handful of reviewers trying to do A-B comparisons between the old and new OSCars. I might also have looked at the impOSCar MIDI map for inspiration, but that’s now very different from the original synth.

    Finally, a look at the progress-o-gram. I’ve done very little code conversion this week, but realised I’ve done more than I thought. The hardware abstraction layer actually counts as quite a lot of the original firmware.

  • Little green wires

    I fell into the gap at Waterloo Station yesterday. A couple of people got off the Bakerloo Line train before me and stood, blocking the doors, staring blankly at the arrows on the walls until they knew which of the two possible directions to take. I, too, was preoccupied with the direction signs, but needed to snake past this couple before the train doors slammed in my face. Distracted by such concerns and obstacles, and wary of running behind for my appointment, my foot plopped between the train carriage and platform, and down I went.

    Fortunately nothing got hurt except my dignity, and that’s just scar tissue these days. But the point is that things that cannot happen to somebody with a brain do happen, and usually because the brain has to be elsewhere.

    Designing hardware involves thousands of decisions and deliberate actions competing for attention, and fills the brain at all times. Most projects therefore involve a period of crossing what I called in my 2021 ADC talk the ‘Valley of Despair’. It’s a first encounter with the physical world that keeps you humble as an engineer because: one, you’ve made stupid mistakes no competent engineer would ever make; two, it’s still going to take you a large, unspecifiable amount of time and ingenuity to find them.

    Pay no attention to the wire about to fall out of its crimp connector. I’ll worry about that when notes fail.

    If you’re lucky, you can just desolder a component and put something else in its place. Otherwise, out comes the scalpel, usually, and the green 30-gauge wire, always. The green wire count on Issue 1 of OSCar Rebirth is only four. But the time I invested in chasing the problems, making running repairs to the two main boards I’m looking after, testing alternative fixes, and getting the PCB CAD data ready for the next go, runs to probably twelve to sixteen hours.

    Animated GIF of fiddling between revisions 1 and 2 of the PCB (internal layers not shown; this is not the final revision 2). All in all, the first guess wasn’t bad.

    Interesting production engineering side note

    if you squint at the GIF above, you’ll notice that I renumber the components between revisions. I can do this because I hand-populated these boards and will probably hand-populate the next ones. Once the design work has gone to a factory, they get very upset if you do this and you quickly learn not to. Component numbers, or designators, are the primary keys in many of their databases. When you arbitrarily change them, some poor sod has to match every component that’s changed, by hand, to their pick-and-place data and procurement spreadsheets.

    There’s no consequence at all for changing numbers on a whim when you’re hand-building, of course, except that you’ve got to make sure you’re working with the right revision of schematic drawing. In fact, an orderly X-Y numbering regime makes placement and debugging easier, so you should.

    Giving away early, untested draft data to a factory is therefore something to do somewhat carefully and reluctantly: after a few revisions when renumbering is prohibited, finding a resistor on a PCB starts to feel like looking for a window on an advent calendar. You soon need machine assistance, and it means yet another bloody screenful of data to juggle on the computer when you’re already performing a complex task.

    I’ve been proclaiming for years that I can tell, from a long glance at a company’s PCBs, how they operate politically: which business processes rule in their executive suite, how eagerly their designers are looking for a new job, what sort of business strategy has been imposed on them this year, and whether they’re in any form of trouble. Obviously, if you can also see the product the board goes inside and have almost completed a third decade in the industry, that gives you a lot more clues, but the organisation of component designators is a tell to recognise. In it, you can see the autonomy of their R&D team, how well their systems work internally, and how much pressure they’re under to rush a design to production. And if the components are labelled off a hierarchical design (R132_4), you’ll know it’s the Wild West there, and nobody from production even dares to talk to R&D anymore. Factories hate it.


    There is a class of problem that is too taxing to repair with a scalpel and wires. Either you have to scrap the circuit board, or bodge it with yet another circuit board, or just live with the consequences. One such fault found its way into this design, and popped into my head about two days after sending the first PCB for manufacture. Fortunately it was one I could live with, so I did: the control voltages for the first-issue board top out at 3.3V rather than 5V, which limits the range of control over the filters and amplifiers. There are a few ways to fix this, but the most economical and easiest to control is simply to add the right sort of buffer chip. It’s U3 in the flickbook gif above, just above the hatched area. They’re made in the billions, have been in production for about forty years, and cost next to nothing. Best of all, this actually simplified the layout and allowed me to replace eight discrete resistors with two packs, so it barely adds cost. Just don’t ask me to wire one into a rev. 1 prototype, unless you’re sponsoring me for charity.

    I’m going to blame Altium CircuitStudio for two of the green wires. See how pin 14 doesn’t quite connect with the wire on the schematic? Neither did I.

    The package is supposed to warn you about wire terminations missing the grid, so this should never happen. When it forgets, it makes errors that much harder to find because you come to rely on the schematic corresponding to the PCB. In Chris’s day when both were drawn by hand, you’d trust it far less.

    The same part in Chris Huggett’s schematic. Soft pencil on yellowed A3 cartridge paper, 1983. Badly photographed in lowish light and scaled up by a blogger, 2026.

    So that was about four hours.

    The long, horizontal wire was a simple naming error which meant that two areas of the design that were supposed to connect across pages didn’t. That can happen to anybody while you’re having ideas and making and reverting changes: a stupid mistake but forgivable if it’s only once in a design. And the fourth piece of green wire is because ST once thought better about the USB peripheral inside its microcontrollers. To announce your presence as a USB device, you connect the D+ line to +3.3V through a 1.5 kiloohm resistor. Only then will the host start trying to talk to you. Newer microcontrollers build that resistor onto the chip so you can switch it in or out of the circuit in software without wasting a precious external pin and having to place a physical resistor on the board. This one, unfortunately, doesn’t, and I got caught out.

    But anyway, after a weekend of finding these problems, the VCFs and VCAs are working, so I can use the line output and filters. It’s starting to sound more like a synth.

    Along with a demo like this is a stark reminder of what else is missing. For what they are, the filters sound right, but they’re stuck in series low-pass mode, and control mappings aren’t in place yet so, in the video, I’m just setting control voltages directly. Also, the VCAs cannot be dimmed down to silence, which means I’ll be looking for the workarounds in Chris’s firmware that achieve this by (probably) turning down the DACs and the noise generator when the volume is low, and finally zeroing the wavetable completely so that volume zero means zero.

    Anyway, next I’m porting the voice manager while it’s fresh in my mind so that I can play the thing properly. Then, I suppose I ought to work on the filter switching, control voltages and modulators so that those start to sound right. All of which means starting to sketch out the program data and patch management for this synth, which is not going to be quite the same as the original OSCar. These days, MIDI has to work much harder, and we can and should store more than 36 patches.

    The PCB still isn’t signed off completely: there’s the trigger input to test, but that’s comparatively low-risk and the whole synth can be demonstrated with that feature missing.

    Epilogue: I have nobody to blame but myself for falling into the gap. But thousands of other passengers a year are also blaming themselves after coming a cropper on the London Underground. The posters that warn people of danger, all of which I’ve read, aren’t much good if everything about station design, from signage to acoustics to crowd management, bombards passengers with noise, then forces them to make split-second choices or else become an obstacle for others. Would it be unreasonable to fit an electronic sign near every train door, so you know which way to walk to your exit or interchange before you’re even at the station? They can have that idea for free.

  • Operation Stylophone

    True to my rules of last week, my first milestone was to reach a stage where I could play a keyboard and get OSCar making its first noise. Voilà:

    This isn’t impressive at all: I was calling it my ‘Stylophone’ milestone as there’s no voice management; no sense of what a program is; no envelopes, LFOs, or anything. I detect a new note from the keybed, set up all the timers, program in a wavetable, and out comes a waveform.

    It’s not in key yet, because the pitch logic isn’t complete. It isn’t even coming out of the line output: you can literally see me pressing a 3.5mm jack to test pins so the voltage there goes straight to a loudspeaker. Without the mixer, VCFs, or VCAs working, the proper line output socket is currently just decorative (the horrible HF whistle you can hear at the start is a consequence of this hack. The loudspeaker signal isn’t ground referenced properly).

    If I weren’t an experienced designer of synths I’d be a bit embarrassed to have this little to show from a week’s work: people tend to talk up their achievements online and I think I owe it to the world to post something honest. It’s been a slow week, but I’m having to make sure that everything gets done the OSCar way.

    The OSCar hardware is the only reason why any of this is remarkable. The sounds are coming from a platform that very closely resembles the original synth. The firmware you can hear running has very carefully been ported and unit-tested to prove that it does exactly what an OSCar would if you probed the correct pins. The two oscillators you hear are exactly the original’s organ and sawtooth waveforms.

    This week in a progress-o-gram

    The section in ‘kbd’ that I’ve finished annotating is the original voice manager: the logic that describes how the notes that are being played get allocated to OSCar’s two voices (or one voice, depending on which mode you’re in). When you stop playing a note, the same routine checks through all the notes that are still held down, and lends one back to the voice. Then it tells the envelope generator if it should retrigger, depending on which mode it’s in.

    Particularly if you’ve ever played an OSCar in duo mode, you’ll know that the voice manager is far from perfect. If you take your finger off the second voice, the voice manager doesn’t tidy up the voices at all, so it just continues to play until either you take your hand away completely or play another voice. I was seeing bugs just by inspecting the code, and I know that Chris must have been aware of them, but there’s only so much you can fix with six bytes free. Now I have a decision to make about how I fix the voice manager while respecting the sound and feel of the original instrument.

    The part marked ‘sums’ (terrible name, Chris) that I’ve turned green this week is the timing logic. OSCar uses seven digital timers internally, three of which are allocated to each of its two voices. It gets so complicated because OSCar uses fixed-size wave tables, so the sample rate changes with every note: two timers have to be maintained to keep the note’s pitch correct. One of these works at the note frequency, and another works at a multiple of it, counting down from 256. Some logic elsewhere in the circuitry uses this counter to convert the right sample from each wave table at the right time.

    When the pitch gets above about 400Hz, it becomes too high for the hardware to traverse the wave table quickly enough. The third timer then comes into play to begin skipping samples on purpose, effectively shortening the wave table from 256 samples to 128, 64, and so on.

    All of this is governed by some reasonably subtle logic Chris wrote so that the sample-skipping compromise happens in a different place whether you’re ascending or descending in pitch, which makes the change in timbre less obvious.

    So much for a week’s progress. The difficulty of all this integration is one excuse I might give myself; the other is that this was the first attempt to dovetail the ported synth code with a new hardware abstraction layer, so I took a few attempts to get into a pattern that looked like it’d scale manageably to the rest of the code.

    In completing Operation Stylophone, I also reached a realisation about how to progress from here. The original mission was to read and annotate all the firmware first: a kind of ‘breadth-first’ strategy. This was invaluable for mapping out the synth and scoping the work but, once I’d done about two thirds of it, it was clear that this isn’t the right way to continue. There are two reasons.

    1. There’s only so much detail I can hold in my head. Revisiting the timer logic had me looking through and revising my notes just so I could remember what I’d found out a few months ago. It’ll be more efficient to write C routines against routines I’ve only just annotated, to keep them fresh in my memory.

    2. I glossed over important details the first time around. The code is packed with twists and turns that manage edge cases. Occasionally I’d miss these, either by mistake or because I was too tired or bored to traverse them, so again I really ought to be writing and testing working C as I go.

    Now I’ve got a Stylophone to improve, there’s a choice about where to go next: my rules just suggest I should serve playability, and pretty much anything I do from here will improve that.

    Right now, it makes most sense to work on the voice manager, and then do something sensible and rudimentary with the VCA and VCF, so I can use the line socket, listen to both voices at once, and assign them notes more sensibly.