El sintetizador fónico Octo (6 / 11 paso)

Paso 6: código de

Conectar tu arduino a tu ordenador. Añadir el siguiente código a su arduino.

OCTOSynth-0.2
//
Joe Marshall 2011
Filtro resonante Meeblip (meeblip.noisepages.com)
Interrumpir el código de configuración basado en código de Martin Nawrath (http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/)
osciladores y optimización de ensamblador en línea por mí.
//
entrada es de 8 capacitivas entradas entrada digital 6, 7, y entradas analógicas 0-6
cada entrada es un solo cable, pasando a algo de metal para tocar
(Yo usé un montón de los pernos de carruaje grande)
//
detección de este es hecho por getNoteKeys, utilizando el método descrito en:
http://www.Arduino.CC/Playground/Code/CapacitiveSensor
//
Usar ensamblador con un bucle desenrollado usando 16 registros para detectar esta
Esto hace las cosas mucho más preciso que el lazo de C que se describe en el enlace de arriba
como estamos midiendo la demora correspondiente en ciclos de procesador único.
Parece ser feliz incluso con energía de la batería, detección de hasta 8 concurrentes
toca.

Las olas son todos definidas en lo más alto, porque estamos forzando a que alinee a los límites de 256 bytes
Esto hace el código de oscilador más rápido (como calcular un desplazamiento de la onda es
una cuestión de sustituir el byte bajo de la dirección).
Dicho esto, otras cosas arduino probablemente se carga aquí primero
porque el atributo alineación parece añadir un par de cientos de bytes del código

#define TEST_PATTERN_INTRO

#define FILTER_LPF_NONE
#define FILTER_LPF_HACK

tabla de 256 valores de seno un seno período / almacenado en memoria flash
char __attributos__ [256] sine256 ((aligned(256))) = {}
0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45,
48, 51, 54, 57, 59, 62, 65, 67, 70, 73, 75, 78, 80, 82, 85, 87,
89, 91, 94, 96, 98, 100, 102, 103, 105, 107, 108, 110, 112, 113, 114, 116,
117, 118, 119, 120, 121, 122, 123, 123, 124, 125, 125, 126, 126, 126, 126, 126,
127, 126, 126, 126, 126, 126, 125, 125, 124, 123, 123, 122, 121, 120, 119, 118,
117, 116, 114, 113, 112, 110, 108, 107, 105, 103, 102, 100, 98, 96, 94, 91,
89, 87, 85, 82, 80, 78, 75, 73, 70, 67, 65, 62, 59, 57, 54, 51,
48, 45, 42, 39, 36, 33, 30, 27, 24, 21, 18, 15, 12, 9, 6, 3,
0 -3, -6, -9, -12, -15, -18, -21, -24, -27, -30, -33, -36, -39, -42, -45,
-48-51 -54, -57, -59, -62, -65,-67, -70, -73, -75, -78, -80,-82, -85, -87,
-89 -91 -94,-96,-98, -100, -102,-103, -105,-107, -108, -110, -112,-113, -114, -116,
-117,-118,-119, -120, -121, -122,-123,-123,-124, -125, -125, -126, -126, -126, -126, -126,
-127 -126 -126, -126, -126, -126, -125, -125,-124,-123,-123, -122, -121, -120,-119,-118,
-117 -116 -114,-113, -112, -110, -108,-107, -105,-103, -102, -100,-98,-96, -94, -91,
-89 -87 -85,-82, -80, -78, -75, -73, -70,-67, -65, -62, -59, -57, -54,-51,
-48 -45, -42, -39, -36, -33, -30, -27, -24, -21, -18, -15, -12, -9, -6, -3
};

char __attributos__ [256] square256 ((aligned(256))) = {}
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,
-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127,-127
};
char __attributos__ [256] triangle256 ((aligned(256))) = {}
-127 -125,-123, -121,-119,-117, -115,-113,-111, -109,-107, -105,-103, -101, -99, -97,
-95 -93 -91, -89, -87, -85,-83, -81, -79,-77, -75, -73, -71, -69,-67, -65,
-63 -61 -59, -57, -55,-53,-51, -49, -47, -45, -43, -41, -39, -37, -35, -33,
-31 -29 -27, -25, -23, -21, -19, -17, -15, -13, -11, -9, -7, -5, -3, -1,
1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31,
33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63,
65, 67, 69, 71, 73, 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95,
97, 99, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127,
129, 127, 125, 123, 121, 119, 117, 115, 113, 111, 109, 107, 105, 103, 101, 99,
97, 95, 93, 91, 89, 87, 85, 83, 81, 79, 77, 75, 73, 71, 69, 67,
65, 63, 61, 59, 57, 55, 53, 51, 49, 47, 45, 43, 41, 39, 37, 35,
33, 31, 29, 27, 25, 23, 21, 19, 17, 15, 13, 11, 9, 7, 5, 3,
1, -1, -3, -5, -7, -9, -11, -13, -15, -17, -19, -21, -23, -25, -27, -29,
-31 -33 -35, -37, -39, -41, -43, -45, -47, -49,-51,-53, -55, -57, -59, -61,
-63 -65,-67, -69, -71, -73, -75,-77, -79, -81,-83, -85, -87, -89, -91, -93,
-95 -97 -99, -101,-103, -105,-107, -109,-111,-113, -115,-117,-119, -121,-123, -125
};
char __attributos__ [256] sawtooth256 ((aligned(256))) = {}
-127,-127, -126, -125,-124,-123, -122, -121, -120,-119,-118,-117, -116, -115, -114,-113,
-112,-111 -110, -109, -108,-107, -106, -105, -104,-103, -102, -101, -100, -99,-98, -97,
-96 -95 -94, -93, -92, -91, -90, -89, -88, -87, -86, -85,-84,-83,-82, -81,
-80 -79 -78,-77, -76, -75, -74, -73, -72, -71, -70, -69, -68,-67, -66, -65,
-64 -63 -62, -61, -60, -59, -58, -57, -56, -55, -54,-53, -52,-51, -50, -49,
-48 -47 -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33,
-32 -31 -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17,
-16 -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127
};

#include "avr/pgmspace.h"

