Virgule/emulsiV: Learning RISC-V Assembly Language

 I finally took a long vacation with my psychiatrist girlfriend. We flew to Portugal--from the USA--10 1/2 hour flight. Super Fun! 

Of course we ignored the COVID-19 warnings like this one

Bad news--when we were leaving, she tested negative for COVID-19, but I didn't, so she left, and I was stuck.  

I self-isolated in a hotel--six days, although the Portuguese health authority said it would be more like 11 days--to do what? 

Ignore the shelter in place mandate and go to museums?  No. Getting the locals sick--I found them calm, polite, and often downright zen--not my thing.

Ignore the mandate and go to the beach?  Nope. See above.

Ignore the mandate and ride the ridiculously crowded tram 28?  I wouldn't do that if I was healthy, so, no.

Learn some new programming skills, of course. RISC-V assembly!! 

RISC-V based dev board from Sparkfun
 
WELL ARMED?

I've already written posts about assembly for the 6502 processor (here) and ARM (here). 

With 6502 it was pretty easy to learn assembly language basics; ARM, not so much.

Another instruction set architecture ("ISA") is RISC-V; it's open source and was designed to help teach newbies like me how processors work. 

I expect RISC-V to become increasing popular as chip makers become weary of giving ARM and Intel bags of money since RISC-V has no license fee.  

So, here I was, stuck in Lisbon, Portugal, alone in a hotel room, only me and my ancient MacBook Pro. Can I learn a new ISA without going crazy?  

Yes. I found an amazing online simulator for learning RISC-V--"Virgule" (a simulated RISC-V processor) with "emulsiV" (an emulsifier for Virgule? No idea what the hell emulsiV means)--find them here.


Documentation for Virgule/emulsiV is a bit sparse, but I could follow it--which means you can too--it's here

A good RISC-V/Virgule introduction video--short and informative--is here. As the video correctly notes: Someone put a lot of work into this simulator. This must have been a scripting project of passion, and it's one of the best, and at the same time simplest, online simulator I've seen to date. Viva la France! 

It has an ASCII display, behind glass GPIO, about 2-3k of simulated RAM and even a memory location where you can load and view bitmap images. 

It gets better: You can animate what happens inside Virgule/emulsiV as you step through your code, and control the speed of the animation. Not only can you see if your code works, you can see how it works at a snail's pace.. This greatly helped me understand RISC-V at a deep level while writing, debugging, and running my code.

There are different ways to get code into the simulator; for me, I hand-coded instructions into the memory column on the left side of the simulator, then stepped through my code to watch it work. 

If I made a really dumb data entry mistake the simulator tried to correct it and did a remarkably good job. Amazing! As a learning tool, this couldn't be more straightforward.

Enter assembly code right into memory slots....


REGISTERS: 

The simulator has 32 general purpose registers.  RISC-V's spec indicates that hardware does not have a central accumulator and that register x0 is always 0.  

Programmatically we call these registers x0 x1 etc....this is not hex, which is denoted 0x000 in the simulator as you'd expect; the registers are called out via decimal with a preceeding "x".  

The documentation talks about RS1, RS2 etc.--these are considered SOURCE registers; also rd1, rd2 etc, these are the DESTINATION registers. 

Other than x0, any register can be used as a source or destination.  



IMMEDIATE VALUES

In the RISC-V ISA, immediate values ("IMM's") don't seem to have the odd rules, complexities, and head scratching limitations that I found in the ARM ISA. 

 An easy way, I think, to get immediate values into registers is to use addi instruction—"add immediate":

 Addi dest, source, value

Source can be an existing register with a value stored in it….this next instruction puts 32 in x1, and register x0 can only have 0 as its value: 

addi x1, x0, 32

However, For some instructions, like lui, Immediate values are entered like this

0xyyyyy000

where  yyyyy is a 32 bit hex value. So the LUI instruction is a good way to put a large immediate value into a register:

 lui x2, 0xc0000000  ;put c0000000 hex in reg 2

But what about the 3 LSBs, they never get can a value?

Ha!—use addi after a lui—a trick!

addi x1, x0, 32

In this instruction: x1 is destination register;  x0 is source register and has value of 0, and 32 is the value to put into the LSB's

STORING VALUES

Virgule emulates a 32 bit RISC-V processor, so  you can store bytes ("SB"),  half words/16 bits ("SH"), or words--32 bits ("SW"). 

The general instruction for storing a byte (bits 0:7) is this:

SB (what to store) (where to store) 

