Octo-phonic syntet (6 / 11 steg)

Steg 6: kod



Ansluter din arduino till datorn. Ladda upp koden nedan till din arduino.

OCTOSynth-0,2
//
Joe Marshall 2011
Resonant filtrera baserat på Meeblip (meeblip.noisepages.com)
Avbryta installationen koden baserat på koden av Martin Nawrath (http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/)
oscillatorer och inline assembler optimering av mig.
//
tangentinmatning är från 8 kapacitiv ingångar på digital ingång 6,7 och analoga ingångar 0-6
varje ingång är en enda tråd, kommer att något metall röra
(Jag använde en massa stora vagnsbultar)
//
avkänning av detta sker genom getNoteKeys, med den metod som beskrivs på:
http://www.Arduino.cc/Playground/Code/CapacitiveSensor
//
Jag använder assembler med en upprullad loop med 16 register för att upptäcka detta
Detta gör saker mycket mer exakt än C slingan beskrivs på länken ovan
som vi mäter relevanta förseningen i enda processorcykler.
Det verkar vara nöjd även med batteridrift, upptäcka upp till 8 samtidiga
berör.

Vågorna är alla definierade högst upp, eftersom vi tvingar dem att anpassa till 256 byte gränser
Detta gör oscillatorn koden snabbare (som beräkningen av en våg offset är bara
en fråga för att ersätta den låga byten av adressen).
Med detta sagt, andra arduino saker förmodligen får lastas här först
eftersom attributet arrangera i rak linje verkar att lägga till ett par hundra byte till koden

#define TEST_PATTERN_INTRO

#define FILTER_LPF_NONE
#define FILTER_LPF_HACK

tabell med 256 sine värden / en sinus period / lagras i flashminne
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"

loggtabell för 128 filter cutoffs
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};

flyktiga unsigned int WAIT_curTime;
#define WAIT_UNTIL_INTERRUPT() WAIT_curTime = loopSteps; While(WAIT_curTime==loopSteps) {}

#define SERIAL_OUT 0

attack, decay är 1/64ths per 125th av en sekund - dvs. 1 = 0 - > 1 i en halv sekund
CONST int DECAY = 3;
CONST int ATTACK = 4;

flyktiga char * curWave = square256;

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

Detta är förmodligen den audio klockfrekvensen - som
Du kan se, uppmätta freq kan variera lite från förmodade klockfrekvens
Jag är inte helt säker på varför
CONST double refclk = 31372.549; = 16MHz / 510
CONST double refclk = 31376.6; uppmätt

variabler som används inuti avbryta tjänsten som voilatile
dessa variabler tillåt du till hålla spår tid - som fördröjning / millis etc. är
gjorde inaktiv på grund av avbrott att inaktiveras.
volatile unsigned char loopSteps = 0; en gång per prov
volatile unsigned int loopStepsHigh = 0; en gång per 256 prover

information om det aktuella läget för en enda oscillator
struct oscillatorPhase
{
unsigned int phaseStep;
char volym;
unsigned int phaseAccu;
};

oscillatorerna (8 av dem)
struct oscillatorPhase oscillatorer [8].

tword_m = pow (2,32) * dfreq/refclk; calulate DDS nya tuning word
för att få hz -> trim ord: (pow(2,16) * frekvens) / 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}.

tröskelvärden för kapacitiv avkänning knapparna
int calibrationThresholds [8] = {0,0,0,0,0,0,0,0}.

