Thursday, January 9, 2025

Button scanner utility board

I've made a chainable button scanner board, similar to the one for potentiometers. Each one connects up to 64 keys/buttons through 8 connectors. When clocked, button statuses are output on a single pin. 

The button status is inverted, so a pressed button reads as 0/GND, an open as 1/V+ 



In addition, a breakout board is available, converting 8 columns + common row to 8 column pins + 8 row pins, making it easy to connect buttons using Dupont connectors.

The breakout boards are made with surface mount connectors to have a flush back, making it easy to glue/tape them to the back of the panel, close to the switches.



Modulation matrix thoughts

I have a working modulation matrix on my XM8 prototype. But something is missing and I haven't had the time to put my finger on exactly what.

Here is a more thorough walkthrough of what could/should be supported.

1) A destination may be modulated by multiple sources, each with their own amount/weight. The sources are summed (to give for example vibrato by modulating a pitch CV by an LFO and summing it with the original pitch)


2) A source may modulate any number of destinations. Again, for example, the LFO may modulate multiple oscillators at the same time etc.

 

Now, these are dead given. But then we have a more complex one

3) A source may modulate the amount of another source. For example, a separate potentiometer may modulate the amount of LFO applied to the VCO pitch.

 

Then we have a special case

4) Multiple destinations may control a function, which in turn is the source of another modulation. For example, multiple pots may control an envelope. The output of the envelope may modulate the output VCA.


Strictly speaking, we could also let the destination directly act as a source, leading to

5) Any destination may be treated as the source of another modulation

 

6) Any destination may be treated as the amout of another modulation


 

Right here it feels like we're entering FM territory...


Summed up into some general rules:

  • A modulation path consists of a source, an amount multiplier and a destination.
  • A source may modulate a destination or the amount of another source
  • A source may modulate multiple destinations or amounts 
  • A destination may be modulated by multiple sources. The sources are summed after being multiplied by individual amounts
  • Multiple destinations may act together to control a function (LFO, envelope)
  • Pots, destinations and function outputs may all act as sources

It would be a good idea to hardwire most pots to specific destinations

Most amount coefficients in the matrix will be zero. It may be better to have a list of 'active' modulations to reduce the number of coefficientds, but that depends on the MCU and what optimizations it may do on the data.

I think my major mental breakthrough here is that I realized that sources, especially pots, must be able to control the amount.

Things I still wonder about

  • Will it always be correct to add, not multiply, the various modulation paths?
  • For simplicity, should we really allow any destination to act as a source?

Oh, and here are some resources for Teensy math:
- https://forum.pjrc.com/index.php?threads/linear-algebra-library-for-teensy-4-1-robotics-project.69778/
- https://github.com/PaulStoffregen/Audio/blob/master/utility/dspinst.h
 

PS: Multiplying and summing two vectors (or matrices) is called a dotproduct.

Sunday, January 5, 2025

Potentiometer scanner utility board

As I prepare to make a function mockup of the front panel, I've designed a utility board that can scan up to 48 potentiometers. The boards can be chained, allowing for a total of 288 potentiometers on six output pins.

The only input from the mcu is clock, reset, +V and GND.



 
Shown here: two input muxes (left), one per 10p connector. Only six of the eight inputs are used but all are adressed as the clock is sequential. The board has 8 input muxes in total. On the right is a single mux that selects one of the 8 input muxes for output to the MCU. Everything is clocked by a CD4520 six bit binary counter. Before scanning starts, clock is reset to make sure it is at 0. It can also be reset early if some of the input ports are not used.

Testing shows that a single channel can be scanned at 50kSamples/second, the limitation is the speed of the ADC on the microcontroller. The analog output of the on board mux'es stabilize after approximately 2uS. 

I've tested the circuit on a Teensy 4.0, and as it uses a single ADC for multiple channels, scanning six channels takes around 113uS. This means that we can do 185 samples/second per potentiometer when using all channels.

As I'm allergic to soldering, I have been looking for a way to connect the pots without solder. My best and simplest solution this far is to insert the potmeter directly into a 10p IDC connector. It stays fairly firmly in place, with the outer potentiometer pins at pin 1/2 and pin 9/10, and the center pin at pin 5/6. 

 

If I connect +V to pin 1/2 and GND to pin 9/10, I can connect the pots at either the front or rear row of the connector, reading the value from pin 5/6. 


 

 

Front row

Rear row

If I modify the cable a bit, crossing pin 3/4 to center and then 7/8 to center, I can connect six potentiometers to a single 10p ribbon cable!

Crossing two and two wires allows me to connect six potentiometers to one ribbon cable


Tuesday, November 19, 2024