so---

SB x1, 0{x2)

SB means take 0:7 bits of what to store--in this case the value in register x1, and copy it to register x2, offset by IMM 0; in other words, copy the value in register x1 to register x2.

And--you can store to memory (as opposed to a register) using an offset value greater than 0—see the "Extra Ram" section below.

LOADING VALUES

Works the same way as storing but going the other direction.  

LB x3, 0(x2). 

Loads a byte to register x3--the value found in register x2. 

If the offset is 1 or greater, you are loading bits 0:7 from a memory cell, not a register.

EXTRA RAM

Not  well documented, but you can store and load values to and from virtual RAM, not just in the 32 registers provided.

For instance:

SB x5 1(x1) 

stores bits 0:7 found in source register x5 into a virtual a memory slot--in this case 1 added to the memory location previously stored into register x1. 

If x1 contains zero, and the offset is a 1, you are storing a byte into memory location 1.

Remember that x1 already contains a value, to which an offsite is applied.  So if x1 already contains the value 3,  SB x5 1(x1) will copy bits 0:7 of  register x5 into memory cell 3 + 1, or virtual memory cell 4. 

As far as how much "extra RAM" we can use in Virgule: As far as I could tell, I had 1-2047 memory locations to offset from (x1), but when I went outside that range things didn't work the way I wanted.  

However the memory map indicates 0-3071, more like 3K locations rather than 2K, including x0-x32 used as registers, but I couldn’t make things work with offset values  >  2047.

It would be great if someone could show me exactly how all the memory 000 to CFF is mapped--because I am missing something here and didn't have time to fully figure it out. 

Comments?  

Unfortunately the sim does not have a way to display what is in this extra virtual RAM. Only register values are shown.

WRITING ASCII TO THE (fake) ASCII DISPLAY

Output from Virgule's virtual ASCII display.  Get the hex code, ready to load into Virgule, here.

Here's one way to do this...

lui x2, 0xc0000000  ;put c0000000 hex in reg 2

addi x1, x0, 75. ;put 75 in reg 1

sb x1, 0(x2) ;store value at x1 (75 is ascii letter “K”) to the simulated text display

IMPORTANT! always make your code use offset 0 above.....I assumed to make the cursor appear at the next spot to the right, use offset 1, and for the next, use offset 2, etc. but that crashed the simulator.

The simulator will automatically increment the cursor to the next available slot the next time you do an ascii write. Just keep writing to the ascii display over and over--this is not well documented, but you can figure this out from the examples.

WRITING TO THE FAKE LEDs

GPIO's! Of course this simulator has them. Virgule has an impressive array of virtual LEDs, switches, and push buttons. They can be configured by right clicking on one of the GPIO points and choosing what you want (impressive by itself!). You need to set the direction (read vs. write) using an SB instruction, then use subsequent instructions to do other things.

I wrote some simple code to light the first row of LEDS:

we put the memory location for our GPIO into reg x1

lui x1, 0xd0000000 ; memory location for virtual GPIO

sb x0, 0(x1) ; this makes the LEDs outputs  

addi x3, x3, 126. ; put 126 into x3 (it can be anything from 1 to 255)

sb x3, 16(x1)

Final instruction writes what is in x3 to x1 offset by 16.....16 is the memory location for VAL, the values you want to write to the GPIO "pin".

JUMPS

These instructions sounded intimidating after watching videos and online reading, but after experimenting, they are not too difficult:

JAL: jump the program counter to immediate value; then put the count of the next program counter instruction to run, after the jump has occurred, into a register. 

let's look at the instruction

jal x1, +24   

So! If Jal x1, 24 is put into instruction "memory" position 00, the program counter jumps to PC 18 (24/4 is 6, you are jumping the program counter forward by 6 instruction memory “slots”); then, Virgule puts 1c into register X1 since 1c is next PC slot after 18.

JALR; register and offset contain where to jump to.

Jalr: x3, x2, 0

x3 stores the next program counter “slot” that would have occurred if the jump didn’t happen.  X2 is the value of where to jump to, offset by value 0.

ENCODING

If you want to understand RISC-V at its deepest level, check out how assembly is turned into the 32 bit values hex values  sent to the processor. 

Understanding encoding would be critical if you are writing a compiler, pulling apart RISC-V hex instructions using C, and so on.  A detailed video (long, deep, and quite informative) covering RISC-V encoding is here.