inline int getNoteKeys (boolean kalibrera = false)
{

char PORTD_PINS = 0b11000000; (stift 6-7 - Undvik pins 0,1 eftersom de används för seriell port comms)
char PORTC_PINS = 0b111111; (analog stift 0-5)

CONST int MAX_LOOPS = 16.
char port_values [MAX_LOOPS * 2];

WAIT_UNTIL_INTERRUPT();
ASM flyktiga)
Port D behandlingen loop:
DDRD & = ~(PORTD_PINS = 0x3f); ställa in stift 8-12 till insatsen läge
"i % [temp], 0x0a" "\n\t"
"andi % [temp], 0x3f" "\n\t"
"ut 0x0a, % [temp]" "\n\t"
PORTD | = (PORTD_PINS); ställa in stift 8-12 pullup på
"i % [temp], 0x0b" "\n\t"
"ori % [temp], 0xC0" "\n\t"
"ut 0x0b, % [temp]" "\n\t"
"i %0, 0x09" "\n\t"
"i %1, 0x09" "\n\t"
"i %2, 0x09" "\n\t"
"i %3, 0x09" "\n\t"
"i %4, 0x09" "\n\t"
"i 5 %, 0x09" "\n\t"
"i 6 %, 0x09" "\n\t"
"i %7, 0x09" "\n\t"
"i 8 %, 0x09" "\n\t"
"i 9 %, 0x09" "\n\t"
"i % 10, 0x09" "\n\t"
"i % 11, 0x09" "\n\t"
"i % 12, 0x09" "\n\t"
"i % 13, 0x09" "\n\t"
"i % 14, 0x09" "\n\t"
"i % 15, 0x09" "\n\t"
:
utgångar
"= 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();
ASM flyktiga)
Port C behandlingen loop:
DDRC & = ~(PORTC_PINS = 0xc0); ställa in stift 5-7 att mata in läge
"i % [temp], 0x07" "\n\t"
"andi % [temp], 0xc0" "\n\t"
"ut 0x07, % [temp]" "\n\t"
PORTC | = (PORTC_PINS); ställa in stift 5-7 pullup på
"i % [temp], 0x08" "\n\t"
"ori % [temp], 0x3F" "\n\t"
"ut 0x08, % [temp]" "\n\t"
"i %0, 0x06" "\n\t"
"i %1, 0x06"\n\t"
"i %2, 0x06"\n\t"
"i %3, 0x06" "\n\t"
"i %4, 0x06" "\n\t"
"i %5 0x06" "\n\t"
"i 6 %, 0x06" "\n\t"
"i %7, 0x06" "\n\t"
"i 8 %, 0x06" "\n\t"
"i 9 %, 0x06" "\n\t"
"i % 10, 0x06" "\n\t"
"i % 11, 0x06" "\n\t"
"i % 12, 0x06" "\n\t"
"i % 13, 0x06" "\n\t"
"i % 14, 0x06" "\n\t"
"i % 15, 0x06" "\n\t"
:
utgångar
"= 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 av stift 8-12
PORTD & = ~ (PORTD_PINS); pullup av stift 5-7
DDRC | = (PORTC_PINS); ansvarsfrihet
DDRD | = (PORTD_PINS); ansvarsfrihet

IF(Calibrate)
{
för (int c = 0; c < 8; c ++)
{
för (int d = 0; d < MAX_LOOPS; d ++)
{
int liveNotes=((int*)port_values) [d];
liveNotes & = 0x3fc0;
liveNotes >> = 6;
om (liveNotes & (1 << c))
{
om (calibrationThresholds [c] < = d)
{
calibrationThresholds [c] = d + 1;
}
bryta;
}
}
}
}
int liveNotes = 0;
för (int c = 0; c < 8; c ++)
{
int val = ((int*) port_values) [calibrationThresholds [c] + 1];
Val & = 0x3fc0;
Val >> = 6;
om ((val & (1 << c)) == 0)
{
liveNotes| = (1 << c);
}
}
återvända liveNotes;
}

få kapacitiv touch på ingång 4 och utgång 3
används för filter modulator
inline int getfiltermodulationtime()
{
statisk int running_average = 0;
statisk int running_min = 1024;
statisk int running_min_inc_count = 0;
statisk boolean initialise_running_min = sant;

unsigned int fördröjningstid = 0;
char PINNUM_OUT = 3;
char PINNUM_IN = 4;
char PIN_OUT = 1 << PINNUM_OUT;
char PIN_IN = 1 << PINNUM_IN;
göra säker ingångar / utgångar är sätta rätt
DDRD| = PIN_OUT;
DDRD & = ~ (PIN_IN);
WAIT_UNTIL_INTERRUPT();
PORTD| = PIN_OUT;
ASM flyktiga)
"loopstart % =:" "\n\t"
"sbic 0x09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [fördröjningstid], 0x01" "\n\t"
"cpi %B [fördröjningstid], 0x02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [fördröjningstid] "+ & w" (fördröjningstid)
: [PINNUM_IN] "I" (PINNUM_IN));
ställa in pin - kanske inte bryr sig timing, om det inte verkar lägga till
mycket noggrannhet?
WAIT_UNTIL_INTERRUPT();
PORTD & = ~ PIN_OUT;
ASM)
"loopstart % =:" "\n\t"
"sbis 0x09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [fördröjningstid], 0x01" "\n\t"
"cpi %B [fördröjningstid], 0x02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [fördröjningstid] "+ & w" (fördröjningstid)
: [PINNUM_IN] "I" (PINNUM_IN));
running_average = (running_average-(running_average >> 4)) + (fördröjningstid >> 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;
} annat {
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.
}
} annat {
touchVal = 0;
}
återvända touchVal;
}

