Sunday, April 14, 2024

Anything to Clock Subcircuit

Readers: If you want to build the project featured in today's post, please go to PCBWAY's Community pages--a gerber ready to download and/or fabricate as well as KiCAD files, PDFs, a BOM, etc., are here.  

Also please visit PCBWAY's site using the link here--it will help this blog immensely. Thanks.

For upcoming projects I needed a breakout board to turn any waveform in the audio frequency or low frequency range into a pulse wave. Then: use the output's rising edges and throw an interrupt on an MCU.

So, I needed a comparator; lots of ways to design and lay this one out, easy. 

I also needed a few more features....

What I came up with:




As usual I recycled ideas used in previous projects. 

The MCP6002, an opamp I discovered looking at buffer subcircuits from Mutable Instruments, provided clamping. An easy way to clamp J6's ground to positive voltage was to limit the MCP6002's power pin, Vcc, pin 8, to 3.3 or 5 volts--whatever voltage my MCU expected. 

The MCP6002's output will match Vcc--easy.

Warning: for any circuit that uses an MCP600x, do not supply greater than 6VDC to its Vcc pin--exceeding 6v may damage the MCP6002.  If you need to use a larger voltage (say +12VDC for VCC) consider using a different op amp--pretty much any dual op amp will work, but you might lose the MCP6002's nifty clamping characteristics.

The MCP6002's second stage provided an inverted output, while J7's non-inverting output voltage was determinded by the voltage present at Vdd and not constrained to the clamp voltage.

VCC-VDD jmp wirepads could be shorted with a small jumper. This allowed the Vcc and Vdd to be supplied by a single voltage source.

The diode in U1A's feedback loop made U1A a precision rectifier, the same idea was used in a VCO triangle to ramp converter.

A final "feature": I could change output shapes with one additional part: C4. C4 can be omitted, but its value along with R2 provided a simple active filter, allowing different output shapes at J6 and different pulse widths at J7. 

With R2 at 1K, values for C4 could be anything from say .01uF to 4.7uF and beyond. Omit C4 to get decently fast rising and falling edges at J6 and J7. 


New boards from the blog's sponsor, PCBWAY.  

Mistakes in the original run: problems with silks not showing up (in Kicad, I put the designations on a non-existent layer instead of front silkscreen--oops) and J1-J7 being incorrectly ordered. These issues are corrected in the project uploaded to the PCBWAY community.


Whole board took minutes to populate--this was an easy one.

100mil spacing for breakout boards presented a challenge to me, so I laid out J1-J7 200mils apart, grabbed some inexpensive 100mil edge connector material, and pulled out every other wire with needle nose pliers. 

Now I have a 7 pin edge connector with pins 200mil apart. This made the board a lot easier wire up I thought and worked a lot better than anticipated.

power tested: no problems



Simple circuit, simple results.  Purple trace is input, Yellow trace is output; screens were captured with Siglent's easy to use.  This was what I was after. 

So--I made a few errors with my silks but otherwise worked first time!  When was the last time I saw that?  


Sunday, March 31, 2024

Python: Digital Audio and DSP--Baby Steps

A goal for 2023--I will blame my tardiness on the pandemic? was to start down the difficult path of teaching myself Digital Signal Processing.

Audio is a good vehicle for this pursuit: there're a lot of good programming examples out there, and every DJ loves delay.  

Question: what platform to use for experiments? 

After research I chose Windows and Python. Windows machines are everywhere; Python is free and easy, and perhaps the path of least resistance.

Before going further: fair warning: Like the last post about learning C++, this post forms my trail of breadcrumbs through my learning process--instead of writing this information in a notebook for later review it's in this blog. 

So: mostly useful to me, maybe not a lot of others--I expect like 5 views on this post. 

More hardware next time.

Let's Get Started....

My dev platform was simple as possible: a Windows 10 Pro computer and Python 3.11.  

The goal was to create Python audio effects and waveforms to create a mono audio signal. If I could get some sound to come out of the crappy speaker I figured it was a good start.

First up: I started by recreating the code found in the video here.

