Le synthétiseur Octo-phonic (6 / 11 étapes)

Étape 6: Code

Connectez votre arduino à votre ordinateur. Télécharger le code ci-dessous sur votre arduino.

OCTOSynth-0,2
//
Joe Marshall 2011
Filtre résonnant basée sur Meeblip (meeblip.noisepages.com)
Interrompre le code de configuration basé sur le code de Martin Nawrath (http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/)
oscillateurs et optimisation assembleur inline par moi.
//
apport essentiel est de 8 entrées capacitives sur l’entrée numérique 6,7 et entrées analogiques 0-6
chaque entrée est un seul fil, passe à quelque chose de métallique au toucher
(J’ai utilisé un tas de gros boulons)
//
détection de cela se faite en getNoteKeys, à l’aide de la méthode décrite au :
http://www.Arduino.cc/Playground/code/CapacitiveSensor
//
J’utilise l’assembleur avec une boucle déroulée avec 16 registres pour détecter ce
Cela rend les choses beaucoup plus précis que la boucle C décrite sur le lien ci-dessus
car nous mesurons le délai pertinent dans les cycles de processeur unique.
Il semble être heureux même avec la puissance de la batterie, détection jusqu'à 8 simultanés
touches.

Les vagues sont tous définis au sommet, parce que nous sommes l’obligeant à s’aligner sur les limites de 256 octets
Cela rend le code oscillateur plus rapide (en calculant une compensation de la vague est juste
une question de remplacer l’octet de poids faible de l’adresse).
Cela étant dit, autres trucs arduino probablement obtient chargé ici en premier
parce que l’attribut alignée semble ajouter quelques centaines d’octets du code

#define TEST_PATTERN_INTRO

#define FILTER_LPF_NONE
#define FILTER_LPF_HACK