mesa de registro de 128 cortes de filtro
unsigned char logCutoffs[128] = {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x08,0x08,0x08,0x09,0x09,0x0A,0x0A,0x0A,0x0A,0x0B ,0x0C,0x0C,0x0C,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1E,0x20,0x21,0x22,0x23,0x24,0x26,0x28,0x2A,0x2C,0x2E,0x30,0x32,0x34,0x36,0x38,0x3A,0x40,0x42,0x44,0x48,0x4C,0x4F,0x52,0x55,0x58,0x5D,0x61,0x65,0x68,0x6C,0x70,0x76,0x7E,0x85,0x8A,0x90,0x96,0x9D,0xA4 0xAB, 0xB0, 0xBA, 0xC4, 0xCE, 0xD8, 0xE0, 0xE8, 0xF4, 0xFF};

volátil unsigned int WAIT_curTime;
#define WAIT_UNTIL_INTERRUPT() WAIT_curTime = loopSteps;    {while(WAIT_curTime==loopSteps)}

#define SERIAL_OUT 0

ataque, decaimiento están en 1/64ths por 125 de un segundo, es decir. 1 = 0 - > 1 en medio segundo
const int decaimiento = 3;
const int ataque = 4;

volátiles de char * curWave = square256;

#define cbi (sfr, bits) (_SFR_BYTE(sfr) & = ~_BV(bit))
#define OSE (sfr, bits) (_SFR_BYTE(sfr) | = _BV(bit))

Esta es supuestamente la frecuencia de reloj de audio - como
se puede ver, freq medido puede variar un poco de la frecuencia de reloj supuesta
No estoy seguro por qué
const doble refclk = 31372.549;  = 16MHz / 510
const doble refclk = 31376.6;      mide

variables utilizadas dentro de interrupción servicio declarado como voilatile
estas variables permiten mantener pista de tiempo - como retardo / millis etc. son
hecho inactivo por interrupciones ser minusválidas.
volatile unsigned char loopSteps = 0; una vez por muestra
volatile unsigned int loopStepsHigh = 0; una vez por 256 muestras

información sobre el estado actual de un oscilador simple
struct oscillatorPhase
{
unsigned int phaseStep;
volumen de Char;
unsigned int phaseAccu;
};

los osciladores (8)
struct oscillatorPhase osciladores [8];

tword_m = pow (2,32) * dfreq/refclk;  calcular nuevo tuning palabra DDS
a hz -> afinación palabra: (pow(2,16) * frecuencia) / 31376.6
const unsigned int NOTE_FREQS [25] = {273,289,307,325,344,365,386,409,434,460,487,516,546,579,613,650,688,729,773,819,867,919,974,1032,1093};

umbrales para los botones de sensores capacitivos
int calibrationThresholds [8] = {0,0,0,0,0,0,0,0};

Inline int getNoteKeys (calibrar boolean = false)
{

char PORTD_PINS = 0b11000000; (pernos 6-7 - Evite pernos 0,1 como se utilizan para comunicaciones de puerto serie)
char PORTC_PINS = 0b111111; (clavijas analógicas 0-5)

const int MAX_LOOPS = 16;
char port_values [MAX_LOOPS * 2];

WAIT_UNTIL_INTERRUPT();
(volátiles) ASM
bucle de lectura de puerto D:
DDRD & = ~(PORTD_PINS = 0x3f);          fijar pasadores 8-12 a modo de entrada
"en % [temp], 0x0a" "\n\t"
'andi % [temp], 0x3f' "\n\t"
"out 0x0a, % [temp]" "\n\t"
PORTD | = (PORTD_PINS);          prendió alfileres pullup de 8-12
"en % [temp], 0x0b" "\n\t"
"ori % [temp], 0xC0" "\n\t"
"out 0x0b, % [temp]" "\n\t"
"en %0, 0 x 09" "\n\t"
"en %1, 0 x 09" "\n\t"
"en %2, 0 x 09" "\n\t"
"en %3, 0 x 09" "\n\t"
"en %4, 0 x 09" "\n\t"
"en 5 %, 0 x 09" "\n\t"
"en %6, 0 x 09" "\n\t"
"en %7, 0 x 09" "\n\t"
"en %8, 0 x 09" "\n\t"
"en %9, 0 x 09" "\n\t"
"en un % 10, 0 x 09" "\n\t"
"en % 11, 0 x 09" "\n\t"
"en % 12, 0 x 09" "\n\t"
"en % 13, 0 x 09" "\n\t"
"en % 14, 0 x 09" "\n\t"
"en el % 15, 0 x 09" "\n\t"
:
salidas
«= r» (port_values[0]),
«= r» (port_values[2]),
«= r» (port_values[4]),
«= r» (port_values[6]),
«= r» (port_values[8]),
«= r» (port_values[10]),
«= r» (port_values[12]),
«= r» (port_values[14]),
«= r» (port_values[16]),
«= r» (port_values[18]),
«= r» (port_values[20]),
«= r» (port_values[22]),
«= r» (port_values[24]),
«= r» (port_values[26]),
«= r» (port_values[28]),
«= r» (port_values[30])
: [temp] "d" (0));

WAIT_UNTIL_INTERRUPT();
(volátiles) ASM
bucle de lectura de Puerto C:
DDR y = ~(PORTC_PINS = 0xc0);          Set de pasadores de 5-7 a modo de entrada
"en % [temp], 0x07" "\n\t"
"andi % [temp], 0xc0" "\n\t"
"hacia fuera 0x07, % [temp]" "\n\t"
PORTC | = (PORTC_PINS);          prendió alfileres pullup de 5-7
"en % [temp], 0x08" "\n\t"
'ori % [temp], 0x3F' "\n\t"
"hacia fuera 0x08, % [temp]" "\n\t"
"en %0, 0 x 06" "\n\t"
"en %1, 0 x 06" "\n\t"
"en %2, 0 x 06" "\n\t"
"en %3, 0 x 06" "\n\t"
"en %4, 0 x 06" "\n\t"
"en 5 %, 0 x 06" "\n\t"
"en %6, 0 x 06" "\n\t"
"en %7, 0 x 06" "\n\t"
"en %8, 0 x 06" "\n\t"
"en %9, 0 x 06" "\n\t"
"en un % 10, 0 x 06" "\n\t"
"en % 11, 0 x 06" "\n\t"
"en % 12, 0 x 06" "\n\t"
"en % 13, 0 x 06" "\n\t"
"en % 14, 0 x 06" "\n\t"
"en el % 15, 0 x 06" "\n\t"
:
salidas
«= r» (port_values[1]),
«= r» (port_values[3]),
«= r» (port_values[5]),
«= r» (port_values[7]),
«= r» (port_values[9]),
«= r» (port_values[11]),
«= r» (port_values[13]),
«= r» (port_values[15]),
«= r» (port_values[17]),
«= r» (port_values[19]),
«= r» (port_values[21]),
«= r» (port_values[23]),
«= r» (port_values[25]),
«= r» (port_values[27]),
«= r» (port_values[29]),
«= r» (port_values[31])
: [temp] "d" (0));

