Random MCU-Based Module Firmware Coding Questions

1. Is the % (mod) operator particularly expensive, processing-wise for 8/32-bit MCUs?
They’re very useful for dividing clocks, I’ve found. Maybe there’s some fiendish bit-manipulation shortcuts to do the same thing.

2. With an MCU-based step-sequencer, what’s the best way to handle gate-lengths? I’m thinking requiring a pulse wave clock, rather than the very short triggers that may be provided by some clock-generator modules may not cut it. If that’s the case, could anyone recommend a good way of calculating gate lengths from the rising edge only off the click source? Would a simple running average of the pulse-to-pulse period do the job, or would some more involved pattern-prediction setup be better?

a|x

Worth bearing in mind that operations which are expensive for DSP processing at audio sample rates may be cheap at musical (melodic and rhythmic) rates.

Depends on the MCU… On an 8-bitter, % calls a division routine which can take about one hundred cycles. On a 32-bit MCU it’s likely to be part of the instruction set (on the cortex M3, it’s 12 cycles).

So it’s cheap, but you probably don’t need to do use it anyway. Since you are counting steps, you can very well do

if (counter >= pattern_length)
counter = 0;

Taking the duration of the previous inter-pulse time will get you there. Unless the clock swings or your module is clocked by an irregular gate pattern. In this case, it can get fairly complicated very rapidly!

1 Like

Thanks guys. Good to know.
My current plan is to use a Cortex M0+ (Teensy LC), so hopefully that will also have % in its instruction set.

@pichenettes I like % because it provides a simple way to allow you to change pattern length without jumps, or having to deal with cases, for example, where we’re on step 67, and we set the pattern length to 15.

Re. clocking; I could add a jumper to select between requiring a square-wave clock (where gate-off is triggered by falling edge), and using a rolling average of inter-clock period.

I’m also thinking I might have to handle the possibility that the clock may be so irregular that gate is still high when the next pulse happens. In this case, I guess I’d set gate low, then wait a short time before setting it high again.

a|x

> Cortex M0+ (Teensy LC)

I don’t think the M0 has a division instruction.

> @pichenettes I like % because it provides a simple way to allow you to change pattern length without jumps, or having to deal with cases,

Can you give me a case in which comparing to the pattern length wouldn’t work? If you’re on step 67 and the pattern length is 15, you’ll have to jump somewhere anyway… Whether you jump to 7 or 0, it’ll appear like a random jump anyway.

The Teensy 3.2 is only a few dollars more… (doesn’t have FP but it does have the full range of integer maths support, at least).

> I like % because it provides a simple way to allow you to change pattern length without jumps, […]

How about this:

int realPlaybackPosition;
int patternLength;
int currentStep=realPlaybackPosition;

while (currentStep >= patternLength)
currentStep -= patternLength;

Might end up being less expensive (two subtractions + a conditional jump per loop cycle) depending on how large realPlaybackPosition gets. But honestly, unless you want to run this at audio rates, why would you even care about it? % is very readable.

Thanks guys.

@pichenettes true, there is still a jump. I guess the only way to avoid that would be to wait for the current pattern length to be reached, before switching to the new length. But then you might have to wait for a while before that point is reached…

I think I’ll stick with the % for the moment. I’m sure it will be ok, since I’m not operating at anything like audio rates.

I’m planning to add a Reset trigger socket, as well as the Clock in, so you can just send a pulse to that, if things get too chaotic. Might be worth adding a button for that too, since I could do that without using any additional pins on the MCU.

I chose the Teensy LC because it’s slightly cheaper, and chose this over an 8-bit chip because I thought it would be easier to add USB MIDI I/O using the builtin socket than to add a USB controller chip to my circuit board design if I were to go for an ATMega or similar 8-bit controller.

a|x

Incidentally, in my JavaScript simulation, I’m driving all the pattern clocks from a single master clock, which keeps incrementing indefinitely.

All numbers in JS are 32-bit, but I guess it would be unnecessarily expensive to use a 32-bit number for the master clock in an MCU implementation.

a|x

> which keeps incrementing indefinitely.

Until it reaches the maximum integer and wraps around.

In which case you have a step skip or repetition if the maximum integer is not a multiple of the pattern length. For example, with an unsigned 32 bit counter, 0xffffffff % 3 is zero, and then the next integer, 0 % 3 also gives zero.

It would take some time to get there, but who knows?

I realised that. But if I was incrementing the clock only on 16th notes, it would take 6x as long before it wrapped. Might be so long it’s not really an issue…

Or, I could make it wrap at 255. That’s 16 bars, at 16 notes per bar, which may be long enough for a nominally 16-step pattern-generator, anyway…

I could use an 8-bit number then.

I have made a pseudo-random feature, too, to add spice. It looks up offsets from a small table, with a random offset to the lookup position every bar.

I must admit, I went a bit overboard with lookup tables on this project. I even made a table for the X and Y cell index and position, rather than using you bit-shifting code from Grids.

Until I try porting the code to the Teensy, I’m not sure if it’s more efficient to use these tables, or just do the maths every time.

a|x

You can look at the assembly output from the compiler. I don’t “speak” much assembly myself, but I usually found the portions of interest (shrinking down the project helps here). For small processors it often is enough to count the number of instructions to get an idea how long it will take to execute.

But then again, I don’t think its necessary to optimize. Optimizing too hard destroys hackability and readability

I’m all for not optimising :wink:
(Mostly because I don’t know how, anyway).

I’m completely new to MCU programming (though had a couple of false starts), so actually getting it to work at all is the first hurdle…

a|x

Oh. And also not breaking the teensy by frying the I/O pins…

I’ll have to look at some of the MI module schematics to see how to protect the in and out pins in a modular environment.

Am I right in thinking Grids probably doesn’t provide a good model for this? It uses a 5V processor, I think, where the Teensy LC can’t deal with anything over 3.3V, apparently.

a|x

> I’ll have to look at some of the MI module schematics to see how to protect the in and out pins in a modular environment.

I can’t think of any module I’ve released where the in and out pins of the processor are connected to the outside world. There are awlays op-amps or transistors in-between.

I think they are in the CVPal (albeit with resistors between).

I think the ATiny MCU has some builtin protection, though.

a|x

I don’t consider the CVpal as an official Mutable Instruments product. Just like the Shruthi, it’ll only teach you how to do cheap and dirty things…

Fair enough. Very useful little module, though…

a|x

So this (from Tides schematic) is the proper way to protect a trigger/clock input?, with a transistor.

And I think these are the High and Low Tide trigger outputs, also protected with transistors.
Is it worth socketing transistors, in case they do get blown?

a|x