Testing the Juno, Moog and JP6 filters

Juno
 

The Juno filter seems to work fine as well. The output is +/- 500mV from a +/-5V input through a 230k input resistor. 

The filter output is compensated on the voice card, with a gain of 5. This will however only get +/-2.5V from the input. Not sure what is going on there but it can be tested more thoroughly when testing with the voice card.

Edit: I misread the schematics, I put an external 230k resistor on the input when the Juno board already has one, meaning the input was attenuated by 50%

Resonance, VCA linear FM and cutoff CVs work fine. The 12/24dB switch has not been tested, neither has the temp sensor.


Moog

The Moog filter also works as it should. The range of the 2p and 4p trimmer CVs are sufficient, the reso balance trimmer needs around 4.6V for centering which is a bit too close for comfort.

The resonance CV at 5V may not be entirely sufficient for self oscillation but that has to be retested when the filter is connected to the voice card.

JP6

The JP6 filter works fine out of the box. I haven't checked the output levels but all filter variants look good and resonance works fine.

Monday, November 18, 2024

Testing the bus mixer and the waveshapers

Not much to say really, the bus mixer works perfectly with VCAs, switches and I2C, though I haven't checked the polarities and gain.

Oh, and for future testing: When leaving out the VCAs and connecting input to output on the FX VCAs - the input 47k resistor and the output 47k resistor will act as a resistor divider. Thus, the output is half of what would be expected, this threw me off a bit before I realised what was going on.

The waveshapers also seem to be working fine - I only tested with a non-symmetric triangle wave from my function generator, but all trim pots and CVs seem to work as they should.

These were the ones I most expected to work. Next up are the filters, I don't particularly look forward to testing those...

Thursday, November 14, 2024

Errata

This is a collection of known PCB fuckups.

56 ch sample-and-hold card v1.0

- Rear rows of the output connectors are not connected to CV output so no CVs will arrive at the mainboard.

Fixed in version v1.1

 

Mainboard v1.1.1

- IC2, selector switch for Waveform/PCM Wave: The control and output pins are mixed up. For testing, a workaround is a manual jumper and no DG413 switch, since PCM Wave is a future ad-on anyway. Can also be solved by creating a custom card with an SMD DG413 on it, with the pins routed correctly

Fixed in v1.1.3

 

- Waveshaper sub oscillator waveform selectors: Waveforms for sub-1 and sub-2 have been reversed, so when sub-1 is square, sub-2 is saw and vice versa. Can be fixed on an updated waveshaper card or the same way as the IC2, by doing a custom DG413.

Fixed in v1.1.3

 

 - The VCO temp sensor is not connected to +3v3 and does not work. There is no 3v3 nearby so best fix would be to add a voltage regulator locally.

Fixed in v1.1.3

 

VCO v2.0

- The saw output from the saw never reaches above 4V, it flatlines halfway through. This is caused by the 1k/1k resistor voltage divider in front of the comparator used to create the square wave. Also, the 1k/1k divider reduces the 0-8V saw to 0-4V, it should have been 0-5V. 

This seems to be fixed by replacing the divider with 100k/168k.
PS: Need to check that this fix does not affect the pitch of the VCO! Isn't this exactly why we have a cusstom pulse wave generator connected? But - there is no reason for the pitch to change because the voltage drop SHOULD be constant.

Distortion, multi FX v1.1

When doing the multi-FX board I used the wrong version of the distortion circuit, so this one has no output gain. Thus, the output is way too low.

There are no spare op amps on the board, but there IS one spare OTA. Perhaps I can reconfigure that one as gain. It would probably be a good idea to add a trim pot to make gain adjustable.

Juno filter

- Not sure this is an error yet, but the output directly from the circuit seems to be +/-500mV from a +/-5V input. It should be +/-1V I think. I misread the schematics, I put an external 230k resistor on the input when the juno board already has one, meaning the input was attenuated by 50%

Filter linear FM

Filter linear FM can never go below 0. It means that it will not oscillate around the set cutoff frequency, instead it will go from the cutoff frequency and up. Not sure if it is an issue or if linear filter FM is usable anyway, I may just remove it entirely.

BUT: VCO lin FM is AC coupled, so the DC component is filtered out. By adding a cap in front of the linear input (or on the filter board) I may not have to do centering/bipolarity. I would have to keep the CV at a normal level of 2.5 volts though. 

TODO: Test both VCO FM and Filter FM without centering but with cap.

Sine phase at output mixer

Sine 1 and 2 direct are not in phase with the output from the SVF and LPFs (it is inverted).

Bus mixer - SVF chain is inverted