Tableau de 256 valeurs de sinus / un sinus période / stockées dans la mémoire flash
char sine256 [256] __attribute__ ((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 square256 [256] __attribute__ ((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 triangle256 [256] __attribute__ ((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 sawtooth256 [256] __attribute__ ((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 »

table de journal pour 128 seuils de filtre
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} ;

volatil unsigned int WAIT_curTime ;
#define WAIT_UNTIL_INTERRUPT() WAIT_curTime = loopSteps ;    {while(WAIT_curTime==loopSteps)}

#define SERIAL_OUT 0

attaque, decay sont en 1/64ths par 125e de seconde - c’est à dire. 1 = 0 - > 1 en une demi-seconde
const int DECAY = 3 ;
const int attaque = 4 ;

volatils char * curWave = square256 ;

#define DRAS (sfr, bit) (_SFR_BYTE(sfr) & = ~_BV(bit))
#define sbi (sfr, bit) (_SFR_BYTE(sfr) | = _BV(bit))

C’est censé être la fréquence d’horloge audio - comme
vous pouvez le voir, freq mesurée peut varier un peu de fréquence d’horloge supposée
Je ne suis pas sûr pourquoi
const double refclk = 31372.549 ;  = 16MHz / 510
const double refclk = 31376.6 ;      mesurée

variables utilisées à l’intérieur de l’interruption service déclarée comme voilatile
ces variables permettent de garder trace de temps - en retard / millis etc. sont
fait inactif en raison d’interruptions sont désactivées.
volatile unsigned char loopSteps = 0 ; une fois par exemple
volatile unsigned int loopStepsHigh = 0 ; une fois par 256 échantillons

informations sur l’état actuel d’un oscillateur simple
struct oscillatorPhase
{
unsigned int phaseStep ;
volume de char ;
unsigned int phaseAccu ;
};

les oscillateurs (8)
struct oscillatorPhase oscillateurs [8] ;

tword_m = pow (2,32) * dfreq/refclk ;  calculer le nouveau réglage mot DDS
pour obtenir hz -> réglage mot ne: (pow(2,16) * fréquence) / 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} ;

seuils pour les boutons de détection capacitives
int calibrationThresholds [8] = {0,0,0,0,0,0,0,0} ;

Inline int getNoteKeys (calibrer boolean = false)
{

char PORTD_PINS = 0b11000000 ; (broches 6-7 - éviter les broches 0,1 car elles servent pour port série comms)
char PORTC_PINS = 0b111111 ; (broches analogiques 0-5)

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

WAIT_UNTIL_INTERRUPT() ;
(volatile) ASM
boucle de lecture port D :
DDDR & = ~(PORTD_PINS = 0x3f) ;          Réglez de façon strictement 8-12 au mode d’entrée
« en % [temp], 0x0a""\n\t »
"andi % [temp], 0x3f" « \n\t »
"out 0x0a, % [temp]" "\n\t"
PORTD | = (PORTD_PINS) ;          Réglez de façon strictement pullup 8-12 sur
« en % [temp], 0x0b""\n\t »
"ori % [temp], 0xC0" « \n\t »
"out 0x0b, % [temp]" "\n\t"
« à 0 %, 0 x 09""\n\t »
"in 1 %, 0 x 09" "\n\t"
« en %2, 0 x 09""\n\t »
« en %3, 0 x 09""\n\t »
« à 4 %, 0 x 09""\n\t »
"à 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 % 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 % 15, 0 x 09""\n\t »
:
sorties
« = 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() ;
(volatile) ASM
boucle de lecture port C :
DDRC & = ~(PORTC_PINS = 0xc0) ;          Réglez de façon strictement 5-7 au mode d’entrée
« en % [temp], 0 x 07""\n\t »
"andi % [temp], 0xc0" « \n\t »
"out 0 x 07, % [temp]" "\n\t"
PORTC | = (PORTC_PINS) ;          Réglez de façon strictement pullup 5-7 sur
« en % [temp], 0 x 08""\n\t »
"ori % [temp], 0x3F" « \n\t »
"out 0 x 08, % [temp]" "\n\t"
« à 0 %, 0 x 06""\n\t »
"in 1 %, 0 x 06" "\n\t"
« en %2, 0 x 06""\n\t »
« en %3, 0 x 06""\n\t »
« à 4 %, 0 x 06""\n\t »
"à 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 % 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 % 15, 0 x 06""\n\t »
:
sorties
« = 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 hors broches 8-12
PORTD & = ~ (PORTD_PINS) ; pullup hors broches 5-7
DDRC | = (PORTC_PINS) ; décharge
DDDR | = (PORTD_PINS) ; décharge

if(CALIBRATE)
{
pour (int c = 0; c < 8; c ++)
{
pour (d int = 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] = j + 1 ;
}
rupture ;
}
}
}
}
int liveNotes = 0 ;
pour (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) ;
}
}
Return liveNotes ;
}

obtenir un tactile capacitif sur 4 d’entrée et de sortie 3
utilisé pour modulateur de filtre
Inline int getfiltermodulationtime()
{
public static int running_average = 0 ;
public static int running_min = 1024 ;
public static int running_min_inc_count = 0 ;
public 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 ;
faire sûrs entrées / sorties sont bonnes
DDRD| = PIN_OUT ;
DDDR & = ~ (PIN_IN) ;
WAIT_UNTIL_INTERRUPT() ;
PORTD| = PIN_OUT ;
(volatile) ASM
"loopstart % =: « « \n\t »
"sbic 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" « \n\t »
"adiw % [delayTime], 0 x 01" « \n\t »
"IPC %B [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" « \n\t »
"outloop % =: « « \n\t »
: [delayTime] "+ & w » (delayTime)
: [PINNUM_IN] « JE » (PINNUM_IN)) ;
Set tige vers le bas - peut-être ne vous embêtez pas moment, si elle ne semble pas ajouter
beaucoup de précision ?
WAIT_UNTIL_INTERRUPT() ;
PORTD & = ~ PIN_OUT ;
ASM)
"loopstart % =: « « \n\t »
« ITT 0 x 09, % [PINNUM_IN] » "\n\t »
"rjmp outloop % =" « \n\t »
"adiw % [delayTime], 0 x 01" « \n\t »
"IPC %B [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" « \n\t »
"outloop % =: « « \n\t »
: [delayTime] "+ & w » (delayTime)
: [PINNUM_IN] « JE » (PINNUM_IN)) ;
running_average = (running_average-(running_average >> 4)) + (/Delay >> 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 ;
}
Return touchVal ;
}