PORTC & = ~ (PORTC_PINS); pullup de pernos 8-12
PORTD & = ~ (PORTD_PINS); pullup de pernos 5-7
DDRC | = (PORTC_PINS); descarga
DDRD | = (PORTD_PINS); descarga

if(Calibrate)
{
para (int c = 0; c < 8; c ++)
{
para (int d = 0; d < MAX_LOOPS; d ++)
{
int liveNotes=((int*)port_values) [d];
liveNotes & = 0x3fc0;
liveNotes >> = 6;
Si (liveNotes & (1 << c))
{
Si (calibrationThresholds [c] < = d)
{
calibrationThresholds [c] = d + 1;
}
rotura;
}
}
}
}
int liveNotes = 0;
para (int c = 0; c < 8; c ++)
{
int val = ((int*) port_values) [calibrationThresholds [c] + 1];
Val & = 0x3fc0;
Val >> = 6;
Si ((val & (1 << c)) == 0)
{
liveNotes| = (1 << c);
}
}
volver liveNotes;
}

Haz táctil capacitiva en la entrada 4 y la salida 3
utilizado para modulador de filtro
Inline int getfiltermodulationtime()
{
Static int running_average = 0;
Static int running_min = 1024;
Static int running_min_inc_count = 0;
Static boolean initialise_running_min = true;

unsigned int delayTime = 0;
char PINNUM_OUT = 3;
char PINNUM_IN = 4;
char PIN_OUT = 1 << PINNUM_OUT;
char PIN_IN = 1 << PINNUM_IN;
hacer seguro de entradas / salidas se encuentra
DDRD| = PIN_OUT;
DDRD & = ~ (PIN_IN);
WAIT_UNTIL_INTERRUPT();
PORTD| = PIN_OUT;
(volátiles) ASM
"loopstart % =:" "\n\t"
"sbic 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [delayTime], 0 x 01" "\n\t"
"IPC ese [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [delayTime] "+ & w" (delayTime)
: [PINNUM_IN] "I" (PINNUM_IN));
configurar pin - tal vez no te molestes en tiempo, si no parece añadir
¿mucha exactitud?
WAIT_UNTIL_INTERRUPT();
PORTD & = ~ PIN_OUT;
ASM (
"loopstart % =:" "\n\t"
"sbis 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [delayTime], 0 x 01" "\n\t"
"IPC ese [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [delayTime] "+ & w" (delayTime)
: [PINNUM_IN] "I" (PINNUM_IN));
running_average = (running_average-(running_average >> 4)) + (delayTime >> 4);
running_min_inc_count ++;
if(running_min_inc_count==255)
{
if(initialise_running_min)
{
running_min = running_average;
running_min_inc_count = 0;
initialise_running_min = false;
} else {}
running_min_inc_count = 0;
running_min ++;
}
}
if(running_average<running_min)
{
running_min = running_average;
}
int touchVal = running_average-running_min;
if(touchVal>15)
{
touchVal-= 15;
if(touchVal>99)
{
touchVal = 99;
}
} else {}
touchVal = 0;
}
volver touchVal;
}

Haz táctil capacitiva de 5 entrada y de salida 3
utilizado para la curva de la echada
Inline int getpitchbendtime()
{
Static int running_average = 0;
Static int running_min = 1024;
Static int running_min_inc_count = 0;
Static boolean initialise_running_min = true;

unsigned int delayTime = 0;
char PINNUM_OUT = 3;
char PINNUM_IN = 5;
char PIN_OUT = 1 << PINNUM_OUT;
char PIN_IN = 1 << PINNUM_IN;
hacer seguro de entradas / salidas se encuentra
DDRD| = PIN_OUT;
DDRD & = ~ (PIN_IN);
WAIT_UNTIL_INTERRUPT();
PORTD| = PIN_OUT;
(volátiles) ASM
"loopstart % =:" "\n\t"
"sbic 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [delayTime], 0 x 01" "\n\t"
"IPC ese [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [delayTime] "+ & w" (delayTime)
: [PINNUM_IN] "I" (PINNUM_IN));
configurar pin - tal vez no te molestes en tiempo, si no parece añadir
¿mucha exactitud?
WAIT_UNTIL_INTERRUPT();
PORTD & = ~ PIN_OUT;
ASM (
"loopstart % =:" "\n\t"
"sbis 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [delayTime], 0 x 01" "\n\t"
"IPC ese [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [delayTime] "+ & w" (delayTime)
: [PINNUM_IN] "I" (PINNUM_IN));
running_average = (running_average-(running_average >> 4)) + (delayTime >> 4);
running_min_inc_count ++;
if(running_min_inc_count==255)
{
if(initialise_running_min)
{
running_min = running_average;
running_min_inc_count = 0;
initialise_running_min = false;
} else {}
running_min_inc_count = 0;
running_min ++;
}
}
if(running_average<running_min)
{
running_min = running_average;
}
int touchVal = running_average-running_min;
if(touchVal>15)
{
touchVal-= 15;
if(touchVal>99)
{
touchVal = 99;
}
} else {}
touchVal = 0;
}
volver touchVal;
}

unsigned int pitchBendTable [201] = {241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 243, 243, 243, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 245, 245, 245, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 247, 247, 247, 248, 248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 249 , 249, 249, 250, 250, 250, 250, 250, 250, 250, 251, 251, 251, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 254, 254, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 256,
256.256, 256, 256, 256, 256, 256, 256, 257, 257, 257, 257, 257, 257, 257, 258, 258, 258, 258, 258, 258, 259, 259, 259, 259, 259, 259, 259, 260, 260, 260, 260, 260, 260, 260, 261, 261, 261, 261, 261, 261, 262, 262, 262, 262, 262, 262, 262, 263, 263, 263, 263, 263, 263, 264, 264, 264, 264, 264, 264, 264, 265 265, 265, 265, 265, 265, 266, 266, 266, 266, 266, 266, 266, 267, 267, 267, 267, 267, 267, 268, 268, 268, 268, 268, 268, 269, 269, 269, 269, 269, 269, 269, 270, 270, 270, 270, 270, 270, 271, 271};

