Thursday, June 23, 2022

Otter Mods "GateKeeper"--Trigger to Gate Euro Module

Hello again. I am still working away on a RP2040 toolchain--stuck on getting I2C to work--so I've turned the post over this time to Elton Glover from Otter Mods--they make really cool analog synth modules, and Elton was nice enough to share one of his designs--"GateKeeper" with me and you, faithful AudioDiWhy readers. 

Take it away Elton!

=====================



The Timer

The core of this module uses a 555 timer to generate a gate of a desired length. If you are not familiar with this versatile chip, there are many tutorials available online. Here is a link to a tutorial and a calculator to help determine component values:


555 Calculator

https://ohmslawcalculator.com/555-monostable-calculator


555 Tutorial

https://www.electronics-tutorials.ws/waveforms/555_timer.html


Configuration

The 555 timer is set up in monostable mode, often referred to as “one-shot” meaning it will not self-oscillate. With the values I chose, the adjustable output gate can range anywhere from ~0.02 seconds up to around 5 seconds. Some of the resistor and capacitor values (specifically RV2 and C3) can be adjusted for longer or shorter duration, but I felt these gave me a good usable range for the typical patches I’m making.




This version of the module build uses through-hole components for easier assembly, but I have also made a double gatekeeper version using SMD components. You can tune the build to your own taste.




Functional Walkthrough

The clock input (J1) can accept nearly any type of signal pulse, which is then fed through the filter made up of C1-R6 and passed through D1 to produce a spike. This is buffered by U1A and the output turns on Q1, which is set up as an inverter.




This inverted pulse is fed into the Trigger (pin 2) of our 555 (U2). This initiates the charging cycle of C3. The combination of R5 with the adjustable value of RV1 sets how long this charge time takes. Once the charge level of C3 reaches the ⅔ supply threshold, the Discharge (pin 7) is opened and drains C3 until another Trigger event occurs. Concurrently, the Output (Q in this schematic, pin 3) turns on during the charge time of C3. The output is buffered by U1B and is the end result used to output the desired Gate signal. R1 and D2 provide an indicator LED to signify the gate output length. R2 is used as a simple means of circuit protection.






PCB Layout

Here is how I chose to layout the board. I am using the 3.5mm jacks as the mount for the faceplate, and thus wanted to space them out evenly across the board to give the module the most support. 

                                                         


This module is 3HP wide, and the standard 3U height for the Eurorack format:


You can get your own Gatekeeper PCB and its front panel on PCBWay's project page, here.

=============

COOL!  Thanks again to Elton Glover for letting me post this extremely useful module. Also for PCBWAY for fabbing the PCB's for the post (there are two--main board and PCB used for the front panel). Get gerbers for both here.  

If you have questions or need more information, please contact Elton via his website--here.

I'll be back soon with more Euro modules, and maybe someday I'll have an RP2040 MCU working well enough on the bench to do useful things. Stay tuned!

Sunday, June 12, 2022

RP2040--SPI "Wrapper" Library for Embedded C

This time I continue working with Raspberry Pi Foundation's RP2040 MCU for future in audio projects.  

Over the last few mornings I created a embedded C library for using SPI peripherals for this MCU.  


Breadboard time....

I couldn't locate many videos about programming RP2040 SPI using C; one I found covered both MicroPython and C. It's from Shawn Hymel--this guy has good stuff--video here. Also, the YouTube channel "Life with David" has some good RP2040 content (such as an interesting arbitrary waveform generator video how to--here) but so far not a lot about SPI; David concentrates on the RP2040's PIO features, primarily.

Using those videos, as well as the (surprisingly abstract) examples found here, and the SDK SPI documentation from Raspberry Pi Foundation, I ported/rewrote the Atmel 328 SPI library I create a few years ago (here) to code for the RP2040.  If you are new to SPI and embedded C, you should read up on SPI first--good article from the Sparkfun folks: here

After a few mornings, I got it to work.  

Proof of concept--1K triangle wave created with the library discussed in this post and an MCP4921 SPI DAC. Code is here.