Téléchargez tactile capacitif sur 5 d’entrée et de sortie 3
utilisé pour la modulation de hauteur
Inline int getpitchbendtime()
{
public static int running_average = 0 ;
public static int running_min = 1024 ;
public static int running_min_inc_count = 0 ;
public 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 ;
faire sûrs entrées / sorties sont bonnes
DDRD| = PIN_OUT ;
DDDR & = ~ (PIN_IN) ;
WAIT_UNTIL_INTERRUPT() ;
PORTD| = PIN_OUT ;
(volatile) ASM
"loopstart % =: « « \n\t »
"sbic 0 x 09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" « \n\t »
"adiw % [delayTime], 0 x 01" « \n\t »
"IPC %B [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" « \n\t »
"outloop % =: « « \n\t »
: [delayTime] "+ & w » (delayTime)
: [PINNUM_IN] « JE » (PINNUM_IN)) ;
Set tige vers le bas - peut-être ne vous embêtez pas moment, si elle ne semble pas ajouter
beaucoup de précision ?
WAIT_UNTIL_INTERRUPT() ;
PORTD & = ~ PIN_OUT ;
ASM)
"loopstart % =: « « \n\t »
« ITT 0 x 09, % [PINNUM_IN] » "\n\t »
"rjmp outloop % =" « \n\t »
"adiw % [delayTime], 0 x 01" « \n\t »
"IPC %B [delayTime], 0 x 02" "\n\t"
"brne loopstart % =" « \n\t »
"outloop % =: « « \n\t »
: [delayTime] "+ & w » (delayTime)
: [PINNUM_IN] « JE » (PINNUM_IN)) ;
running_average = (running_average-(running_average >> 4)) + (/Delay >> 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 ;
}
Return 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 * /)
{
oscillateurs [0] .phaseStep = NOTE_FREQS [baseNote] ;
oscillateurs [1] .phaseStep = NOTE_FREQS [baseNote + 2] ;
oscillateurs [2] .phaseStep = NOTE_FREQS [baseNote + 4] ;
oscillateurs [3] .phaseStep = NOTE_FREQS [baseNote + 5] ;
oscillateurs [4] .phaseStep = NOTE_FREQS [baseNote + 7] ;
oscillateurs [5] .phaseStep = NOTE_FREQS [baseNote + 9] ;
oscillateurs [6] .phaseStep = NOTE_FREQS [baseNote + 11] ;
oscillateurs [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) ;
pour (int c = 0; c < 8; c ++)
{
multiplier 2 nombres 16 bits ensemble et passer 8 sans perte de précision
nécessite l’assembleur vraiment
volatile unsigned char zeroReg = 0 ;
volatile unsigned int multipliedCounter = oscillateurs [c] .phaseStep ;
ASM volatile
(
mult octets élevés ensemble = octet haut
« ldi %A [outVal], 0 » "\n\t »
"mul %B [phaseStep], %B [pitchBend]" "\n\t"
"mov %B [outVal], r0" "\n\t"
ignorer le débordement en r1 (ne doit jamais déborder)
octet de poids faible * octet haut -> les deux octets
"mul %A [phaseStep], %B [pitchBend]" "\n\t"
"Ajouter %A [outVal], r0" "\n\t"
transportent dans l’octet haut
"adc %B [outVal], r1" "\n\t"
haute octets * octet de poids faible -> les deux octets
"mul %B [phaseStep], A [pitchBend]" "\n\t"
"Ajouter %A [outVal], r0" "\n\t"
transportent dans l’octet haut
"adc %B [outVal], r1" "\n\t"
octet de poids faible * octet de poids faible -> rond
"mul %A [phaseStep], A [pitchBend]" "\n\t"
l’adc ci-dessous est d’arrondir basé sur peu élevé de faible * faible :
"adc %A [outVal], r1" "\n\t"
"adc %B [outVal], % [ZERO]" "\n\t"
"clr r1" "\n\t"
: [outVal] "= & d" (multipliedCounter)
: [phaseStep] "d" (oscillateurs [c] .phaseStep), [pitchBend] "d" (pitchBendMultiplier), [ZERO] "d" (zeroReg)
: "r1", "r0"
);
oscillateurs [c] .phaseStep = multipliedCounter ;
}
Serial.Print(":") ;
Serial.Print(NOTE_FREQS[baseNote]) ;
Serial.Print(":") ;
Serial.println(oscillators[0].phaseStep) ;

}

void setup()
{
Serial.Begin(9600) ;        se connecter au port série
#ifndef FILTER_LPF_NONE
setFilter (127, 0) ;
#endif

pinMode (sortie 11) ;     PIN11 = sortie PWM / fréquence de sortie

setupNoteFrequencies(12,0) ;

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

Setup_timer2() ;

désactiver les interruptions pour éviter des distorsions de chronométrage
CBI (TIMSK0, TOIE0) ;              désactiver le Timer0!!! Delay() n’est actuellement pas disponible
SBI (TIMSK2, TOIE2) ;              activez le Timer2 interrompre

étalonner les valeurs de clés non enfoncés

pour (int x = 0; x < 1024; x ++)
{
getNoteKeys(true) ;
étapes d’int = loopSteps ;
WAIT_UNTIL_INTERRUPT() ;
int afterSteps = loopSteps ;
Serial.println(afterSteps-Steps) ;
}
intro de mire
#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};
pour (Remarque int = 0; Notez < sizeof(notes)/sizeof(byte);note++)
{

int noteCount = 0 ;
pour (int c = 0; c < 8; c ++)
{
Si (notes [note] & (1 << c))
{
noteCount += 1 ;
}
}
pour (int c = 0; c < 8; c ++)
{
Si (notes [note] & (1 << c))
{
oscillateurs [c] .volume = 63/noteCount ;
} else
{
oscillateurs [c] .volume = 0 ;
}
}
pour (int c = 0; c < 50; c ++)
{
pourrait ainsi garder étalonnage ici
NB: chaque boucle d’étalonnage = au moins 1 interruption

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

}
}
#else
juste un bip pour indiquer l’étalonnage est réalisé
oscillateurs [0] .volume = 63 ;
pour (int c = 0; c < 20; c ++)
{
WAIT_UNTIL_INTERRUPT() ;
}
oscillateurs [0] .volume = 63 ;

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

}