The video, as straightforward as it was, still covered math and terminology unfamiliar to me--as with a lot of DSP concepts, I soon realized that learning DSP could (and probably has) made many sane techs run screaming.

Nevertheless I tried to unpack it....

Oh no--right away imaginary numbers and complex planes reared their ugly heads. 

 I didn't cover these in school but maybe after decades I am getting the hang of is centered around a seemingly impossible number: the square root of -1.  

How can you square a real number and get -1? Turns out it's like online dating: You can only do it if you imagine you can do it....

A square root of -1 makes as much sense as a negative number--you can't have a basket with -3 apples in it--but -3 apples might mean you owe your neighbor 3 apples--negative numbers exist only in our minds.

I had to remember: negative numbers are a human, and not a physical construct; imaginary numbers are the same.

Like negative numbers, imaginary numbers help us solve otherwise unsolvable problems (like x*x + 1 = 0)

Interesting Introductory video to imaginary numbers is here

I saw imaginary numbers everywhere in the DSP literature I was reading. 


Turns out, convenience: It takes a lot less ink to solve math found in DSP using imaginary numbers vs. real numbers--therefore it's what DSP pros use. A good article about this is here.   

S plane, Z plane: more complex number stuff--an X-Y grid of real (X-axis) and imaginary (Y-axis) numbers. S plane is analog; Z plane is discrete.  A to D conversions are accomplished with math: "Z plane transform"--just as ADC's chop up analog signals into digital chunks, the transform equation in this context does the same.

I also heard a lot about "Zeros and poles" found in these planes. Hello? A video covering this that I could follow for the most part is here.

And on and on forever....tons and many kilogram tons more. 

DSP means math, and not the math you learned in 10th grade. DSP is difficult, unfamiliar math. I am curious how far I can go with this.  

But enough reading. The rest of the weekend was spent coding.


First thing I did with Python DSP was follow the example here to create an audio filter. It worked. Cool!

For the example I needed to include and import the Python numpy and sounddevice libraries--numpy created arrays of samples and sounddevice played them back. Here's the code:

import numpy as np

import sounddevice as sd

# create numpy array filled with random numbers 

sampling_rate = 48000

duration_in_seconds = 5

highpass = False  # False for lowpass

amplitude = 0.3  # scale output for your PC

duration_in_samples = int(duration_in_seconds * sampling_rate)

#watch the line wrap....

white_noise = np.random.default_rng().uniform(-1,1,duration_in_samples)

#next the creator sets up an "all pass filter" 

#which uses phase tricks to knock 

#out audio frequencies creating a 12db Q=0 type filter:

cutoff_frequency = np.geomspace(20000, 20, input_signal.shape[0])

#array for output processing.  

#We create a np array with all zeros w the length of the output.

allpass_output = np.zeros_like(input_signal)

#create all pass filter

#First, create inner buffer of all pass filter.

dn_1 = 0

#process each sample

for n in range(input_signal.shape[0]):

    break_frequency = cutoff_frequency[n]

    #calculate output coefficient

    tan = np.tan(np.pi * break_frequency/sampling_rate)

    a1 = (tan  - 1 )/(tan + 1)

    #all pass filter difference equation

    allpass_output[n] = a1 * input_signal[n] + dn_1

    #store value in buffer for next iteration

    dn_1 = input_signal[n] - a1 * allpass_output[n]

    # we now need to set up the feedback loop based on our filter

if highpass:

    allpass_output *= -1

filter_output = input_signal + allpass_output

#scale amplitude of loop

filter_output *=0.5

#played out using the sounddevices library....

filter_output *= amplitude

#play out.  soundlibrary, sampling_rate)


Ha! This worked.  This was an excellent introductory video, and the content creator goes over the math and the code but still keeps it all sane.

And at the end of it--I wrote my first DSP code (well, not really--I just copied the code to my PC with a few minor changes and ran it)  


What next?

If I could play back and filter white noise numpy arrays, how about doing the same with a ramp wave? 

