søndag 16. april 2017

Juno 60 pre-filter level control

The Juno 60 mixes several waveforms before the filter, and it has a clever way of controlling the sub oscillator volume. As the sub oscillator output is a square wave, the wave is considered a binary on/off signal. It is connected to the base of a transistor, which when turned on and off either sinks its collector to ground or leaves it as it is.

To control the wave volume, the collector input is connected to the panel potentiometer (through a series of buffers/mux/demuxes, but that doesn't really matter, the principle is the same). The wave's amplitude (or "on value") will then equal the level of the panel potentiometer, though negative as the potentiometer value is inverted by IC17 on panel board A. The voltage is passed through an analog switch, IC16, which in turn is controlled by the Sub oscillator on/off switch, to completely disable the sub oscillator (incidentally, this feature has been removed from the Juno 106, here the potentiometer voltage is connected directly to the transistor collector).

Interestingly, the same arrangement exists for the pulse wave, only this time the analog switch connects the transistor to -15V instead of to a variable voltage. If one would like a controllable pulse wave volume, it would likely be easy to inject the control signal here.

As for the saw wave, it also has a switch and a transistor connected to it. However, as the saw wave is not binary, it cannot be controlled the same way. Instead, the wave is connected to the collector, and the transistor base is connected to the analog switch on panel board A. The wave is then sunk to ground if the transistor is on. In other words, the saw wave has no pre-filter volume control, only an on/off switch.

The noise input has its own volume control on panel board A (all voices use the same noise generator).

Oh, and by the way - all waveforms have a range of 0 to maximum -15V (the datasheet says the saw wave is 12V p.p, I have not checked the others but they have to be about the same to be mixable - the sub oscillator level for example originates as a 0 to +5V voltage but is inverted and amplified by IC17, and the pulse wave level is always 0 to -15V). They are fed through a 10uF non-polar capacitor (C5) just before the filter, which probably centers them around 0V.



onsdag 5. april 2017

Juno 106 vs 6/60 DCOs

There are some differences between the DCOs in the Juno 106 and the Juno 6/60 - except for the fact that the DCOs on the 106 are integrated into a single chip.

First of all, according to the datasheet, the 106 uses an NPN instead of a PNP transistor to reset the integrator (saw wave converter).

More interestingly, the way they sum the saw wave and the pulse waves are very different.

The Juno 60 has a separate control line for the pulse wave, connected to TR2. It looks just like the one for the saw wave (TR3) so one can assume that it turns on and off the pulse output. Also, the output of the pulse is sent through D2 which will block any positive halves of the pulse (? which sort of makes sense as the saw wave is also negative only).

The 106 on the other hand, has no such control line, which means that the pulse output is always on. The pulse output has a diode to ground which I assume means that it will never be negative (?).

So how can the 106 output a saw wave and no square wave? One theory may be that if the user selects saw wave only, the pwm is set to 50%. Summing the sqare and saw waves will chop up the saw wave just as it reaches its half period, and move the remainder upwards. If the amplitude of the saw and square waves are equal, the saw wave will magically realign with its phase shifted half a period, this time centered around 0V.

DISCLAIMER: This is only my initial theory after studying the datasheets, no measurements have been made. 

But how about when both the saw and pulse waves are on? Wouldn't this mess up how the wave turns out? Since the saw wave is positive and the pulse is negative, couldn't the total amplitude end up being double?

Well, the high part of the pulse will always come at the second half of the period, thus it will never "lift" the saw wave from higher that minus half the total voltage p-p. Also, The parts that are lifted will only be lifted by 1 x the voltage p-p.

In practice, this means that if we could set the duty cycle to 0%, the output would be a saw wave that starts at 0 and drops to minus the total voltage p-p. If the duty cycle is 50%, we get a saw wave with the same amplitude centered around 0V.

This is interesting and may reveal a flaw in my assumptions. As the wave is centered around 0V by a capacitor later, summing a pulse and saw wave this way will only shift the saw wave phase! I need to check if the polarity and phase assumptions for the square wave actually holds. What happens if instead the polarity is reversed or the phase shifted by half a period?


TODO: Write about SUB OSC and level control (done by using the output from the DAC) and how the passing through a diode affects the signal (reversed in one)- one uses NPN and the other uses PNP, 60 has a resistor to GND at the transistor base. The 106 has no on-off switch for the SUB OSC, only a volume control.

Both the 106 and the 60 DCOs have their outputs mixed with noise (with adjustable volume) right before a 10uF non-polarized cap and injected into the IR3109/800170 filter chips. The mixing point has no opamp connected to it so I assume this job is done by the chips. I guess the cap is there to filter out any DC component and center the waves around 0V. I have not looked closely at this - what happens here when the frequency changes for example, will still stay centered during the transition because the amplitude is still the same?

BTW: NP in the juno datasheet means Non-polarized (capacitor). MF means metal film (resistor).  G (capacitor) may mean 2% (needed for accuracy in the integrator).


mandag 3. april 2017

DCO saw core testing

I built the DCO saw core on a prototyping board Friday evening, and after some initial trouble, I got it working very well.

The core is heavily inspired by the Juno 6/60 DCO. The output of the MCU charges a capacitor, turning the output square wave into positive/negative spikes on each square wave edge. These in turn briefly switch on a transistor that discharges a capacitor. When the transistor is off, the capacitor is charged using a constant-current scheme where the cap is connected across an opamp (just like in a normal saw core VCO, see section "That old opamp trick again" of http://xonik.no/theory/vco/reference_current.html).

The Juno 60 uses a 2SA1015 PNP transistor. I tried replacing this with both a 2N3906 and a BC557, they both work very well.

MCU output pulse train (top) vs. transistor control spikes (bottom). top is 5V/square, bottom is 1V/square and shifted down to make both visible

I had no DAC available for the trial, so the charging current was regulated using a potentiometer as a voltage divider, buffering the output with an opamp and piping the result through a resistor to convert it to a current. After initially screwing up and connecting the center pin of the pot to ground, things started working very well.
A perfect 5v p-p saw wave generated from the pulse train on top. 

A few challenges still persist:

1) The output wave starts at 0 and goes downwards until it is reset. It has to be centered

2) My calculations are based on an assumption that the maximum voltage should be 5V. I completely forgot that it has to be 5V on each side of the wave, making the full wave 10Vp.p.

3) For some reason, the charging stops at -8V. Not sure if this is due to the opamp or something else, but it has to be fixed. The Juno 60 service manual says they have a 12Vp-p output, so it should be possible to fix this.
The charging of the cap maxes out at 8V (looks like 10V here but Y-offset was wrong).
4) Charging starts at the negative going edge of the MCU output wave while the MCU output wave is first high then low through the course of a cycle. This has to change, either in code or by replacing the PNP with an NPN transistor (The Juno 106 service manual says it uses an NPN but I couldn't get this working immediately. I'll look into it).

5) With a 100k charging current resistor, the charging current won't be strong enough for the highest frequencies. A 39k resistor may work (but not for a 10Vp-p wave).

6) I should check if a constant reset timer interval may work (e.g. not a 50/50 duty cycle for the MCU output wave). If so I'll save some clock cycles during frequency calculations.

torsdag 30. mars 2017

Alternative approach - DCO MCU

It would be possible to use a lower-end PIC32 MCU as the DCO MCU. We'll get a few advantages:

1) It can run at a higher speed so calculations will be faster
2) It may have enough ROM to store a full lookup table, or where we may only have to interpolate every second sample. As the MCU is 32bit, interpolation is a simple case of adding two adjacent samples and shifting right by one (dividing by 2).
3) Even with a lookup table, 16 bit multiplications are supported in hardware so calculations will be very fast
4) Both input and output SPIs are buffered so we need not fear losing bytes
5) It natively supports I2S so interfacing with cheap DACs from ebay is possible.

Cons:
1) It may possibly be harder to write an accurate timer as it has a different architecture with more complex pipelining?
2) Price (but not an issue if using DACs from ebay).

BTW: a faster interpolation without the use of a derivative lookup table is also possible on the PIC18F if we choose one with at least 64k program memory, such as the PIC18F26k40. Chosing the PIC18F27K40 means we will not have to do any interpolation at all as it has 128k program memory.

søndag 26. mars 2017

SPI Daisy chaining

Just  a quick tip from the PIC18F datasheet: SPI interfaces on multiple MCUs may be daisy chained, connecting the output of one to the input of the next. They will then function as a long shift register, shifted 8 bits for every SPI send. NB: Chip select must be connected to all MCUs if used.

DCO: SPI and DAC accuracy

A few compromises have to be made when making the DCO. There are however a few things that must be done right.

First of all, we cannot afford to lose any input commands. This will put the SPI input buffer in an unknown state, possibly locking up the DCO.

With this in mind, we can do a few calculations.

First of all - each frequency update is based on a 16bit integer. The SPI buffer is only 8 bits long, so two bytes must be transferred. Each transfer triggers an interrupt, and that interrupt must copy the transferred byte from the SPI buffer to somewhere else before the next byte arrives.

Fortunately, the SPI buffer is, as it says, buffered. This means that it is not written until the last bit of the byte is received. In addition, there is a short delay between bytes.

As an example, when running the SPI bus at 200kHz, a byte is 40uS long. The delay between two bytes is 7.5uS (when output from node.js on a Raspberry PI).

Running the MCU at 20MHz we have an instruction clock of 5MHz, and each instruction takes 0.2uS. This means that with a 200kHz SPI bus and 20MHz clock, we have 237 instruction cycles to handle a received byte.

This is of course much more than we need - as long as the interrupt handler triggers immediately. But for the DCO to be as accurate as possible, we have given priority to the timer that sets the output wave period. The SPI interrupt will be blocked if a timer interrupt has been received and will not be treated until the timer interrupt handler returns. Thus, we have to make sure the time it takes to enter the timer interrupt handler, do whatever it needs to do, return from the handler and then enter the SPI (low priority) interrupt handler, takes less than 237 instructions - if not, we may be inside the timer interrupt handler when the next SPI byte arrives and we'll lose the previous byte.

This sounds all good, right? The time it takes to reset the timer is not that long. Well, we do actually have a problem. If we are to both reset the timer AND change the DAC value (that controls the current that charges the integrator capacitor making the saw wave), we run into trouble. The DAC is written to using SPI, and we have to write three bytes to set it. Unless the DAC SPI runs at several MHz, we do not have time to write to it within the 47uS we have available. In simple terms, we cannot write to the DAC inside the interrupt handler.

So what is the consequence of this? 

The only other place to write to the DAC is inside the main program loop. As we will be at an arbitrary place in the code when a timer interrupt triggers, we will get a delay from when the timer triggers to where the DAC update call is found (+ the time spent writing to the DAC).

To reduce the maximum delay, we may check if a DAC update has been requested and update the DAC at several spots in the main loop.

But how big is the consequence of delaying the DAC?

At 200kHz, updating the DAC takes approximately 135uS = 675 instruction cycles. This delay is unavoidable.

The longest single method within the main loop, recalculating the frequency, takes 723 cycles. If we break this up into 5 intervals, we'll add around 150cycles to the maximum delay, which will then be around 825 cycles or 165uS.

What does this mean?

It means that for 165uS, the DAC will output the wrong voltage, and the capacitor will charge too fast or too slow. If it charges too slow, the capacitor will be at less than 5V when the charging is reset by the period timer. If it charges too fast, it will be at more than 5V. But how much?

Let's look at the two extremes:

Going from 16.5Hz to 20kHz

Here, the DAC will have a very low charge current. The period at 20kHz is 50uS. This means that for a little more than three periods, the charging will be way too low, in fact probably so low that the wave will look completely flat. However, this is only for 3 of 20.000 cycles within a second. Question is if it is audible.

Going from 20kHz to 16.5Hz

The DAC will have a very high charge current. It charges at the same level as when the frequency is 20kHz, which means that after 50uS, the output value is 5V and after 150uS it has reached 15V (but the buffer opamp or other parts of the circuit probably saturates, keeping the maximum at around 14.3V. The cap stays at this level for one full charging cycle, around 61mS. This is not a very ideal situation.

This is of course in the extreme cases. Most often the change in pitch will be small, but a few octaves are still likely.

What can be done to remedy this?

1) Increased DAC SPI speed - pushing the speed to 2MHz will reduce the write delay to 13.5uS, with a total of 43.5uS including the delay before we reach the reset DAC code. This is if the MCU and DAC can handle the increased SPI speed

2) Increase the MCU speed from 20MHz to 32MHz - this will reduce the maximum time before the DAC write is started from 30uS to 18.75uS (as each instruction now takes 0.125uS instead of 0.2uS.

3) Check more often if we need to update the DAC, further reducing the maximum time before the DAC is written to

4) If the DAC SPI speed is sufficiently high, put the write back into the interrupt routine, removing the delay before a write altogether.

If 1) is possible, and the rest of the timer interrupt handler takes less than 47.5uS - 13.5uS = 34uS, 4) is certainly the best option.


Input SPI speed