THE WHOLE J, S, R, U thing: RISC-V in its 32 bit form expects all its opcodes, functions, values, etc, to fit into 32 bit words. The opcode is always in bits 6:0.  But from there it varies how the opcode, values, register/memory locations etc, are encoded. In the RISC-V spec, there are a few different “formats” used, with letters like J, S, R, U to designate how this it's done; in other words, each letter designates how a given 32 bit word is encoded

Encoding instructions: I assumed for everything RISC-V the opcode contained the instruction itself. "When you assume" right? 

Um, no. In some cases the opcode alone isn’t enough. Instead, an instruction's opcode (bits 0:6) can be a general marching order, while one or two “functions” further define what needs to be done during decode step. They are called “function 3” and “function 7”. You knew that right?

For instance, for ADDI, opcode is OP-IMM. And function is “ADDI”.  

However, for the LUI instruction, the opcode itself tells the CPU's decoder everything it needs. You knew this as well?

Encoding Register values: to try to better understand this, I dug into how a 32 bit RISC-V instruction knows what registers we want to use for an instruction. 

Turns out RISC-V, in its 32 bit version, uses 5 bits for register values. Hello?  That should allow for 2 raised to the 5 registers or 32.   

So, how does the system encode the value 0xC000000 to register x30?  and not send it to x7 by mistake? 

Here is how: mask everything else in the 32 bit word, that, by the aforementioned letter designation, does not represent a register, then turn the 5 bits left into a decimal number. For instance you have an RD of 0 0 1 0 1 that means we want to use register x5.

The entire encoding process, turning commands into bytes, opcodes + functions into instructions, numbers into signed or unsigned numbers, etc., is a bit complex, but like all things RISC-V--it's manageable if you put a bit of time into digging deeper. 

Overall I figure RISC-V is what happens when friendly, helpful, well meaning college professors and grad students--as opposed to apathetic/screw-you-I'm-tenured/screw-you-again-I'm-a-certifiably-bonkers-T.A./I-give-not-a-poop-about-you-wanting-to-learn-things-I'm-too-busy-bedding-coeds/I'm-busy-boozing-and-making-my-research-paper-deadline-so-don't-bug-me basket case profs I had back in my college days--um, when they create a cool ISA for pimply faced freshmen.  

COVID CODA  

I will spare you the puns of RISCing things by traveling abroad...too late.

Experimenting with RISC-V using this simulator helped me keep my limited sanity during the days I was locked in a hotel room, waiting for the Portuguese government to let me back on the plane. I have to say that for a vacation with a big bummer ending, this RISC part of the trip was fun! 

RISC-V is a blast to code as I see it--it's fun, interesting, and for those wanting to try something new that's even legal: highly recommended.

In the future I might create some RISC-V based projects and get my sponsors PCBWAY (had to get a plug in right?) to help with the fab. Stay tuned.

In the meantime: there are code examples included in Virgule but some of them seemed a bit complex to me, so I wrote some of my own code, attempting to make things as simple as possible. 

My trail of breadcrumbs? Sure. You can get my code examples, in hex, ready to load into Virgule/emulsiV, with a brief readme about what does what.  

Go to my github--here.

As far as COVID-19: turns out I was lucky and my symptoms were mild. In six days I got a doctors note and was back on the plane to the good old USA. Now I am happily blogging, and the weather here is fantastic. 

COVID-19! It's what you get when you breathe the fumes.  I would not feel so all alone...Keep coding, jester. 


Tube Timbre Trasher, Not Done, But It Works

DiWhy QUESTION! why start building something that you don't completely finish? 

Answer: Because you can!!

it works!

This time I used two 1J24B low voltage pentodes, a tube I first learned about from Ken Stone's tube VCA, to create a timbre modifier. The result is a "waveform folder" common to the West Coast synthesizer sound.  Two 1J24B pentodes a few op amps and caps are almost all you need.

You may want to read previous posts here (introduction to 1J24B), here (experimenter PCB for this concept), and here (the 2x tube breakout board) before running with this project. 

We begin with 3 PCBs from my generous and always enthusiastic sponsor PCBway, check them out here

Clockwise from the right: primary signal processing and conditioning, a dual tube breakout board, and I/O like jacks and pots.

First I built up the 2x tube breakout board:

 

Then on the the main PCB. 

There was a trace error in the main main PCB, which is fixed in the project's post at github (here). I was sending too much current through D1 and D2 on the dual pentode breakout board and I kept blowing up the diodes. Took me a while to figure that one out, but I got it sorted.

Bodges R Us! Can you spot the trace fix?