It was not too hard to create a ramp wave using some numpy trickery. For instance in this fragment linspace creates a numpy array from x to y with step z. while tile repeats the elements of numpy array x y times.  Viola: Ramp wave.

sample_rate = 44100

grain_size = 100

repeat_grain = 4800

wave_audio = np.linspace(-.9999, .9999, grain_size)

ramp_wave = np.tile(wave_audio, repeat_grain)

Or a x% pulse wave?  That was not too bad either, but I got stuck...I also found out (not documented?) that sounddevice as sd won't play a sample if it's greater than or equal to 1 or less than or equal to -1. I couldn't figure out why until I started messing around with floats less than 1 for the max and min values in the array. When I did that suddenly I heard a raspy pulse wave coming from my speaker.

#numpy array for square/Pulse

#enter 1-100 below, PW as percent

PW = 5

PW_as_percent = PW * .01

PW_high = int(grain_size* PW_as_percent)

PW_low = int(grain_size - PW_high)

x = np.full(PW_high,.99)

y = np.full(PW_low,-.99)

sq_wave_single_grain = np.concatenate((x,y))

sq_wave = np.tile(sq_wave_single_grain,repeat_grain)

Finally, a numpy array where the PW varies for each "grain", in this case, PW modulated by a ramp wave. 

This one made me look up some numpy techniques but I got it to work.  

For this fragement I used "simpleaudio", a library similar to sounddevices, but it uses 16 bit values between 32767 and -32768 instead of floats between -.9999 and .9999--in general, there are a lot of audio libraries for python, a good video summarizing some I messed around with is here.

Here's the PWM code:

sq_wave_pwm_np = np.array([], dtype=np.int16)

x = range(20,99,1) #new PWM value each grain

for n in x:

    PW_as_percent = n * .01

    PW_high = int(grain_size * PW_as_percent)

    PW_low = int(grain_size - PW_high)

    pwm_x = np.full(PW_high, 32767)

    pwm_y = np.full(PW_low, -32768)

    sq_wave_pwm_grain = np.concatenate((pwm_x, pwm_y))

    #combine new grain and existing array.

    sq_wave_pwm_np  = np.append(sq_wave_pwm_grain,sq_wave_pwm_np)

pwm = np.tile(sq_wave_pwm_np,10)


I had used Jetbrains Pycharm as my Python IDE for many years but as I was working on baby DSP it started to feel bloated--too feature rich for what I do.

I was using VSCODE  at work so figured, why not try that for Python.

I followed the basic setup VSCODE and Python steps from our most honorable, raze the world for our shareholders bestest buddies at Microsoft, here

What do you want for free?

So far, seems OK.

Turned out to be not as easy as expected, but the video here was helpful.  

To summarize:

using Windows Explorer, I created a new directory for the virtual environment

cd'd to the new directory

in the VSCODE terminal, typed this

python -m venv myenv 

(myenv could be whatever I wanted to call the new virtual environment)

This created a framework for a new Python virtual environment.

next I navigated to the newly created myenv\scripts directory.....

typed this


finally installed numpy, in the same myenv/scripts directory:

./pip install numpy

For me, I had to include the dot forward slash (as if I was using a linux system) probably because of a PATH statement somewhere.  

...if I typed  

pip install numpy

as seen in the video and elsewhere, without the dot slash, numpy got installed in my roaming profile, not in the virtual environment. Nice!

As a last step, before running or debugging the .py files I created using VSCODE, I had to tell VSCODE which interpreter to use for the virtual environment (it prompted me).  

I had to navigate to the python.exe file in new myenv/scripts folder and choose that one.

From there, it all worked. 

What's Next?

I could not get sounddevices' buffering too work, too bad, because it'd be cool to send changes to numpy arrays to a buffer in real time. This would get me a lot closer to what I'd be doing with an embedded system. 

I am not sure I have time to get that working, and using numpy arrays sent to sounddevices buffers isn't well documented. But I felt I could have figured it out with more time and effort.  

For now it's back to hardware for a bit. 

I find myself more and more drawn to the software side of DiWHY. DSP of course is a huge challenge, but I might be up for it--maybe? Not just for audio--for all of it. This could become a big problem.