få kapacitiv touch input 5 och utgång 3
används för pitch bend
inline int getpitchbendtime()
{
statisk int running_average = 0;
statisk int running_min = 1024;
statisk int running_min_inc_count = 0;
statisk boolean initialise_running_min = sant;

unsigned int fördröjningstid = 0;
char PINNUM_OUT = 3;
char PINNUM_IN = 5;
char PIN_OUT = 1 << PINNUM_OUT;
char PIN_IN = 1 << PINNUM_IN;
göra säker ingångar / utgångar är sätta rätt
DDRD| = PIN_OUT;
DDRD & = ~ (PIN_IN);
WAIT_UNTIL_INTERRUPT();
PORTD| = PIN_OUT;
ASM flyktiga)
"loopstart % =:" "\n\t"
"sbic 0x09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [fördröjningstid], 0x01" "\n\t"
"cpi %B [fördröjningstid], 0x02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [fördröjningstid] "+ & w" (fördröjningstid)
: [PINNUM_IN] "I" (PINNUM_IN));
ställa in pin - kanske inte bryr sig timing, om det inte verkar lägga till
mycket noggrannhet?
WAIT_UNTIL_INTERRUPT();
PORTD & = ~ PIN_OUT;
ASM)
"loopstart % =:" "\n\t"
"sbis 0x09, % [PINNUM_IN]" "\n\t"
"rjmp outloop % =" "\n\t"
"adiw % [fördröjningstid], 0x01" "\n\t"
"cpi %B [fördröjningstid], 0x02" "\n\t"
"brne loopstart % =" "\n\t"
"outloop % =:" "\n\t"
: [fördröjningstid] "+ & w" (fördröjningstid)
: [PINNUM_IN] "I" (PINNUM_IN));
running_average = (running_average-(running_average >> 4)) + (fördröjningstid >> 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;
} annat {
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.
}
} annat {
touchVal = 0;
}
återvända 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 * /)
{
oscillatorer [0] .phaseStep = NOTE_FREQS [baseNote];
oscillatorer [1] .phaseStep = NOTE_FREQS [baseNote + 2];
oscillatorer [2] .phaseStep = NOTE_FREQS [baseNote + 4];
oscillatorer [3] .phaseStep = NOTE_FREQS [baseNote + 5];
oscillatorer [4] .phaseStep = NOTE_FREQS [baseNote + 7];
oscillatorer [5] .phaseStep = NOTE_FREQS [baseNote + 9];
oscillatorer [6] .phaseStep = NOTE_FREQS [baseNote + 11];
oscillatorer [7] .phaseStep = NOTE_FREQS [baseNote + 12];

om (pitchBendVal < -99)
{
pitchBendVal =-99;
} annat if(pitchBendVal>99)
{
pitchBendVal = 99.
}
Serial.Print("*");
Serial.Print(pitchBendVal);
unsigned int pitchBendMultiplier = pitchBendTable [pitchBendVal + 100];
Serial.Print(":");
Serial.Print(pitchBendMultiplier);
för (int c = 0; c < 8; c ++)
{
multiplicera 2 16-bitars nummer tillsammans och SKIFT 8 utan precision förlust
kräver assembler verkligen
volatile unsigned char zeroReg = 0;
volatile unsigned int multipliedCounter = oscillatorer [c] .phaseStep;
ASM flyktiga
(
hög byte mult tillsammans = övre byte
"ldi %A [outVal], 0" "\n\t"
"mul %B [phaseStep], %B [pitchBend]" "\n\t"
"mov %B [outVal], r0" "\n\t"
Ignorera overflow i r1 (bör aldrig overflow)
låga byte * övre byte -> båda byte
"mul %A [phaseStep], %B [pitchBend]" "\n\t"
"Lägg till %A [outVal], r0" "\n\t"
bära in övre byte
"adc %B [outVal], r1" "\n\t"
hög byte * låg byte -> båda byte
"mul %B [phaseStep], administrationskostnader [pitchBend]" "\n\t"
"Lägg till %A [outVal], r0" "\n\t"
bära in övre byte
"adc %B [outVal], r1" "\n\t"
låga byte * låg byte -> runda
"mul %A [phaseStep], administrationskostnader [pitchBend]" "\n\t"
adc nedan är att runda upp baserat på hög bithastighet för low * låg:
"adc %A [outVal], r1" "\n\t"
"adc %B [outVal] % [noll]" "\n\t"
"clr r1" "\n\t"
: [outVal] "= & d" (multipliedCounter)
: [phaseStep] "d" (oscillatorer [c] .phaseStep), [pitchBend] "d" (pitchBendMultiplier), [noll] "d" (zeroReg)
: "r1", "r0"
);
oscillatorer [c] .phaseStep = multipliedCounter;
}
Serial.Print(":");
Serial.Print(NOTE_FREQS[baseNote]);
Serial.Print(":");
Serial.println(oscillators[0].phaseStep);

}