void loop()
{
Nous gardons une liste des volumes « raw » - et baissez le volume si un accord se > 64 volume total
Cela doit permettre chording sans réduire le volume des notes seules
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 ;
non signé curStep = loopStepsHigh ;
while(1)
{
lastStep = curStep ;
curStep = loopStepsHigh ;
Remarque : les minuteries ne fonctionnent pas dans ce code (interruptions désactivé / vitesses changé), donc ne pensez même pas à l’appel : delay(), millis / micros etc..
chaque loopstep est à peu près 31250 / seconde
Cette boucle principale est appelée une fois tous les 3 ou 4 échantillons si la sortie série a été désactivé, peut-être plus lentement dans le cas contraire

int liveNotes=getNoteKeys() ;
Nous sommes tout de suite après une interruption (comme loopStep a juste été incrémenté)
donc, nous devrions avoir suffisamment de temps pour faire les contrôles clés capacitive

if(lastStep!=curStep)
{
int totalVolume = 0 ;
pour (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(".") ;
}
d’autre
{
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)
{
pour (int c = 0; c < 8; c ++)
{
oscillateurs [c] .volume = rawVolumes [c] ;
}
} else
{
volume total réduire trop, pour éviter l’écrêtage
pour (int c = 0; c < 8; c ++)
{
oscillateurs [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 ;
}
ElseIf (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()) ;

Nous sommes juste après une interruption à nouveau (comme loopStep a juste été incrémenté)
donc nous devrions avoir suffisamment de temps pour vérifier la capacité du pitch bend sans aller sur un autre échantillon, timing est très important ici
ont besoin d’équilibrer en utilisant une résistance assez grande pour obtenir la distance de détection décent avec prend trop de temps d’échantillon
Vérifiez la source de courbure de tangage

}
}
//******************************************************************
installation du TIMER2
prscaler la valeur 1, le mode PWM à phase PWM correct, 16000000/510 = 31372.55 Hz horloge
void Setup_timer2() {}

Diviseur d’horloge TIMER2 pour: 1
SBI (TCCR2B, CS20) ;
CBI (TCCR2B, CS21) ;
CBI (TCCR2B, CS22) ;

TIMER2 PWM Mode de réglage de Phase PWM Correct
CBI (TCCR2A, COM2A0) ;  effacer le Match comparer
SBI (TCCR2A, COM2A1) ;

SBI (TCCR2A, WGM20) ;  Mode 1 / Phase PWM Correct
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 ;
volatils char filtCoeffB1 = 127 ;
volatile unsigned char filtCoeffB2 = 255 ;
#endif
#ifdef FILTER_LPF_HACK
filtre passe-bas piraté - 2 pole résonant-
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, unsigned char résonance)
{
unsigned char tempReg = 0, tempReg2 = 0 ;
ASM volatile (« ldi % [tempReg], 0xff » « \n\t »
"sub % [tempReg], [filtF]" "\n\t"
"DSL % [tempReg]" "\n\t"
« ldi % [tempReg2], 0 x 04 » « \n\t »
"Ajouter % [tempReg], [tempReg2]" "\n\t"
"sub % [reso], [tempReg]" "\n\t"
"brcc Res_Overflow % =" « \n\t »
« ldi % [reso], 0 x 00 » « \n\t »
"Res_Overflow % =: « « \n\t »
"mov % [filtQ], [reso]" « \n\t »
: [tempReg] "= & d" (tempReg), [tempReg2] "= & d" (tempReg2), [filtQ] "= & d" (filterQ): [reso] "d" (résonance), [filtF] « d » (filterF)) ;
}

Inline setFilter Sub (f unsigned char, unsigned char résonance)
{
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))

la boucle principale oscillateur (incrémente le pointeur de la table d’ondes et l’ajouter à des registres de sortie)
13 instructions - devrait prendre 14 cycles du processeur selon la feuille de données
en théorie, selon moi, que cela signifie que chaque oscillateur devrait prendre 1,5 % de cpu
(plus une surcharge constante pour interruption appelle etc..)
Remarque : Ceci a l’habitude de faire tous le stepvolume charge peu après le début, mais ils sont maintenant entrelacées dans la
code, c’est parce que la ldd (charge avec décalage) prend 2 instructions,
versus ld, + 1 (charge avec incrément post) et st, + 1 qui sont 1 instruction - nous pouvons le faire parce que :
//
a) l’étape (qui ne doit pas être stocké à l’arrière) est en mémoire avant le
accumulateur de phase (qui a besoin d’être stockées une fois que l’étape est ajoutée
//
b) la phase assumulator est stocké dans l’octet de poids faible, ordre d’octet élevé, ce qui signifie que nous
peut additionner les premiers octets, puis stocker cet octet incrémentation de l’aiguille,
puis l’octet haut, additionnez les octets de hautes et de stocker incrémenter le pointeur
//
Je pense que c’est le nombre minimum d’opérations possibles de coder cet oscillateur, parce que
1) il y a 6 opérations de chargement requises (pour charger stepHigh/bas, phaseH/L, volume et la valeur de la vague)
2) il y a 2 ajouter les opérations requises pour ajouter à l’accumulateur de phase
3) il y a 2 operations magasin requises pour enregistrer l’accumulateur de phase
4) il est 1 multiplier (2 cycles d’instruction) nécessaire pour faire du volume
5) il y a 2 ajouter les opérations requises pour ajouter à la sortie finale
//
6 + 2 + 2 + 2 + 2 = 14 cycles d’enseignement