void setupNoteFrequencies (int baseNote, int pitchBendVal / * -100 -> 100 * /)
{
.phaseStep osciladores [0] = NOTE_FREQS [baseNote];
.phaseStep osciladores [1] = NOTE_FREQS [baseNote + 2];
.phaseStep osciladores [2] = NOTE_FREQS [baseNote + 4];
.phaseStep osciladores [3] = NOTE_FREQS [baseNote + 5];
.phaseStep osciladores [4] = NOTE_FREQS [baseNote + 7];
.phaseStep osciladores [5] = NOTE_FREQS [baseNote + 9];
osciladores [6] .phaseStep = NOTE_FREQS [baseNote + 11];
osciladores [7] .phaseStep = NOTE_FREQS [baseNote + 12];

Si (pitchBendVal < -99)
{
pitchBendVal =-99;
} else if(pitchBendVal>99)
{
pitchBendVal = 99;
}
Serial.Print("*");
Serial.Print(pitchBendVal);
unsigned int pitchBendMultiplier = pitchBendTable [pitchBendVal + 100];
Serial.Print(":");
Serial.Print(pitchBendMultiplier);
para (int c = 0; c < 8; c ++)
{
multiplicar a 2 números de 16 bits juntos y cambiar 8 sin pérdida de precisión
requiere realmente ensamblador
volatile unsigned char zeroReg = 0;
volatile unsigned int multipliedCounter = .phaseStep de osciladores [c];
volátiles de ASM
(
bytes altos mult junto = byte alto
"ldi % [outVal] a 0" "\n\t"
"mul ese [phaseStep] %B [pitchBend]" "\n\t"
"mov ese [outVal], r0" "\n\t"
caso de desbordamiento en r1 (nunca debe desbordar)
byte bajo * byte alto -> dos bytes
"mul % [phaseStep], a %B [pitchBend]" "\n\t"
"añadir %a [outVal], r0" "\n\t"
llevar en byte alto
"adc ese [outVal], r1" "\n\t"
byte bajo alto byte * -> dos bytes
"mul ese [phaseStep], %A [pitchBend]" "\n\t"
"añadir %a [outVal], r0" "\n\t"
llevar en byte alto
"adc ese [outVal], r1" "\n\t"
byte bajo * byte bajo -> Ronda
"mul %a [phaseStep], %A [pitchBend]" "\n\t"
el adc a continuación es redondear basado en poco alta de baja * bajo:
"adc %a [outVal], r1" "\n\t"
"adc ese [outVal], % [cero]" "\n\t"
"clr r1" "\n\t"
: [outVal] "= & d" (multipliedCounter)
: [phaseStep] "d" (osciladores [c] .phaseStep), [pitchBend] "d" (pitchBendMultiplier), [ZERO] "d" (zeroReg)
: "r1", "r0"
);
osciladores [c] .phaseStep = multipliedCounter;
}
Serial.Print(":");
Serial.Print(NOTE_FREQS[baseNote]);
Serial.Print(":");
Serial.println(Oscillators[0].phaseStep);

}

void setup()
{
Serial.Begin(9600);        conectar al puerto serie
#ifndef FILTER_LPF_NONE
setFilter (127, 0);
#endif

pinMode (11, salida);     pin11 = salida PWM frecuencia de salida

setupNoteFrequencies(12,0);

para (int c = 0; c < 8; c ++)
{
.volume osciladores [c] = 0;
}

Setup_timer2();

deshabilitar las interrupciones para evitar la distorsión del tiempo
CBI (TIMSK0, TOIE0);              desactivar Timer0!!!!!! Delay() ya no está disponible
OSE (TIMSK2, TOIE2);              habilitar interrupción del Timer2

calibrar los valores de clave sin prensar

para (int x = 0; x < 1024; x ++)
{
getNoteKeys(true);
pasos de int = loopSteps;
WAIT_UNTIL_INTERRUPT();
int afterSteps = loopSteps;
Serial.println(afterSteps-Steps);
}
patrón de prueba intro
#ifdef TEST_PATTERN_INTRO
int filtValue = 255;
byte notes[]={0x1,0x4,0x10,0x80,0x80,0x80,0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80,0x40,0x20,0x10,0x8,0x4,0x2,0x1,0x1,0x1,0x00,0x00,0x1,0x1,0x1,0x1,0x00,0x00,0x5,0x5,0x5,0x5,0x00,0x00,0x15,0x15,0x15,0x15,0x15,0x00,0x00,0x95,0x95,0x95,0x95,0x95,0x95,0x00};
para (Nota int = 0; cuenta < sizeof(notes)/sizeof(byte);note++)
{

int noteCount = 0;
para (int c = 0; c < 8; c ++)
{
Si (notas [Nota] & (1 << c))
{
noteCount += 1;
}
}
para (int c = 0; c < 8; c ++)
{
Si (notas [Nota] & (1 << c))
{
.volume osciladores [c] = 63/noteCount;
} else
{
.volume osciladores [c] = 0;
}
}
para (int c = 0; c < 50; c ++)
{
así podría seguir calibrando aquí
Nota: cada lazo de calibración = interrupción de al menos 1

getNoteKeys(true);
#ifndef FILTER_LPF_NONE
setFilter (127-c, 64);
#endif

}
}
#else
solo pitido para mostrar la calibración se realiza
osciladores [0] .volume = 63;
para (int c = 0; c < 20; c ++)
{
WAIT_UNTIL_INTERRUPT();
}
osciladores [0] .volume = 63;

#endif
Serial.println("calibrations:");
para (int c = 0; c < 8; c ++)
{
Serial.Print(c);
Serial.Print(":");
Serial.println(calibrationThresholds[c]);
}

}