We chose 200kHz as the SPI speed at the start of this post. At this speed, 16 bytes will take 47.5uS to transfer (inc delay between bytes), giving an effective transfer rate of 21kB/s.  The Xonik M8 voice controller runs at less than 4k updates/second, so this is sufficient for updating tree DCOs at that rate. The PIC32 has a multi-byte SPI buffer, so we may actually write all bytes to the SPI buffer and forget about them, leaving the voice card MCU to do other duties while the buffer is written (though we have to write to the separate DCOs one at the time as the chip select lines must be changed between the DCO writes.

To further improve the performance of the main MCU (and reduce the delay between when a frequency update is requested and a new frequency is visible on the output), we should calculate the maximum time spent in the period timer interrupt handler and optimize the SPI speed such that the time spent transferring a byte is just barely longer than this.


Maximum delay

The maximum delay from a byte request has been received at the main voice controller to it is visible at the DCO input may be calculated as follows:

2 x matrix calculation time
+ 2 x byte transfer time
+ 1 x transfer delay
+ 1 x time spent calculating new frequency params
+ 1 x delay writing to timer registers
+ 1 x time that must be left for an update
+ 1 x longest cycle time
+ 1 x time within period interrupt handler
+ 1 x maximum delay before DAC write starts
+ 1 x DAC write time.

2 x matrix calc time because the command may arrive just after a calc has started and be written at the end of a calc update


Update: SPI and DAC speeds

The MAX5216 SPI can run at 50Mhz. The PIC SPI runs at maximum Fosc/4, which equals 5MHz with a 20MHz crystal, 8MHz with a 32Mhz. In any case, transferring 24 bits takes approx 27 instruction cycles, so setting the DAC in the interrupt routine is well within what is feasible. Thus, the delay from period start to the DAC is set is 27 * 0.125uS = 3.4uS + any cycles between the timer reset and the call to set the DAC - 7 cycles + the time it takes to call the SPI function - an estimate may be 40 cycles = 5uS in total (at 32MHz).

This means that in the case of a too-high charging current, the cap will be charged at max for about 1/10th of the charge time at 20kHz, contributing about 0.5V too much to the end result (5.5V instead of 5V). This is probably tolerable.

Similarly, the whole interrupt function will take 33 cycles (timer) + 40 cycles (DAC). Add 10 cycles to enter and store the SPI byte and the total is 83 cycles or 10.4uS. Transmission speed will then have to be more than 1.3uS per bit, which gives a max SPI speed of 769kHz (at 32MHz)

Update 2:

The only times we should have to update the charging current will be right after we have calculated and set a new frequency. For most frequencies, this update will happen right after an SPI write (for low frequencies we will get a delay, though). If we keep the DAC update outside of the interrupt handler, we will still normally not be inside the calculation routine for a new frequency when the interrupt returns, so the delay between timer update and DAC update will be minimal. We may still encounter a large delay as it may take up to one period from frequency calculation to the frequency has been set. If SPI bytes arrive faster than this (as they most likely will if the main controller runs at 2-4kHz), we may still be inside the calculation routine.

By moving the DAC update we'll shorten the delay to 43 cycles = 5.38uS, giving us a bit time of 0.673uS and a max SPI speed of 1.49MHz (at 32MHz clock speed)

Ultimately it all comes down to what is most important - a high SPI speed to minimize the time the master spends writing or a short delay before the DAC is set to assure a high max voltage accuracy.

As mentioned previously, we may use the multi-byte SPI buffer on the PIC32 based voice controller, so the exact write speed is not all that important (as we do writes as fire-and-forget) but faster is still better - we will have to write some special code that writes to the DCOs at regular intervals through one matrix recalculation cycle as we cannot afford wasting calculation time waiting for a write to complete before filling the SPI buffer with the next DCO values (Though perhaps it would be possible to come up with a chaining scheme where six bytes are clocked through the three DCOs before they are "commited" and the values read - perhaps by a chip select line going low or similar. The PIC32 is capable of generating an interrupt once the SPI buffer is empty, so it's easy to add a single line change when transmission is complete).

onsdag 22. mars 2017

SPI from raspberry PI to PIC18F

This is mostly for my own reference later:

The following is confirmed to work:

I've connected the raspberry PI as an SPI master. Only output and clock from the PI must be connected, not the PIC18F SPI out, as the PI is not 5V tolerant.

In my special PI-to-xonik m8 voice controller cable, the following pins are used:

PIN0: Signal (Master out/slave in, PI is master)
PIN2: Clock
PIN7: GND - NB - NOT PIN9!

These must be connected to the following on the EasyPIC 3 card:
RC3: Clock
RC4: Signal (SPI in)
RC9: GND

With this connection, the following settings work:

PIC18F:
SPI1_Init_Advanced(
SPI_SLAVE_SS_DIS,
SPI_DATA_SAMPLE_MIDDLE,
SPI_CLK_IDLE_LOW,
SPI_HIGH_TO_LOW
);

(incidentally the same as in my libstock example)

Raspberry PI:
let mode = 'MODE_1';     // clock idle low, clock phase active to idle.

function initSPI(){

  var spiConfig = {
    'mode': SPI.MODE[mode],   
    'chipSelect': SPI.CS['none'], 
    'maxSpeed': 200000
  };

  spi = new SPI.Spi(
    config.spi.device, 
    spiConfig, 
    function(s){
      s.open();
    }
  );

}

lørdag 18. mars 2017

Vocoder analysis/synthesis boards arrived

I picked up the vocoder analysis/synthesis boards yesterday. They look good as always, though I noticed some differences. Nothing to be alarmed about but I get why they are a bit cheaper than other boards:

- The silk screen is a bit misplaced on some boards
- The holes aren't always dead center on the pads
- One of the boards isn't completely flat, i.e. the fibre glass is slightly bent.

These are just very tiny deviations and well within what is acceptable, they just aren't perfect.

I'm very excited to get started on the build, to see if I've managed to get the circuit and layout right :)






mandag 27. februar 2017

ETI Vocoder voltage to current converter

The VCAs in the  ETI vocoder use a voltage to current converter that is slightly different than what I'm used to. This post tries to understand what is going on. It may be wrong, so do not use the findings without verifying them first.

The transistor in the vocoder has its base tied to ground, collector connected to the control pin of the LM13600 and the emitter to the output of an opamp (and a trim pot) through a resistor.

Unlike other converters I've seen, it does not have the transistor inside the feedback loop of the op amp.

I suspect that the converter does not rely on the \(\beta\) or Hfe of the transistor, it only has to be high enough. I believe that what is important is the relationship between \(V_b\), \(V_e\) and the output voltage of the op amp.

I've chosen the VCA in the internal excitation circuit as my reference when analysing the circuit.

R34 is a 10k resistor, you can see these in most all designs using the LM13600 OTA. It's most likely there to protect the lm13600 from self destructing - the maximum control current of an LM13600 is 2mA. See my post on the Xonik VCA for an explanation of its value.

So how do we calculate the collector current (which is what controls the OTA, Iabc)?

Here is a page that explains how a transistor may be used as a constant current source:

http://www.radio-electronics.com/info/circuits/transistor/active-constant-current-source.php

It says that

\(I_{load} = \frac{\beta \cdot V_e}{(\beta + 1) \cdot R_e}\)

If \(\beta\), the transistor gain, is large, \(\frac{\beta}{\beta + 1}\) is approximately 1 (and thus \(I_{load} = I_c = I_e\)). Also, \(V_e\) is always one diode drop below \(V_b\) when the transistor is on (\(V_e = V_b - 0.6V\)), which means that the formula above may be simplified to

\(I_{load} = \frac{V_b - 0.6V}{Re}\)

In our case, \(I_c = I_{load}\) and \(R_e = R32\) (=22k).

What the page above fails to mention is that the bottom of \(R_e\) must be connected to ground, or at very least that \(V_e\) is the voltage across \(R_e\).

This final detail is of importance to us, because in our case the voltage at the op amp end of \(R_e\) (R32) is what varies, not the voltage at the base. The base is stuck at 0V/GND. Thus, the voltage across the resistor is not \(V_e\), it is \(V_{out} - V_e\), where \(V_{out}\) is the output voltage of the opamp (IC8b).

We also have to take into account that the vocoder uses a PNP transistor, not an NPN as in the constant current source above. while the emitter of an NPN transistor is 0.6V below the base, the emitter of a PNP transistor is 0.6V above the base. Thus, for a PNP transistor:

\(V_e = V_b + 0.6V\)

Now we can calculate the emitter current = current through \(R_e\), which will also be approximately the collector current if \(\beta\) is large:

\(I_e = \frac{V_{out} - V_e}{R_e} = \frac{V_{out} - V_b -0.6V}{R_e} = \frac{V_{out} - 0V -0.6V}{22k}\)
\(I_e = \frac{V_{out} - 0.6V}{22k}\)

What does this mean

Well, first of all, Ie is independent of the transistor \(\beta\), which means that we can replace the BC212L transistor with something else without having to look too hard for a perfect match.

Second, we can calculate the maximum current through the base. Knowing that

\(I_e = (\beta + 1) \cdot I_b\)

we get that

\(I_b = \frac{\frac{V_{out} - 0.6V}{22k}}{\beta + 1}\)

The vocoder uses a +/-12V power supply. Thus, the maximum output value of the opamp is +/-12V (in practice it will be a bit lower than this, and the vocoder may even be designed to use an even lower control voltage, but the absolute theoretical maximum is +/-12V).

The transistor only conducts if the emitter is more positive than the base. Thus, only \(V_{out}\) values > 0.6V will turn on the transistor. As the maximum \(V_{out}\) is 12V, the maximum \(I_b\) can be found as

\(I_e = \frac{12V - 0.6V}{22k} = \frac{11.4V}{22k} = 0.52mA\)


\(I_b = \frac{0.52mA}{\beta + 1}\)


Thus, when selecting the transistor to use, we need to make sure that it has a maximum \(I_b\) higher than this when entering its \(\beta\) in the formula above.

Also, we can see that \(I_e = I_c = 0.52mA\) is well within the 2mA maximum for the LM13600.

Trimming

As for the trimmer potentiometer PR1 and its associated resistor R33, I assume they add a constant current that trims the 0-point of the VCA.

The potentiometer acts as a voltage divider, so the maximum current through R33 will be:

positive:

\(\frac{12V - 0.6V}{470k} = 0.024mA\)

negative:

\(\frac{-12V -0.6V}{470k} = -0.027mA\)


A final note

I suspect that the diode D5 in the op amp feedback loop is there for this reason:

When the opamp positive input is at 0V, the opamp output must be at 0.6V (one diode drop above to keep the negative output at 0V. This means that the opamp output always stays 0.6V above its positive input, which cancels out the -0.6V from \(V_e\) in the calculations above.

The voltage to current conversion formula will then be

\(I_e = \frac{V_{out} - 0.6V}{R_e}\)
\(I_e = \frac{V_{in} + 0.6V - 0.6V}{R_e}\)
\(I_e = \frac{V_{in}}{R_e}\)

where \(V_{in}\) is the input voltage at the positive opamp input terminal, i.e. the control voltage.

I tried breadboarding the circuit to confirm my suspicions.

R31, D5 and IC8b form what is called a simple precision rectifier, see this wikipedia post: https://en.wikipedia.org/wiki/Precision_rectifier. As we tap the output at the opamp output instead of at the negative input, we should see the 0.6V offset.

My measurements clearly showed that this is indeed true. The positive input and the output of IC8b follow each other closely, with a difference of 0.6V.

Input at the bottom, output on top. The difference is almost exactly 0.6V

Also, to confirm that this is indeed the precision rectifier from the wikipedia article, once the input goes below 0V, the output immediately drops to the negative rail - no surprises there. As the input is connected to the previous rectifier however, this doesn't really matter, the CV will never be negative.

The output saturates to the negative rail once the input is less than 0V



As for R31, removing it makes the circuit act like a normal buffer. Increasing the value from 3.9k to 12k has no effect at all. Replacing the diode with a wire also changes the circuit back to a buffer.


Some transistor rules:
The load should always be on the collector side
\(V_b = V_e + 0.6V\) for NPN
\(V_b = V_e -0.6V\) for PNP
The \(V_b\) to \(V_e\) relationship stays constant, the currents are what change.

If \(\beta\) is large, \(V_c = V_e\). Good designs do not rely on \(\beta\) as is varies widely.

torsdag 23. februar 2017

TL0x2 opamps - difference

- TL062 is the low power version of the TL082. 
- TL072 is the low noise version of the TL082. 

So: the TL062 uses less power, but is more noisy than the TL072.


From: http://www.freestompboxes.org/viewtopic.php?f=17&t=328

onsdag 22. februar 2017

ETI Vocoder article errors - internal excitation

There is a mismatch between the schematics and the parts list for the internal excitation module.

Schematics says C11 is 22nF, parts list says 220nF.

C11 forms a low pass filter together with R39. Together with the 100k resistor on each channel of the analysis card - the whole setup is called an inverting amplifier filter or active inverting op amp low pass filter.

According to wikipedia:

https://en.wikipedia.org/wiki/Low-pass_filter

the cutoff frequency is 1 / 2 * pi * R*C

where R is the resistor in the feedback loop of the op amp.

For 22nF this is 1 /  6.28 * 47000 * 22 * 10^-9 = 154Hz
For 220nF it is 1 / 6.28 * 47000 * 220 * 10^-9 = 15.4Hz

In comparison, C12 and R40 gives:

1 / 6.28 * 10000 * 1 * 10^-6 = 1 / 0,01 = 15.9Hz.

The output from the analysis boards is the value of the envelope follower. If the volume of a frequency band is at its max continously, the envelope follower will be a DC voltage with a similar max value.

The two circuit parts sum up channels 1-9 (for the <2kHz input) and channel 13 and 14 (for the >4kHz input). For the sums to be comparable, the max sum of each parts must be the same.

R39 and R40 are selected to achieve this:
The gain of <2kHz is -10k/100k = -0.1
The gain of >4kHz is -47k/100k = -0.47

Multiplied by the number of channels on each input we get a 'maximum' sum for each input:
<2kHz: 9 channels * -0.1 = -0.9
>4kHz: 2 channels *-0.47 = 0.94

These are similar enough to be compared.

The low-pass filter is there to make sure the Vocoder only reacts to slow changes in envelope amplitudes. It is reasonable to assume that they should be roughly the same. The capacitor has been matched with the feedback resistor (R39, R40), which in turn was selected to give correct gain as described above.

The closest matching alternatives are then 15.4Hz and 15.9Hz. Thus, the correct value for C11 is 220nF.

tirsdag 21. februar 2017

Transistors in the ETI Vocoder

Many of the transistors in the ETI vocoder are either hard to find or very expensive (or both). I am trying to figure out if alternatives are available.

For the internal excitation board, two BC182L (NPN) and two BC212L (PNP) are used.

Q1 is definitely replaceable, probably with a 2N3904. It only acts as a logical inverter together with R20 and R21. It is similar to the one found here:

http://www.cs.unca.edu/~brock/classes/Fall2012/csci255/labs/lab05.html

Not sure if we have to change the resistor values, but probably not.

Q2 is a voltage to current converter. I am not entirely sure how it is meant to work so I cannot say for sure right now what parameters to look for. The same converter circuit can be found in the analysis/synthesis section, so if one is solved, both are solved. I think looking at the exponential converter theory I've written earlier may solve some of it - the way it works is that the base is tied to ground while the emitter is connected to the output of IC8b which probably follows the envelope follower. D5 is similar to what I have in my Xonik VCA. R33 and PR1 probably adds a constant current to trim offness or similar.

Q3 and Q4 control two switches. Again, I believe they are considered binary - the output of the comparator is either high or low and the switches are also controlled by high or low voltages. We should definitely try 2N3904 and 2N2906 here.

Update: I've confirmed that Q2 is not depending on Hfe and may thus be replaced by a difference transistor (see my post on the ETI voltage to current converter). The BC557 has the same pin-out (CBE, PNP) and at least the 557B has a Hfe in the same region.

As for the BC182L, it seems that its pin out (ECB, NPN) is harder to find. However, the BC182 is still available from Farnell and RS Components (though not mouser). If the circuit board is redesigned, using a different transistor will be problem free.

BTW: Here is a nice comparison page for different transistors: http://www.edutek.ltd.uk/Transistors_NPN.html

As for the BF244 N-channel JFET, I have yet to find a replacement. It could possibly be replaced with a J112 (which also has interchangeable source and drain). I would have to look at the exact function of the transistor but I suspect that it is only used as a switch. The difference between J111/112/113 is the gate-source cutoff voltage, the zero-gate voltage drain current and the drain-source on resistance. The cutoff voltage for the BF244 varies widely, more than between the various J variants, as does the zero gate voltage drain between the versions (A,B,C) of the BF244. The vocoder article does not specify a particular version of the BF244 so this may not be very important either.


søndag 5. februar 2017

Linear interpolation

As I intend to use lookup tables for the DCO frequency and amplitude, I started looking for ways to do linear interpolation of the values in such a table to keep the number of entries low.

I may have mentioned it in a previous post, but I bought an early 80s digital sound creation book, and it has a thorough description of how to do this fast and efficiently. It is particulary space saving for symmetric waves such as sines but may be of some help even to me. Here is the text (for me to remember):




søndag 29. januar 2017

DCO

I've started working on a DCO circuit, as this will probably require fewer (but perhaps more expensive) parts and be easier to tune.

I want the DCO to work for all midi notes (C0-B8) and be within 1 to 3 cents of the correct frequency for all notes.

Looking at the Juno 6/60/106 and JX-3P DCOs I've so far set up a google docs spreadsheet, calculating all periods to get correct frequencies and the necessary voltages (currents) to get a constant amplitude.

A short intro to DCO theory

DCOs are (often) based around a relaxation oscillator, exactly like a saw core VCO (http://xonik.no/theory/vco/reference_current.html - this also explains how the capacitor is charged). A current charges a capacitor and a transistor short circuits and discharges it to restart the period.

DCOs are stable because they use a digital timer to control the discharging of a capacitor instead of relying on an accurate charging current - the period and thus frequency is computer controlled and highly accurate. For the saw ramp to reach the same amplitude as the charging period (time available to charge the capacitor during a cycle) changes, the DCO instead changes the charging current. As the frequency changes exponentially with rising notes, so must the charging current.

In my spreadsheet I have calculated two important aspects for a physical circuit - the accuracy of the timer generating the period/frequency and the accuracy of the charging current generation.

Frequency

A microcontroller timer has two properties - the minimum period and the maximum count. These limits the length of an output period and the accuracy of its length. A 16bit timer can at most count to 65535 and has a maximum accuracy of +/- 0.5 times its minimum period. For example, if the timer frequency is 8MHz, each tick of the timer is 0.125uS and the accuracy is thus +/-0.0625uS. Its maximum output period length is 65536 * 0.125uS = 8192uS or 8.19mS. The consequency is that a 16 bit timer running at 8MHz has a minimum output frequency of 1/8192uS = 122Hz. (Here we assume that the timer restarts the period whenever it has counted to its maximum).

The accuracy limitation is most important to the upper end of the frequency range. The maximum needed frequency (B8 = 7902,13282Hz) has a period of 126,55uS. An inaccuracy of 0.0625 equals an error of about 0.05%. The human ear is able to hear a difference between two notes played after eachother of about 10 cents/0.6% if the notes are sine waves, less if they are complex tones. Thus, this inaccuracy is well within what is acceptable.

But what can we do to make the timer count long enough for deeper notes? We can either use a bigger timer (32bit) or more often, use a prescaler that divides the clock running the timer. If we use a prescaler of 2, the timer frequency changes from 8MHz to 4MHz, the minimum period changes from 0.125uS to 0.25uS and the maximum time from 8.19mS to 16.38mS. This makes the lowest possible frequency 61Hz. Changing the prescaler to 8 gives a minimum frequency of 15.25Hz, which is low enough for C0.

Unfortunately, increasing the prescaler also decreases the accuracy as the minimum period gets longer. I have set 3 cents as the maximum error acceptable at the highest frequency. Using a prescaler of 8 makes some of the notes at the top of the frequency range fall outside the target accuracy.

In short - using a 16bit timer, we cannot use a single prescaler value and achieve both the frequency range and the accuracy needed. To solve this, we need to change the prescaler somewhere towards the lower end of the frequency scale. To get a constant time used setting up the timer, i propose always setting the prescaler when reloading the timer.

Amplitude

DCOs use different ways of creating a control current. As mentioned previously, the necessary charging current changes exponentially as the notes change. The Juno 6/60 seems to use an exponential converter (I may be wrong about this though, I haven't studied it closely) to achieve this, but such a converter has the same temperature dependency problems as the one controlling the pitch in a VCO (but the effect in the DCO is on the amplitude, not the pitch, and will thus not be as noticeable).

The Juno 106 and JX-3P however just feed the output of a DAC through a resistor and into the integrator (saw ramp generator). This means that the DAC must generate a voltage that accurately approximates the exponential curve needed throughout the note range (the voltage is converted to a current through a resistor). This may be problematic as the rate of change is very small at one end then suddely very large at the other.

I've once again used the spreadsheet to calculate first the real the charging voltage needed, then the current created using a DAC of arbitrary resolution. By rounding off the needed current to the nearest value achievable with the DAC, then multiplying with the per-step voltage, then using the capacitor charging formula with the known period as t, we will find the real amplitude of the wave and thus the maximum error per note.

Using a 16bit DAC and charging a 1nF capacitor through a 100k resistor, we are able to charge the capacitor to within 0.02V (of a maximum of 5V), or 0.4% of the wanted amplitude for all notes.

When calculating the capacitor charging, I've assumed that we can follow the same formula as in my older VCO research, where I found that the voltage across the capacitor at a time t after the charging starts, V(t) = t * I/C. I is found by dividing the DAC voltage Vdac with the input resistor R. Rearranging for Vdac gives us Vdac = V(t) * C * R / t, and to calculate the resulting max charging voltage, V(t_max) = Vdac * t_max / C * R.

My calculations can be found here: https://docs.google.com/spreadsheets/d/1ROhU0L4UZ2CWLu3h5LHopaB0Jv7ewNRziecj5I6D27M/pub?gid=0&single=true&output=pdf

Further work:
- Figure out how to calculate timer values and dac settings (lookup tables?)
- How to interpolate efficiently between values in the lookup table to reduce its size while still allowing input pitch to be a 16 bit value
- How to do DCO sync
- Possibly: Changing timer/charge voltage in the middle of a cycle in order for the DCO to respond instantly (the Juno DCOs apparently only change pitch at the start of a cycle.

søndag 8. januar 2017

The ETI Vocoder

I can't remember if I've posted about this earlier, but for quite some time now I've planned on building the ETI Vocoder. I was approached by a guy who wanted me to help him etch the circuit boards, and we spent at least a year planning for this, touching up the original drawings and adding/moving connectors etc.

In the end though, after buying presensitized PCBs and doing a few test etchings, I decided not to do this at home anyway. I simply have too few time slots long enough to do the setup, etching and cleanup.

What I ended up doing instead was redoing the boards and send them off to be professionally produced. I have shrunk all the boards as much as possible (while still using through hole components). I've split the internal excitation board into two separate pcbs so that all pots are soldered to a board.


In addition, I've combined the LP/BP/HP versions of the voice board into a single circuit. This means that you have to add some solder bridges and that some parts are left out for some of the boards, so populating them is slightly harder. However, it also means that I was able to make dual channel boards that, when repeated 7 times, turns into the full voice board. Using a service like dirtyPCBs, 7 similar smaller cards are much cheaper than one large one.


In retrospect I've realized that I could possibly simplify the circuits a bit, since the left channel on a card will never be HP and the right never LP (or the other way around, I can't remember).

I've also managed to jam all the non voice boards (except one of the internal excitation parts) into two 10 x 10 cm pcbs, keeping the cost really low.



lørdag 30. juli 2016

The Ultrasaw explained

While looking at the Matrixbrute from Arturia I noticed that it has an additional waveform called the Ultrasaw. I have heard about it previously, but got curious about exactly what it was and started looking at the documentation.

Apparently it is two additional saw waves with the same frequency as the first one, but phase shifted. The phase shift varies and is controlled by two built in LFOs. One wave has a constant phase shift rate while the other one is user variable.

I began thinking about how I would create such a circuit. Then I discovered that Yves Usson, designer of the xxxBrutes, had actually posted the MiniBrute circuit diagram on his site Hack a Brute.

I have studied the circuit closely and it seems half of the design matches my initial thoughts, but how the wave is phase shifted is really quite simple and ingenious. It resembles how my saw sub oscillator works, by shifting parts of the original wave up and down.


Let me explain.



The circuit looks like this (disclaimer: I do not own this circuit diagram, nor have I asked for the permission of Arturia or Mr. Usson to post it here. It is not in the public domain and is only reprinted here for educational use).

Figure 1

I have separated the circuit into three logical parts:
- The LFOs controlling the rate of phase change (left)
- The phase shifter (center)
- The wave mixer and volume control (right)

The LFOs

The LFOs consists of two main parts. To the left is a triangle wave oscillator. According to the MiniBrute documentation, the top one is fixed at 1Hz while the bottom one is user variable between 0.1Hz and 10Hz. The triangle wave design is the exact same one as the one in Texas Instruments' "Op amps for everyone", see Circuit 1-9 here or A.5.8 on page 446 of the original book. (PS: The book uses a unipolar power supply while the MiniBrute has a bipolar (+/- 12V) PSU).

To the right of the triangle wave oscillators is a triangle-to-sine wave converter. Its design is the same as the one in mr Usson's Yusynth VCO module.

Formula A-49 in the TI book gives us the amplitude of the triangle wave oscillator: Amplitude = +/- 24V * 47kOhm / 2 * 120kOhm = +/- 4.7V.

I have not calculated the output amplitude of the sine converter. Neither do I know the amplitude of the input saw wave, but it would be a reasonable guess that it is +/- 5V, a common value in synths.

A sine wave amplitude of +/- 5V would give a +/-100% phase shift in the phase shift in the next stage. Since a phase shift of -10% is really the same as a +90% percent shift, it seems unnecessary to have a shift larger than +/- 50%. It could even be that a smaller range is desireable, who knows. In the next section I'll assume that both the phase shift CV (sine LFO output) and the saw wave amplitudes are +/- 5V. It makes no difference for the understanding of the circuit.

The phase shifters

This is the funny part. The phase shifter circuits take a control voltage (the output from the LFOs) and the output from the MiniBrute's saw wave oscillator, and shifts the saw wave phase back or forward.

But how?

For simplicity, lets forget that the CV is coming from an LFO and instead treat it like a constant value. The control voltage (CV) desides how much we want to shift the saw wave back or forth. It does this by comparing the CV with the saw wave. When the rising input saw wave reaches the same value as the CV, thats where the shifted wave will start its cycle. This means that the phase shift is relative to the frequency of the input wave, it stays the same (in percent or degrees) even if the input saw wave's frequency changes. (This, by the way, was what I got right in my initial idea).

When the circuit has found where it wants to reset the saw wave, it sort of "chops off" the top of the input wave and moves it to the bottom of the wave instead. It then re-centers the wave for an even amplitude, and voilà, the saw wave has been shifted.

The detection and shifting happens in three sub circuits that are then summed to get the shifted wave:
1) The original saw wave
2) A comparator that compares the saw wave and the CV
3) An inverter that inverts the CV

Number 1 and 3 are simple to understand, but number 2 requires a bit of explanation.

An op amp without any feedback acts as a comparator. Whenever the input on the positive terminal is higher than the input on the negative terminal (usually called V ref), the output will instantly change to equal the positive supply voltage. If the input on the positive terminal is below the input on the negative terminal, the output will change to equal the negative supply voltage.

In our circuit the saw wave is connected to the negative terminal and acts as Vref:

Figure 2

Here is a graph that shows the how the input saw wave and the CV relate to the output of the comparator:
Figure 3

Again, whenever the saw wave is lower than than the CV, the output is 12V. When the saw wave is higher than the CV, the comparator output drops to -12V.

The output is scaled by the 220kOhm resistor and the diode at its output. PS: I have not thought enough about what the diode actually does. It may chop of the negative output from the comparator. For now we'll assume that the output is bipolar and scaled to +/- 5V.

Now, this is where the magic happens. The output from the comparator is summed with the original saw wave and the inverted CV, and out pops a shifted wave. Lets see how.

First, lets see what happens when we sum the saw wave with the comparator output
Figure 4

To make things easier to understand, I've color coded the parts where the CV is higher than the wave red and the parts where the CV is lower than the wave blue. As mentioned earlier, the point where the color changes from red to blue is the point where we want the phase of the output wave to start.

Summing the saw wave and the comparator output effectively moved the blue parts down and the red parts up, in a way that makes the lines align again. the fourth graph in the figure above shows how the result (red) is phase shifted in relation to the initial saw wave (grey dotted lines). It is however also shifted vertically.

So how do we fix this? Take a closer look at the first graph in figure 4. The top corner of the red triangles are what becomes the top corners of the resulting wave. The top corner should be at exactly 5V in the output. The comparator output will move the tip upwards 5V, but since the corner starts at a positive voltage instead of 0V it will end up higher than 5V. Thus, we have to move it back down a bit. How much? Well, things had been ok if the corner was initially at 0V, But it is at CV volts (remember, that is the definition of the corner, the intersection between the CV and the saw wave). Thus, we have to move everything downwards by CV volts:


The last graph in figure 5 shows the result - the saw wave has been phase shifted. The two operations in figure 4 and 5 plus the scaling of the comparator output happens simultaneously in the summer of the Phase Shift blocks of the circuit.

Finally the two saw waves are summed and sent through the SuperSaw (!) amount pot RP1A, which acts as a voltage divider scaling the output to between 0 and 100%. The SawAnimator out is then mixed with the raw saw wave elsewhere.

torsdag 14. juli 2016

XM8 progress

I've been working a lot on the xm8 lately. All the work has been gui related, and now I have a working matrix, virtual controllers, setup for nodes, controllers, links and more. I am working on a visual tool to create whole control surfaces and it's looking pretty good. No major feature is missing except for a gui for wifi configuration. I still have a bit of work to do on input configuration serialization (and deserialization on the microcontroller) but things are coming along nicely. Of course there are tons of things to add, like voice assignment, arpeggiator or sequencer functionality, cloud storage etc, but these aren't necessary in the initial version.

Screenshots will be up soon.

onsdag 25. mai 2016

A dac as a replacement for a VCA

A DAC may be used to digitally control the attenuation of a signal by connecting the signal to the DACs Voltage reference input. Most DACs only allow a positive reference voltage lower than the positive supply voltage, so one has to use a device called a multiplying DAC, such as the MX7521.

A circuit like this may be called a NCA (numerically controlled amplifier) or DCA (digitally controlled amplifier)

Some possible devices:
MX7520 - single 10bit dac @ NOK 32,-
MX7501 - single 12bit dac @ NOK 51,-
AD5414 - dual 12bit dac @ NOK 96,-
DAC8803 - quad 14bit dac @ NOK 211,-

lørdag 26. mars 2016

T-baneklokke - coundown clock

Some time ago I grew tired of my wife asking if she had to leave soon to get to the metro in time. I did what any sensible techie would and made her a battery powered countdown clock.

The clock counts down to a selectable time, and repeats the countdown every 15 minutes (the normal interval for the metro over here). Three minutes before it is time to leave, the clock display starts flashing slowly to get your attention. Then, once you should have left, the clock counts UP, blinking fast, as you still have time to make it if you walk briskly. Once your time is TRULY up the countdown to the next metro starts.

To save batteries, the clock goes into as low power mode as possible after about an hour, and you have to switch it off and on again to restart it.

The clock is built using an Arduino, and has a battery powered real time clock to remember the time while powered off.

To make it truly stand alone I added the possibility to set the time and time-to-leave using buttons.

The clock was built into a custom made plexiglass box, and the outside covered with a design printed onto photo paper with a sticky back side. I used my wife's Cameo vinyl cutter printer to cut the paper - I just love that machine!

Here are some pictures from the process:
The Arduino with the RTC module to the right, time-set buttons in the middle and 7 segment display at the bottom.

To keep the top and bottom of the case in place while gluing on the sides, I built a little Lego rig. We all use Legos for prototyping, don't we?


The finished box

Sanded down to make the photo paper stick. 

Power switch and stand-offs added.

Everything fits snuggly. Notice that I kept the USB input to be able to update the software if necessary


Voila! The finished product. Now my wife is never late for the metro ever again. Riiight.


søndag 6. mars 2016

Roland resistor nets for the IR3109

While researching IR3109 based filters I came across the schematics for the Jupiter 6. It has a neat multi mode filter, but the schematics show three resistor networks, and the resistor values for those are not shown.

Luckily, someone has figured out that the same resistors are used in the MKS80, which has most of the values - though not all of them.

From a bit of guessing I have come up with what I believe is the values and internal connections.

RM0688 - The schematics do not show the value for the resistor between 2 and 3, but it is rather safe to assume that it is a 100k resistor like all the others.

RM0690 - The MKS80 schematics shows a 7.7k resistor between 2 and 1. The Jupiter 6 schematics show two resistors without values, one from 1 to 2 and one from 1 to 3. As a 33k and a 10k resistor in parallel equals a 7.7k resistor, and these values are already used in the net, it is very likely that these are the missing values. If we at the same time assume that the positions are reverse those in the other half of the net, just like in the RM0688, we get the schematics above. PS: I have yet to see a usage of this net where 2 and 3 are not connected, so it is in reality only the combined value that matters.

RM0891
The resistor nets have different part numbers and designations in the various synths:

13919128 - RM0688 - RKM8C066
13919130 - RM0690 - RKM8C068
13919132 - RM0891 - RKM9F561/683GP

fredag 26. februar 2016

typedef, structs and function pointers

Just a quick reminder about structs and typedefs in C:


A named struct is created like this:

struct MyStruct{
  int anInt;
}

A custom type like this:

typedef int MyType;


The two syntaxes may be combined like this

typedef struct MyStruct{
  int anInt;
} MyType;


In use you can then either write

void myFunction(struct MyStruct someValue);

or

void myFunction(MyType someValue);


in the latter case omitting the struct keyword.


Function pointers


A variable containing a pointer to a function can be written like this:

returnType (*pointerName)(parameterType)

For example:

void (*myFunctionPointer)(int)


The pointer is then for example assigned like this:

myFunctionPointer = &someFunction;


Combined with typedef you can get:

typedef void (*myFunctionPointerType)(int)

and then use myFunctionPointer as a type:

myFunctionPointer aFunction = &someFunction;

søndag 21. februar 2016

XM8 32 channel CV works

I've spent some time the last few days getting the sample and hold part of the 32 channel DAC to work properly.

As is usual, I messed some things up in the initial design. The DAC board is connected to the 32ch sample/hold via a connector. This goes in a U-shape but I forgot that this means that pin 1 on connector one becomes pin 2 on the other and vice versa. As power as well as signals are transferred through this connector, nothing worked right. Weirdly enough though, nothing broke, it just got very hot.

From the initial tests I learned a few things:

- The type of opamp used with the DAC matters, at least visibly on the scope. Using a stock TL07x opamp produces slight a slight overshoot when the DAC output changes a lot. Using a AD8672 precision opamp instead removes the overshoot.

The S&H circuit shows a similar overshoot when it is set. As the S&H is all TL074 it could be that it is fixed in a similar manner. I just don't know how much it matters.
The output as seen between the DAC and the sample and hold shift register - the initial rising curve shows the output from the DAC. The drop is caused by the enabling of the shift register, connecting the DAC to the sample and hold which is currently at its most negative, so it takes a short amount of time before it charges to the same level as the DAC. The peak is where the charging of the sample and hold capacitor overshoots. It is of the same kind but more dramatic than then one we see in the DAC output photos above and may be caused by the TL074.
A more detailed photo showing the charging and overshoot.

- I connected the output of the S&H to the pitch and filter inputs of a Moog Little Phatty. It worked very well, but I got an audible clicking noise four times per second. It went away when I removed sampling of all but one input potentiometer from the PIC32, so it may not be a problem in real life where the potmeters will be sampled from a completely separate circuit.

- At very high frequencies there is a slight ringing to the sound, I presume this is some kind of aliasing. I could not hear much of it when I turned off sampling of all potmeters but it should be investigated further.

- Oscilloscopes have a horizontal scale calibration potmeter. I spent hours trying to understand why the results I got did not seem to match the output frequency I was expecting, untill I realised that I had made two crucial mistakes: The oscilloscope scale was way off (fixed by connecting a function generator) and I had not set the internal PLL divider in the PIC32 correctly (it was running five times slower than expected!)


The output of one of the 32 sample and hold cells when running at full speed with 32 operating cells. DAC switches between +/- 5V.


Just for fun: My test rig. From left: Four potmeters that sets the CV (read using the ADC in the PIC32), a solderless breadboard that just reconfigures one of the ribbon cables, the EasyPIC fusion 7 development board from Mikroelektronika, which contains the PIC32, and on top of it: four quarter inch jacks connected to outputs 29,30 ,31 and 32 of the DAC circuit. To the right: My Moog Little Phatty


onsdag 10. februar 2016

XM8 DAC board works after all

It's been almost a year since I designed the XM8 DAC and sample and hold boards. When testing the original DAC board I couldn't make it work.I suspected I had broken the DAC chip, and at $20-30 per chip I did not want to waste another untill I had verified my design.

The AD5547 DAC is a 38 pin smd component, with 0.5mm pitch. A real pain in the ass to solder. To breadboard it I had to order an adapter PCB. First time off I got an 0.8mm pitch adapter which of course was useless. Then I designed and ordered another adapter. Due to lack of time and other projects having priority, I never got around to soldering and trying it.

About a week ago I finally worked up the courage and found the time to try breadboarding the circuit. It worked flawlessly and let me write a code example that could be adapted to the PCB version.

Today, after about one hour of trial and error, and with six toddlers screaming and crying around me, I got the original board working! Without any modification! (I did however mess up and somehow connected analog or digital ground to +3v3 (I think) when trying to connect the two grounds, giving me some very weird results. After reconnecting however, everything works like it should.

Here is a picture of the result. The code runs at almost maximum speed on an 80MHz PIC32MX. The output is increased by 10 every time the DAC is updated, giving us about 6500 steps per rise. The scope is set to 2v/square vertically which shows a perfect +/-5V swing.

Horisontally the scope is set to 0.5ms/square which means that each rise takes about 2,5ms which gives a frequency of about 400Hz and a sample rate of 2.5MHz

The assembly code of the loop is 23 commands long. On the 80MHz microcontroller we should be able to run the loop at about 3.5MHz if each command takes one clock cycle, so 2.5MHz seems entirely reasonable. I may have misunderstood something but I think this is the correct speed.

søndag 20. desember 2015

Working node.js SPI code connecting a Raspberry PI with a PIC32MX

var SPI = require('spi');

var spi = new SPI.Spi('/dev/spidev0.0', {
    'mode': SPI.MODE['MODE_1'],   // clock idle low, clock phase active to idle.
    'chipSelect': SPI.CS['none'], // 'none', 'high' - defaults to low
    'maxSpeed': 8000000
  }, function(s){s.open();});

var rxbuf = new Buffer([ 0x00 ]);

var state = 0;

function writeToSpi(){
    var txbuf = new Buffer([ state ]);
    spi.transfer(txbuf, rxbuf, function(device, buf) {
        console.log("Wrote " + state + " to SPI");
        console.log("Received " + buf[0] + " from slave");
    });

    state++;
    setTimeout(writeToSpi, 100);
}

writeToSpi();

SPI gotchas

I am working on SPI communication between the Raspberry PI and a PIC32MX microcontroller for use in the Xonik M8 polysynth.

SPI is a very easy protocol once you get the hang of it, but it has a few gotchas:

1) Setup - SPI mode

There are two important parameters that control transmission. It is not essential to understand exactly what they do, but it IS important that they are set up the same way on the master and the slave. The parameters are:

CPOL - clock polarity
This defines when the clock is "idle" and when it is "active".  The clock stays in idle mode whenever data is not transferred and goes active once per bit that should be transferred. The two possible states are:

CPOL=0 - clock is idle low, e.g. it is 0 when it is not running
CPOL=1 - clock is idle high, e.g. it is 1 when it is not running

CPHA - clock phase
This defines when new data should be read from and written to the bus. The two modes are "Idle to Active" and "Active to Idle". When the mode is "Idle to Active", data is READ (captured) when the clock changes from idle to active. Data must be WRITTEN to the bus when the clock changes from active to idle.

It is important to remember that CPHA is in relation to CPOL. Idle to Active does NOT always mean when the clock changes from 0 to 1 - if CPOL is 1, Idle to Active happens when the clock changes from 1 to 0.

The two possible states are:

CPHA=0 - Idle to Active, data is read when the clock changes from idle to active
CPHA=1 - Active to Idle, data is read when the clock changes from active to idle

This may sound a bit complex, but unless you are writing your own SPI slave/master code on a device without hardware support, all is taken care of for you. You just have to select the same config on the master and the slave.

The four common modes are:

0 - CPOL=0, CPHA=0 - clock is idle low, data is read on the rising edge
1 - CPOL=0, CPHA=1 - clock is idle low, data is read on the falling edge
2 - CPOL=1, CPHA=0 - clock is idle high, data is read on the falling edge
3 - CPOL=1, CHPA=1 - clock is idle low, data is read on the rising edge

2) Data transfer

