Sunday, 14 June 2026

Improving Tape Loading on Minstrels Part 4 - A New Hope

The new Minstrel 4th V4.52 is here - looks rather splendid, doesn't it?

Those are available to order now, and will be shipping next week once I have finalised the ROM(s).

I will go through all the changes in another post.

For now, I will roll back time to a Patreon post from a few weeks ago, when I was still trying to find a better solution to loading from tape.


In the last post, I had a brilliant idea, or at least I thought so. It seemed really neat, and it worked very well in certain cases, but not all, some needed various values tweaked to make it work, others just wouldn't work due to the signal level.

I accepted that was not, actually, the answer, even it the breadboard I tested it on did look very pretty.

So what is?

I went right back to the start with the input circuit from the Jupiter Ace.

At this stage, after all the different versions I have been through , I decided to go back to the original values, even the 12KΩ, which together with the 47nF, makes a high-pass filter at 282Hz.

There are lots of 47nF and 1KΩ parts in the Ace design, so you can see why they chose those values. This is the only 12KΩ, so I presume the value was chosen for a reason.

The seems to be tailored for an input threshold of about 1V, based on the original 74LS367 input gates.

The top trace (yellow) shows the input signal, the middle trace (green) shows the filtered signal, and the bottom trace (blue) shows the processed digital output. This will be the same for all the scope shots in this post.

You can see the filtered signal from the longer pulse (representing a 1) has decayed to about 1.5V by the end of the pulse. The shorter pulse (representing 0) only drops to about 2.5V.

This is from an ideal input source, but this could be used with various different media players, various different tape players playing tapes of various different ages and origins.

I tried various logic gates last time with different input thresholds, but most of those require too high an input. I think the best option is going to be a comparator as that can have a variable threshold which can be set to suit the input source.

To that end, I am going to fit a variable resistor labelled "Threshold". This will allow the user to set the threshold level of the input to suit their particular input source.