#define OSCILLATOR_ASM \
/ * chargement phase étape et volume * / \
« ld %A [tempStep], % un [stepVolume] + "« \n\t » \
« ld %B [tempStep], % un [stepVolume] + "« \n\t » \
« ld [tempVolume], % un [stepVolume] + "« \n\t » \
/ * chargement phase accumulateur - octet haut va droit * / \
/ * dans le tableau de recherche vague (wave est sur la limite de 256 octets * / \
/ * Si nous pouvons le faire sans aucune ajoute * / \
/ * La phase ajoute entre les deux charges, comme charge avec offset est plus lent que
juste une charge normale
*/\
"ld %A [tempPhaseLow], % un [stepVolume]" "\n\t" \
/ * Ajouter phase étape basse * / \
« \n\t"\ « ajouter % [tempPhaseLow], %A [tempStep] »
/ * stocker phase accu faible * / \
"st %a [stepVolume] +, % [tempPhaseLow]" « \n\t » \
/ * chargement phase accumulateur haute * / \
"ld %A [waveBase], % un [stepVolume]" "\n\t" \
/ * Ajouter phase étape haut - avec retenue dans l’ajouter ci-dessus * / \
"adc %A [waveBase], %B [tempStep]" "\n\t"\
/ * stocker phase étape haute * / \
"st %a [stepVolume] +, %A [waveBase]" « \n\t » \
/ * maintenant la recherche de la vague - octet = pointeur de vague, octet de poids faible = offset * / \
« ld % [tempPhaseLow], un [waveBase] » « \n\t » \
/ * maintenant multipliez par volume * / \
"muls % [tempPhaseLow], [tempVolume]" « \n\t » \
/ * r0 contient à présent un échantillon - ajouter à la sortie valeur * / \
"Ajouter %A [outValue], r0" « \n\t » \
"adc %B [outValue], r1" « \n\t » \
/ * aller au prochain oscillateur - stepVolume pointe sur suivant * / \
/ * oscillateur déjà * / \

//******************************************************************
TIMER2 interrompre le Service à 31 372 550 KHz = 32uSec
Il s’agit de la base de temps REFCLOCK pour le générateur DDS
S’en FOUT = (M (REFCLK)) / (2 exp 32)
Duree: ?
{ISR(TIMER2_OVF_vect)}

maintenant mis en place la prochaine valeur
Cette boucle dure environ 172 cycles (214 dont le push/pop) - nous avons 510, donc environ 50 % de la roue de secours va processeur pour des tâches non audio
le filtre passe-bas prend également quelques cycles

int outValue ;

pointeurs :
X = accumulateur de phase oscillateur
Y = étape oscillateur et volume
Z = vague pos - a besoin d’ajouter à la base
int tempStep = 0 ;
char tempPhaseLow = 0, tempVolume = 0 ;
int tempWaveBase = 0 ;
(volatile) ASM
« ldi %A [outValue], 0"« \n\t »
« ldi %B [outValue], 0"« \n\t »
oscillateur 0
Supprimez le code ci-dessous pour vérifier
que les registres ne reçoivent doubles assignés
/ * "lds %A [outValue], 0 x 00" "\n\t"
"lds %B [outValue], 0 x 01" "\n\t"
"lds %A [tempPhaseLow], 0 x 02" "\n\t"
"lds %B [tempPhase], 0 x 03" "\n\t"
"lds %A [tempStep], 0 x 04" "\n\t"
"lds %B [tempStep], 0 x 05" "\n\t"
"lds % [tempVolume], 0 x 06" « \n\t »
"lds % [zéro], 0 x 07" « \n\t »
"lds %A [tempWaveBase], 0 x 08" "\n\t"
"lds %B [tempWaveBase], 0 x 09" "\n\t"
"lds %A [phaseAccu], 0x0a" "\n\t"
"lds %B [phaseAccu], 0x0b" "\n\t"
"lds %A [stepVolume], 0x0c" "\n\t"
"lds %B [stepVolume], 0x0d" "\n\t"
"lds %A [waveBase], 0x0e" "\n\t"
"lds %B [waveBase], 0x0f" "\n\t"*/
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
OSCILLATOR_ASM
:
sorties
[tempPhaseLow] "= & d" (tempPhaseLow),
[tempStep] "= & d" (tempStep),
[tempVolume] "= & d" (tempVolume),
[outValue] "= & d" (outValue)
:
entrées
[stepVolume] « y » (& oscillators[0].phaseStep),
[waveBase] « z » (256 * (((unsigned int) curWave) >> 8))
:
autres registres que nous écrase (en faisant des multiplications)
« r1 »
);

