Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
Help about MediaWiki
Sandbox Pedal Wiki
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Writing your first FV-1 program
Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
This guide builds up a working tremolo from nothing, one step at a time. Every example here assembles cleanly and can be pasted straight into the [https://fv1.sandboxpedal.com Sandbox FV-1 Editor]. You do not need a pedal to follow along β the [[Using the FV-1 simulator|simulator]] will play all of it. == How an FV-1 program works == The FV-1 runs your program '''once per audio sample''', 32768 times a second. There is no main loop that you write; the chip loops for you. That gives you a hard budget of '''128 instructions'''. Anything shorter is padded with NOPs automatically. There is no way to spend more time on one sample than another. Almost everything flows through a single '''accumulator''' (ACC). You read a value into it, do arithmetic on it, and write it somewhere. Most instructions multiply by a coefficient on the way past. The registers you will use first: {| class="wikitable" ! Register !! Meaning |- | <code>ADCL</code>, <code>ADCR</code> || Audio input, left and right |- | <code>DACL</code>, <code>DACR</code> || Audio output, left and right |- | <code>POT0</code>β<code>POT2</code> || The three control knobs, 0.0 to 1.0 |- | <code>REG0</code>β<code>REG31</code> || General-purpose storage |} Coefficients are fixed-point fractions in the range β1.0 to just under 1.0. You cannot write <code>1.0</code> and expect exactly one in every field, which is why you will see <code>0.999</code> in places where you might expect 1. == Step 1: pass-through == The smallest useful program copies input to output. <pre> RDAX ADCL, 1.0 ; ACC = left input WRAX DACL, 0.0 ; left output = ACC, then clear ACC RDAX ADCR, 1.0 ; ACC = right input WRAX DACR, 0.0 ; right output = ACC, then clear ACC </pre> Two instructions per channel. <code>RDAX</code> reads a register into the accumulator, multiplying by the coefficient on the way in. <code>WRAX</code> writes the accumulator to a register and then multiplies what remains in ACC by ''its'' coefficient. That second coefficient is the part that catches people out. <code>WRAX DACL, 0.0</code> means "write ACC to the left DAC, then zero the accumulator" β which is what you want before starting work on the other channel. Using <code>WRAX DACL, 1.0</code> would leave the value in ACC and the right channel would come out as a mix of both. Assemble this and play it through the simulator. It should sound like nothing at all, which is the correct result. == Step 2: a volume control == Now put POT0 in charge of the level. <pre> RDAX ADCL, 1.0 MULX POT0 ; ACC = ACC * POT0 WRAX DACL, 0.0 RDAX ADCR, 1.0 MULX POT0 WRAX DACR, 0.0 </pre> <code>MULX</code> multiplies the accumulator by the contents of a register. Because <code>POT0</code> reads 0.0 to 1.0, this is a straightforward volume knob. Open the SIM panel and move the POT0 slider while it plays. == Step 3: an LFO == A tremolo is a volume control that moves on its own, so the next piece is a low-frequency oscillator. The FV-1 has two sine LFOs (<code>SIN0</code>, <code>SIN1</code>) and two ramp LFOs (<code>RMP0</code>, <code>RMP1</code>). You start a sine LFO with <code>WLDS</code>: <pre> WLDS SIN0, 40, 32767 ; LFO 0: rate 40, full amplitude </pre> This only needs to happen once, not on every one of the 32768 samples per second. The idiom for that is a conditional skip on the <code>RUN</code> flag, which is clear on the very first pass through the program and set on every pass after: <pre> SKP RUN, loop WLDS SIN0, 40, 32767 loop: </pre> On the first sample, <code>RUN</code> is clear, so the skip does not happen and the LFO is set up. On every subsequent sample the program jumps straight over <code>WLDS</code> to the <code>loop</code> label. To read the LFO's current value, use <code>CHO RDAL</code>: <pre> CHO RDAL, SIN0 ; ACC = the sine LFO, swinging -1.0 to +1.0 </pre> == Step 4: shaping the LFO into a gain == The LFO swings from β1.0 to +1.0, but a gain needs to be positive. <code>SOF</code> β scale and offset β fixes that in one instruction. <code>SOF a, b</code> computes <code>ACC = ACC Γ a + b</code>. <pre> CHO RDAL, SIN0 ; -1.0 .. +1.0 SOF 0.5, 0.5 ; halve it, shift it up: now 0.0 .. 1.0 </pre> Next, depth. Multiplying by POT1 scales the swing down, and a second <code>SOF</code> flips it so the gain sits just below unity at minimum depth: <pre> MULX POT1 ; 0.0 .. depth SOF -1.0, 0.999 ; (1 - depth) .. 1.0 </pre> With POT1 at zero the gain is a constant 0.999 β effectively off. With POT1 fully up the gain swings across the full range. == The finished tremolo == <pre> ; Simple tremolo ; POT0 = rate, POT1 = depth EQU mod REG0 ; Start the sine LFO once, on the first pass only SKP RUN, loop WLDS SIN0, 40, 32767 loop: ; POT0 sets the LFO rate RDAX POT0, 0.5 SOF 1.0, 0.02 WRAX SIN0_RATE, 0.0 ; Read the LFO and fold it into a 0..1 gain CHO RDAL, SIN0 SOF 0.5, 0.5 MULX POT1 SOF -1.0, 0.999 WRAX mod, 0.0 ; Apply the gain to both channels RDAX ADCL, 1.0 MULX mod WRAX DACL, 0.0 RDAX ADCR, 1.0 MULX mod WRAX DACR, 0.0 </pre> Sixteen instructions, out of the 128 available. Two new things appear here. <code>EQU mod REG0</code> gives <code>REG0</code> a readable name β the assembler substitutes it, and it costs nothing at runtime. Writing to <code>SIN0_RATE</code> changes the LFO rate while the program runs, which is what turns POT0 into a rate knob; the <code>SOF 1.0, 0.02</code> keeps the rate from reaching zero at the bottom of the sweep. Load it into the simulator, press Play, and move POT0 and POT1. == Where to go next == * '''Delay memory.''' The <code>MEM</code> directive allocates space in the FV-1's 32768 words of delay memory: <code>MEM delay 16000</code>. It creates three symbols β <code>delay</code> (start), <code>delay#</code> (end) and <code>delay^</code> (midpoint). <code>RDA</code> and <code>WRA</code> read and write it. * '''The built-in examples.''' '''Load Fileβ¦''' in the editor offers Pass-through, Delay, Chorus and Tremolo. Reading working code is the fastest way to pick up the idioms. * '''The instruction reference.''' The '''HELP''' tab lists the full instruction set with operand formats. * '''Spin's documentation.''' The FV-1 datasheet and application note AN-0001 are the authoritative source on LFO behaviour and the fixed-point formats. == A few things that bite beginners == * '''Forgetting to clear ACC.''' If a channel sounds like it has the other channel bleeding into it, check your <code>WRAX</code> coefficients. * '''Coefficient range.''' Coefficients are fractions below 1.0. If you need gain above unity, do it in stages or use a format that allows it. * '''Setup code running every sample.''' <code>WLDS</code> and friends belong behind a <code>SKP RUN</code> guard. * '''Running out of instructions.''' 128 is a hard ceiling. If you hit it, the answer is usually a cheaper filter, not a cleverer one. * '''Trusting the simulator on chorus.''' <code>CHO</code> interpolation is approximated. Confirm modulation effects on hardware. == See also == * [[Using the Sandbox FV-1 Editor]] * [[Using the FV-1 simulator]] * [[Programming an EEPROM with HEX files]] [[Category:How-to]]
Summary:
Please note that all contributions to Sandbox Pedal Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
My wiki:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)