This means that we need to invert the SVF output to prevent it from cancelling the LPF signal. If one was to use both SVF and LPF outputs directly to the voice mixer, AND chain the SVF to the LPF as well, SVF and LPF at the bus mixer would cancel out. Definitely a corner case but if it can be fixed, it should.

Bus mixer - gain error in output B

Because of the chaining input, sum B gain is doubled (even when chain switch is open it seems) due to R69 and R50 forming a voltage divider.

A possible fix for both bus mixer problems is to add a two channel op amp. Invert both SVF_CHAIN and SUM_B, then IC2C can be a normal inverting summer.

IC2B can probably be left as is.

Waveshaper

The waveshaper sings! Some caps oscillate and make and audible sound. It can hopefully be fixed by replacing the 100nF caps on the flip flops with C0G.

Fixed in v2.3

 

The LM311 comparator circuit on the sub oscillator creates noise on the ground plane, which is picked up by the VCO, making it wobble. The fix is to redo the comparator using an op amp and reduce the CMOS power to +5V.  

Fixed in v2.3

Testing the CV generator card

I've finally started testing the new cards. First off is the 56 channel CV generation card.

After first testing the 4ch DAC on a breadboard, driving the old 16ch sample and hold cards, and making sure the code ran perfectly on that, I connected the DAC to the CV board and the CV board to a Teensy 4.0 and...

...nothing.

No output at all on the output pins.

A quick check in Eagle revealed the first major bug - I've forgotten to connect the rear row of the connectors, only the front one is connected. Not a problem for testing but it will require a lot of soldering to bridge all the 56 outputs. 

I then switched to the rear pins and...

...again, nothing.

Damn. I do however try to run the DAC at 50MHz and 5V logic supply, from a 3v3 Teensy. It wouldn't be surprising if that lead to some issues.

 I left the card for a few days and returned yesterday. This time I disconnected the DAC and put it on a separate breadboard, running 16 wires over there. I could then connect probes to the inputs and outputs to see if the DAC itself was actually doing anything.

And what do you know, this time everything worked immediately! Very strange. Perhaps the long wires or the connected probes changed something.

Thus, today, I moved the DAC back to the CV board, but left it slightly high to be able to connect clip on probes onto the DAC board pins while it was inserted into the CV board. And this time it worked!

Finally, I disconnected the probes, one by one. When I got to the probe on the SPI clock pin, everything stopped working. I reconnected it and disconnected all the rest, and it started working again.

As a last try, I connected the probe to the other end of the SPI clock wire, close to the teensy. This time it stopped working too.

Sooo... not sure EXACTLY what is going on, but perhaps the added load/capacitance of the probe slows down or filters the clock slightly?

Anyway, once I got everything working, the output looks great!

Closeup of one of the outputs shows a fairly stable level, the noise seen is 0.005V which is most likely the minimum step on the scope ADCs.

 


Four simultaneous outputs


 

Update:

I've tested all channels and they work great. I also tried reducing the SPI speed to 25MHz to see if that changed anything with regards to needing the probes on the clock bus but it didn't help.

I did notice too that the sample and hold op amps get very hot but I experienced the same on the previous 16ch board so I'm not too worried.


Logic level converter

I have designed a small 4 channel logic level converter board based on the TI SN74LVC2T45 IC. It will translate the 3v3 Teensy level to the 5V the DAC expects. I use 5V on the DAC as that's necessary to run at 50MHz.

Most level converters are way too slow for 50MHz, but the TI chip datasheets says that 420 Mbps is possible when doing 3.3V to 5V translation. We'll see.

I also have the option of rewiring the CV board by cutting a jumper and soldering another one, to make the DAC run at 3V3. My most recent breadboard tests seemed to show that it would be possible but it DOES feel a bit risky for a final design.

Monday, July 29, 2024

New PCBs from JLCPCB - Voice card ++

All new cards. Top left: Bus mixer, VCO and Juno filter. Top right: Moog and Jupiter filter. Center left: Voice mainboard. Center right: 2X waveshaper, FX module and bus mixer angled connector. Bottom: CV board
 
Everything mounted together. Looks a bit Frankenstein-ish but it fits!

Even the Juno filter, sandwiched between the voice card and the Moog/JP6 filter fits. I wonder how hot it will get though.

A true beauty!


Assembling voice card and other boards

The day after we left for our summer vacation, the voice card and associated cards arrived from JLCPCB.

I won't test the cards for a while but I DID try mounting everything. It fits beautifully. I had to adjust the spacer/standoffs a bit, here are my new measurements:

Red = expected spacer heights
Blue = actual spacer heights

My conclusion is thus:

Left most (waveshaper) spacer: 11mm + 2 x 0.3mm washer
Left bus mixer spacer: 28mm + 3 x 0.5mm washer (or 29 + 0.5, but I ordered 28mm and it works fine)
Right bus mixer spacer: Not needed, but IF needed, combine a 15mm with 3 x 0.5mm washer (or 16mm + 0.5mm washer) on top.
Top filter spacer: 4mm + 0.5mm washer
Bottom filter spacer: 5mm + 0.3mm washer


Output module - thoughts on architecture

 It's summer time again, and a few days away from home really gets my creativity going!

This time I've started looking at the output module for the synth. I have several goals for the output:

  • Design should support 16 voices
  • Stereo, with per-voice panning
  • Individual outputs per voice
  • Multiple (2 or more) stereo FX pipelines
  • Voice chaining through the voice's ext input, with summing of multiple voices to each input and return to same voice

I also want the following to make a future vocoder feature possible

  • Each voice's SVF can be used as a carrier modulation channel
  • Selectable vocoder carrier: Voice 1 Juno LPF, Sum of multiple voices, external input, noise (for voiced/unvoiced)
  • Voiced/unvoiced selector that effects return to voice


Outputs

We can use two 16 x 16 crosspoint switches (left and right) to select one of 16 outputs for each of the 16 voices. This will support both individual outs and grouping of multiple voices into a single output group. For example channel 1 to 4 can be output 1, 5 to 16 as output 2 etc. We would also need a similar setup to send the effect outputs to the right output groups. PS: Unless we have the same number of FX pipelines as we have voices, it won't be possible to have per-voice effects at the output.

Thought: Do we need per-voice group output amps or will it be enough to use the amps on each voice card?

Effect pipelines

I've designed each voice card with two FX outputs. I intended this to be one output per FX pipeline, but I'm reconsidering using them as left and right outputs instead. I COULD have just tapped the main L/R voicecard outputs, but this will let us pan the FX and main outputs separately - not sure if it is anything worth doing but since the outputs and VCAs are already there it might be a cool feature. 

As a start, each pipeline should consist of a chorus module and a DSP based multieffects module. These will be chained, with the chorus feeding into the DSP. Both chorus and DSP should be possible to disable/bypass. As a side note, the juno chorus always mixes its output with the dry output. In my pipeline the dry signal is completely separate, so  if we include the original signal in the chorus output, the base signal will be twice as high as all other delayed signals. If we REMOVE the original, we need to consider what should happen when chaining, will the original be included in the DSP input??

Either chorus is always added to the input before the fx dsp (but with mute possibility), which adds the original dry signal to the mix - or the chorus replaces the dry signal before the FX, but that means we have to re-add the dry signal later. Not sure it really matters but lets test. Also, the input to FX DSP at the bottom is missing.

At the moment I have two options for the DSP. The Spin Semiconductor FV-1 or the Daisy seed. The FV-1 has a lot of ready-made effects and may be compatible with cards from Tiptop audio. It is however harder to control as it doesn't have any digital inputs and is limited to three analog CVs. It is also limited to a fixed set of effects (8?) but that can be worked around.

The Daisy is a more modern platform with a much higher-performing DSP and DACs. I think it can be digitally controlled as well as controlled using CVs. 

It would be a good idea to see if a future proof FX pipeline bus can be made - using a fixed number of CVs and I2C/SPI bus inputs. 

Vocoding

Now, this is something I promised myself not to work too much on, but it would be stupid not to include support for it, so here goes.

Each voice card has a state variable filter that can be used to create separate bands from the synth/carrier signal by feeding it into the external audio input of each voice. We can then (obviously) use an external synth as the carrier.

A vocoder switches between a carrier signal (normally a harmonics rich synth sound) and a noise source to make voiced/unvoiced sounds, so we need to be able to select between these. By adding an input selector mux to the external input signal, this can select between external input and noise.

It would be cool to be able to use the synth engine of the XM8 itself for the synth part. I previously considered using voice 1's LPF output as the synth/carrier for all bands. This would let us use the SVF of voice 1 for vocoding as well, giving us up to 16 bands.

I've since reconsidered this, perhaps it would be cool to be able to sum multiple of the voices to get a more harmonic-rich signal? By summing multiple voices and sending them to the external input of every other voice card, we can get a compromise between the number of voice cards used as vocoder bands and voice cards used for generating the carrier. For example, voice 1 to 3 can generate the carrier, and the remaining 13 channels can be vocoder bands.

We do get an issue though, as we need to change the center frequencies of each vocoder band when we reduce the number of bands. This means that instead of having fixed filter frequencies in the vocoder analyzis module, we need voltage controlled ones. These can use a subset of the JP6 SVF, requiring two LM13700 per band.