à ce stade outValue = valeur de l’oscillateur
Il est actuellement cotisé au maximum à plein volume / 4
certaine marge permettant de filtrage


#ifdef FILTER_LPF_HACK

un passe-bas filtre basé sur celui de MeeBlip (http://meeblip.noisepages.com)
un += f*((in-a) + q*(a-b)
b + = f * (a-b)
outValue >> = 3 ;
commencé à 4700
4686
int tempReg, tempReg2 = 0 ;
unsigned char zeroRegFilt = 0 ;
de-volatilisati
unsigned char filtF = filterF ;
unsigned char filtQ = filterQ ;
(volatile) ASM
"sub %A [outVal], A [filtA]" "\n\t"
"sbc %B [outVal], %B [filtA]" "\n\t"
"brvc No_overflow1 % =" « \n\t »
« ldi %A [outVal], 0b00000001 » "\n\t »
« ldi %B [outVal], 0b10000000 » "\n\t »
"No_overflow1 % =: « « \n\t »
outVal = (in French - filtA)
"mov %A [tempReg], A [filtA]" "\n\t"
"mov %B [tempReg], %B [filtA]" "\n\t"
"sub %A [tempReg], A [filtB]" "\n\t"
"sbc %B [tempReg], %B [filtB]" "\n\t"
"brvc No_overflow3 % =" « \n\t »
« ldi %A [tempReg], 0b00000001 » "\n\t »
« ldi %B [tempReg], 0b10000000 » "\n\t »
"No_overflow3 % =: « « \n\t »
tempReg = (a-b)
« mulsu %B [tempReg], % [filtQ] » "\n\t »
« movw %A [tempReg2], r0 » "\n\t »
tempReg2 = (HIBYTE(a-b)) * Q
"mul %A [tempReg], % [filtQ]" "\n\t"
"Ajouter %A [tempReg2], r1" "\n\t"
"adc %B [tempReg2], % [ZERO]" "\n\t"
« rol r0 » "\n\t »
"brcc No_Round1 % =" « \n\t »
"%A inc [tempReg2]" "\n\t"
"No_Round1 % =: « « \n\t »
à ce point tempReg2 = (a-b) * Q (décalé de façon appropriée et arrondi)
"clc" "\n\t"
"lsl %A [tempReg2]" "\n\t"
« rol %B [tempReg2] » "\n\t »
"clc" "\n\t"
"lsl %A [tempReg2]" "\n\t"
« rol %B [tempReg2] » "\n\t »
tempReg2 = (a-b) * Q * 4
"Ajouter %A [outVal], A [tempReg2]" "\n\t"
"adc %B [outVal], %B [tempReg2]" "\n\t"
"brvc No_overflow4 % =" « \n\t »
« ldi %A [outVal], 0b11111111 » "\n\t »
« ldi %B [outVal], 0b01111111 » "\n\t »
"No_overflow4 % =: « « \n\t »
outVal = ((in-a) + (a-b) * (Q >> 8) * 4) - coupé, etc.
« mulsu %B [outVal], % [filtF] » "\n\t »
« movw %A [tempReg], r0 » "\n\t »
"mul %A [outVal], % [filtF]" "\n\t"
"Ajouter %A [tempReg], r1" "\n\t"
"adc %B [tempReg], % [ZERO]" "\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 »
"Ajouter %A [filtA], A [tempReg]" "\n\t"
"adc %B [filtA], %B [tempReg]" "\n\t"
A = A + f * ((in-a) + (a-b) * (Q >> 8) * 4)
"brvc No_overflow5 % =" « \n\t »
« ldi %A [outVal], 0b11111111 » "\n\t »
« ldi %B [outVal], 0b01111111 » "\n\t »
"No_overflow5 % =: « « \n\t »
maintenant calculer B = f * (a - b)

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

multiplier outval par 4 et clip
"Ajouter %A [outVal], A [filtB]" "\n\t"
"adc %B [outVal], %B [filtB]" "\n\t"
« brbs 3, Overflow_End % = "« \n\t »

"Ajouter %A [outVal], A [filtB]" "\n\t"
"adc %B [outVal], %B [filtB]" "\n\t"
« brbs 3, Overflow_End % = "« \n\t »

"Ajouter %A [outVal], A [filtB]" "\n\t"
"adc %B [outVal], %B [filtB]" "\n\t"
« brbs 3, Overflow_End % = "« \n\t »
"rjmp No_overflow % =" « \n\t »
"Overflow_End % =: « « \n\t »
"brbs 2, Overflow_High % =" « \n\t »
« ldi %A [outVal], 0b00000001 » "\n\t »
« ldi %B [outVal], 0b10000000 » "\n\t »
"rjmp No_overflow % =" « \n\t »
"Overflow_High % =: « « \n\t »
« ldi %A [outVal], 0b11111111 » "\n\t »
« ldi %B [outVal], 0b01111111 » "\n\t »
"No_overflow % =: « « \n\t »
char valOut = ((unsigned int)(outValue)) >> 8 ;
valOut += 128 ;
OCR2A = valOut (octet) ;
"Felix %B [outVal], 0 x 80" "\n\t"
« m 0x00b3, %B [outVal] » "\n\t »
Décommentez les lignes ci-dessous pour voir la répartition du Registre
/*
"lds %A [filtA], 0 x 01" "\n\t"
"lds %B [filtA], 0 x 02" "\n\t"
"lds %A [filtB], 0 x 03" "\n\t"
"lds %B [filtB], 0 x 04" "\n\t"
"lds % [filtQ], 0 x 05" « \n\t »
"lds % [filtF], 0 x 06" « \n\t »
"lds %A [outVal], 0 x 07" "\n\t"
"lds %B [outVal], 0 x 08" "\n\t"
"lds %A [tempReg], 0 x 09" "\n\t"
"lds %B [tempReg], 0x0a" "\n\t"
"lds %A [tempReg2], 0x0b" "\n\t"
"lds %B [tempReg2], 0x0c" "\n\t"
"lds % [zéro], 0x0d" "\n\t"*/
:
sorties / lecture/écriture arguments
[filtA] "+ & w » (filterA),
[filtB] "+ & w » (filterB),
[tempReg] "= & un » (tempReg),
[tempReg2] "= & d" (tempReg2)
:
[filtQ] « a » (filtQ),
[filtF] « a » (filtF),
[outVal] « a » (outValue),
[ZÉRO] "d" (zeroRegFilt)
entrées
: "r1") ;

#endif

sortie se fait dans le code assembleur de filtre si les filtres sont sur
dans le cas contraire nous sortir à la main ici
#ifdef FILTER_LPF_NONE
gain intégral
outValue * = 4 ;
à ce stade, outValue est une version signée de 16 bits de ce que nous voulons, c’est à dire. 0 -> 32767, puis -32768 -> -1 (0xffff)
Nous voulons 0 -> 32767 pour aller à 32768-65535 et -32768 -> -1 à l’aller 0-32767, ensuite, nous ne souhaitons que l’octet haut de la page
prendre l’octet haut de la page, ajouter 128, puis effectuer un cast en unsigned. Le (unsigned int) dans le Voici pour éviter d’avoir à changer (ie.just prend albums octets)
char valOut = ((unsigned int)(outValue)) >> 8 ;
valOut += 128 ;
OCR2A = valOut (octet) ;
#endif
incrémente le compteur de boucle étape (et compteur haute)
ils sont utilisés parce que nous avons arrêter le chronomètre
interruption en cours d’exécution, ne donc aucun autre moyen pour indiquer l’heure
Cette asm n’est probablement pas vraiment nécessaire, mais il enregistre environ 10 instructions
parce que les variables doivent être volatile
ASM)
"inc % [loopSteps]" "\n\t"
« brbc 1, loopend % = "« \n\t »
"%A inc [loopStepsHigh]" "\n\t"
« brbc 1, loopend % = "« \n\t »
« %B inc [loopStepsHigh] » "\n\t »
"loopend % =: « « \n\t »
: [loopSteps] "+" (loopSteps), [loopStepsHigh] "+" (loopStepsHigh):) ;
}

