## First steps

Discussion, support, and resources for our noise making modules and kits.

Moderators: Kent, scottwilson

trotz
Learning to Wiggle
Posts: 40
Joined: Fri Jan 20, 2012 7:28 pm

### First steps

Hi,

I'm trying to learn C++ and to use the nw2s at the same time.

Today I've set it up correctly, managed to upload some sketches and make them work.

I would like to learn to do the following:

1) set up an LFO and make it change its frequency according to incoming cv

2) scale/offset the CV with the potentiometers

3) crossfade between different waveforms (using the wavetables provided) using cv and pots

4) build a quadrature LFO with the options above (very important to me)

5) more than one LFO would be possible(?)... 4 of them, each with a sin/cos output?

What would be the maximum frequency available at the analog outs for these LFO's ?".

Maybe some tutorials could be posted? I'd be also more than happy with some general indications to start with.

Thanks a lot.

scottwilson
Wiggling with Experience
Posts: 432
Joined: Mon Sep 16, 2013 12:54 pm
I'll answer the easier questions first...

I'm sure the max frequency is well above audio frequency, but as you increase the number of channels, it will take some experimentation. SPI is a fast bus 20Mhz. Divide by 16 and divide by 12 (or so, not sure how many bits there are per command)... You see there's a fair amount of bandwidth there.

The limiting factor is more likely how efficient you can make your code. With efficient code, you'll have no trouble generating 16 gates, 16 CV/LFO type things and two audio frequency range outputs.

One example of efficiency is never use sin/cos - Your Intel-based PC is really good at calculating trig. Never mind -how- it does it, it's got a dedicated machine-language instruction and returns to you a floating point.

The Cortex M3 contains no such instruction. So if you include math.h and try to do some slick math, it's going to be really slow. Really, really slow. You might be able to find some C code geared towards microcontrollers to help you, but really, you'll want to create a SIN/COS/TAN table that simply uses a lookup table to return the sin value of a given integer (at some scale that makes sense). This is exactly what wavetable synthesis is.

If you're building LFO's, a better place to start is a sawtooth wave since the value of a saw wave can be calculated extremely easy using integer math. y = mx + b, basically. Or, translated to another language:

outputval = ((frequency * t) + offset) % 4096

Okay, we added the mod 4096 bit, but you've gotta keep your signal within a range and that's what does that. Makes it repeat.

Once you get that working, you'll have a beautiful saw wave - LFO or audio frequency range.

Then you'll soon come to the realization that in order to translate this to a sine wave, what you want is a table of sin values that are values from 0 - 4096 and that is 4096 values long. Use Excel to generate the list and make some C code from that. Then to create a sin wave at any given frequency, you use the output of your saw wave (repeated values from 0 to 4096) to address values on that sin table.

Then you'll realize that - this table doesn't need to only be a sin wave... it can be anything... any wave table.

I'm simplifying a little bit... but only a little bit. The concept is simple... executing efficiently takes time and sweat and tears.

I'm sure you want to build one of your own, and you should, but I do have a wavetable-based LFO on my list to be done with soon... we'll see if I can get it done before the end of the weekend so I can include it in the 1.0 firmware announcement.

s

scottwilson
Wiggling with Experience
Posts: 432
Joined: Mon Sep 16, 2013 12:54 pm
Another note... as to some more specific pointers, get some code going, post it, and lessee how we can make it work (or work better)

-s

trotz
Learning to Wiggle
Posts: 40
Joined: Fri Jan 20, 2012 7:28 pm
scottwilson wrote:Another note... as to some more specific pointers, get some code going, post it, and lessee how we can make it work (or work better)

-s
Thanks a lot!

I will start with a simple cv controlled sawtooth and build up from that

scottwilson
Wiggling with Experience
Posts: 432
Joined: Mon Sep 16, 2013 12:54 pm
Yeah, try even just doing it where it's not CV controlled... just start with the basics. A fixed frequency saw LFO...

1. Base your sketch on the template at

https://github.com/nw2s/b/blob/master/s ... mplate.ino

2. Statically declare an output in the ino file above the setup() function. Lets also declare a counter for good measure.

Code: Select all

``````AnalogOut out1;

unsigned long t;
int phase1;
``````
3. In setup(), initialize the output...

Code: Select all

``````out1 = AnalogOut&#58;&#58;create&#40;DUE_SPI_4822_01&#41;;

phase1 = 0;
t = 0;
``````
4. in loop(), do stuff every few milliseconds. When you get to audiofrequency stuff, you'll want to use timers which are tough. So lets just do LFOs for now:

Code: Select all

``````
/* Do this once per millisecond */
if &#40;millis&#40;&#41; > t&#41;
&#123;
t = millis&#40;&#41;;
int outputval = &#40;phase * 100&#41; - 5000;

out.outputCV&#40;outputval&#41;;

phase = &#40;phase + 1&#41; % 10000;
&#125;

``````
This should create a saw wave from -5V to 5V with a period of 1/20th of a second. I'm writing from memory, so that may not all be 100% valid C code.

Benefit - this is still basically just C - no real C++ yet.

s

trotz
Learning to Wiggle
Posts: 40
Joined: Fri Jan 20, 2012 7:28 pm
Sorry! Far too many syntax errors to correct for the true beginner of mine

Any help would be appreciated.

For example, could it be that the variable phase in loop() should be phase1 instead?

/*

nw2s::b - A microcontroller-based modular synth control framework
Copyright (C) 2013 Scott Wilson (thomas.scott.wilson@gmail.com)

This program is free software: you can redistribute it and/or modify
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

*/

#include <EventManager.h>
#include <Key.h>
#include <Trigger.h>
#include <Clock.h>
#include <Slew.h>
#include <Oscillator.h>
#include <Sequence.h>
#include <IO.h>
#include <SPI.h>
#include <Wire.h>
#include <SD.h>
#include <ShiftRegister.h>
#include <aJSON.h>
#include <SDFirmware.h>

using namespace nw2s;

AnalogOut out1;

unsigned long t;
int phase1;

void setup()
{
Serial.begin(19200);

EventManager::initialize();

/* Put your setup() code here */
out1 = AnalogOut::create(DUE_SPI_4822_01);

phase1 = 0;
t = 0;
}

void loop()
{
/* Put your loop() code here */
/* Do this once per millisecond */
if (millis() > t)
{
t = millis();
int outputval = (phase * 100) - 5000;

out.outputCV(outputval);

phase = (phase + 1) % 10000;
}
EventManager::loop();
}

scottwilson
Wiggling with Experience
Posts: 432
Joined: Mon Sep 16, 2013 12:54 pm
Couple of small tweaks:

https://github.com/nw2s/b/blob/b-1.1.0- ... tarter.ino

1. out1 needs to be declared as a pointer
2. phase should indeed be phase1
3. out should be out1
4. method calls on out1 should use -> notation instead of dot notation since it's a pointer.

Sorry for not coming back and correcting my example before. Lemme know if you have any more questions.

s