void loop()
{
mantenemos una lista de volúmenes 'crudos' - y baje el volumen si un acorde es tomando > 64 volumen total
para permitir acordes sin reducir el volumen de notas individuales
int rawVolumes [8] = {0,0,0,0,0,0,0,0};
int curNote = 0;
unsigned int filterSweep = 64;
const int MIN_SWEEP = 64;
const int MAX_SWEEP = 127;
const int SWEEP_SPEED = 3;
int sweepDir = SWEEP_SPEED;
unsigned int lastStep = loopStepsHigh;
unsigned curStep = loopStepsHigh;
while(1)
{
lastStep = curStep;
curStep = loopStepsHigh;
Nota: temporizadores funcionan en este código (desactiva interrupciones / cambiaron de velocidades), por lo que ni siquiera pensar en llamar: delay(), millis / micros etc..
cada loopstep es aproximadamente 31250 / segundo
este bucle principal será llamada una vez cada 3 o 4 muestras si la salida serial está apagada, quizás más despacio de lo contrario

int liveNotes=getNoteKeys();
Estamos justo después de una interrupción (como loopStep solo se ha incrementado)
así que debemos tener suficiente tiempo para hacer los controles claves capacitativa

if(lastStep!=curStep)
{
int totalVolume = 0;
para (int c = 0; c < 8; c ++)
{
Si ((liveNotes & (1 << c)) == 0)
{
rawVolumes [c]-= DECAY*(curStep-lastStep);
Si (rawVolumes [c] < 0) rawVolumes [c] = 0;
if(SERIAL_OUT)serial.Print(".");
}
otra cosa
{
rawVolumes [c] += ATTACK*(curStep-lastStep);
Si (rawVolumes [c] > 63) rawVolumes [c] = 63;
if(SERIAL_OUT)serial.Print(c);
}
totalVolume += rawVolumes [c];
}
WAIT_UNTIL_INTERRUPT();
Si (totalVolume < 64)
{
para (int c = 0; c < 8; c ++)
{
.volume osciladores [c] = rawVolumes [c];
}
} else
{
volumen total achicar demasiado, para evitar el recorte
para (int c = 0; c < 8; c ++)
{
osciladores [c] .volume =(rawVolumes[c]*63)/totalVolume;
}
}
}
if(SERIAL_OUT)serial.println("");
#ifndef FILTER_LPF_NONE
/ * if(liveNotes==0)
{
filterSweep = 64;
sweepDir = SWEEP_SPEED;
}
filterSweep += sweepDir;
Si (filterSweep > = MAX_SWEEP)
{
filterSweep = MAX_SWEEP;
sweepDir =-sweepDir;
}
else if (filterSweep < = MIN_SWEEP)
{
sweepDir =-sweepDir;
filterSweep = MIN_SWEEP;
}*/
Serial.println((int)filterValue);
filterSweep=127-(getpitchbendtime() >> 1);
WAIT_UNTIL_INTERRUPT();
setFilter(150-(getfiltermodulationtime()),220);
#endif
WAIT_UNTIL_INTERRUPT();
setupNoteFrequencies(12,-getpitchbendtime());

Estamos justo después de una interrupción otra vez (como loopStep solo se ha incrementado)
por lo que debemos tener suficiente tiempo para comprobar la capacidad de curva de la echada sin pasar sobre otra muestra, sincronización es muy importante aquí
necesidad de equilibrar con una resistencia lo suficientemente grande como para obtener la distancia de detección decente con tarda demasiado en la muestra
Compruebe la entrada de la curva de pitch

}
}
//******************************************************************
configuración del TIMER2
establezca prscaler en 1, modo de PWM a la fase correcta PWM, 16000000/510 = 31372.55 Hz reloj
void Setup_timer2() {}

TIMER2 Clock Prescaler para: 1
OSE (TCCR2B, CS20);
CBI (TCCR2B, CS21);
CBI (TCCR2B, CS22);

TIMER2 PWM modo PWM correcta fase
CBI (TCCR2A, COM2A0);  claro comparar partido
OSE (TCCR2A, COM2A1);

OSE (TCCR2A, WGM20);  Modo 1 trifásico PWM correcta
CBI (TCCR2A, WGM21);
CBI (TCCR2B, WGM22);
}

#ifdef FILTER_LPF_BIQUAD
char filtValueA1 = 0, filtValueA2 = 0, filtValueA3 = 0, filtValueB1 = 0, filtValueB2 = 0;
volatile unsigned char filtCoeffA1 = 255;
filtCoeffB1 char volátiles = 127;
volatile unsigned char filtCoeffB2 = 255;
#endif
#ifdef FILTER_LPF_HACK
filtro de paso bajo hackeado - 2 poste resonante-
un += f*((in-a) + q*(a-b)
b += f * (a-b)
int filterA = 0;
int filterB = 0;
unsigned char filterQ = 0;
unsigned char filterF = 255;

Inline void setFilterRaw (unsigned char filterF, resonancia de char sin signo)
{
unsigned char tempReg = 0, tempReg2 = 0;
volátiles de ASM ("ldi % [tempReg], 0xff" "\n\t"
"\n\t sub-[tempReg], % [filtF]" "
"lsr % [tempReg]" "\n\t"
"ldi % [tempReg2], 0 x 04" "\n\t"
"add [tempReg], % [tempReg2]" "\n\t"
"\n\t sub-[conversor], % [tempReg]" "
"brcc Res_Overflow % =" "\n\t"
"ldi % [conversor], 0 x 00" "\n\t"
"Res_Overflow % =:" "\n\t"
"mov % [filtQ], [conversor]" "\n\t"
: [tempReg] "= & d" (tempReg), [tempReg2] "= & d" (tempReg2), [filtQ] "= & d" (filterQ): [conversor] "d" (resonancia), [filtF] "d" (filterF));
}

Inline void setFilter (f unsigned char, unsigned char resonancia)
{
if(f>127) f = 127;
filterF = logCutoffs [f];
setFilterRaw(filterF,resonance);
}
#endif

#define HIBYTE(__x) ((char) (((unsigned int) __x) >> 8))
#define LOBYTE(__x) ((char) (((unsigned int) __x) & 0xff))

bucle principal de oscilador (incrementa puntero de tabla de ondas y añadir a los registros de salida)
instrucciones de 13 - debe tomar 14 ciclos del procesador según la hoja de datos
en teoría creo que esto significa que cada oscilador debe tomar 1.5% de la cpu
(más una sobrecarga constante para interrupción llama etc.).
Nota: esto se solía hacer la stepvolume carga cerca del comienzo, pero ahora están intercalados en la
código, esto es porque ldd (carga con offset) toma 2 instrucciones,
frente a ld, + 1 (carga con incremento de correos) y st, + 1 que son 1 instrucción - podemos hacer esto porque:
//
a) el paso (que no necesita ser almacenado detrás) está en la memoria antes de la
acumulador de fase (que tiene que ser almacenado una vez que se agrega el paso
//
b) la fase assumulator se almacena en el byte bajo, orden de byte alto, significando que
puede sumar los primeros bytes, a continuación, guarde ese byte incrementar el puntero,
luego carga el byte alto, sumar los bytes alto y almacenar incrementando el puntero
//
Creo que es el mínimo número de operaciones posibles codificar este oscilador, ya que
1) allí son 6 las operaciones de carga (para cargar stepHigh baja, phaseH/L, volumen y el valor de la onda)
2) existen 2 Añadir las operaciones necesarias para agregar al acumulador de fase
3) existen 2 operaciones de almacén necesarias para guardar el acumulador de la fase
4) existe 1 multiplicar (2 ciclos de instrucción) necesaria para hacer el volumen
5) existen 2 Añadir las operaciones necesarias para agregar a la salida final
//
6 + 2 + 2 + 2 + 2 = 14 ciclos de instrucción