Otherwise, other than calibrating the 2 trimmers, it worked first time. It was tricky to set it up. 

If I over-biased the CV's and audio signals it distorted the incoming signal so much that I ended up getting nothing at the output except an op amp slammed against its supply rail.  

Best way to calibrate: put a 0-5V triangle wave the CV input and a 10V ramp audio in then look at the corresponding testpoints with a scope. Turn the CV and audio input pots full up. You should see the grid signal modulating from about -1V to about -6 and the screen between about +12 and +15V.  If not, you may have a mistake somewhere, trace the signal to figure it out....If the incoming signals are making it to the tubes, put a 10V ramp signal at audio input use a 0 to 5 control voltage at CV in.  Adjust the trimpots until it sounds the way you want. The CV trim will have to be adjusted a fair amount, but you will hear the modulation effect come and go when you start to hit the sweet spot.


Overall this design is not finished--I never fabricated a front panel for it, for instance, but as it is, it's OK. For the complexity of this design, it makes more sense to use a simpler approach, perhaps use a Norton 3900 instead of 2 tubes--the two different approaches sound very similar at in terms of how they fold a ramp wave.  



You can hear what the Tube Trasher sounds like here.  I intentionally made the audio clip simple, just a single ramp or triangle audio wave modulated by a single VCO, into my DAW. No effects, no other modules....we hear a 10V P/P ramp, sine triangle from a VCO, modulated by a 0-5v triangle CV from an LFO Prime. 

For normal audio (say, vocals, a string section, a Solina, whatever) the distortion you end up with sounds pretty--well, really, bad. I didn't bother recording that....

And of course as per this sad post, 1J24B's are hard to get right now, and maybe will from here on, due to world politics. 

Power used for the prototype is +/- 15V, 20mA for V+, 40mA for V-.

For euro fans, aka doepfer smokers: the design works with +/- 12V power but I had to recalibrate the trimpots. I got it to work to +/- 10V as well.

If anyone wants to improve and refine this tube based wave folder, have at it, but for me it's time to move on. 

thanks to PCBWay for their support and encouragement while I was building the Tube timbre trasher. 

So what could be next?  

  • The tubes can be flipped 180 degrees to not stick off the side of the main PCB. I put the tubes off the side as you see above to help with design and troubleshooting, but flipping them to be less obtrusive is trivial--mount the BOB with 90 degree edge connectors on the other side of the main PCB.  
  • You may want to 3D print something to fit between the board and the tubes, and drill some holes to tie wrap the tubes down. As it is, they are pretty fragile.
  • I think building a VCA or some sort of high-gain amplification device ahead of the trasher would be beneficial to its performance.  Things sound pretty good with very hot input waveforms, say 15V P/P vs. 10V. The incoming amplitude at input very much influences the wave folding you hear at output.
  • Can this fold "normal audio" vs. waveforms? It should be able to. What would it take to do that? I  think I'd have to redesign the way the audio inputs are biased, which might be a lot of work.
  • What does a quad version of this sound like, or 2 of these 2x tube designs in parallel? I was pretty excited about this design at first, but lost a lot of steam when 1J24Bs got hard to acquire due to the war in the Ukraine. That alone, at least for now, makes me not want to work on this project too much more; it is so sad..... 

After all that encouragement: Get all the gerbers, pdfs, BOMs, wiring guides, etc., at my github here. Nevermind the spooning--I encourage forkers.

Onwards: It's time to conjure a new C/C++ toolchain and MCU for the next batch of projects. I am thinking RP2040 or STM32, both popular, inexpensive, and fast, and each more capable (albeit complex) than the beloved Atmel 328.  

I won't be posting as much in the next few weeks while I experiment with toolkits and these processors. Oh and return to my day job after 2+ years under pandemic house arrest. After that, I'll be back with a vengeance. Stay tuned.

124B Pentode Dual Tube Breakout Board. Not a fun Post.

 

Sad to say that AudioDiWHY has not been fun over the last few weeks. A pervasive sadness has crept in and my pychiastrist girlfriend says I need a break.

I finished working on the tube timbre trasher (part one here).....where I am designing and prototyping a synthesizer waveform distortion module using a Soviet-era low voltage pentode, the 1J24B. For this post, let's focus on the breakout board needed for the prototype. I'll post the rest in a few days.

Tube audio! Fun stuff right? The Soviets—they knew tubes!! Long gone and good riddance?  Let’s take some tiny, low voltage tubes used in USSR fighter jets, turn swords into plowshares, and use them for audio! 