void setup()
{
Serial.BEGIN(9600); ansluta till den seriella porten
#ifndef FILTER_LPF_NONE
setFilter (127, 0);
#endif

pinMode (11, OUTPUT); pin11 = PWM-utgång / frekvens output

setupNoteFrequencies(12,0);

för (int c = 0; c < 8; c ++)
{
oscillatorer [c] .volume = 0;
}

Setup_timer2();

Inaktivera avbrott för att undvika timing distorsion
CBI (TIMSK0, TOIE0); Inaktivera Timer0!!! Delay() finns nu inte
SBI (TIMSK2, TOIE2); Aktivera Timer2 avbryta

kalibrera de Kolfiberförstärkt nyckelvärdena

för (int x = 0; x < 1024; x ++)
{
getNoteKeys(true);
int steg = loopSteps;
WAIT_UNTIL_INTERRUPT();
int afterSteps = loopSteps;
Serial.println(afterSteps-Steps);
}
testmönster 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};
för (int Obs = 0; Observera < sizeof(notes)/sizeof(byte);note++)
{

int noteCount = 0;
för (int c = 0; c < 8; c ++)
{
om (anteckningar [not] & (1 << c))
{
noteCount + = 1;
}
}
för (int c = 0; c < 8; c ++)
{
om (anteckningar [not] & (1 << c))
{
oscillatorer [c] .volume = 63/noteCount;
} annat
{
oscillatorer [c] .volume = 0;
}
}
för (int c = 0; c < 50, c ++)
{
kan också hålla kalibrera här
NB: varje kalibrering slinga = minst 1 avbrott

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

}
}
#else
bara ett pip om du vill visa kalibreringen sker
oscillatorer [0] .volume = 63.
för (int c = 0; c < 20; c ++)
{
WAIT_UNTIL_INTERRUPT();
}
oscillatorer [0] .volume = 63.

#endif
Serial.println("Calibrations:");
för (int c = 0; c < 8; c ++)
{
Serial.Print(c);
Serial.Print(":");
Serial.println(calibrationThresholds[c]);
}

}

void loop()
{
Vi håller en lista över "raw" volymer - och sänk volymen om ett ackord tar > 64 volym total
Detta är att låta chording utan att minska volymen av enstaka anteckningar
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;
osignerade curStep = loopStepsHigh;
While(1)
{
lastStep = curStep;
curStep = loopStepsHigh;
Obs: timer fungerar inte i den här koden (avbryter inaktiverat / hastigheter förändrats), så inte ens tänka på kallelse: delay(), millis / micros etc.
varje loopstep är ungefär 31250 / sekund
denna huvudloop kommer få kallas en gång varje 3 eller 4 prover om den seriella produktionen är vände bort, kanske långsammare annars

int liveNotes=getNoteKeys();
Vi är rätt efter ett avbrott (som loopStep har bara ökats)
så vi bör ha tillräckligt med tid att göra de capacitative viktiga kontrollerna

IF(lastStep!=curStep)
{
int totalVolume = 0;
för (int c = 0; c < 8; c ++)
{
om ((liveNotes & (1 << c)) == 0)
{
rawVolumes [c]-= DECAY*(curStep-lastStep);
om (rawVolumes [c] < 0) rawVolumes [c] = 0;
IF(SERIAL_OUT)Serial.Print(".");
}
annat
{
rawVolumes [c] += ATTACK*(curStep-lastStep);
om (rawVolumes [c] > 63) rawVolumes [c] = 63.
IF(SERIAL_OUT)Serial.Print(c);
}
totalVolume += rawVolumes [c];
}
WAIT_UNTIL_INTERRUPT();
om (totalVolume < 64)
{
för (int c = 0; c < 8; c ++)
{
oscillatorer [c] .volume = rawVolumes [c];
}
} annat
{
totala volymen för mycket, förminska för att undvika klippning
för (int c = 0; c < 8; c ++)
{
oscillatorer [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;
om (filterSweep > = MAX_SWEEP)
{
filterSweep = MAX_SWEEP;
sweepDir =-sweepDir;
}
annars om (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());

Vi är rätt efter ett avbrott igen (som loopStep har bara ökats)
så vi bör ha tillräckligt med tid att kolla pitch bend kapacitans utan att gå över ett annat prov, är timing ganska viktigt här
måste balansera med ett tillräckligt stort motstånd för att få anständigt fjärranalys avstånd med tar för lång tid att prova
Kolla pitch bend indata

}
}
//******************************************************************
timer2 inställningar
Ställ in prscaler på 1, PWM läge att gradvis rätt PWM, 16000000/510 = 31372.55 Hz klocka
void Setup_timer2() {

Timer2 klocka Prescaler till: 1
SBI (TCCR2B, CS20);
CBI (TCCR2B, CS21);
CBI (TCCR2B, CS22);

Timer2 inställt PWM på fas rätt PWM
CBI (TCCR2A, COM2A0); Rensa jämför Match
SBI (TCCR2A, COM2A1);

SBI (TCCR2A, WGM20); Läge 1 / fas rätt PWM
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;
flyktiga char filtCoeffB1 = 127;
volatile unsigned char filtCoeffB2 = 255;
#endif
#ifdef FILTER_LPF_HACK
hackade lågpassfilter - 2 polig resonant-
en += 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 resonans)
{
unsigned char tempReg = 0, tempReg2 = 0;
ASM flyktiga ("ldi % [tempReg], 0xff" "\n\t"
"sub % [tempReg], [filtF]" "\n\t"
"lsr % [tempReg]" "\n\t"
"ldi % [tempReg2], 0x04" "\n\t"
"Lägg % [tempReg], [tempReg2]" "\n\t"
"sub % [reso], [tempReg]" "\n\t"
"brcc Res_Overflow % =" "\n\t"
"ldi % [reso], 0x00" "\n\t"
"Res_Overflow % =:" "\n\t"
"mov % [filtQ], [reso]" "\n\t"
: [tempReg] "= & d" (tempReg), [tempReg2] "= & d" (tempReg2), [filtQ] "= & d" (filterQ): [reso] "d" (resonans), [filtF] "d" (filterF));
}

inline void setFilter (unsigned char f, unsigned char resonans)
{
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))

oscillator huvudloop (öka wavetable pekaren och lägga det till register som utdata)
13 instruktioner - bör ta 14 processorcykler enligt databladet
i teorin tror jag att detta innebär att varje oscillator bör ta 1,5% av cpu
(plus en konstant overhead för avbrott kallar etc.)
Obs: detta brukade göra alla stepvolume laddar nära början, men de är nu interleaved i den
kod, detta beror på att ldd (load med offset) tar 2 instruktioner,
kontra ld, + 1 (load med post ökning) och st, + 1 som är 1 instruktion - kan vi göra detta eftersom:
//
en) steg (som inte behöver lagras tillbaka) är i minnet innan den
fasen ackumulator (som behöver lagras tillbaka när steget läggs
//
b) fas assumulator lagras i låg byte, hög byteordningen, menande att vi
kan lägga till första byte tillsammans, sedan lagra det byte uppräkning pekaren,
sedan ladda den höga byten, lägga till hög byte tillsammans och lagra uppräkning pekaren
//
Jag tror detta är det minsta antalet operationer möjligt att koda detta oscillator i, eftersom
1) det finns 6 belastning som krävs (att läsa in stepHigh/låg, phaseH/L, volym och värde från vågen)
2) det är 2 lägga till operationer som krävs för att lägga till fas ackumulatorn
3) finns det 2 butik åtgärder krävs för att spara fas ackumulatorn
Är 4) där 1 multiplicera (2 instruktion cykler) krävs för att göra volymen
5) finns det 2 lägga till operationer som krävs för att lägga till i den slutliga utmatningen
//
6 + 2 + 2 + 2 + 2 = 14 instruktion cykler