#define OSCILLATOR_ASM \
/ * cargar fase paso y volumen * / \
«ld %a [tempStep], % [stepVolume] + ""\n\t"\
«ld ese [tempStep], % [stepVolume] + ""\n\t"\
«ld % [tempVolume], [stepVolume] + ""\n\t"\
/ * carga fase acumulador - byte alto va recto * / \
/ * en la matriz de búsqueda de onda (la onda es el límite de 256 bytes * / \
/ * así que podemos hacer esto sin cualquier agrega * / \
/ * Hacer la fase añade entre las dos cargas, carga con desplazamiento es más lento que
a una carga normal
*/\
«ld %a [tempPhaseLow], % [stepVolume]» "\n\t» \
/ * Añadir fase paso bajo * / \
"% [tempPhaseLow], [tempStep] del %A agregar" "\n\t"\
/ * almacenar fase acumulador bajo * / \
"st %a [stepVolume] +, % [tempPhaseLow]" "\n\t" \
/ * cargar fase acumulador alta * / \
«ld %a [waveBase], % [stepVolume]» "\n\t» \
/ * Añadir fase paso alto - con transporte desde la añada anterior * / \
"adc % [waveBase], a %B [tempStep]" "\n\t"\
/ * almacenar paso fase alta * / \
"st % [stepVolume] a +, A % [waveBase]" "\n\t" \
/ * ahora la búsqueda de la ola - byte alto = onda puntero, byte bajo = offset * / \
«ld % [tempPhaseLow], [waveBase]» "\n\t" \
/ * Ahora multiplique por volumen * / \
"mul % [tempPhaseLow], [tempVolume]" "\n\t" \
/ * r0 contiene ahora una muestra - agregar para salida de valor / \
"añadir %a [outValue], r0" "\n\t" \
"adc ese [outValue], r1" "\n\t" \
/ * ir a siguiente oscilador - señala en el siguiente stepVolume / \
/ * oscilador ya * / \

//******************************************************************
Servicio de interrupción del TIMER2 en 31.372.550 KHz = 32uSec
Esta es la base de tiempo REFCLOCK para el generador DDS
FOUT = (M (REFCLK)) / (2 exp 32)
¿tiempo de ejecución:?
{ISR(TIMER2_OVF_vect)}

ahora establecer el siguiente valor
este bucle tiene aproximadamente 172 ciclos (214 incluyendo los push/pop) - tenemos 510, así aproximadamente el 50% de los repuestos va de procesador para tareas de audio no
el filtro de paso bajo también lleva algunos ciclos

int outValue;

punteros:
X = acumulador de fase del oscilador
Y = paso del oscilador y el volumen
Z = onda pos - necesita agregar a la base
int tempStep = 0;
char tempPhaseLow = 0, tempVolume = 0;
int tempWaveBase = 0;
(volátiles) ASM
"ldi %a [outValue],"\n\t"0"
"ldi ese [outValue],"\n\t"0"
oscilador de 0
comentario el código siguiente para comprobar
que los registros no están recibiendo doble asignado
/ * "lds %a [outValue], 0 x 00" "\n\t"
"lds ese [outValue], 0 x 01" "\n\t"
"lds %a [tempPhaseLow], 0 x 02" "\n\t"
"lds ese [tempPhase], 0 x 03" "\n\t"
"lds %a [tempStep], 0 x 04" "\n\t"
"lds ese [tempStep], 0 x 05" "\n\t"
"lds % [tempVolume], 0 x 06" "\n\t"
"lds % [cero], 0x07" "\n\t"
"lds %a [tempWaveBase], 0x08" "\n\t"
"lds ese [tempWaveBase], 0 x 09" "\n\t"
"lds %a [phaseAccu], 0x0a" "\n\t"
"lds ese [phaseAccu], 0x0b" "\n\t"
"lds %a [stepVolume], 0x0c" "\n\t"
"lds ese [stepVolume], 0x0d" "\n\t"
"lds %a [waveBase], 0x0e" "\n\t"
"lds ese [waveBase], 0x0f" "\n\t"*/
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
:
salidas
[tempPhaseLow] "= & d" (tempPhaseLow),
[tempStep] "= & d" (tempStep),
[tempVolume] "= & d" (tempVolume),
[outValue] "= & d" (outValue)
:
entradas
[stepVolume] "" (y oscillators[0].phaseStep),
[waveBase] "z" (256 * (((unsigned int) curWave) >> 8))
:
otros registros que clobber (haciendo multiplicaciones)
"r1"
);

en este punto outValue = valor de oscilador
Actualmente es sobrepasado a todo volumen / 4
para permitir un espacio para el filtrado


#ifdef FILTER_LPF_HACK