Articles Liés

Synthétiseur de temporisateur NE555

Synthétiseur de temporisateur NE555

Bonjour, je vous vois WAN ' t de savoir comment faire un NE555 minuterie basée 3 synthétiseur d'octave qui s'inscrit dans une boîte de conserve. Eh bien, vous êtes venu au bon endroit:)Pour ce projet, vous aurez besoin :1. 36 boutons tactiles (les bo
Synthétiseur MIDI programmable avec Intel Edison et Csound

Synthétiseur MIDI programmable avec Intel Edison et Csound

Un contrôleur MIDI est comme le clavier de l'ordinateur, mais au lieu d'envoyer des caractères à l'ordinateur, il envoyer des notes (et beaucoup de plus d'informations sur comment se joue la note). Vous pouvez en apprendre plus sur contrôleurs MIDI i
Synthétiseur : Un clavier UI avec sortie Audio

Synthétiseur : Un clavier UI avec sortie Audio

Nous avons construit un clavier UI avec cinq modes de synthèse tout en Javascript, pour montrer la puissance de l'aide des broches de matériel de sortie audio de Kinoma Create. Vous pouvez télécharger le projet open source maintenant pour s'exécuter
Contrôleur de synthétiseur humain/Game

Contrôleur de synthétiseur humain/Game