#define OSCILLATOR_ASM \
/ * Ladda fas steg och volym * / \
"ld %A [tempStep], % en [stepVolume] +" "\n\t" \
"ld %B [tempStep], % en [stepVolume] +" "\n\t" \
"ld % [tempVolume], [stepVolume] +" "\n\t" \
/ * belastning fasen ackumulator - övre byte går rak * / \
/ * i våg lookup vektorn (wave är på 256 byte gräns * / \
/ * så vi kan göra detta utan att någon lägger * / \
/ * Fasen läggs mellan de två lasterna, som laddar med offset är långsammare än
bara en normal belastning
*/\
"ld %A [tempPhaseLow], % en [stepVolume]" "\n\t" \
/ * Lägg till fas steg låg * / \
"Lägg % [tempPhaseLow], %A [tempStep]" "\n\t"\
/ * lagra fas ackumulator låg * / \
"st %a [stepVolume] + % [tempPhaseLow]" "\n\t" \
/ * Ladda fas ackumulator hög * / \
"ld %A [waveBase], % en [stepVolume]" "\n\t" \
/ * lägga till fas steg höga - med bär från Lägg till ovan * / \
"adc %A [waveBase], %B [tempStep]" "\n\t"\
/ * lagra fas steg hög * / \
"st %a [stepVolume] + %A [waveBase]" "\n\t" \
/ * nu sökning från våg - övre byte = våg pekare, låg byte = offset * / \
"ld % [tempPhaseLow], [waveBase]" "\n\t" \
/ * nu multiplicera med volym * / \
"muls % [tempPhaseLow], [tempVolume]" "\n\t" \
/ * r0 innehåller nu ett prov - Lägg till det att mata värde * / \
"Lägg till %A [outValue], r0" "\n\t" \
"adc %B [outValue], r1" "\n\t" \
/ * gå till nästa oscillator - stepVolume pekar på nästa * / \
/ * oscillatorn redan * / \

//******************************************************************
Timer2 avbryta tjänsten på 31372,550 KHz = 32uSec
Detta är timebase REFCLOCK för DDS generator
FOUT = (M (REFCLK)) / (2 exp 32)
runtime:?
ISR(TIMER2_OVF_vect) {

nu ställa in nästa värde
denna slinga tar ungefär 172 cykler (214 inklusive de push/pop) - vi har 510, så ungefär 50% av processor kommer reservdelar för icke-audio uppgifter
lågpass filtret tar även några cykler

int outValue;

Tips:
X = oscillator fas ackumulator
Y = oscillator steg och volym
Z = våg pos - lägga till om du vill basera
int tempStep = 0;
char tempPhaseLow = 0, tempVolume = 0;
int tempWaveBase = 0;
ASM flyktiga)
"ldi %A [outValue], 0" "\n\t"
"ldi %B [outValue], 0" "\n\t"
oscillator 0
avkommentera koden nedan för att kontrollera
att registren inte får dubbel tilldelade
/ * "lds %A [outValue], 0x00" "\n\t"
"lds %B [outValue], 0x01" "\n\t"
"lds %A [tempPhaseLow], 0x02" "\n\t"
"lds %B [tempPhase], 0x03" "\n\t"
"lds %A [tempStep], 0x04" "\n\t"
"lds %B [tempStep], 0x05" "\n\t"
"lds % [tempVolume], 0x06" "\n\t"
"lds % [noll], 0x07" "\n\t"
"lds %A [tempWaveBase], 0x08" "\n\t"
"lds %B [tempWaveBase], 0x09" "\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
:
utgångar
[tempPhaseLow] "= & d" (tempPhaseLow),
[tempStep] "= & d" (tempStep),
[tempVolume] "= & d" (tempVolume),
[outValue] "= & d" (outValue)
:
ingångar
[stepVolume] "y" (& oscillators[0].phaseStep),
[waveBase] "z" (256 * (((unsigned int) curWave) >> 8))
:
andra register vi clobber (genom att göra uppförökningar)
"r1"
);

