A volume control is essentially a way to scale a signal somewhere between a minimum and maximum value. If you're used to analog signal design, you'd usually implement this with a voltage divider like this:
Input enters at the Vin port, and output is taken from the Vout port. The ratio of the two impedances Z1 and Z2 determines how much of the signal is allowed to exit Vout.
Vout = Vin * (Z2 / (Z1+Z2))
In practice you'd use a potentiometer to do this, it's the basis of everything in guitar effects. Your guitar probably even has one or two volume controls just like this.
In FXCore, we do have pots but they're not connected to anything in the analog domain, so we have to go through a couple of extra steps to get what we want.
Here's the most basic possible code for a volume control:
Code: Select all
; BUILDING BLOCK 01a - VOLUME CONTROL
; Read input, scale with POT0, write output
.rn temp r0
cpy_cs acc32, in0 ; read input into accumulator
cpy_cs temp, pot0_smth ; get smoothed value from pot0, will range from 0 to 0.99999
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0
Type or copy that code into your editor of choice and then upload it to your dev board. You should be able to play a signal into in0, output from out0, volume control on pot0. If you don't hear anything, check the troubleshooting steps in BB00 - Getting Started.
This will not amplify / make your input louder, it just passes it on at unity gain or less. If you want to boost things, you'll need to do an extra step.
Code: Select all
; BUILDING BLOCK 01a - VOLUME CONTROL WITH BOOST
; Read input, apply gain, scale with POT0, write output
.rn temp r0
cpy_cs acc32, in0 ; read input into accumulator
sls acc32, 1 ; shift input left by one bit, this is the same as multiplying by 2 or gain of +6dB
cpy_cs temp, pot0_smth ; get smoothed value from pot0, will range from 0 to 0.99999
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0
If you want to bump the signal down, you can use the barrel shifter in reverse, shifting right to cut signal:
Code: Select all
; BUILDING BLOCK 01b - VOLUME CONTROL WITH ATTENUATION
; Read input, apply attenuation, scale with POT0, write output
.rn temp r0
cpy_cs acc32, in0 ; read input into accumulator
sra acc32, 1 ; shift input right by one bit, this is the same as divding by 2 or gain of -6dB
cpy_cs temp, pot0_smth ; get smoothed value from pot0, will range from 0 to 0.99999
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0
For our last trick, we'll create a volume control with a limited range. This is useful when you don't want the knob to go all the way down to zero, or maybe you don't want it to go quite all the way to maximum
Code: Select all
; BUILDING BLOCK 01c - VOLUME CONTROL WITH LOWER LIMIT
; Read input, limit range, scale with POT0, write output
.rn temp r0
cpy_cs acc32, pot0_smth ; read smoothed value from pot0, will range from 0 to 0.9999
multri acc32, 0.8 ; multiply pot by 0.8, this means it now ranges from 0 to 0.79999
addsi acc32, 0.2 ; add 0.2 to pot, this means it now ranges from 0.2 to 0.9999
cpy_cs temp, in0 ; read input into accumulator
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0
Code: Select all
; BUILDING BLOCK 01d - VOLUME CONTROL WITH UPPER LIMIT
; Read input, limit range, scale with POT0, write output
.rn temp r0
cpy_cs acc32, pot0_smth ; read smoothed value from pot0, will range from 0 to 0.9999
multri acc32, 0.8 ; multiply pot by 0.8, this means it now ranges from 0 to 0.79999
cpy_cs temp, in0 ; read input into accumulator
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0
Code: Select all
; BUILDING BLOCK 01e - VOLUME CONTROL WITH UPPER AND LOWER LIMIT
; Read input, limit range, scale with POT0, write output
.rn temp r0
cpy_cs acc32, pot0_smth ; read smoothed value from pot0, will range from 0 to 0.9999
multri acc32, 0.6 ; multiply pot by 0.6, this means it now ranges from 0 to 0.59999
addsi acc32, 0.2 ; add 0.2 to pot, this means it now ranges from 0.2 to 0.7999
cpy_cs temp, in0 ; read input into accumulator
multrr temp, acc32 ; multiply input * pot, the result will be held in acc32
cpy_sc out0, acc32 ; write acc32 to output 0