CSUSM FM Synth 2017 / Mbed 2 deprecated FMSynthCSUSM

Dependencies:   mbed

Fork of STM32FMSynth by Steven Clark

Committer:
davolfman
Date:
Fri Dec 15 04:50:56 2017 +0000
Revision:
23:7a9ff5230149
Parent:
22:0307adac8c35
Integration of main comments and added FastSin comments.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davolfman 0:b2f7400596ce 1 #include "mbed.h"
davolfman 3:83ac767f3a63 2 #include "sintable.h"
davolfman 0:b2f7400596ce 3
davolfman 9:86c0035f5321 4 AnalogOut outMono(PA_4);//Not labeled in the docs for the f401, but seems to be for all
davolfman 7:b0cd74923bc6 5 //AnalogOut DAC1(PA_5);
davolfman 0:b2f7400596ce 6
davolfman 9:86c0035f5321 7 AnalogIn inVol(PA_0);
davolfman 7:b0cd74923bc6 8 AnalogIn inModAmt(PA_1);
davolfman 6:9f8c8c3c111d 9 //AnalogIn ADC2(PA_2);//these are the uart pins!!
davolfman 6:9f8c8c3c111d 10 //AnalogIn ADC3(PA_3);//these are the uart pins!!
davolfman 0:b2f7400596ce 11 //AnalogIn ADC4(PA_4);//we're using these for output
davolfman 0:b2f7400596ce 12 //AnalogIn ADC5(PA_5);//we're using these for output
davolfman 9:86c0035f5321 13 AnalogIn inCarA(PA_6);
davolfman 9:86c0035f5321 14 AnalogIn inCarD(PA_7);
davolfman 0:b2f7400596ce 15 //AnalogIn ADC8(PB_0);//lets leave the 2 we aren't using in a single port
davolfman 0:b2f7400596ce 16 //AnalogIn ADC9(PB_1);//that way we know there's not ADCs on one of them
davolfman 9:86c0035f5321 17 AnalogIn inCarS(PC_0);
davolfman 9:86c0035f5321 18 AnalogIn inCarR(PC_1);
davolfman 9:86c0035f5321 19 AnalogIn inModA(PC_2);
davolfman 9:86c0035f5321 20 AnalogIn inModD(PC_3);
davolfman 9:86c0035f5321 21 AnalogIn inModS(PC_4);
davolfman 9:86c0035f5321 22 AnalogIn inModR(PC_5);
davolfman 0:b2f7400596ce 23
lenzi002 8:13b0594510de 24 //BusIn keyBank(PC_10, PC_11, PC_12, PC_13, PD_2, PH_1); old
lenzi002 8:13b0594510de 25 BusIn keyBank(PH_1, PD_2, PC_13, PC_12, PC_11, PC_10);
davolfman 7:b0cd74923bc6 26 BusOut bankSelect(PB_0, PB_1, PB_2, PB_3, PB_4, PB_5, PB_6, PB_7, PB_8);
davolfman 2:5454dee210ed 27 BusIn numerator(PA_8, PA_9, PA_10, PA_11);
davolfman 2:5454dee210ed 28 BusIn denominator(PA_12, PA_13, PA_14, PA_15);
davolfman 2:5454dee210ed 29
davolfman 16:c2f912cdd919 30 //Serial pc(USBTX, USBRX);
lenzi002 8:13b0594510de 31
davolfman 20:7ecec5738790 32 Ticker synthesisClock;// this object sets up an ISR to execute every given fraction of a second.
davolfman 0:b2f7400596ce 33
davolfman 20:7ecec5738790 34 #define numKeys 49// our keyboard includes from two octaves above middle c to two octaves below it
davolfman 0:b2f7400596ce 35
davolfman 4:1d2a699c95c7 36 //constants
davolfman 20:7ecec5738790 37
davolfman 20:7ecec5738790 38 //These are the pitches of the notes of our keyboard in hz * int16_max / sampling rate(20khz)
davolfman 16:c2f912cdd919 39 const int carrierIncrements[] = {214, 227, 240, 254, 270, 286, 303, 321, 340,
davolfman 16:c2f912cdd919 40 360, 381, 404, 428, 454, 481, 509, 540, 572, 606, 642, 680, 720, 763, 809,
davolfman 16:c2f912cdd919 41 857, 908, 962, 1019, 1080, 1144, 1212, 1284, 1360, 1441, 1527, 1618, 1714,
davolfman 16:c2f912cdd919 42 1816, 1924, 2039, 2160, 2288, 2424, 2568, 2721, 2883, 3055, 3236, 3429};
davolfman 20:7ecec5738790 43
davolfman 20:7ecec5738790 44 //The maximum value of our envelopes is int16_max
davolfman 15:34ba7c2ef718 45 #define attackLimit 0xFFFF
davolfman 20:7ecec5738790 46
davolfman 20:7ecec5738790 47 //this gives us a value of pi to multiply things by
davolfman 10:59c829586a4f 48 #define U_PI 3.14159265358979
davolfman 20:7ecec5738790 49
davolfman 0:b2f7400596ce 50 //non-constants
davolfman 1:f3350a372732 51 //Most of these will be recalculated or reset on every input cycle of the main
davolfman 1:f3350a372732 52 // loop, as appropriate
davolfman 20:7ecec5738790 53
davolfman 20:7ecec5738790 54 int FMmult = 1;//The modulator pitch is FMmult * the base carrier pitch for that note
davolfman 20:7ecec5738790 55 int Volume = 0xffff;//the maximum volume to start, our number format is fixed 16 bits of fractional
davolfman 20:7ecec5738790 56 // inside a 32bit integer usually only in that fractional allowing for
davolfman 20:7ecec5738790 57 // integer multiplications and shifts to recenter instead of floating
davolfman 20:7ecec5738790 58 // -point arithmetic
davolfman 20:7ecec5738790 59 int modVol = 0x2000;//the amount of modulation to apply, most useful relatively low
davolfman 20:7ecec5738790 60 int64_t keyboard = 0;//our key state is stored as bit flags in the lower 49 bits of this
davolfman 20:7ecec5738790 61 int64_t modattack = 0x1ffffffffffff;//similar to keyboard, if the corrsponding bit is
davolfman 20:7ecec5738790 62 // zero the envelope for that bit is in decay or sustain instead of attack
davolfman 18:4992aa537387 63 int64_t carattack = 0x1ffffffffffff;
davolfman 20:7ecec5738790 64 int carrierPhases[numKeys];//store the phases of the notes in between samplings
davolfman 0:b2f7400596ce 65 int modulatorPhases[numKeys];
davolfman 20:7ecec5738790 66 int envelopeAmpsC[numKeys];//store the amplitudes of the envelopes in between samplings
davolfman 1:f3350a372732 67 int envelopeAmpsM[numKeys];
davolfman 1:f3350a372732 68
davolfman 20:7ecec5738790 69 //the envelope parameters for synthesis are read from these registers
davolfman 20:7ecec5738790 70 int modA = 0xffff;//modulator attack rate
davolfman 20:7ecec5738790 71 int modD = 0xffff;//modulator decay rate
davolfman 20:7ecec5738790 72 int modS = 0;//modulator sustain level
davolfman 20:7ecec5738790 73 int modR = 0xffff;//modulator release rate
davolfman 20:7ecec5738790 74 int carA = 0xffff;//carrier attack rate
davolfman 20:7ecec5738790 75 int carD = 0xffff;//carrier decay rate
davolfman 20:7ecec5738790 76 int carS = 0;//carrier sustain level
davolfman 20:7ecec5738790 77 int carR = 0xffff;//carrier release level
davolfman 1:f3350a372732 78
davolfman 23:7a9ff5230149 79 ///@brief Converts a phase of period 2^16 into a sine value
davolfman 23:7a9ff5230149 80 ///@phase The phase to calculate the sine of in phase/65536 * 2 pi radians
davolfman 23:7a9ff5230149 81 ///@return the sine as a signed 16 bit fractonal part inside a 32 bit int
davolfman 1:f3350a372732 82 int fastSin(const int phase){
davolfman 23:7a9ff5230149 83 //the middle 12 bits are used to index into a lookuptable of pre computed sines
davolfman 5:ac5c4bd3ef4b 84 int index = (phase & 0x3ffc) >> 2;
davolfman 23:7a9ff5230149 85
davolfman 23:7a9ff5230149 86 //we used linear interpolation given out bottom 2 bits to turn a 2^12 Look Up Table into a 2^14 LUT
davolfman 5:ac5c4bd3ef4b 87 int subindex = phase & 0x3;
davolfman 23:7a9ff5230149 88
davolfman 23:7a9ff5230149 89 //We use mirroring of a quarter wave of sine so we only have to store a quarter of the samples again
davolfman 5:ac5c4bd3ef4b 90 int quadrant = (phase & 0xc000) >> 14;
davolfman 3:83ac767f3a63 91 int sum = 0;
davolfman 23:7a9ff5230149 92 switch (quadrant) {//perform the mirroring and add the memebers of the weighted average for interpolation
davolfman 5:ac5c4bd3ef4b 93 case 0:
davolfman 7:b0cd74923bc6 94 sum += (4 - subindex) * sinTable[index];
davolfman 7:b0cd74923bc6 95 sum += subindex * sinTable[index+1];
davolfman 5:ac5c4bd3ef4b 96 break;
davolfman 5:ac5c4bd3ef4b 97 case 1:
davolfman 7:b0cd74923bc6 98 sum += (4 - subindex) * sinTable[1+4095-index];
davolfman 7:b0cd74923bc6 99 sum += subindex * sinTable[4095-index];
davolfman 5:ac5c4bd3ef4b 100 break;
davolfman 5:ac5c4bd3ef4b 101 case 2:
davolfman 7:b0cd74923bc6 102 sum -= (4 - subindex) * sinTable[index];
davolfman 7:b0cd74923bc6 103 sum -= subindex * sinTable[index+1];
davolfman 5:ac5c4bd3ef4b 104 break;
davolfman 5:ac5c4bd3ef4b 105 case 3:
davolfman 7:b0cd74923bc6 106 sum -= (4 - subindex) * sinTable[1+4095-index];
davolfman 7:b0cd74923bc6 107 sum -= subindex * sinTable[4095-index];
davolfman 5:ac5c4bd3ef4b 108 break;
davolfman 5:ac5c4bd3ef4b 109 }
davolfman 23:7a9ff5230149 110 sum = sum >> 2;//divide the weighted sum of the neighborign samples by 4
davolfman 23:7a9ff5230149 111 //to get a weighted average
davolfman 3:83ac767f3a63 112
davolfman 3:83ac767f3a63 113 return sum;
davolfman 1:f3350a372732 114 }
davolfman 0:b2f7400596ce 115
davolfman 21:6dc8d091e878 116 ///@brief calculates one audio sample given the keyboard state and envelope paramaters and passes it to the DAC
davolfman 1:f3350a372732 117 void synthesize(){
davolfman 21:6dc8d091e878 118 int wave = 0;// holds the sample being constructed.
davolfman 21:6dc8d091e878 119 int subsignal;// the subsample for one note
davolfman 21:6dc8d091e878 120 int64_t keymask;// holds a mask of the current note for easy access to keyboard and attack registers
davolfman 21:6dc8d091e878 121
davolfman 21:6dc8d091e878 122 //for all keys
davolfman 15:34ba7c2ef718 123 for(int64_t i = 0; i < numKeys; ++i){
davolfman 21:6dc8d091e878 124 keymask = 1ll << i;//set the key mask
davolfman 15:34ba7c2ef718 125
davolfman 21:6dc8d091e878 126 if(!(keymask & keyboard)){//if the key is NOT pressed
davolfman 21:6dc8d091e878 127 carattack |= keymask;//allow attack the next time it is
davolfman 12:3a1e7fde5040 128 modattack |= keymask;
davolfman 15:34ba7c2ef718 129
davolfman 21:6dc8d091e878 130 //if envelope is still positive, decrement by decay rate
davolfman 15:34ba7c2ef718 131 if(envelopeAmpsC[i] > 0){
davolfman 15:34ba7c2ef718 132 envelopeAmpsC[i] -= carR;
davolfman 15:34ba7c2ef718 133 }
davolfman 15:34ba7c2ef718 134 if(envelopeAmpsM[i] > 0){
davolfman 18:4992aa537387 135 envelopeAmpsM[i] -= modR;
davolfman 15:34ba7c2ef718 136 }
davolfman 21:6dc8d091e878 137
davolfman 21:6dc8d091e878 138 }else{//if the key IS pressed
davolfman 21:6dc8d091e878 139
davolfman 21:6dc8d091e878 140 if(envelopeAmpsC[i] <= 0){//if this key was silent before,
davolfman 21:6dc8d091e878 141 carrierPhases[i] = 0;//reset the wave states
davolfman 21:6dc8d091e878 142 modulatorPhases[i] = 0;//this should prevent frequency drift from stopped FM
davolfman 18:4992aa537387 143 envelopeAmpsM[i] = 0;
davolfman 21:6dc8d091e878 144 envelopeAmpsC[i] = 1;//only do it once
davolfman 11:286386c0db40 145 }
davolfman 21:6dc8d091e878 146
davolfman 21:6dc8d091e878 147 //if carrier has not left attack phase
davolfman 15:34ba7c2ef718 148 if(keymask & carattack){
davolfman 21:6dc8d091e878 149 //add attack rate to envelope if not already maximised
davolfman 15:34ba7c2ef718 150 if(envelopeAmpsC[i] < attackLimit ){
davolfman 15:34ba7c2ef718 151 envelopeAmpsC[i] += carA;
davolfman 21:6dc8d091e878 152 }else{//otherwise clip to maximum and leave attack pahse
davolfman 15:34ba7c2ef718 153 envelopeAmpsC[i] = attackLimit;
davolfman 15:34ba7c2ef718 154 carattack &= ~keymask;
davolfman 15:34ba7c2ef718 155 }
davolfman 21:6dc8d091e878 156 }else{//if in decay/sustain
davolfman 21:6dc8d091e878 157 if(envelopeAmpsC[i] > carS){//subtract the decay rate if above sustain level
davolfman 15:34ba7c2ef718 158 envelopeAmpsC[i] -= carD;
davolfman 15:34ba7c2ef718 159 }
davolfman 15:34ba7c2ef718 160 }
davolfman 15:34ba7c2ef718 161
davolfman 21:6dc8d091e878 162 //do all that again for the modulator envelope
davolfman 15:34ba7c2ef718 163 if(keymask & modattack){
davolfman 15:34ba7c2ef718 164 if(envelopeAmpsM[i] < attackLimit){
davolfman 15:34ba7c2ef718 165 envelopeAmpsM[i] += modA;
davolfman 15:34ba7c2ef718 166 }else{
davolfman 15:34ba7c2ef718 167 envelopeAmpsM[i] = attackLimit;
davolfman 18:4992aa537387 168 modattack &= ~keymask;
davolfman 15:34ba7c2ef718 169 }
davolfman 15:34ba7c2ef718 170 }else{
davolfman 15:34ba7c2ef718 171 if(envelopeAmpsM[i] > modS){
davolfman 15:34ba7c2ef718 172 envelopeAmpsM[i] -= modD;
davolfman 15:34ba7c2ef718 173 }
davolfman 15:34ba7c2ef718 174 }
davolfman 15:34ba7c2ef718 175
davolfman 22:0307adac8c35 176 }
davolfman 22:0307adac8c35 177
davolfman 22:0307adac8c35 178 //If this subsignal is not silent
davolfman 22:0307adac8c35 179 if(envelopeAmpsC[i] > 0){
davolfman 22:0307adac8c35 180 //calculate the new phase of the modulator
davolfman 22:0307adac8c35 181 modulatorPhases[i] += (carrierIncrements[i] * FMmult)>> 16;
davolfman 22:0307adac8c35 182
davolfman 22:0307adac8c35 183 //get the sine for that phase and scale it by the envelope
davolfman 22:0307adac8c35 184 int modulation = (fastSin(modulatorPhases[i]) * envelopeAmpsM[i])>>16;
davolfman 22:0307adac8c35 185
davolfman 22:0307adac8c35 186 //scale it again by the modulation amount
davolfman 22:0307adac8c35 187 modulation = (modulation * modVol) >> 16;
davolfman 22:0307adac8c35 188
davolfman 22:0307adac8c35 189 //calculate the new phase of the carrier, modualting frequency by the modulation
davolfman 22:0307adac8c35 190 carrierPhases[i] += carrierIncrements[i] + modulation;
davolfman 22:0307adac8c35 191
davolfman 22:0307adac8c35 192 //get the sine for that carrier phase and scale by the envelope
davolfman 22:0307adac8c35 193 //additionally divide by 8 to allow 8 notes to play without saturating the DAC
davolfman 22:0307adac8c35 194 subsignal = (fastSin(carrierPhases[i]) * envelopeAmpsC[i])>>19;
davolfman 22:0307adac8c35 195
davolfman 22:0307adac8c35 196 //add the sample for this note into the overall sample
davolfman 22:0307adac8c35 197 wave += subsignal;
davolfman 12:3a1e7fde5040 198 }
davolfman 15:34ba7c2ef718 199
davolfman 15:34ba7c2ef718 200 }
davolfman 22:0307adac8c35 201
davolfman 22:0307adac8c35 202 //Scale the complete sample by the volume
davolfman 15:34ba7c2ef718 203 wave = wave * Volume >> 16;
davolfman 12:3a1e7fde5040 204
davolfman 22:0307adac8c35 205 //clip the sample to within the limits of the DAC if neccessary
davolfman 15:34ba7c2ef718 206 wave = (wave > 32767) ? 32767 : wave;
davolfman 15:34ba7c2ef718 207 wave = (wave < -32768) ? - 32768 : wave;
davolfman 22:0307adac8c35 208
davolfman 22:0307adac8c35 209 //Center the waveform within the range of the DAC
davolfman 15:34ba7c2ef718 210 wave += 32768;
davolfman 22:0307adac8c35 211
davolfman 22:0307adac8c35 212 //output the sample
davolfman 15:34ba7c2ef718 213 outMono.write_u16(wave);
davolfman 1:f3350a372732 214 }
davolfman 0:b2f7400596ce 215
davolfman 0:b2f7400596ce 216
davolfman 0:b2f7400596ce 217 int main() {
davolfman 2:5454dee210ed 218 int ratNumer;
davolfman 18:4992aa537387 219 int ratDenom;
davolfman 18:4992aa537387 220 int64_t keytemp;
davolfman 18:4992aa537387 221 int tempCarA, tempCarD, tempCarR, tempModA, tempModD, tempModR;
davolfman 9:86c0035f5321 222
davolfman 23:7a9ff5230149 223 for(int i = 0; i < numKeys; ++i){ //zero out values
davolfman 9:86c0035f5321 224 carrierPhases[i] = 0;
davolfman 9:86c0035f5321 225 modulatorPhases[i] = 0;
davolfman 9:86c0035f5321 226 envelopeAmpsC[i] = 0;
davolfman 9:86c0035f5321 227 envelopeAmpsM[i] = 0;
davolfman 9:86c0035f5321 228 }
davolfman 9:86c0035f5321 229
davolfman 23:7a9ff5230149 230 keyBank.mode(PullNone); // we're using external pullup resistors,
davolfman 23:7a9ff5230149 231 //and things weren't working this didn't fix it but better safe
davolfman 23:7a9ff5230149 232
davolfman 23:7a9ff5230149 233 synthesisClock.attach(synthesize, 0.00005); //this runs every 50 us or 20khz
lenzi002 8:13b0594510de 234
davolfman 2:5454dee210ed 235 while(true){
davolfman 23:7a9ff5230149 236 ratNumer = 0xf & ~ numerator; //read ratio numerator
davolfman 23:7a9ff5230149 237 ratDenom = 0xf & ~ denominator; //read ratio denominator
davolfman 23:7a9ff5230149 238 FMmult = (ratNumer << 16) / ratDenom; //FM multiplier = numerator / denominator
davolfman 23:7a9ff5230149 239
davolfman 23:7a9ff5230149 240 Volume = (int)inVol.read_u16(); //read volume
davolfman 2:5454dee210ed 241
davolfman 23:7a9ff5230149 242 modVol = (int)inModAmt.read_u16(); //read modulation amount
davolfman 12:3a1e7fde5040 243
davolfman 23:7a9ff5230149 244 //ensure we don't divide by zero on any of these
davolfman 23:7a9ff5230149 245
davolfman 23:7a9ff5230149 246 //read carrier attack
davolfman 18:4992aa537387 247 tempCarA = inCarA.read_u16();
davolfman 18:4992aa537387 248 if(! tempCarA)
davolfman 9:86c0035f5321 249 carA = 0xffff;
davolfman 9:86c0035f5321 250 else
davolfman 18:4992aa537387 251 carA = 0xffff / tempCarA;
davolfman 9:86c0035f5321 252
davolfman 23:7a9ff5230149 253 //read carrier decay
davolfman 18:4992aa537387 254 tempCarD = inCarD.read_u16();
davolfman 18:4992aa537387 255 if(! tempCarD)
davolfman 9:86c0035f5321 256 carD = 0xffff;
davolfman 9:86c0035f5321 257 else
davolfman 18:4992aa537387 258 carD = 0xffff / tempCarD;
davolfman 9:86c0035f5321 259
davolfman 23:7a9ff5230149 260 //read carrier sustain
davolfman 2:5454dee210ed 261 carS = (int)inCarS.read_u16();
davolfman 9:86c0035f5321 262
davolfman 23:7a9ff5230149 263 //read carrier release
davolfman 18:4992aa537387 264 tempCarR = inCarR.read_u16();
davolfman 18:4992aa537387 265 if(! tempCarR)
davolfman 9:86c0035f5321 266 carR = 0xffff;
davolfman 9:86c0035f5321 267 else
davolfman 18:4992aa537387 268 carR = 0xffff / tempCarR;
davolfman 2:5454dee210ed 269
davolfman 23:7a9ff5230149 270 //read modulation attack
davolfman 18:4992aa537387 271 tempModA = inModA.read_u16();
davolfman 18:4992aa537387 272 if(! tempModA)
davolfman 9:86c0035f5321 273 modA = 0xffff;
davolfman 9:86c0035f5321 274 else
davolfman 18:4992aa537387 275 modA = 0xffff / tempModA;
davolfman 9:86c0035f5321 276
davolfman 23:7a9ff5230149 277 //read modulation decay
davolfman 18:4992aa537387 278 tempModD = inModD.read_u16();
davolfman 18:4992aa537387 279 if(! tempModD)
davolfman 9:86c0035f5321 280 modD = 0xffff;
davolfman 9:86c0035f5321 281 else
davolfman 18:4992aa537387 282 modD = 0xffff / tempModD;
davolfman 9:86c0035f5321 283
davolfman 23:7a9ff5230149 284 //read modulation sustain
davolfman 2:5454dee210ed 285 modS = (int)inModS.read_u16();
davolfman 9:86c0035f5321 286
davolfman 23:7a9ff5230149 287 //read modulation release
davolfman 18:4992aa537387 288 tempModR = inModR.read_u16();
davolfman 18:4992aa537387 289 if(! tempModR)
davolfman 9:86c0035f5321 290 modR = 0xffff;
davolfman 9:86c0035f5321 291 else
davolfman 18:4992aa537387 292 modR = 0xffff / tempModR;
davolfman 13:29705e6bf718 293
davolfman 23:7a9ff5230149 294 keytemp = 0; //zero the keys before we start ORing on top of everything,
davolfman 23:7a9ff5230149 295 //keytemp is a buffer that waits until every key is read, then it pushes
davolfman 23:7a9ff5230149 296 //into the 'keyboard' variable
davolfman 23:7a9ff5230149 297
davolfman 23:7a9ff5230149 298 for(int i = 0; i < 9; ++i) {//for all 9 half-octaves of the keyboard
davolfman 23:7a9ff5230149 299 bankSelect = (~(1 << i)) & bankSelect.mask();//supply power (as ground) to that bank
davolfman 23:7a9ff5230149 300 wait_us(200); //delay to get to get full reading
davolfman 23:7a9ff5230149 301 int shiftOffset = 6LL * i; //read the keys in the bank
davolfman 13:29705e6bf718 302
davolfman 23:7a9ff5230149 303 //assign the bank to its corresponding position in the overall keyboard
davolfman 9:86c0035f5321 304 keytemp |= ((~(unsigned long long)keyBank) & (unsigned long long)keyBank.mask()) << (unsigned long long)shiftOffset;
davolfman 7:b0cd74923bc6 305 }
davolfman 23:7a9ff5230149 306 keytemp >>= 5;//shift 5 over because bank 0 only has 1 key and it is the 6th key (...111111 111111 100000)
davolfman 9:86c0035f5321 307
davolfman 23:7a9ff5230149 308 keyboard = keytemp;//push our read values once we are complete.
davolfman 23:7a9ff5230149 309 //This only takes 1 cycle, especially since we are using 'keyboard' in the ISR
davolfman 13:29705e6bf718 310
davolfman 23:7a9ff5230149 311 //wait_ms(10);//we've stopped bothering to wait here. it didn't make a difference
davolfman 2:5454dee210ed 312 }
davolfman 0:b2f7400596ce 313 }