Until….until....when cleaning out my lab, I mindlessly dug up the box the 1J24B's came in:

 


I redacted the Ukrainian vendor's name and address, but after searching the web, as far as I could tell, the Ukraine was the primary source of the worlds' NOS, affordable 1J24B's

Needless to say these parts, which were really easy to obtain 2 months ago, are no longer available on Ebay, and perhaps anywhere else, due to heartbreaking world events.  

Specifically, the 1J24B's I had been using for my prototypes came from the same Ukrainian city you see in the war correspondence here

The news from this part of the world is maddening, confusing, and at times, terrifying. My psychiatrist girlfriend, usually tough as nails, was about as scared and upset at the news of the conflict as I've ever seen. The battle at Zaporizhzhia made her frightened for her kid, who is studying abroad, not too far away from the conflict, as well as for herself, for the world, and for me. 

This made me want to stop working on this for-fun project and spend my time doing more useful and constructive things. But I am still stuck at home due to the global pandemic, and found myself continuing to work with my remaining 1J24B's.

 


Anyway....putting politics and emotions temporarily aside, well before I realized where I sourced the parts from, I created a two tube version of the 1J24B breakout board you see in previous posts here and here. I posted the files for this board on my faithful sponsor, PCBWAY's project page, here. 

The design requires you have some 1J24B’s already or can get some.

UPDATE: 5-25-23 Tragically: the war in Ukraine drags on, but these tubes are available again from Western retailers. Synthcube for instance has them in stock as of today it appears: go here.

If so, you can use this PCB to breadboard a low cost, low voltage dual tube design, say a push pull amplifier or a tube based op amp. 




Cathodes for this BOB require ground and -2 to -15VDC. See the post here for how the 1.5V direct cathode power works.


Under different circumstances, I’d be all over further experimentation; finding audio uses for these extremely interesting tubes would be a lot of fun.

 



Now, not so much. Due to the war, it's not much fun experimenting with these parts.  Maybe it's just me.

Damn. 

 

Differential Op Amps--Analog Math Fun! Simple Curve Tracer!

The folks at the incredible Bell Labs were on fire right?  

I see that the C programming language came from those guys, along with the transistor.  

They were pioneers in electronic music creation, even.  

But, arguably, we audio DIWHY folks' favorite Bell Labs creation is the op amp--the handy 25cent  IC commonly used in a negative feedback loop for analog data processing.

Yes, Bell labs invented that as well.  


Op amps are everywhere! I use them everywhere in my designs....so does everyone else--adding two signals, changing a DC offset, inverting an audio signal, as a comparator.... 

Question: Can we use it for simple subtraction? 

Of course. It's easy.


Simple math fun: subtract two voltages--if R1 = R2 = R3 = R4, the output is V2 - V1.  


By setting R1 = R4 and R2 = R3, you can gain up V2 - V1; the relationship of R2-R3/R1-R4 gives you your gain.



You can add more inputs and do more math, but it starts to get a bit more complex fast (Hope I got that equation on the right, right?)


So what else can we use the difference amp for?  How about a very simple mic preamp (here)? 

Can we use a differential op amp in test equipment, to measure the voltage drop across a shunt resistor ? Yes.


Indeed. This is an extremely common circuit fragment in audio--you can find a differencial op amp in the output stage of YuSynth's popular VCA design, for instance:

    



Pun Intended 

I took a "different" approach; I wondered if I could use a difference op amp to form a basic V-I component tracer (a good video about how to build a simple tracer--without op amps--is here).  

To motorize this pursuit, I could have breadboarded a $2 curve tracer, but I hate breadboards. Instead, I crafted a very simple differential op amp PCB and sent the gerber off to my sponsor: PCBWAYHere we go again with the shameless plug: Help out this blog and check 'em out OK?




The board came back to the USA really fast....here it is.


Populating it took about 30 seconds....give or take.....


Ready to hook up +/- 15V and ground and start testing things....



To trace a diode I put a 100hz 10V P/P triangle wave from a Siglent 1025 waveform generator into "FG-in"; put a diode under test between TEST1 and TEST2 wirepads, soldered a 1K resistor into R4, and jumpered R1. 

Next I tied IN1 to J1 and In2 to J2 (or IN1 to J2/In2 to J1, depending on how I wanted my scope trace to appear along the X axis--both work). 

I increased the gain of the circuit by increasing R2 and R3 to 10K. This made the range of the traces easier to see on my scope. 