IntroductionVous pouvez apprendre comment jouer un solo de clavier en donnant à vos amis un Saluez ! Vous pouvez devenir un champion Tetromino ou écureuil en donnant à vos amis un h.o.t., trop ! Suivez les instructions ci-dessous pour en faire un con
Maître de l’accordéon - un synthétiseur de musique python/arduino

Maître de l’accordéon - un synthétiseur de musique python/arduino

Ce projet a été créé par une équipe de trois étudiants de l'Université de Pennsylvanie à MHacks 2014 Detroit (un week-end Hackathon). L'objectif de ce projet est de créer un synthétiseur de musique qui génère des signaux basé sur les gestes de l'util
Synthétiseur génial

Synthétiseur génial

Alors, j'ai fait un synthétiseur de consonance cool sur mon portable. Je vais mettre un échantillon vidéo vers le haut à ce sujet bientôt. Pour l'instant, voici un enregistrement audio. Dans l'ordre, il va la lettre à Élise, Moonlight Sonata, Canon d
Le synthétiseur Arduino

Le synthétiseur Arduino

L'Arduino est en mesure de sortie son par une bibliothèque qui a été développée, appelée la Bibliothèque de ton.En créant une interface et un programme qui peut appeler certaines valeurs pour être sortie d'une sortie audio, le synthétiseur de l'Ardui
Déclencher le câble pour synthétiseur Moog

Déclencher le câble pour synthétiseur Moog

Cette semaine j'ai eu un séquenceur modulaire, ce qui fait normalement partie d'un synthétiseur modulaire. J'ai un synthétiseur MiniMoog Voyager qui contient de nombreux éléments qu'un synthé modulaire inclurait normalement, alors j'ai voulu brancher
Synthétiseur MIDI SoundFont avec Intel Edison et Fluidsynth

Synthétiseur MIDI SoundFont avec Intel Edison et Fluidsynth

Sur ce Instructable, je vais montrer comment construire votre propre synthétiseur MIDI SoundFont utilisant Intel Edison et Fluidsynth.En suivant les étapes décrites ici, vous aurez un synthétiseur qui peut jouer presque n'importe quel SoundFont dispo
Conception et construction d’un synthétiseur avec Meeblip et Arduino, ajouté des vidéos !

Conception et construction d’un synthétiseur avec Meeblip et Arduino, ajouté des vidéos !

Pour mon stage chez Create Digital Music/Meeblip j'ai créé un amusant petit synthétiseur. Cette chose est censée être plus souples que les autre synthétiseur en le rendant complètement indépendant ; C'est une batterie a son propre amplificateur/encei
Synthétiseur numérique VRA8-P pour Arduino Uno

Synthétiseur numérique VRA8-P pour Arduino Uno

Commercialisée par ISGK Instrumentshttps://github.com/risgk/Digital-Synth-vra8-pConcept3 voix polyphone Pseudo pour Arduino UnoCaractéristiques3 voix Pseudo polyphone (Paraphonic synthétiseur), Module de sons MIDISerial MIDI en (38400 bits/s), le tau
Synthétiseur numérique VRA8-x pour Arduino Uno

Synthétiseur numérique VRA8-x pour Arduino Uno

Commercialisée par ISGK Instrumentshttps://github.com/risgk/Digital-Synth-vra8-xConceptSynthétiseur expérimentale pour Arduino UnoCaractéristiquesSynthétiseur monophonique (ou Module sonore MIDI)Serial MIDI en (38400 bits/s), le taux PWM Audio Out (P
Synthétiseur utilisant 555

Synthétiseur utilisant 555

dans ce instructable, je vais vous montrer comment faire un synthétiseur avec des composants communs. Il utilise des condensateurs, mais vous pouvez facilement modifier le circuit pour utiliser des résistances à la place. Il y a beaucoup de choses qu
Comment faire un synthétiseur sonore Arduino avec interface MIDI

Comment faire un synthétiseur sonore Arduino avec interface MIDI

Avec ce synthétiseur, vous pouvez faire Arduino reproduire des formes d'ondes totalement personnalisés. En raison de l'interface MIDI, il peut être connecté à n'importe quel instrument qui disposent et jouer avec le son souhaité.Étape 1: matériauxArd