på denna punkt outValue = oscillator värde
Det är för närvarande maxade till full volym / 4
att tillåta vissa utrymme för filtrering

#ifdef FILTER_LPF_HACK

ett lågpassfilter baserat på en från MeeBlip (http://meeblip.noisepages.com)
en += f*((in-a) + q*(a-b)
b + = f * (a-b)
outValue >> = 3;
började på 4700
4686
int tempReg, tempReg2 = 0;
unsigned char zeroRegFilt = 0;
de-volatilisati
unsigned char filtF = filterF;
unsigned char filtQ = filterQ;
ASM flyktiga)
"sub %A [outVal], administrationskostnader [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 = (i - filtA)
"mov %A [tempReg], administrationskostnader [filtA]" "\n\t"
"mov %B [tempReg], %B [filtA]" "\n\t"
"sub %A [tempReg], administrationskostnader [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"
"Lägg till %A [tempReg2], r1" "\n\t"
"adc %B [tempReg2] % [noll]" "\n\t"
"rol r0" "\n\t"
"brcc No_Round1% =" "\n\t"
"inkl %A [tempReg2]" "\n\t"
"No_Round1% =:" "\n\t"
på denna punkt tempReg2 = (a-b) * Q (skiftat på lämpligt sätt och rundade)
"clc" "\n\t"
"Amilia %A [tempReg2]" "\n\t"
"rol %B [tempReg2]" "\n\t"
"clc" "\n\t"
"Amilia %A [tempReg2]" "\n\t"
"rol %B [tempReg2]" "\n\t"
tempReg2 = (a-b) * Q * 4
"Lägg till %A [outVal], administrationskostnader [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) - klippt etc
"mulsu %B [outVal] % [filtF]" "\n\t"
"movw %A [tempReg], r0" "\n\t"
"mul %A [outVal] % [filtF]" "\n\t"
"Lägg till %A [tempReg], r1" "\n\t"
"adc %B [tempReg], % [noll]" "\n\t"
"rol r0" "\n\t"
"brcc No_Round2% =" "\n\t"
"inkl %A [tempReg]" "\n\t"
tempReg = f * ((in-a) + (a-b) * (Q >> 8) * 4)
"No_Round2% =:" "\n\t"
"Lägg till %A [filtA], administrationskostnader [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"
nu beräkna B = f * (a - b)

"mov %A [tempReg], administrationskostnader [filtA]" "\n\t"
"mov %B [tempReg], %B [filtA]" "\n\t"
"sub %A [tempReg], administrationskostnader [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"
"Lägg till %A [tempReg2], r1" "\n\t"
"adc %B [tempReg2] % [noll]" "\n\t"
tempReg2 = f*(a-b)
"Lägg till %A [filtB], administrationskostnader [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"
nu b = b+f*(a-b)
"mov %A [outVal], administrationskostnader [filtB]" "\n\t"
"mov %B [outVal], %B [filtB]" "\n\t"

multiplicera outval av 4 och klipp
"Lägg till %A [outVal], administrationskostnader [filtB]" "\n\t"
"adc %B [outVal], %B [filtB]" "\n\t"
"brbs 3, Overflow_End % =" "\n\t"

"Lägg till %A [outVal], administrationskostnader [filtB]" "\n\t"
"adc %B [outVal], %B [filtB]" "\n\t"
"brbs 3, Overflow_End % =" "\n\t"

"Lägg till %A [outVal], administrationskostnader [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 = ((osignerade int)(outValue)) >> 8.
valOut += 128;
OCR2A = (byte) valOut;
"Johan %B [outVal], 0x80" "\n\t"
"sts 0x00b3, %B [outVal]" "\n\t"
ovanlig linjen nedan för att se de register anslag
/*
"lds %A [filtA], 0x01" "\n\t"
"lds %B [filtA], 0x02" "\n\t"
"lds %A [filtB], 0x03" "\n\t"
"lds %B [filtB], 0x04" "\n\t"
"lds % [filtQ], 0x05" "\n\t"
"lds % [filtF], 0x06" "\n\t"
"lds %A [outVal], 0x07" "\n\t"
"lds %B [outVal], 0x08" "\n\t"
"lds %A [tempReg], 0x09" "\n\t"
"lds %B [tempReg], 0x0a" "\n\t"
"lds %A [tempReg2], 0x0b" "\n\t"
"lds %B [tempReg2], 0x0c" "\n\t"
"lds % [noll], 0x0d" "\n\t"*/
:
utgångar / läsa/skriva argument
[filtA] "+ & w" (filterA),
[filtB] "+ & w" (filterB),
[tempReg] "= & en" (tempReg),
[tempReg2] "= & d" (tempReg2)
:
[filtQ] "a" (filtQ),
[filtF] "a" (filtF),
[outVal] "a" outValue (),
[NOLL] "d" (zeroRegFilt)
ingångar
: "r1");