There are differences aplenty between Atmel 328 and RP2040 hardware and firmware. For example, the RP2040 supports 16 bit SPI communication; as far as I know, the Atmel 328 natively only supports 8 bits. The RP2040 has 2 SPI peripherals on-chip, the 328P has one. 

Pulseview is open source logic analysis software; I used it with an inexpensive Saleae clone to see what was happening with SPI at a low level. A logic analyzer is essential for debugging libraries like this one.

One of the main differences I found is that the RP2040 requires buffers for SPI data being sent and returned; this is required by the Pico SDK

This was easily accommodated; I created a suitably sized variable or array, then, when calling a SPI write method from the SDK, I used the address of the buffer to pass the data to the peripheral:

void  SPI_TransferTx16_SingleCS(spi_inst_t *spi, const uint16_t data) // cs low, 2 bytes, cs high)

 {   

  gpio_put (cs_pin,0);   

          spi_write16_blocking(spi,&data, 1);  

  gpio_put (cs_pin,1);

 }


The number 1 you see above indicates how many words occur between the CS down and CS up; so it was  easy to create another function where you can argue in as many bytes as needed:

void SPI_TransferTx8_variable_num_words(spi_inst_t *spi, const uint8_t a[0], uint8_t numwords) 

// 8bit write, cs down; variable # of bytes before CSup 

{

    gpio_put (cs_pin,0);   

  spi_write_blocking(spi,a, numwords);

          gpio_put (cs_pin,1);

 }


I already had a single method MCP4921.c file I've used for Atmel 328/embedded C (here), but since the RP2040 can accommodate 16 bit words for SPI, I simplified the code for the MCP4921 DAC 12 bit writes to just three lines:

void write4921(uint16_t data4921)

    {

     // code assumes LDAC (4921 pin 5) tied to ground

     data4921 &= ~(1 << 15); // must always be zero 

     // buffered ref in, gain = ref; no shutdown

     data4921 |= (1 << 14) | (1 << 13) | (1 << 12) ;  

     SPI_TransferTx16_SingleCS(spi0,data4921);    

    }


To test and troubleshoot, I used PulseView, the amazing and extremely useful open source logic analyzer. Using Pulseview I could quickly see if a given library call worked or not:

I tested sending hex FF, F0, and 03 (so 24 bits) between a single CS down and up.  Yes, it worked. However, SPI tests don't reveal useful information without an appropriate peripheral connected to the MCU. So, I tested this write method using an AD5761, which requires 24 bit words for each SPI transmission.

I posted the initial build of the RP2040 SPI library "wrapper" on github, here. I am calling this a wrapper because RP2040's C SDK already has functions for SPI, but I wrapped them up into something more along the lines of how my mind works. 

I didn't have any suitable SPI chips for reads/MISO, so, as of the writing of this post, I am guessing at those functions. I have ordered a few MCP3001/3002 IC's (SPI ADC). I will test with that in a week and update the post and/or the library once I am sure those functions are debugged.  Update: reads work!


I got the MCP3201's on my bench and yep, the functions for MISO/ADC read worked first time.  You ca n see the wiring I used for the ADC chip; I added MCP3201.c and .h files to the github SPI repository. 

One more tidbit: VSCODE, the IDE I chose for this RP2040 toolchain, supports a Microsoft technology called Intellisense

Among other things, Intellisense allows the user to hover over a method and see details about its use. 

OK how did I add Intellsense detail to the 2040 SPI C library?  It's easy: in my declarations (specifically: SPI_rp2040.h) I commented immediately above where I defined the function. But I added no comments on the same line as the declaration: 


These comments appeared via Intellisense when I hovered over a function in Visual Studio Code:


                                 

Next, onward to an ADC C library for RP2040.  The RP2040 has 3 12 bit ADC's, a built in temperature sensors, and some interesting features like ADC round robin. Update: done, here. 

In general, in the coming weeks and months, I will probably port more Atmel 328 libraries I have already written to this new MCU, and try to improve and optimize the code in the process.  Geek out, baby!




JTAG to SWD Converter

Readers: If you'd like to build the project featured in today's post, please go to PCBWAY's Community pages--gerber file, KiCAD ...