Data transfer is full duplex, meaning that data is sent and received at the same time. One bit of data is transfered every clock cycle - in both directions.

If any data exists in the output buffer, it will be sent when the clock ticks once. Similarly, any data on the wire will be put into the input buffer when the clock ticks once. In other words, anything found in the output buffer on the master AND slave will be put on the wire once the clock starts running.

But what does this really mean?
First of all it means that in order to receive bits, the master has to pulse the clock the same number of times as the number of bits it wants to receive.

To do this, many SPI libraries including those on the Raspberry PI and the Microchip microcontrollers require you to actually send a byte. The byte may be zero as we are often only interested in the received data (this, of course, means that the transfer is only half duplex), but it can also be data usefull to the slave such as the next command/address to retrieve.

Secondly, to retrieve data from a slave you first need to transfer a command from the slave to the master. This could be a memory address, an action or similar, telling the slave to fill its output buffer. After the initial command/once the output buffer has been filled, you have to send a second byte to run the clock in order to transfer the data from the slave to the master. As mentioned above, this byte could either be bogus data or a new command, it all depends on how the slave is implemented. (As a side note, it is not strictly necessary to send a command before receiving data. For example, a ADC SPI slave could continously put its latest sampled value into its output buffer, which the master will read whenever it needs a new value from the ADC).


