woensdag 13 december 2023

PICmicro PWM VCO

Many of the 8-bit PICmicro microcontrollers have a PWM built in, which usually is used to do D/A conversion by changing the pulse width and adding a low pass filter (see other posts on this blog). I was curious whether instead of doing this, it might be possible to use the actual PWM output as the waveform, turning this into a VCO.

I used the 16F690, mostly because I am familiar with it and because I have a number of them in a drawer. It has analog inputs that can be used to convert the input voltage, and a single PWM. To get the PWM frequencies in the audible range I changed the clock frequency of the microcontroller to 125 kHz. Fortunately this is easy. I then computed which notes it could play, from C1 to D#6 and determined the appropriate values. I decided that I'd accept an input voltage from 0V for C1 to 5.33V for D#6. Since the PICmicro can only accept voltages up to 5V this meant I had to have a voltage divider. I decided to use two OPAMP for this: one that allowed adding and subtracting -6V to 6V to the input voltage, and the other to divide the voltage and invert it back to the normal range. This worked fine.

For the PWM input I used a default of 5V which was fed through an attenuator, so if the cable is not plugged in it had a range from 0-5V, and if the cable was plugged in the incoming voltage could be attentuated. That was fed to the second analog channel. Since the PWM range changes with each note I had to build a clever piece of code that checked each bit of the incoming data and add various divisions of the maximum range.