(I don't want to dampen the sense of "will it work?" jeopardy, but this photo of the pot in the final product is maybe a slight give away. There is much tension in the universe these days, so I hope this little glimpse of the future will allow you to continue this, no doubt suspenseful, roller-coaster of a development blog, safe in the knowledge that everything is going to be fine.)

When set horizontally to the left (about 9 o'clock), should be about right for many cases, and 8 to 10 o'clock is probably the range for most things.

I have added a capacitor there to stabilise the input from the variable resistor.

The value of 47nF is arbitrary, I could have used 100nF like the rest of the decoupling, but I am conscious of managing the parts list.

There is already one 47nF in the new load circuit, and another in the save circuit, so by adding a third, it keeps all the load and save circuit capacitors the same, and also means there are now 3x47nF caps, which should make it easier for the kit builder to differentiate from the 1x1µF and 2x22pF.

I have shown an LM392 comparator, as these are the ones I used during testing. This is a single 8 pin package with a comparator and an op-amp, although I am not using the op-amp anymore.

You sometimes see spare op-amps in dual or quad packages with the pins left floating, or with both input tied to ground. According to the datasheet, it is best to set it up as a unity gain amplifier connected to some fixed signal rather than tied to either rail. The Vref reference voltage from the pot seems a good choice. I did consider using the buffered output to feed the comparator input, but as I saw last time, the output range of the op-amp is a bit over 0V to about 3.5V, so not the 0V-5V range the reference voltage would cover.

I may change this in future to an LM393, which is similar, but both halves are comparators. I don't need the second one, but it is cheaper than the LM392. There is also the LM311, which is a single comparator, but that is more expensive. For this first batch anyway, I will stick with the LM392.

The comparator doesn't like inputs below 0V, so I should add some input protection to the negative half of the input waves after the 47nF capacitor removed any DC offset.

Again, the 12KΩ is arbitrary, it is there to protect the input source when the signal is negative and the diode is shorting it out. A value of around 10KΩ would normally be used, so 12KΩ is near enough, and keeps with the other two 12KΩ resistors in these circuits.

That resistor will also double as an input resistor.

Next I want to add a bit of hysteresis to clean up the input signal.

The 220KΩ resistor adds some positive feedback. We all need positive feedback (don't forget to hit the like and comment on the social media post that led you here please folks, there is no algorithm on here, only my fragile ego, and that needs all the help it can get)

Before I explain how that works, there is one final thing to add. The output of the comparator is open collector, so it needs a pull-up resistor to drive a logic gate input.

The 74HC245 input buffer is nearly sandwiched between two 10KΩ resistor arrays, and there is a spare pin in just the right place, so I will use that rather than adding another discrete resistor.

(10KΩ is about right, 1KΩ would add 5mA to the power consumption all the time the comparator output was low - i.e. most of the time. The current board only draws 50mA in total, so that is a little unnecessary. A 10KΩ pull-up would use 0.5mA. 100KΩ would only use 0.05mA, but at the expense of slower rise time of the output, so 10KΩ is about right).

How Does the Hysteresis Work?

I am glad you asked. Let me explain.

The output of the comparator will be either 0V (when the output transistor drives it low), or pulled up to 5V (when the transistor is off).

This 0V or 5V is fed back to the input via the 220KΩ resistor. (why 220KΩ? well, there is already a 220KΩ resistor on the board, in the reset circuit, and is in the right range, around 20 times the value of the resistor feeding the input gives a maximum of about 5% hysteresis)

Let us look at those two conditions separately. Firstly, when the output is low.

One end of the 220KΩ is driven to ground by the comparator, the other to the input to the comparator.

I have rearranged the circuit, and removed some components that are not relevant here.

The 12KΩ and 220KΩ resistors form a potential divider across Vear, the input signal. The signal which drives the input of the comparator is Vcomp.

Vcomp = Vear * (220KΩ /(220KΩ + 12KΩ) )
Vcomp = Vear * 0.95

When the output of the comparator is low, the input to the comparator is a slightly attenuated version of the input, letting about 95% of the signal through.

When the output is high, the right hand end of the 220KΩ resistor is now pulled up to 5V via a 10KΩ resistor, so the circuit can be rearranged again.

There are different ways to calculate this, usually involving working out current flow at each node etc.

The way I looked at it is to imagine the case where Vear (the input on the left) is 0V. There will then be a potential divider with 12KΩ on one side and the 220KΩ and 10KΩ on the other, with the voltage across it being 5V-0V.

If Vear was 1V, then the end of the potential divider would be at 1V, so the actual potential across the potential divider would be 5V-1V.

With the potential as 5V-Vear, Vcomp can now be calculated.

Vcomp = Vear + ( (5V - Vear) * 12KΩ / (12KΩ + 220KΩ + 10KΩ) )
Vcomp = Vear + (5V * 12/242) - (Vear * 12/242)
Vcomp = Vear - (Vear * 12/242) + (5V * 12/242)
Vcomp = Vear (1 - 12/242) + (5V * 12/242)
Vcomp = Vear * 0.95 + 0.25V

The 95% attenuation is back, but now the input at the comparator is 250mV higher.

This means the input signal gets a 250mV boost whenever the output is high.

Note, this means the 250mV boost is fixed, and is relative to the 5V supply voltage, not the input voltage. This will have more of an effect on smaller signals, which are more likely to suffer from noise, so will benefit from the hysteresis more, and relatively less of an effect on larger signals (which should not need it as much). Perfect.

At the maximum expected input of 5V, this is 5% of that, so with the 5V input is attenuated to 95%, 4.75V, add the 0.25V boost and you get back to 5V.

At 1V, that is attenuated to 0.95V. The boost takes that to 1.20V.

To test that, I am using a triangle wave from the signal generator on the scope.

With no feedback, the filtered signal is just the triangle wave with negative half cut off by the diode.

With the feedback resistor added, you can see a slight step in the filtered signal.

If I zoom in, you can see the step lines up with the output.

That is a 5V triangle wave, so the 0.25V is not that visible, if I drop that to 1V then it is much more obvious.

Yes, I Know What it Says, But What Does it Mean?

This should ensure clean square wave output.

Suppose the threshold voltage is set at 1V.

Let's start with the input voltage as 0.75V, this is below 1V, so the output is off.

If there is some noise on the input, it might be varying all the time between 0.70V and 0.80V for example.

As it approaches the 1V threshold, the first time it crosses the line, the output goes high. But since the input is noisy, the input might be varying between 0.95V and 1.05V, so, it might immediately fall just a little below the line, so the output goes low. Then back up again, and repeat until the range of the input is all past the 1.0V threshold.

With hysteresis, the first time it passes 1V, the feedback adds 0.25V to the input, so the voltage the comparator sees is 1.25V. Even if the input is noisy, this would translate to 1.20V to 1.30V, well away from the threshold.

The same happens on the way down, The threshold is 1V, but the comparator is seeing the input voltage boosted by 0.25V, so it will not turn the output off until the actual input drops to 1V - 0.25V, 0.75V.

When this happens, the 0.25V boost is removed, so the comparator now sees the 0.75V, which is well under the threshold of 1V, so it will it will be a clean downward pulse as well.

The input voltage is now at 0.75V, with no boost, back to where we started, the output will not turn on until it hits 1V again.

Testing Ace Loading

Time to go through some tests, Jupiter Ace first, since this is the Minstrel 4th.

To start with I am looking at the best case. Driving the input direct from a 5V square wave from an Arduino based player, TZXDuino or one of the many variations.

Ace tapes start with a leader tone, this should appear as evenly spaced black and white lines.

If you don't see the spacing at the start like that, then you need to adjust the threshold.

If you have the threshold too low, you might see no lines.

If you have the threshold very high, you might see no lines.

If you have the threshold a little too hot for Goldilocks, then you might catch the top of the pulses, and the outputs will be too short and you will see thin lines.

The load data is always text colour, so it still works in inverse mode, the data is white lines here, rather than black.

Here the threshold is too high, close to the top of the green spikes, so the output pulse is correspondingly short.

Turning the threshold down, the lines will get thicker, until this get the the right size. Stop when the lines are about 50:50, they won't get any wider, they will just disappear if you go too far.

One the same scale, data is represented by a slightly shorter pulse for a one.

And an even shorter pulse for a zero.

Zooming out you see the sequence of ones and zeroes.

The data should look like thick and thin lines.

The threshold should already be set right, but it it was wrong you would again see nothing or only short pulses / thin lines.

This shows up as thin lines, and no thick lines.

You can see the point in the downward slope the output turns off and the 250mV boost is removed.

Once you get the level right, you probably won't need to adjust it, about 9 o'clock is usually about right.

I am not sure if it is the TZXDuino code, or the actual TZX file, but at the end of loading, it goes through a series of low frequency clicks.

It seems they are about 15Hz.

These show up as thick horizontal bars.

The bars you see are short compared to the actual pulses as they are filtered out, and drop below the threshold relatively quickly.

Computer, zoom and enhance.

That all seems to be working nicely.

It is A 3D Maze, but not that 3D Maze. Presumably set sometime after Rex went extinct.

RIP Rex.

Hang on.

Who built that other maze then? Surely Rex doesn't have opposable thumbs, or a propensity to use tools?

Did they use the time-scoop?

Anyway, sorry, this is a different maze game. One which draws a maze.

You can watch it building the maze as it goes.

Then you just need to navigate from the starting point (black circle, bottom right) and see if you can find the exit (hole it the wall at the top)

Which I did (although I may have selected a slightly smaller maze....).

Testing ZX81 Loading

Whilst I have it setup ready to go, it would be rude to not load the other 3D Maze, the one with Rex in, and the original ZX81 version.

Using the same scale as before, the ZX81 data pulses are shorter again.

Although it takes nine of these pulses to represent a logic one and four for a logic zero.

You can see the groups of pulses as it is loading.

The countdown is a useful diagnostic tool for loading.

When you have the setting wrong, you only see occasional lines, and the loading box shows "....", which indicates it is yet to received a valid byte.

When it does, it starts loading data into memory starting at $4009. A few bytes in, it writes to $4014 and $4015. Those sets the address of the end of the file.

The countdown then updates to show how many bytes are left to load.

Most games are less than 16K, so the countdown would be a few thousand up to almost $4000.

If you see anything above $4000, it is probably wrong, and is going to fail.

However, it is still a useful test as you need to adjust the volume of your player, and/or the threshold level until you see the countdown continually ticking down.

Once you have that set, you can rewind the tape, reset the computer and start loading again.

If you see any stuttering, this means bytes have been missed, and when you get to the tape, the count down will not have reached $0000.

Ooof. So close, but 15 bytes did not read correctly, give it a go again, maybe with a slight tweak, or try the other side of the tape.

In this case, it was a reliable source, so it loaded fine.

I am still not convinced Rex built this maze. Look at how even the walls are...

Oh no!, he heard me...

Oh well, that's what I get for daring to question his undoubted talents as a maze builder.

I will not annoy Rex any further for the moment, instead I will turn my attention to a new ZX81 game I have been testing. Blake's Zevious Seven, by David Stephenson.


This works very well on the Minstrel 4th port of ZX81 BASIC.


(with one exception, the keyboard remapping of the bottom row, so all you need to know is press N for fire, not M, or press K to redefine the keys and pick a different key)

David has even added support for the Boldfield joystick RC2014 card.