paso un bajo filtro basado en el de MeeBlip (http://meeblip.noisepages.com)
un += f*((in-a) + q*(a-b)
b += f * (a-b)
outValue >> = 3;
Iniciado en 4700
4686
int tempReg, tempReg2 = 0;
unsigned char zeroRegFilt = 0;
de volatilisati
unsigned char filtF = filterF;
unsigned char filtQ = filterQ;
(volátiles) ASM
"\n\t sub-%a [outVal], %A [filtA]" "
"sbc ese [outVal] %B [filtA]" "\n\t"
«brvc No_overflow1% = ""\n\t"
"ldi %a [outVal], 0b00000001" "\n\t"
"ldi ese [outVal], 0b10000000" "\n\t"
"No_overflow1% =:" "\n\t"
outVal = (en - filtA)
"mov %a [tempReg], %A [filtA]" "\n\t"
"mov ese [tempReg] %B [filtA]" "\n\t"
"\n\t sub-%a [tempReg], %A [filtB]" "
"sbc ese [tempReg] %B [filtB]" "\n\t"
«brvc No_overflow3% = ""\n\t"
"ldi %a [tempReg], 0b00000001" "\n\t"
"ldi ese [tempReg], 0b10000000" "\n\t"
"No_overflow3% =:" "\n\t"
tempReg = (a-b)
"mulsu ese [tempReg], % [filtQ]" "\n\t"
"movw %a [tempReg2], r0" "\n\t"
tempReg2 = (HIBYTE(a-b)) * Q
"mul %a [tempReg], % [filtQ]" "\n\t"
"añadir %a [tempReg2], r1" "\n\t"
"adc ese [tempReg2], % [cero]" "\n\t"
"rol r0" "\n\t"
"brcc No_Round1% =" "\n\t"
"%a inc [tempReg2]" "\n\t"
"No_Round1% =:" "\n\t"
en este punto tempReg2 = (a-b) * Q (cambiado de puesto apropiadamente y redondeado)
"CVX" "\n\t"
«lsl %a [tempReg2]» "\n\t»
"rol ese [tempReg2]" "\n\t"
"CVX" "\n\t"
«lsl %a [tempReg2]» "\n\t»
"rol ese [tempReg2]" "\n\t"
tempReg2 = (a-b) * Q * 4
"\n\t"añadir %a [outVal], %A [tempReg2]""
"adc ese [outVal] %B [tempReg2]" "\n\t"
«brvc No_overflow4% = ""\n\t"
"ldi % [outVal], a 0b11111111" "\n\t"
"ldi ese [outVal], 0b01111111" "\n\t"
"No_overflow4% =:" "\n\t"
outVal = ((in-a) + (a-b) * (Q >> 8) * 4) - recortado etc.
"mulsu ese [outVal], % [filtF]" "\n\t"
"movw %a [tempReg], r0" "\n\t"
"mul %a [outVal], % [filtF]" "\n\t"
"añadir %a [tempReg], r1" "\n\t"
"adc ese [tempReg], % [cero]" "\n\t"
"rol r0" "\n\t"
"brcc No_Round2% =" "\n\t"
"%a inc [tempReg]" "\n\t"
tempReg = f * ((in-a) + (a-b) * (Q >> 8) * 4)
"No_Round2% =:" "\n\t"
"\n\t"añadir %a [filtA], %A [tempReg]""
"adc ese [filtA] %B [tempReg]" "\n\t"
A = A + f * ((in-a) + (a-b) * (Q >> 8) * 4)
«brvc No_overflow5% = ""\n\t"
"ldi % [outVal], a 0b11111111" "\n\t"
"ldi ese [outVal], 0b01111111" "\n\t"
"No_overflow5% =:" "\n\t"
calcular B = f * (a - b)

"mov %a [tempReg], %A [filtA]" "\n\t"
"mov ese [tempReg] %B [filtA]" "\n\t"
"\n\t sub-%a [tempReg], %A [filtB]" "
"sbc ese [tempReg] %B [filtB]" "\n\t"
«brvc No_overflow6% = ""\n\t"
"ldi %a [tempReg], 0b00000001" "\n\t"
"ldi ese [tempReg], 0b10000000" "\n\t"
"No_overflow6% =:" "\n\t"
tempReg = (a-b)
"mulsu ese [tempReg], % [filtF]" "\n\t"
"movw %a [tempReg2], r0" "\n\t"
"mul %a [tempReg], % [filtF]" "\n\t"
"añadir %a [tempReg2], r1" "\n\t"
"adc ese [tempReg2], % [cero]" "\n\t"
tempReg2 = f*(a-b)
"\n\t"añadir %a [filtB], %A [tempReg2]""
"adc ese [filtB] %B [tempReg2]" "\n\t"
«brvc No_overflow7% = ""\n\t"
"ldi % [filtB], a 0b11111111" "\n\t"
"ldi ese [filtB], 0b01111111" "\n\t"
"No_overflow7% =:" "\n\t"
ahora b = b+f*(a-b)
"mov %a [outVal], %A [filtB]" "\n\t"
"mov ese [outVal] %B [filtB]" "\n\t"

multiplicar outval por 4 y clip
"\n\t"añadir %a [outVal], %A [filtB]""
"adc ese [outVal] %B [filtB]" "\n\t"
"brbs 3, % de Overflow_End =" "\n\t"

"\n\t"añadir %a [outVal], %A [filtB]""
"adc ese [outVal] %B [filtB]" "\n\t"
"brbs 3, % de Overflow_End =" "\n\t"

"\n\t"añadir %a [outVal], %A [filtB]""
"adc ese [outVal] %B [filtB]" "\n\t"
"brbs 3, % de Overflow_End =" "\n\t"
"rjmp No_overflow % =" "\n\t"
"Overflow_End % =:" "\n\t"
"brbs 2, % de Overflow_High =" "\n\t"
"ldi %a [outVal], 0b00000001" "\n\t"
"ldi ese [outVal], 0b10000000" "\n\t"
"rjmp No_overflow % =" "\n\t"
"Overflow_High % =:" "\n\t"
"ldi % [outVal], a 0b11111111" "\n\t"
"ldi ese [outVal], 0b01111111" "\n\t"
"No_overflow % =:" "\n\t"
char valOut = ((unsigned int)(outValue)) >> 8;
valOut += 128;
OCR2A = (byte) valOut;
"subi ese [outVal], 0 x 80" "\n\t"
«sts 0x00b3, %B [outVal]» "\n\t»
descomentar las líneas a continuación para ver las asignaciones de registro
/*
"lds %a [filtA], 0 x 01" "\n\t"
"lds ese [filtA], 0 x 02" "\n\t"
"lds %a [filtB], 0 x 03" "\n\t"
"lds ese [filtB], 0 x 04" "\n\t"
"lds % [filtQ], 0 x 05" "\n\t"
"lds % [filtF], 0 x 06" "\n\t"
"lds %a [outVal], 0x07" "\n\t"
"lds ese [outVal], 0x08" "\n\t"
"lds %a [tempReg], 0 x 09" "\n\t"
"lds ese [tempReg], 0x0a" "\n\t"
"lds %a [tempReg2], 0x0b" "\n\t"
"lds ese [tempReg2], 0x0c" "\n\t"
'% de lds [cero], 0x0d' "\n\t"*/
:
salidas / leer/escribir argumentos
[filtA] "+ & w" (filterA),
[filtB] "+ & w" (filterB),
[tempReg] "= & a" (tempReg),
[tempReg2] "= & d" (tempReg2)
:
[filtQ] "a" (filtQ),
[filtF] "a" (filtF),
[outVal] "a" (outValue),
[CERO] "d" (zeroRegFilt)
entradas
: "r1");

#endif

salida se hace en el código de ensamblador de filtro si los filtros son en
de lo contrario nos emitirlo a mano aquí
#ifdef FILTER_LPF_NONE
aumento completo
outValue * = 4;
en este punto, outValue es una versión firmada de la 16 bits de lo que queremos es decir. 0 -> 32767, luego-32768 -> -1 (0xffff)
queremos 0 -> 32767 para ir a 32768-65535 y-32768 -> -1 para ir a 0-32767, luego queremos sólo el byte superior
tomar el byte superior, añadir 128, luego en unsigned. (Unsigned int) en el a continuación es para evitar tener que cambiar (ie.just toma superior bytes)
char valOut = ((unsigned int)(outValue)) >> 8;
valOut += 128;
OCR2A = (byte) valOut;
#endif
incrementar contador de pasos del bucle (y contador de alta)
se utilizan porque detenga el temporizador
interrupción de corriente, así no tiene más remedio que contar el tiempo
Esta asm probablemente no es realmente necesario, pero se guarda unos 10 instrucciones
porque las variables tienen que ser volátil
ASM (
«inc % [loopSteps]» "\n\t»
"brbc 1, % de loopend =" "\n\t"
"%a inc [loopStepsHigh]" "\n\t"
"brbc 1, % de loopend =" "\n\t"
"ese inc [loopStepsHigh]" "\n\t"
"loopend % =:" "\n\t"
: [loopSteps] "+ a" (loopSteps), [loopStepsHigh] "+ a" (loopStepsHigh):);
}