Monday, March 11, 2024

C++: Learning, Links, and TidBits

No posts so far for 3-2024....I have been brushing up on C++ skills.

 After years of writing code in embedded C, which works fine for what we usually do, why C++?

I was talking with a talented DIYer at my friendly (and let's not forget) geeky meetup.

We discussed the 4011 based hardware debounce circuit--post here

He was baffled: why not do this in software? 

His advice--other professional engineers have told me this also: If you can do something in software you should do it in software. 

Software is easy to change--hardware, not as much.  

He emailed me his debounce C++ class which was only 40 lines, contained in a single cpp file.  

I could follow the basics--maybe--and figured I'd port it to C, then thought, why, Stroutty, why? 

It should be easy to attend an online C++ class and get to the point where I could port the debounce code and drop it into my current RP2040 project or whatever else I was working on.

Besides, I was a bit tired of troubleshooting hardware after a disappointing Moog HPF build and needed a different challenge.

 So....I signed up for the C++ Mosh class. 

 I already attended an online Mosh GIT class I found useful. His C++ offering was affordable ($99USD for a three part course).  You can find a free version of the Mosh C++ course Part I here.  

Do the Monster Mosh....

Turns out it parts I and II of this 3 part class were good for C review and C++ basics, but by part III  but the lack of source code became problematic; I was spending too much time typing Mosh's lessons into Visual Studio Community to see if they worked. 

I stopped attending classes entirely after about a third of the way through part III where not only was it ridiculously painful and time consuming to type example code into my IDE, but some of the damn lessons wouldn't compile even after meticulous typing. Hello?

The forum for the class wasn't helpful either, some members were oddly rude and many basic questions (like--where the hell is the source code?) went unanswered.  

$99 was still a good value for what I got, but, no source code and examples that don't compile? 

Time to move on.

What Else?

Fortunately even if Mosh part III was the pits there was a ton of materials about C++ everywhere.

C++ references: 

cppreference;   Damn hard to follow for a beginner, and maybe for almost everyone, but, as I learned more C++, I could begin to sort of kinda of make some sense of some of it. Sorta. Kinda. 

C++ for C programmers. Useful to me, since I am already OK at embedded C.

C++ tutorials:

TutorialsPoint  this has become my go-to reference for learning. These lessons are super clear, lots of simple examples, and unlike Mosh Pits--this guy includes his source code. Yeah!

W3 C++ Tutorial  -- who says these guys can only teach you to write HTML and CSS. Another good source for learning.

C++ video tutorials:

  • Hank Stalica -- practical C++.  Like for a college freshman.
  • The Cherno -- a bit more advanced--you have to be OK at C++ to follow some of his C++--still, useful.
  • Code Beauty  -- easy to follow lessons and yes, she is a cutey. 
  • Caleb Curry  -- whole enchilada here. This kid must have spent hours and hours and hours (!!) putting together these tutorials--we owe him our gratitude.

What Was Next?

With a few weekends and evenings of C++ practice I went back to some embedded examples (for instance an AD4725 C++ class for Arduino--here or AD1115 for RP2040--here) and was happy to see that for embedded open source C++ most programmers stuck to basics. No virtual classes, no friend classes, no lamda expressions, not even smart pointers. I could follow this.  

Perhaps for embedded systems, the kind of stuff DiWhyers do anyway--we don't need/don't want crazy advanced modern C++ foobar.  "Just the Class, ma'am".

I went back to the bench to see if I could rewrite the debounce C++ class that started me down the C++  rabbit hole--Could I get it to work with an RP2040 MCU?  

The original code was written for a Teensy 3.1--which is based on an NXP MCU.  

The RP2040's SDK handles interrupts quite differently; but how could this port be?

Turned out--hard. Very hard.  

Interrupt handlers in C++ are oddly difficult to code (explanation here), but to make things worse, the PICO uses callbacks as Interrupt handlers, after a few hours looking into this, yes, C++ is, umm...err..., odd?, and I thought it made the most sense to write a interrupt driven debounce algo for RP2040 in C or continue to use hardware to debounce. 

It would take too much time to sort this out in C++ and the resulting code would be overly complex, especially for someone new to C++. Really?  Really. In this case: "C: the right tool for the job".  

Next I went over a few recently C classes I wrote. For example, the C code for the MCP4922--what would be involved in porting that to C++?  Sure, I could do it.

Right now I don't think I have time. 

Moved on.


For now I will see if the next IC I need to incorporate into a digital project has a C++ class I can use or modify.  Maybe I will create my own C++ class for it.

Beyond that, I will keep at the C++ learning as time permits. Even if I never code with it, understanding the syntax basics has already been useful for decyphering open source class files and perhaps even helped me to better understand embedded C.

After about a month--yeh, I am convinced--C++ sucks. It has the oddest syntax I have ever seen, is endlessly dense, endlessly confusing, has even has its own bizarre terminology (lvalue? rvalue? Storage class specifier? there are thousands of these damn things) along with a lot more to make a normal person trying to get some damn thing to work run screaming.

Worse of all, some of the C++ programmers I discovered on my month long journey have the atonal bebop jazz complex: "screw you if you are not as awesome and talented and smart as I am". 

Right! Toot your trumpet, Ornette, while I cover my ears. 

I still have no idea why C++ is so popular, nevertheless I will keep plugging away at it. Thank you Bjane, may I have another? I am that kind of masochist.

Thursday, February 29, 2024

AudioDiWHY Moog HPF clone--"WFTBSLC."

The video here got me started on this project--cool sounding filter. Can I build one too?

Moog HPF--looks OK, works not so OK....

Sure I can. 

EFM Schematic is here--video and online posts say to add a few 22pF caps; I also added variable gain at audio input and output.  

It was a fair amount of work in Kicad to make sure everything lined up, but I thought I got it right, and off the gerbers went to this blog's patient sponsor, PCBWAY.

Whiz and bang, back came the boards:

To make the layout sane, I used 3 boards--main board, pots and jacks board, and a front panel.

Before soldering--did everything line up? Yes. Good start. 

I got building....

Taped down the boards to the bench; used my microscope (post here) to solder SOIC IC's.

Oh yeah, SOIC's on both boards....

main board done.

ready to start soldering the pots; Board in the center is the "jacks n pots"; it also has an OP07 to buffer the module's audio output.

Almost ready to test...

Two evenings--Built!

I put the project down, I needed a break. 

I remember walking up the stairs to my bench the next evening thinking--I had not had a "work the first time" (W.F.T) moment in a long time, would I get lucky?  

Probably not.

Fired it up, yes, the thing passed audio. Good!

yes, mod1 and mod2 swept the filter.  Good!

Yes, the Q adds a (slightly) buzzy "rez" sound to the filter. Good!


after time at the bench and in my rack--sadly, the filter S.L.C. --

"sounded like crap".  

Crap?  Yes, crap. Big, stinky, BART commute seat type crap. 

Better out then in? Nope.

To whit: SLC (int w; int* s; s = &w;)

The filter blocked all audio too frequently--I didn't think this was because only dogs could hear whatever frequencies the filter was passing....Instead--there was something more fundamentally wrong, like at many sweep settings the output was getting slammed to an op amp rail..  

When sweeping the cutoff frequency, often only a fraction of cutoff settings--sometimes 9 to 10 o'clock on the frequency pot--would pass audio at all.  Not good.

In spite of adding an attenuator at input and adjustable gain at output, I often had terrible distortion and level mismatches.

Mod1 and Mod2 interacted with one another--this might be a design "feature"?

"Q" worked but lacked the pleasing whistle-like resonance of the filter in the video.

In general, I was extremely disappointed in my build of this filter so far--

Hence the entire acronym:

WFTBSLC: the confusing acronym in the subject of this post.

"Worked First Time but Sounded like Crap".


Where did I go wrong?

A mistake somewhere--maybe a resistor value was incorrect? Perhaps? probably?

It could be a mistake in the traces as well, I have definitely made both mistakes before.

I didn't match transistors, and maybe I should have? This was due to laziness, and I read you must match transistors for Moog ladder designs to sound, well, Moog-like.  

But to me, this sounded a lot worse than transistor mismatching.

Something wrong with the resonance loop?  Maybe. Probably. 

I will wait a few days, maybe more, then go back to work on it. 

Hopefully it's a dumb mistake and will be easily fixed. 

Probably not.

I have signed up for some additional DIY audio forums, maybe some folks there will help me get this working?  

One of the experienced builders at my geeky Meetup said to reflow the cap solder joints. Tried that. 

Nope.  Still SLC.

I will not be defeated!  Until next time: DBTF.

update 3-11-24: after going over the build with a scope and DVM, I found no build issues but did find a few mistakes in the layout.  I will get new boards made and try again.

Tuesday, February 20, 2024

A Few Evenings with Logisim

 It's been raining like crazy and I am waiting for the last round of boards to come back, so I spent a few evenings and weekends trying to learn a bit about logic design.  

I have a junk box full of CMOS DIP IC's; I could breadboard experimental logic circuits but I hate breadboarding.

Instead, I started up Logisim Evolution, a fantastic and free logic simulation program, which I will abbreviate as "L-E" going forward.

Aside: Evolution is a fork from the original Logisim--there is more information online about Logisim vs. the L-E fork. The UI has changed in L-E, but for what I've seen so far the 2 versions are pretty interchangable; if you read or see a tutorial about one you can generally apply it to the other.

L-E: What Can (and Can't) You Do?

Good news--If your circuit can be realized with 1's and 0's you can probably simulate it in L-E. 

However, as far as I can tell there is no analog anything in L-E--no ADC's, no DAC;s, no op amps, no resistors, no caps, no analog scopes.

In spite of this limitation, or maybe taking advantage of it, I found some amazing Logisim and L-E creations online. 

One of my favorites is here; this guy seems to have not only simulated his own 16 bit CPU and PC, but also created a primitive operating system for his sim. Wow! 

Where to start?

I knew pretty much zilch about logic design, so, for me? Anywhere.

I started emulating some CMOS IC's I used frequently, such as the CD4051; I have read the datasheet and have successfully designed 405x's in working circuits, but, how do these IC's really work?  

My 4051 Sim. There is a mux simulator tool in L-E; I could have used that for the 4051; instead as an exercise I primarily used AND gates.

Running some test signals through this "IC" it seems to work. Off to a good start....

New Idea--Transmission Gates

OK with some understanding of basic gates (a good summary is here) I felt some improvement--from newbie to "a bit beyond Newbie" perhaps?

What next? 

Again: anything.

"Transmission gates" were new to me. 

They are sort of like VCA's, FETs or BJT transistors when used as a switch--in a transmission gate, if control data goes North to South, logic can flow East to West.  

I hadn't heard of these before, but digging into datasheets, yes, they are present by the bushel basket in many of our beloved CMOS IC's...for instance on the 4014 datasheet--i.e., below, circled in red:

That's a transmission gate.  

Here's a transmission gate in L-E:


Emulating the 4014 datasheet fragment somewhat:

Clock and ClockInv: Feed one side to North, the other side to South. Now, on every positive clock you can pass data through the gate. On negative clock you can't.  

Datasheet Limitations?

Next: I went through more CMOS IC datasheets--most have a logic diagram--to get more IC CMOS favorites working in L-E.  

Bad news--I found that simulating the datasheet's logic diagram sometimes and perhaps often (?) didn't work.  

Apparently whoever drew up the diagram for one logic sheet or another just got the damn thing wrong--some of the diagrams had serious mistakes and/or omissions; not sure if this was intentional--protecting intellectual property, or perhaps multinational IC manufacturers getting lazy?

Regardless, in some cases I had to modify the datasheet's diagrams or start from scratch to get the IC simulation to work. 

You can look at what I've "finished" on github, here--please fork 'em and improve 'em. 

CPU/MPU is Next....

With some CMOS IC's under by belt--next question--could I simulate a basic 8- or 16-bit CPU of my own design?

Having watched all one thousand of  Ben Eater's awesome Vids  I felt I had a basic idea of how CPU's work--registers, ALU, busses, memory, mux's etc., so instead of planning I dug in and started simulating. 

Bad idea?

During my logic simulation equivalent of the Dead's space jams I realized I wasn't simulating a CPU--I was trying to make an entire computer:

Jerry's Kids! What I created as of 2-20-24. "CharPU" uses 16 12-bit opcodes, supports (so far) a Program Counter, one 16 bit register, 256 bytes of 8 bit ROM. Works--but the simulation has a long way to go....

To get this working I needed a "counter within a counter"--to step through, say, the 5 or 6 clock cycles needed to write from ROM to a register.  For this I simulated a ring counter....using simulated D flip-flops.  

Ring Counter simulation. The inverted feedback path creates a "Johnson Counter".  

At this point I started to see some of the limits of L-E:

  • I couldn't assign pins to be an Input and Output at the same time--see the discussion here. Which means (as I see it): I couldn't easily create a bidirectional data and address bus. Apparently this not changing any time soon. This meant I needed a data bus for input abd aniother for output. Extra wiring, but this remains better than breadboarding but to me.
In L-E you cannot have bi-direction busses....
  • Don't expect a lot of I/O from the real world into your SIM. Apparently you can enhance your Sim using TCL ("tickle") but I don't have time to learn a new high level would be nice if the serial I/O could attach to one the host's PC "real" serial ports, but that's wishful thinking. There is a keyboard simation tied to the host PC's keyboard and a behind glass TTY display. The list of improvements slated for L-E is huge (here) and with everyone clamoring to get more FPGA's working with L-E I doubt anything a newbie audio guy like me wants to see some UART enhancement will get much traction....but still, serial port I/O would be cool, hook your L-E sim to an arduino!
  • My big battle has been staying organized. L-E allows for the creation of subcircuits and importing preexisting Logisim libraries, but still, I found keeping everything straight, especially when things got a bit complex, became a major challenge--even with the primitive CPU above I struggled with things like consistent tunnel names, zooming in and out, and making things easy to follow and understand.
  • When viewing projects, how come there is a vertical scroll in L-E but a not horizontal one? 

Conclusions--is a life of logic for me?

Maybe. On a different planet/different reality/different universe I could be working for Intel, laying out CPU logic and being happy (and not showering, ever).


Coda...I spent a lot of time with L-E for a few evenings and an entire weekend and it really played hell with my OCD. Little eating; little sleeping, zero breathing fumes, just me and my PC. Something about the reward of seeing the little red lines (doesn't work) in L-E turn green (works) was appealing. 

My psychiatrist wife is worried--L-E and a life of logic could be dangerous for me. We will see.

Tuesday, January 30, 2024

Rotary Encoder--Hardware Debounce

 Readers: If you want to build the project featured in today's post, please go to PCBWAY's Community pages--a gerber ready to download and/or fabricate as well as KiCAD files, PDFs, a BOM, etc., are here.  

Also please visit PCBWAY's site using the link here--it will help this blog immensely. Thanks.


Hidy Ho! Welcome back for more blog fun. 

I have been super busy with my day job--correct, I don't blog for a living. 

But I've had a tiny bit of time this month to work with Elton at Otter Mods to design a small PCB for debouncing a cheap rotary encoder.

For a background check the post here

I got a $2USD clone rotary encoder to "work" with an RP2040 and 1306 display, but try as I might I couldn't craft an effective algorithm in C to debounce the cheesy thing. 

Sure, there is a takes-no-brains-to-use debounce library for Arduino, but dammit Gil Amelio we are no longer in Kansas--I tried to port the C++ Arduino library into something for RP2040 and so far no dice...not enough time.

Is it a cop out to use hardware for this? Well, maybe, but here it is:

The Encoder hardware debounce board; available from the blog's generous sponsor PCBWAY. Get it from their community site here.



Elton at Otter Mods and I passed some KICAD schematics and PCB ideas back and forth, and here's what we came up with:

R1 and C1 integrate the encoder output while the 4011's make things into a nice clear rising or falling edge. Q1 and Q2 buffer and invert and set the logic "high" level.

Laying out the board in Kicad was pretty easy.  I used SMD 1206 parts where I could--they are easier to swap out vs. through hole if a value change is needed; no solder sucking--heat up the SMD part, get it out of there with tweezers, and drop in the new part.

I only had DIP 4011 IC's so that's what ended with on the PCB.  

To buffer the 4011 outputs and bring the logic levels up to Vdd I could have used a lot of things but ended up employing trusty 2N3904 transistors: they were what I had lying around.

This was a super easy build--fab took less than an hour and worked the first time. 

As far as mistakes: a few of the legends on the board were incorrect; this is fixed on the 1-29-24 version I uploaded to PCBWAY. 

Otherwise, the board seems to be A-OK.

Some useless build photos:

Happiness: unbagging the boards....

"SMD ahoy"

Oops, extra solder bit by the 4011, and note the Sharpee corrected legends, but hey it worked.


The result is super clean edges for the encoder outputs, instead of the hash and scrambled eggs the encoder produced on its own.

Scope at 500uS per division--using the PCB the encoder state change produces a clean rising edge--good enough for what I do.


I am still looking for the killer software debounce algorithm, but in the meantime, I see this RC/4011 idea used for debouncing and "quickly rising edge" square wave creation.  

I figure it'll work no matter what MCU or digital doodads are in your design. 

I have a Moog hi-pass filter clone on the bench to next blow up; also, I am considering employing the debounce/encoder madness in this post into some sort of simple clock multiplier. Hope you can stay tuned.

Monday, January 1, 2024

Vactrol Envelope Follower: Double Sided SMD Fabrication

 Readers: If you want to build the project featured in today's post, please go to PCBWAY's Community pages--a gerber ready to download and/or fabricate as well as KiCAD files, PDFs, a BOM, the front panel gerber etc. are here.  

Also please visit PCBWAY's site using the link here--it will help this blog immensely. Thanks.


This time I revamped a circuit I laid out a long time ago--a envelope follower based on a 5C3 Vactrol.  

The reason: the original  module was large; could I shrink the size of the module by putting all hardware and SMD components on a single PCB?



I began exploring envelope followers when I got a Mutron III decades ago, a stompbox I seriously wish I still had. 

It's a filter fed by control voltages derived from the amplitude of an incoming audio signal. 

The Mutron (schematic here) responsed to the incoming amplitude in a way I found musically pleasing. It uses a 0805 opto coupler; to get its slow, sloppy feel I breadboarded the amplitude to CV subcircuit based on a 5C3 vactrol

I found the Vactrol version useful for things other than auto-wah--used in front of a VCA for instance I got some interesting audio compression effects.

Soooo...20 years later I wanted to see if I could make a smaller version of this for get it to 6HP I had to put SMD parts on both sides of the board.

Thanks to PCBWAY for sponsoring this boards are back from them....

Turns out the layout (in Kicad) was a bit tricky since I had to keep straight what parts were on what side of the board; where it made sense to put vias, etc., but after a bit I got the hang of it.

SMD parts on both sides....

I used a small vice to hold the board in place while I soldered SMD parts (I have settled for now on 1206 and SOIC, which are large enough to not always require a microscope for hand soldering).

The board and module worked first time. The only thing I'd like to redo is the front panel, which could be laid out to make the legends easier to read from a distance. 

Overall I thought hand soldering SMD parts on both sides of a PCB, including SMD electrolytic caps, would be challenging, but no--this was a piece of cake. 

Using the Vactrol EF

Plug in a preamp'd guitar or clav; the EG CV out goes to a bandpass filter; turn the EF's three knobs until the LED lights the way you like; riff on like Jerry Garcia and Stevie Wonder.  

My goodness, it was 1984, it's 2024 already. See ya next time.

Anything to Clock Subcircuit

Readers:  If you want to build the project featured in today's post, please go to  PCBWAY's  Community pages --a gerber ready to dow...