Paso 6: código de
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):);
}