#endif

produktionen sker i filtret assembler kod om filtren är på
annars mata vi den för hand här
#ifdef FILTER_LPF_NONE
full vinst
outValue * = 4;
vid denna punkt, outValue är en 16-bitars signerad version av vad vi vill dvs. 0 -> 32767,-32768- > -1 (0xffff)
Vi vill ha 0 -> 32767 för att gå till 32768-65535 och-32768 -> -1 att gå till 0-32767, då vi vill bara den övre byten
ta övre byte, och sedan lägga till 128, sedan till osignerade. (Unsigned int) i den nedan är att undvika att behöva skifta (ie.just tar övre byte)
char valOut = ((osignerade int)(outValue)) >> 8.
valOut += 128;
OCR2A = (byte) valOut;
#endif
öka loop steg counter (och hög counter)
dessa används eftersom vi stoppa timern
avbryta igång, så har inget annat sätt att berätta tid
denna asm behövs förmodligen inte riktigt, men det sparar ca 10 instruktioner
eftersom variabler måste vara flyktiga
ASM)
"inc % [loopSteps]" "\n\t"
"brbc 1, loopend % =" "\n\t"
"inkl %A [loopStepsHigh]" "\n\t"
"brbc 1, loopend % =" "\n\t"
"inkl %B [loopStepsHigh]" "\n\t"
"loopend % =:" "\n\t"
: [loopSteps] "+" (loopSteps), [loopStepsHigh] "+" (loopStepsHigh):);
}

Se Steg
Relaterade Ämnen

Arduino syntet

Arduino kan mata ut ljud via ett bibliotek som har utvecklats som kallas Tonen bibliotek.Genom att skapa ett gränssnitt och ett program som kan ringa vissa värden för att vara utdata till en ljudutgång, är Arduino syntet ett robust verktyg för att gö...

Octo-ljus: LED kamera Ring

Octo-ljuset är en kamera ring lampa som består av LED ljus remsor. Det är billigt att göra och perfekt för nybörjare makro fotografi och video!Denna lampa är utmärkt vid översvämningar scener med enhetliga ljus, som mjukar upp hårda skuggor och tar b...

Naturliga syntet (plast gaffel skulptur)

I detta Instructable Visa jag dig hur du skapar naturliga syntet plast gaffel skulpturer. Naturliga syntet är plast bestick skulpturer gjorda av repurposed material och värme. Du kan komma igång att skapa dina egna skulpturer i bara några minuter. Na...

Octo-squid