To wire the PCB to my scope (a Siglent 1202XE--for X-Y mode, press the "acquire" key and then using the soft buttons below the display, set "XY"  to "on") I ran the FG-IN signal to Y input terminal and the output of the op amp to the X input terminal.




Some meatballs with my spaghetti?


For a diode--the result is a quasi-decent curve:

4004 diode....

5V zener....

The problem I faced: op amp rails max out at maybe +/-15 or 20V, but for a useful trace cursor, I needed a much wider voltage range, maybe +/- 60V, which would fry any ordinary op amp.  This single differential op amp design cannot accommodate the high voltages needed to create traces for parts like the one here. Oh well.  

I also needed a staircase generator to generate traces for transistors (example schematic can be found here, but I'd probably use an Atmel 328 MCU and a MCP4911 Digital to Analog converter instead) , as well as a switch or relay to compare the curves of 2 different transistors under test. 

Maybe in the coming months I'll work on this.....

Anyway if you are a fellow breadboard hater and would rather get this very simple differential op amp configuration on a thru-hole PCB, you can get the gerber, Eagle files, BOMs, PDF's etc. from PCBWAY's project page, here.

Coda 

I am curious: what happened to Bell Labs?  They got sold to Nokia. I didn't know that--you learn something every day. So much for American Ingenuity right? The trust busters broke up Bell in 1984, so the biggest monopoly we're left with are these guys.  Has Nokia made the transistor obsolete? Come up with a more popular programming language than C? Not yet. But! They have given the planet a ubiquitous ring tone

Al Fine 

In the immortal words of the Chambers Brothers: Time! Time to start wearing real shoes again. Time to shave every morning....time to go back to my 1.5+ hours a day work commute--after two years--wow.  

It was real, it was fun, but it wasn't real fun.

Sequential Quad Sample/Hold

I've not had time to post to this blog lately; COVID stats are improving here in the Northwest US, and thus I am commuting to my day job again. 

This is good news I guess--the "health is improving" aspect, anyway? 

During the (hopefully) final few weeks of our collective two year COVID house arrest I found myself digging through my box of old audio IC's: which puzzle to solve next?  

The Curtis ElectroMusic System's CEM3394, intrigued me: an "all in one" synthesizer chip used in the Sequential Multitrak, an instrument I owned and loved back in the late 90's.

I don't know what happened to the Multitrak.....I sold it? Loaned it? Couldn't remember.....



I had four new old stock CEM3394's in my junk box. Could I make a single board, low parts count synth out of these IC's? 

Where would I start?

Like the popular CEM3340 IC, the CEM3394 required analog control voltages to function. I wanted to understand how the internal control voltages ("CV's") were implemented in early digital/analog synthesizers--and use that in a future 3394 project--since I wanted to stay true to the spirit of these venerable old designs.

I'd need a to pick an MCU for the project--the 3394 chips were designed to be microprocessor controlled. Some old synths used Z-80's, but would an Atmel328 work?

I started to research and came across this post. Short answer: yes, this could work!

(Aside: The post's final comment from "Grumpy Mike" makes me sad, it's the kind of fear and loathing and BS I really dislike; besides, he's wrong. Sequential CEM based gear from that era didn't use 16 or whatever DACs in a single synth, and when they worked correctly had internal CV's that didn't sag--you could hold a single chord for hours and it was solid). 

How did Sequential avoid putting several (expensive) digital to analog converters ("DACs") in every instrument? And how did they keep critical MCU controlled CV's, like oscillator V/octave, rock solid?

Turns out they used multiplexers, or MUX's (for the Prophet 5, CD4051 IC's) and had a Z-80 processor refresh a DAC that in turn fed many MUX'd sample and hold capacitor + op amps circuit fragments, quickly, over and over--sequentially.

That way the SH's outputs would not droop, and very few MCU and DAC's--relatively expensive components then and now--I see just one of each in the Prophet 5, right?--were needed for a complete, complex microprocessor controlled analog synth. 

Prophet-5--thing of beauty!

No Holds Barred

The Prophet-5's service manual helped me understand Sequential's no-droop sample and hold. Get its PDF here; an excellent explanation of how the MPU > DAC > S/H mux's work is on page 29.

But!! As a curious DiWHY dude, why read when you can build? 

I designed and laid out a simple quad sample and hold board, which I called, predictably, "Sequential Quad SH". 

Coded it--built it.

Worked first time (WFT).

MCU control was from a "Minimalist" Atmel328 C dev board; you can get that from sponsor PCBWay's project site, here.  