More info about the SPI bus can be found on wikipedia.

SPI and the Microchip PIC using Mikroelektronika's MikroC

There is another gotcha in the naming of SPI states in MikroC. For the 8 bit microcontrollers, CPHA modes are "high to low" and "low to high". These are NOT describing 0 and 1. Instead they are the same as "Active to Idle" and "Idle to Active".

søndag 29. november 2015

Etching trials

Today I finally had time to do some photoresist developing and etching to try to figure out a sweet spot before doing all the vocoder cards.

I got some AA16 cards from C.I.F at Farnell and got to work.

After reading a lot about various methods, I landed on using Sodium Metasilicate as the developer. Incidently, I had some laying around. More specifically, I had a 25g sample of the Mega Electronics universal developer, but after reading the datasheet I figured it is what I wanted.

For etching I used "Etching power for PCBs" from Scan Kemi that I bought last time I did any cards. It seems it is mostly sodium peroxidisulfate (sodium persulfate).


I tried various exposure times as well as developer strengths and development time. Three of them failed and three were closer to success

The failed ones:

1) 2 minutes of exposure, developed in a 13g/2.5dl solution. This was not long enough, the developer had a hard time doing much at all.

2) 3 minutes of exposure, developed in a 25g/2.5dl solution. I left the card in the developer for three minutes. When etching, the resist floated away.

3) 4 minutes of exposure, developed in a 13g/2.5dl solution. Some of the traces were too thin and broke.

The better ones:

4) 3.5 minutes of exposure, developed in a 13g/2.5dl solution for 5 minutes. When etching some of the tracks got too thin and some were not etched enough



5) 3 minutes of exposure, developed in a 13g/2.5dl solution. The development time was a bit on the short side so some resist still stuck and was etched away later. The result was probably the best one of all the trials.


6) 3 minutes of exposure, developed in a 25g/3.5dl solution for 1m 30sec. The solution was a bit warm as the additional water was hot when added. This turned out almost as well as the previous one but with slightly thinner traces and one short circuit.



My conclusion is that 3 minutes of exposure seems perfect, and that I should probably retry the 13g/2.5dl developer solution but leave the cards in a little longer.

The etching times was around 10 minutes, depending on the heat of the water. I did the etching in a small plastic box in a bath of hot water which started out at 44 degrees celcius. The recommended temperature is 50 degrees.