Freestyled denna lilla kille, som min man påpekade är båda och varken en bläckfisk eller en bläckfisk.Kul ändå, och hemska ska han visas i din dusch!...

Utbildning pojke och flicka läromedel

hälsningar Karl utbildning älska instuctavillians! Idag kommer vi att undersöka hur man skapar en rolig interaktivt lärande verktyg för studenter att använda quiz sig själva och varandra och ge en händer på lärande aktivitet för att hjälpa dem inform...

Arctic tossor

vattentät päls fodrad baby tossor tillverkade av återvunnet material.Material som används i projektet:Vinyl (från en gammal uppblåsbar säng)Päls (från en gammal räv ruff)Industriell styrka trådHampa garnMässing GrommetsVerktyg:KnivSaxSmå och stora nå...

Burning skor

Tja var min 12 år gammal med hans vedeldning kit för första gången på ett skolprojekt när jag var på instructables och såg denna tävling. Kismet-vi alla älskar platsen men har aldrig försökt utstationering. Så han är alla glada (men inte fyllt) jag v...

Hur du gör din egen bläckfisk Plushie

Någonsin velat ha en bläckfisk vän till din egen utan rädsla för att få vatten över hela platsen eller det fly från din fisk tank med lätthet? Tja, nu kan du! Inom detta projekt är enkel stammen till göra din alldeles egna Octo-kamrat!Steg 1:Vad du b...

Skapa regnbågar med is!

Jag älskar att färga mina egna kläder och göra hand-färgat tyg för min täcken! Jag har kommit över en verkligen lätt teknik som vem som helst kan utföra med bra resultat! Denna metod för färgning kan även vara gjort med barn-bara vara säker på att al...

Hur man färga garn med Kool Aid

drog ut ye olde Kool-Aid igen. Vad kul!! Kool-Aid gör en stor färg eftersom det är färg snabb och säker mat så du kan använda oavsett kastruller och stekpannor du har i köket. Ingen specialutrustning som behövs. Plus, det är kul för barnen att göra!L...

Tryck motstå färgning (itajime)

Itajime är en japansk metod för att skapa mönster vid färgning, något som liknar tie-dye. Men i stället för sträng eller tråd för att komprimera tyget på platser för att förhindra dye sprit från genomträngande, fasta objekt som kallas motstår spänns...

Snabb och smutsiga "Avskärma att skriva ut"

Screentryck är awesome: det kan du skriva ut samma design flera gånger och det ger dig rena linjer med fina detaljer och öar. Men om du behöver bara göra en av något - en dekal på en kostym, en dum t-shirt, oavsett - screentryck kan vara mycket mer ä...

Hemgjord flamskyddsmedel

Detta är min första instructable, så snälla ha tålamod med mig. Många gånger under byggnad / åter purposing objekt för olika projekt har jag stött på ett behov av att lägga till någon form av Flamskydd i vissa delar av projektet.Medan denna procedur...

Aluminium sport X copter ramkonstruktion för styrka, lightwieght, och lätt.

Detta helt i aluminium X copter är starka, lätta och enklaste att reparera på alla ramar. Eftersom bitarna görs av platta aluminium, även om du kraschar det riktigt hårt, det bara blir böjda, du kan platta det tillbaka ut med en hammare. Det minskar...

Bleach bad och andra billiga eksem åtgärder

eksem drabbade är lätt märken. När du är klåda att krypa ur din hud verkar en $100 flaska orm olja vara ett fynd! Marknadsförare främja exotiska och dyra ingredienser på grundval av osynligt problem trådar av vetenskapliga bevis. Krämer som innehålle...

Hur jag blev en tvättpåse till ett flöde genom masken bag

jag inspirerades av Amy Youngs instructable om att göra en filt version av ett flöde genom masken inn. Men jag har inte alla verktyg för att göra trä arbete att ramen kräver, och jag är billigt. Så när du är ute shopping och letar efter ett billigare...

Att göra en ficka pistol rengöringssats

Denna handledning kommer att berätta hur man gör en mycket kompakt rengöring kit som kommer att hantera grundläggande rengöring för de flesta skjutvapen, liksom många airguns. Främsta kännetecken som gör detta kit kompakt är användningen av en sträng...

Designa och bygga en "akustisk" synthesizer

för min praktikplats på Skapa digitalmusik/Meeblip jag har skapat ganska kul liten synthesizer. Det här är tänkt att vara mer flexibla än andra synthesizer genom att göra det helt oberoende. Det är batteridriven, har egen förstärkare/högtalare och st...

Arduino flöjt Synth

Innan du skapar denna flöjt synth, byggde jag en annan Arduino synthesizer med källkoden från en Instructable kallas postbox syntet. Jag satte modet inuti en gammal speldosa och wired en MIDI ingång för att kontrollera den. Det lät mycket bra och jag...