For the Digital to Analog Converter (DAC) I chose a SPI 12-bit Microchip MCP4921; download an embedded C library for it and its 10 bit cousin for AVR328 processors here

I used Eagle to lay out the PCB:

The PCB has provisions for an External DAC feeding the 4051 MUX, if you use the MCP4921 make sure to jumper the 2 "DACLINK" pins in the middle of the board; if you want to use a different DAC IC (for a CEM3394, an AD5792?), tie your external DAC's output to the right pin of DACLINK and omit the MCP4921.

The Eagle gerbers were uploaded to this blog's enthusiastic, burning-the-midnight-oil sponsor: PCBWAYPlease help support this blog and check 'em out.

Soon the PCB was back, so I built it....





Board, breadboard and minimal Atmel 328 dev board....next, hook it all up....

Let's try some different caps....

Ready to test!


The board worked pretty much first time....I made a few dumb mistakes during fab--I forgot to solder on some caps, but once I corrected that mistake this was a win.

Code Me Up Scotty! 

Crafting the Embedded C firmware for the Sequential Quad SH was pretty easy. I used my usual toolchain: Atmel ICE and Atmel Studio 7.  I leveraged my minimalist AVR board (here) for the brains of this proof of concept but most Arduino development boards with AVR processors should work with little to no modification to the code. I uploaded code for the SH project to Github--repo is here.  

I also created repos for the drivers used in the project, each with its own main.c. Get the DAC code here. For the 4051 MUX the .c and .h files are here.

The main.c's infinite loop sent hand-coded values to each channel of the mux. For real-world applications I would change the demo code to read values from the outside world--from the MCU's ADC's for example.

    while (1) 

    {

write4921(4000);

_delay_ms(2);

        single4051_out(0);

        single4051_inhibit();

        _delay_ms(1);


write4921(0);

_delay_ms(1);

single4051_out(1);

        single4051_inhibit();

        _delay_ms(1);


write4921(2500);

_delay_ms(2);

single4051_out(2);

        single4051_inhibit();

        _delay_ms(1);

write4921(1000);

_delay_ms(2);

single4051_out(3);

single4051_inhibit();

_delay_ms(1);


}

I had to experiment with timing--the Sequential manual says one should inhibit MUX operation whenever the DAC value changes, and I found that doing so got me the cleanest looking DC output on a scope.



Here's one of the 4 S-H outputs, with a 12 bit DAC value of decimal 4000:


And yes, the CV never sagged as long as the PCB and Dev board had stable DC power. I went away for coffee and came back a half hour later--spot on.   


Bust a Cap


One of four sample and hold subcircuits. Voltages are captured in C9; since the non-inverting input of the opamp is almost infinitely high impedance, while DAC2 has associated current of something like 20mA, the voltage is held until changed.



I didn't know what type of capacitor to use for each sample and hold subcircuit; I have heard techs (passionately) discuss what is the best and most stable capacitor for sample and hold applications. 

I tried poly film, polystyrene axial, and mylar .01uF's. No difference was seen on my scope for any of these. 

I ended up using .01uF poly box film caps because I had a lot of them lying around.



Samples to Hold

If you want to play along at home, get the embedded C code, Eagle files, gerber, drawings and so on from Github (here). The project can also be found on a PCBWAY project page (here).  

Overall, this was a fun proof-of-concept to research and build. 

Once finished, the circuit provided a simple way to get a lot of horsepower out of a single inexpensive DAC. I figure with a reasonably fast MCU this idea can be expanded to accommodate 40 CV channels, maybe more; for more ideas see the Sparkfun page here.  

I can now see why MUX's were so critical to the Prophet-5's design as well as other classic computer controlled synthesizers: mux IC's are relatively inexpensive; DACs, not as much.

It would be pretty easy to turn this design into a Euro 4- or 8-channel "no sag" S/H Eurorack module, but I don't have time for that now, with my post-Covid19 day job ramping back up. 

Overall, with affordable multichannel DAC's like the MCP4728 available the CD4051 MUX approach may not always be necessary, but it's a good tool to have in one's toolbox. But in general, this MCU > DAC > MUX paradigm, I figure, will be find inclusion into upcoming audio DiWHY projects.

Hats off to Sequential for providing rock solid CVs that don't sag, in a manner that doesn't break the bank, presented in a the service manual is clearly written--so much so, even I can follow it!

Sample well, Luke. See ya next time. 