Finally, since the output only moves between 0V and 5V, I added a transistor inverter with CV input, so I got a free VCA. The output of this I pushed through a high pass filter to remove the DC component and will be multiplying by two so I get 10 Vpp (I didn't make this currently, but it just means adding two 47k resistors to the OPAMP). I will add schematics later, but I wanted to at least publish the current source code.

I needed to use assembly because at 125 kHz the processor is quite slow, and I do need to do the A/D conversion and output fast enough to not have issues with latency between notes.



donderdag 26 oktober 2023

Twin Twin-T Kickdrum

 For my next project I wanted to take the two kick drums I had in one of my most dense modules and give them some space. I also decided to use the design of Moritz Klein instead of the design I used then, because it allowed for longer decay times due to the second OPAMP (see his video for more details). I still wanted to have two drums, rather than one, so I decided to forgo the CV inputs for accent and tone and instead double the drums and add a mixer that mixes them together.


 The purple drum is missing the tone control, and instead is fixed at 47k/22nF. I used 10nF and 22nF capacitors for the drums, tuning one slightly higher and the other slightly lower. I didn't use the 3.3nF capacitor for the distortion, so the sound is a bit harsher. I tried to minimize the wires, but it still ended up rather a big mess.


One big modification I did was to use the gate to trigger circuit I made for a 10F206, apply it to a 10F202 instead. This made the trigger circuit a lot easier. The complete schematic is as follows:

I also have a short video showing how it works and what it sounds like.




vrijdag 13 oktober 2023

PS/2 MIDI Eurorack module edition

 

I made a Eurorack version of the PS/2 MIDI project I did a while ago. It features a PS/2 input (which can accept USB keyboards that comply with the PS/2 protocol as well, which my most recent mechanical keyboard does), a MIDI output (now with 5 channels: 1 direct play, 3 recorded and 1 for drums), a 1v/oct output of the main notes and a gate belonging to that 1v/oct. There is also an LED that will show that the gate output works when there is no plug in the jack (this is done to prevent unnecessary energy use by the LED, given that my own power supplies can only supply 300 mA).

The source code is available, and I will try to keep it updated with future improvements. The source code can run both on a 20 MHz PIC16F690 or a 8 MHz one, depending on the presence of the MODULE definition.

F1-F4 can be used to record the different tracks. It can play 4 different drum sounds at the same time, each with a selection of 3 different drums for a total of 12 options. A future module will expose the recorded channels as 1v/oct as well.

Originally I used a Sallen-Key filter for the PWM, but it turned out this created some spiky behavior that especially my Chipz module didn't like on the input, so I switched it to a plain two pole low pass filter.

This is the first module for which I made by own panel out of aluminum, which was an exciting and slightly scary thing to do, involving sawing, drilling, dremeling, sanding and painting. The painting was the biggest struggle, as you can see the bottom part has a slightly different hue.

zondag 1 oktober 2023

PS/2 Keyboard Output (sending data to a keyboard)

As you have seen on this blog I have made multiple implementations that allow reading data from a PS/2 keyboard. However, in order to control the LED you have to also be able to write to the keyboard. This is far trickier than it seems, and the documentation on the Internet is limited. Basically the best document is only available using the wayback machine. There is also a working piece of code for the Arduino which isn't pretty and uses interrupts, which can be something people would shy away from (although I might try to implement a version with it).

The most important aspect is the timing schedule. There are many diagrams on the Internet, and most of them are wrong. This is the correct diagram, made by Craig Peacock and copied from the above linked website.


And here is a simplified C code implementation for PicMicro processors (suspendKeyboard() will take the clock line and move it to 0, resumeKeyboard() will release the clock line, keyboardClockHigh() waits for the clock line to go high, keyboardClockLow() waits for the clock line to go low, RB4 is considered to be the data line):

void sendKeyboard(unsigned char value, unsigned char parity) {
    suspendKeyboard();
    __delay_us(60);
    TRISBbits.TRISB4 = 0;
    PORTBbits.RB4 = 0;
    resumeKeyboard();
    keyboardClockHigh();
    for (int i = 0; i < 8; i++) {
        keyboardClockLow();
        if (value & 1) {
            PORTBbits.RB4 = 1;
        } else {
            PORTBbits.RB4 = 0;
        }
        value = value >> 1;
        keyboardClockHigh();
    }
    keyboardClockLow();
    if (parity) {
        PORTBbits.RB4 = 1;
    } else {
        PORTBbits.RB4 = 0;
    }
    keyboardClockHigh();
    keyboardClockLow();
    TRISBbits.TRISB4 = 1;
    while (PORTBbits.RB4) {};
    while (!PORTBbits.RB4) {};
    keyboardClockHigh();
    suspendKeyboard();
}

The full version of this code I will add later. Note that in order to actually change the LED on the keyboard, you need to send two bytes, as follows: first you need to send 0xED, then wait for the keyboard to respond with 0xFA, after which you send 0-7 based on which LED you wish to turn on. 

vrijdag 25 augustus 2023

Katoomba: Triple LFO

 

Katoomba is the triple LFO that featured previously on this blog, but with its own panel and custom PCB. It has the following features:

* Power usage: -12V 43mA/+12V 46mA.

* A medium speed LFO (0.01 Hz to 2 Hz) with triangle wave, square wave (0-5V) and square wave (-5-5V) outputs.

* A slow speed triangle LFO (0.001 Hz to 0.3 Hz).

* A fast speed LFO (1 Hz to 200 Hz) with two triangle wave outputs (0-5V and attenuated -5-5V).

Each LFO has an LED indicating its current polarity and the panel is language agnostic (although it still reads left to right).

The Katoomba was designed in EasyEDA (schematic will be at the bottom of this blog post) based on the circuit from David Haillant with modifications to allow multiple outputs at the same time and different voltage levels. This version uses a 16-pin voltage connector, because it is more convenient for my setup, but it doesn't use 5V, so it could use a more standard 10-pin connector as well.

In this version I decided to use the smaller potentiometers to allow more room for the cables, but since these have the same footprint as the other potentiometers this can always be changed.








donderdag 3 augustus 2023

Black box - Gate to trigger

There are a number of cases where it is preferred to have a short trigger rather than a gate signal. This is yet another project for which a PIC10F206 was used. It uses all inputs and outputs, with one pair triggering each time the gate goes high (+2.1V or higher) and the other pair triggering each time the gate goes high OR low. This latter option can be used to double a clock if needed. Both can operate in the audio rate range, although it falters when the triggers get the same width as the incoming square wave.

The source code is here. The circuit just uses 2.2k jacks connecting things to the microcontroller, relying on the internal diodes to protect against voltages outside of the 0-5V range (since they can handle 20mA, this shouldn't be a problem at all with these resistors. Of course it would push the circuit out of specification, as it can't protect against other disturbances anymore).


woensdag 2 augustus 2023

Black Box - Decay

 The decay of the black box is different from the decay that I made for eurorack. That decay had the voltage drop as the capacitor filled, this decay is the more classic model which first quickly charges the capacitor (using a 200 Ohm resistor) and then discharges it through the potentiometer with an added resistor for safety.

The trigger is made using another PIC10F206, because it allowed precise control over the charging time, which needed to be around 5ms, as the capacitor I chose was a 4.7uF ceramic one. I used an MCP6272 to buffer the output as well as control the LED. Finally I used my classic transistor inverter circuit using the 2N2222 to feed the signal back into the trigger jack. This means that if no cable is plugged in the decay will feed on itself: each time the voltage drops below 600mV it will trigger itself again. This means it can basically be used as a kind of LFO.

Because of the code, there is a possibility that this fails if the speed is increased too much. After this happens it will not restart until a normal trigger is applied. This can, of course, be done using the 0-5V dial of the black box itself. In the code there is a loop to charge the capacitor. The reason why the same if statement appears twice is to time the loop to be close to 5ms.

Here is a (hopefully correct) version of the schematic.