Artículos Relacionados

Sintetizador digital VRA8-P para Arduino Uno

Sintetizador digital VRA8-P para Arduino Uno

Hecho por ISGK instrumentoshttps://github.com/risgk/digital-Synth-vra8-pConcepto3 voz sintetizador polifónico de Pseudo para Arduino UnoCaracterísticasVoz 3 Pseudo Polyphonic Synthesizer (sintetizador de Paraphonic), módulo de sonido MIDISerial MIDI
La caja sintetizador

La caja sintetizador

en este proyecto, tome un viejo post-box y un Arduino, para crear un sintetizador monofónico muy funcional. Este sintetizador incluye características tales como:-Osciladores duales-6 formas de onda (ver pecado, triángulo, izquierda, derecho de sierra
Sintetizador de música analógico controlado por MIDI

Sintetizador de música analógico controlado por MIDI

Para mi proyecto de diseño senior de ingeniería eléctrica, decidí diseñar un sintetizador de música analógica con control MIDI. Tengo que admitir, esto era lo que quería hacer desde la escuela secundaria y fue mi objetivo como músico, artista, bricol
Sintetizador digital VRA8-M para Arduino Uno

Sintetizador digital VRA8-M para Arduino Uno

Hecho por ISGK instrumentoshttps://github.com/risgk/digital-Synth-vra8-mConceptoSintetizador monofónico (módulo de sonido MIDI) para Arduino UnoCaracterísticasSerial MIDI en (38400 bps), tasa de salida (Pin 6), de Audio PWM PWM: 62500 hertziosTarifa
El Arduino OctoSynth

El Arduino OctoSynth

¿qué es el OctoSynth puede pedir? El octosynth es un sintetizador polifónico que es capaz de producir ocho tonos modulación de la amplitud del pulso que juntos forman una escala musical. En inglés, es un órgano electrónico clave 8 que puede desempeña
Secuenciador de MIDI Arduino Old-School

Secuenciador de MIDI Arduino Old-School

con un equipo estándar de una placa Arduino y un tablero de "escudo", este proyecto crea un secuenciador MIDI que puede grabar y reproducir secuencias de notas MIDI.  Es similar a la vieja escuela Secuenciadores que la secuencia es monofónica (u
Construir una caja de música mecánica programable

Construir una caja de música mecánica programable

¿Si alguna vez has visto esas cajas de música de viento poco, o manivela, y juegan una pequeña melodía una y otra vez de metal un pequeño tambor de notas, pero deseo que hicieran más que reproducir la misma melodía de 10 segundos una y otra vez para
La flauta eléctrico

La flauta eléctrico

Ok, primero...  Sí, esto no es realmente una "flauta" :)Es realmente un "grabador", pero este proyecto le permitirá hacer sonidos como una flauta, grabadora o espacio incluso extraños ruidos.   Los niños les encanta este proyecto!Le da
Hacking el Spy Video Trakr con maldita ' rayos láser... Y misiles!

Hacking el Spy Video Trakr con maldita ' rayos láser... Y misiles!

Cortesía de Hans de la CPT.Compré un lanzador de misiles USB-accionada de la espuma, que tiene pan & tilt e incluso un objetivo laser! Soy alimentación del puerto USB interno de Trakr y controlar con las líneas GPIO.Paso 1: El cuadro original fue bas
Hacking el Spy Video Trakr II

Hacking el Spy Video Trakr II

en el Instructable anterior, "Hacking the Spy Video Trakr" ( aprendió a abrir el Trakr e instalar masculinos encabezados en las conexiones de GPIO en el circuito. También aprendió a escribir, compilar e instalar un programa corto en el Trakr a p
Coche RC para conversión RC tanque con Arduino

Coche RC para conversión RC tanque con Arduino

He siempre sido fascinado por las máquinas grandes, tanques en particular. El alemán tanque del tigre, como aparece en la película furia!, es una máquina impresionante. Yo quería uno! Hice algunas búsquedas y encontrar que réplicas de RC Tiger Tank m
Super Duper Microtonal MIDI Converter

Super Duper Microtonal MIDI Converter

Hice este convertidor MIDI microtonal de Arduino basado en como mi primer proyecto de Arduino:Quería tocar escalas microtonales con mi teclado MIDI, así que hice este dispositivo basado en arduino que lee en notas MIDI y envía correspondientes altura
Añadir llaves a un sintetizador de Arduino el camino duro-el Blacklord: el órgano donante proyecto parte 2

Añadir llaves a un sintetizador de Arduino el camino duro-el Blacklord: el órgano donante proyecto parte 2

(Nota-Este es mi instructable 20! Gracias a todos los siguientes y commenting.on mis proyectos y a los funcionarios que hacen esto posible. Este sitio definitivamente me ha hecho llevar mi juego al Banco de trabajo.)El sintetizador granular Auduino p
Directa Digital sintetizador basado en Arduino llano

Directa Digital sintetizador basado en Arduino llano

Microcontrolador se significa para controlar cosas y no para generar periódicosseñales - para esto proponen que usaríamos un hardware dedicado - algo así como Atmega328 y AD9850.Por otro lado esto podría ser un proyecto interesante - no muy útil, per