1J24B part II: Tube Based Audio Timbre Trasher and Experimenters' Board

From this previous post: audio bench experiments using the interesting, inexpensive, small, low voltage 1J24B pentode continue. 

What else can we use this miniature valve for, in our rack, our bench, and so on?

How about a timbre modifier? While breadboarding, I noticed that putting a capacitor between the tube's screen and ground seemed to distort the waveform found at the anode (the tube's "output").  As the screen voltage changed, differing frequencies were driven through the cap, causing odd waveform distortions you could see on a scope (to use US slang--we are "trashing" the signal--a "timbre trasher"?  Why/why not?).  

Breadboarding a 1J24B, with its tiny exposed wires, proved difficult, so last time I designed a 100mil breakout board for the tube and its power (post here, project notes with gerber is here).  

I could probe the buffered and cap coupled output of the single 1J24, and auditioned the prototype through my bench preamp/amp/speakers. 

To my ears, with all the buffers set up correctly, the design sounded a bit "filter like", maybe reminiscent of a 12db/octave VCF without resonance.  Cool!

But even with the 1J24B breakout board on my bench things got unwieldy. 

I figured a dedicated "tube trasher" PCB for further experimentation would help a lot. So I drew one up....

The PCB looks like this:



I got this fabbed by the blog's sponsor, PCBWAY, and here's the shameless plug: please help out the audiodiWHY blog and check them out.

The design pretty simple; the 1J24B is the center of the design, with a 30V cathode/plate voltage differential (an idea borrowed from Ken Stone's tube VCA, read more about that here--clever!)  Also a few op amps, since tube circuits like this require bias offsets and buffering, as well as 4 pots set up as voltage dividers between the V+ and V- rails.



 

The PCB is relatively large for the number of components used, making trace cuts, customizations, and/or offloading parts of the design to a breadboard, relatively easy and quick.


For fabrication I elevated the passive components somewhat, to make it easy to get a probe on one of the leads, or do modifications.





Then was a matter of populating whatever part of the board I felt I needed for the experiments. 

For the videos you see and hear below, I used 2 experimenter boards in series, with a 1uF AC-coupled feedback paths between boards' input and output buffers. 

Anyone who wants to follow along, see the wiring setup, get PDFs and Eagle files for design so far, and so on, should please go to the github repository here

You can also get a gerber for the experimenter board from PCBWAY's project page here.

Benchomania: I used "tall trimmer pots" to manually dial in the offsets, which I then noted; I will make a 3rd revision of this board soon with the values for the voltage dividers approximated with resistors, hopefully making the board less expensive to fabricate.




It works....


So far, this month's experiments have yielded a satisfying timbre shifter when 0-5V CV was applied to the first 1J24B's PCB screen, and an buffered and bias offset 1-2V P/P is applied to the grid, but the offset voltages seemed too sensitive for this to be fully practical, so this design still has a way to go; perhaps multiturn trimmers will have to be designed into the next PCB iteration along with some other tweaks?  Probably.

The video is a single experiment board, built and calibrated, being modulated by a 0-5V control voltage. The bias offsets used throughout are roughly documented at the bottom of the post here, but each 1J24B seems a bit different.  Again trimmers might be the way to go here.

For the incomings signal I used a 1-2V ramp wave with about -3V DC offset, from a Siglent waveform generator, but I had to try different things; the bias offset and amplitude of a source audio signal greatly influences what you hear at output, and too much or too little offset and amplitude for the source can make the entire output go dead--but once it's dialed in correctly, it works, but the "timbre mod" is pretty subtle and is more visible on a scope than with my ears. 


Next I wired 2 boards in series, and got the feedback going between the two. CV modifying the timbre comes from the output of an "LFO PRIME".  In this configuration, you can hear a bit more drama in the CV sweep.....if you want to learn more about what I've gotten to work so far, a wiring diagram, notes, PDFs etc., of the setup you see in the video below, is available via github, here.




Since 2V P/P saw wave gets nicely transformed into other strange shapes reminds me maybe a bit of "West Coast" work by Serge--back in the early 2000's I built a clone of the Serge Waveshape modifier, this design sounds a bit like that. So far, so good.

OK! For the next revision I'd like the 2 tubes and the buffer board to be reasonably small, but the design can't be SMD (yet) because too many design points are still being worked out. Maybe by next month I will have rev 3 ready to go? Stay tuned.

 Update 3-3-22: boards are designed, I should have them back from PCBWAY next week.  Assuming I can make it work, I will post the updated design in an upcoming post.