The first and last bands (LPF and HPF respectively) may stay the same but their CVs must be routed to different voices (at least one of them - we can let the top band always map to the last voice card).

External input select vs voiced/unvoiced

Given the following four channel mux selection truth table:

A B = SRC

---------

0 0 = external input

0 1 = Voice card 1 juno LPF

1 0 = Voice 1 return channel

1 1 = Vocoder noise source.


If we OR the selector signals A and B from the MCU with the V/U signal from the vocoder analyzis module, the V/U will override the MCU, turning on the noise whenever needed.


Return routing

We should make it possible to return the signal from any voicecard to itself or any other voice card. It should also be possible to sum and route multiple voices to the same target. All this can be achieved with a 16 x 16 crosspoint switch. The switching point should be at the summing point of an op amp at each output. This will, however, mean that an input may be routed to ONE output at a time. We can still route multiple inputs to the same output though. Also, we may have to add a resistor to ground at the summing point, to be used when no inputs are connected to that channel?



It must then be possible to select between (global) external in and the per-voicecard return as inputs to the voice card's external input.

Some uses of this would be:

  • Overdrive/feedback - by returning the signal to the same voice card (in phase!) we can make up for the lack of feedback-based overdrive in the filter module. This is how the minimoog does it. It may still lock up filtes though, so it must be properly tested.
  • Phasing - we can sum a set of voices and then chain the output through the rest of the voices' SVF filters, which each one having a different notch frequency set. NB: 
  • Vocoding - return routing lets us sum multiple voices to use as the carrier signal. This requires a special case for the first voice where the routing output is sent to the external input selector to be used as external input for all the other voices


A suggested output block schema


EDIT:

As the ETI vocoder has 14 bands, a simplification would be to allow two of the 16 XM8 voices to generate the carrier, and use the 14 others for vocoding. By doing this, and not allowing a varying number of vocoder bands, we greatly simplify the analysis module - it can have fixed frequency filters and fixed output routing. Two voices for carrier will still mean 6 oscillators which should be plenty for making a complex signal.

We could then also leave out the LPF input to the ext in mux, making the voiced/unvoiced switching much simpler (no need for or-gates). 
 
We should even tap the carrier signal before the return mux to make the routing logic simpler. We need a way to disable output of the two carrier voices from the output. Since the Voice out signal is pre-output VCAs we can tap this and just turn down the voice output VCAs.

Friday, July 5, 2024

Fatar TP9/S in Fusion 360

I've created a 5 octave fatar keybed in fusion 360 to be able to test collisions and to position screw holes correctly. The drawing is based on the Fatar technical drawing so it should be good enough for production






Tuesday, June 25, 2024

All things voice card related ordered

 ...well, almost - the digital parts remain.

But still - tonight I placed a huge order with JLCPCB, 5 copies of every card needed for a voice:

VCO

Pre-filter FX

Bus mixer

Bus mixer angled connector

Juno filter

Moog + JP6-filter

Waveshapers

Mainboard


Ordering 5 instead of just 2 copies is kind of a gamble as I don't know if everything works yet. But the cost (excluding shipping) is only 50% more for five than for 2. I guess I just have to wait and see if the gamble pays off. 

I have yet to sign off on everything, but I expect that part to go smoothly. So while we wait, here are some cool board shots

3D model

I've used Fusion 360 to check that everything fits together and that we have the clearances between cards that we need. 

I COULD have converted the eagle designs into something that Fusion can read, but this is the next best thing:

All the cards making up the voice. To the left is the (yet to come) digital board.


The narrow board closest to the camera is the bus board. To the left is a combined Moog/JP6 board and to the right a dual waveshaper board. Top left is the bit crusher (the only PCB I am not redoing!), below it is the FX board. Below the Waveshapers is the VCO


Under the Moog/JP6 filter board is the Juno filter. I really wonder if this will work out, the spacing is very narrow and it may get hot in there. Also note the vertically mounted board connecting the bus mixer to the mainboard.

On to the PCBs

A panelized board containing two waveshapers, the FX board (ring mod, distortion and noise) plus a special board that will make it possible to mount the bus mixer board parallel to the mainboard but 3cm away from it


Another panelized board, this time it's the VCO, Juno filter and bus mixer boards


The third board is the dual filter PCB, containing the moog-style ladder filter and the extended JP6 state variable filter.


The CV board - made on a four layer card to minimise noise (hopefully). This one has 56 output CVs!


Finally, the mainboard. I've spent six months or close to 200 hours on routing this, I REALLY hope it works.