// Rail buzzer Gijs Gieskes 2012 // Use with Arduino version 1.0.1 #include const int ENDPOS = 690; int vibratiodepth; boolean vibratobool; boolean vibratocount = 50; int smoother; int tposition; //pots int AV3; int AV4; //millis unsigned long prevVibMil; unsigned long prevVolMil; //vibrato byte vibratoDepth = 68; volatile byte octaver; byte wave[701]; byte wavei2c[128]; int frame = 0; unsigned long time = 0; byte recTime = 10; int frequency = 60; int position = 255; float volume = 0; void setup() { Wire.begin(); //draw waveform byte pseq[10] = {250, 60, 160, 20, 250, 4, 210, 40, 170, 127}; boolean prevFlip = false; byte peaks = 0; boolean flip = true; byte j = 127; for(int i=0; i<700; i++){ if(flip != prevFlip){ prevFlip = flip; peaks++; } if(peaks < 10){ if(j < pseq[peaks]){ flip = false; } if(j > pseq[peaks]){ flip = true; } if(flip){ j -= 2; }else{ j += 2; } }else{ j = 127; } wave[i] = j; } pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT); pinMode(6, OUTPUT); pinMode(7, OUTPUT); //pitch shifting buttons pinMode(8, INPUT); digitalWrite(8, HIGH); pinMode(9, INPUT); digitalWrite(9, HIGH); //record button pinMode(10, INPUT); digitalWrite(10, HIGH); //LED pinMode(11, OUTPUT); cli(); TCCR1B = TCCR1B & B11111000 | B00000001; TCCR2A = TCCR2A & B11111000 | B00000010; TCCR2B = TCCR2B & B11111000 | B00000010; TIMSK2 = TIMSK2 & B11111000 | B00000010; OCR2A = frequency; sei(); } //From TIMSK2 ISR(TIMER2_COMPA_vect) { frame += octaver; if(frame >= ENDPOS){frame = position;} PORTD = wave[frame] * volume; } void loop() { static boolean trigger; static boolean startADSR; if(!digitalRead(8) && !digitalRead(9)){ octaver = 4; }else if(!digitalRead(9)){ octaver = 3; }else if(!digitalRead(8)){ octaver = 2; }else{ octaver = 1; } //dummy analogread to switch to analog 0.. for smoothing. int none = analogRead(0); //let it settle delayMicroseconds(500); //read only when value is greater then the pulled down value if(analogRead(0) > 90){ //measure conection for adsr startADSR = true; if(trigger){ trigger = false; //reset trigger //sample only once for every connecting action of the sensor //this helps especialy to prevent random pullup reads, when the //sensor is released from the contact. tposition = 0; //rest previus read //read adc several times to get best result, debounce and other things maybe byte i = 0; for(i=0; i<35; i++){ smoother = analogRead(0); if(smoother > tposition){ //set new read when greater then already taken read tposition = smoother; } delayMicroseconds(1); } if(tposition > 95){ position = mapper(tposition); } } }else{ startADSR = false; trigger = true; } if(millis() - prevVibMil > ((AV4 >> 3)+10)){ prevVibMil = millis(); vibratof(); } //sequence vars static boolean recording; static boolean madearec; static boolean prevMode; static unsigned int recArr[2][96]; static unsigned long prevMilRec; static unsigned long prevMilPlay; static byte arposrec; static byte reclength; static byte arposplay; if(!digitalRead(10)){ //record and playback, maximum 16 steps (can be more). //and maximum about 65 seconds between steps, because of unsigned ints array digitalWrite(11, HIGH); //reset variables. if(prevMode){ prevMode = false; reclength = 0; arposrec = 0; arposplay = 0; prevMilRec = millis(); prevMilPlay = millis(); madearec = false; } //recording.. if(startADSR){ if(recording){ //record one time madearec = true; recording = false; recArr[0][arposrec] = millis() - prevMilRec; //store when note is played. prevMilRec = millis(); //reset prev millis to measure from last press.. recArr[1][arposrec] = position; //store frequency arposrec++; if(arposrec >= 96){ //maximum 96 recordings arposrec = 0; } if(reclength <= 96){ //set recorded length reclength++; } } }else{ recording = true; } adsr(startADSR, false); }else{ prevMode = true; //playback if(millis() - prevMilPlay > recArr[0][arposplay] && madearec){ prevMilPlay = millis(); position = recArr[1][arposplay]; //set frequency. arposplay++; if(arposplay >= reclength){ arposplay = 0; } adsr(true, true); }else{ adsr(false, true); } adsr(startADSR, false); //enable normal adsr withour record function. } static byte LCDdelay; LCDdelay++; if(LCDdelay > 100){ LCDdelay = 0; draw(); } static byte requestCount; requestCount++; if(requestCount > 50){ //request not to often.. requestCount = 0; wireRequest(); } vibratiodepth = analogRead(3); } inline void adsr(boolean active, boolean led){ static boolean start = 0; static boolean startA = 0; if(active){ if(start){ //trigger one time if(led){ //only show led when sequence is used. digitalWrite(11, HIGH); } start = false; startA = 1; } }else{ if(led){ //only show led when sequence is used. digitalWrite(11, LOW); } start = true; } if(startA == 1){ //attach if(volume < 0.999){ volume += (analogRead(1) + 5) * 0.00001; }else{ startA = 2; } }else if(startA == 2){ //decay if(volume > 0.6){ volume -= (analogRead(2) + 5) * 0.00001; }else{ startA = 3; } }else if(startA == 3 && active){ //sustain //do nothing.. sustain }else if(startA == 3){ //release if(volume > 0.00001){ volume -= (analogRead(2) + 5) * 0.000003; }else{ startA = 0; } volume = max(volume, 0.000001); } } inline void vibratof(){ //vibrato if(vibratobool){ if(vibratocount < (vibratiodepth >> 4)+64){ vibratocount++; }else{ vibratobool = false; } }else{ if(vibratocount > 64){ vibratocount--; }else{ vibratobool = true; } } OCR2A = vibratocount; } void draw() { //store waveform in array for sending via i2c to display int xcount = ENDPOS; for(byte x = 0; x<127; x++){ //add volume settings and vitical offset int ydraw = (32-(wave[xcount] >> 2)) * volume; wavei2c[x] = (byte) 32+ydraw; //move in big steps thrue array to cover the whole array. xcount += (6*octaver); if(xcount >= ENDPOS){ xcount = position; } } //cannot send more then 32 bytes in one transmission, so make chunks. Wire.beginTransmission(2); // transmit to device #2 for(byte x = 0; x<32; x++){ Wire.write(255); //reset display } Wire.endTransmission(); Wire.beginTransmission(2); // transmit to device #2 for(byte x = 0; x<32; x++){ Wire.write(wavei2c[x]); } Wire.endTransmission(); Wire.beginTransmission(2); // transmit to device #2 for(byte x = 32; x<64; x++){ Wire.write(wavei2c[x]); } Wire.endTransmission(); Wire.beginTransmission(2); // transmit to device #2 for(byte x = 64; x<96; x++){ Wire.write(wavei2c[x]); } Wire.endTransmission(); Wire.beginTransmission(2); // transmit to device #2 for(byte x = 96; x<128; x++){ Wire.write(wavei2c[x]); } Wire.endTransmission(); } void wireRequest(){ Wire.requestFrom(2, 1); // request 1 bytes from slave device #2 while(Wire.available()) // slave may send less than requested { AV4 = Wire.read() << 2; // receive and convert to "10bit" } } int mapper(int in){ //map wave in array to position on the bar. /////////// <- this mark position on the bar for every "bend point" int out = 0; byte off = 5; //ofset to not get to close to the read value, but just over/under it. if(in < 95 + off){ out = ENDPOS; }else if(in < 98 + off){ out = 674; }else if(in < 108 + off){ out = 662; }else if(in < 118 + off){ out = 651;/////////// }else if(in < 128 + off){ out = 640;//////////// }else if(in < 138 + off){ out = 629; }else if(in < 148 + off){ out = 618; }else if(in < 158 + off){ out = 607; }else if(in < 167 + off){ out = 596; }else if(in < 177 + off){ out = 585;//////////// }else if(in < 187 + off){ out = 574;////////// }else if(in < 197 + off){ out = 563; }else if(in < 207 + off){ out = 553; }else if(in < 216 + off){ out = 542; }else if(in < 226 + off){ out = 531; }else if(in < 236 + off){ out = 520; }else if(in < 245 + off){ out = 510; }else if(in < 255 + off){ out = 499;////////////// }else if(in < 264 + off){ out = 488;////////////// }else if(in < 274 + off){ out = 478; }else if(in < 284 + off){ out = 468; }else if(in < 294 + off){ out = 457; }else if(in < 304 + off){ out = 447; }else if(in < 313 + off){ out = 437; }else if(in < 323 + off){ out = 426; }else if(in < 332 + off){ out = 416; }else if(in < 341 + off){ out = 405; }else if(in < 351 + off){ out = 395;////////// }else if(in < 359 + off){ out = 384;////////// }else if(in < 370 + off){ out = 372; }else if(in < 381 + off){ out = 361; }else if(in < 391 + off){ out = 350; }else if(in < 401 + off){ out = 339; }else if(in < 410 + off){ out = 327; }else if(in < 420 + off){ out = 316; }else if(in < 430 + off){ out = 305; }else if(in < 440 + off){ out = 294; }else if(in < 450 + off){ out = 282; }else if(in < 460 + off){ out = 271;///////// }else if(in < 469 + off){ out = 260;///////// }else if(in < 479 + off){ out = 250; }else if(in < 489 + off){ out = 239; }else if(in < 499 + off){ out = 229; }else if(in < 509 + off){ out = 218; }else if(in < 521 + off){ out = 208; }else if(in < 532 + off){ out = 197; }else if(in < 543 + off){ out = 186; }else if(in < 553 + off){ out = 176; }else if(in < 563 + off){ out = 166; }else if(in < 573 + off){ out = 155;/////////// }else if(in < 586 + off){ out = 145;////////// }else if(in < 598 + off){ out = 135; }else if(in < 608 + off){ out = 125; }else if(in < 619 + off){ out = 114; }else if(in < 632 + off){ out = 104; }else if(in < 643 + off){ out = 94; }else if(in < 654 + off){ out = 84;/////////// }else if(in < 666 + off){ out = 71;////////// }else if(in < 679 + off){ out = 58; }else if(in < 691 + off){ out = 46; }else if(in < 704 + off){ out = 33;///////// }else if(in < 715 + off){ out = 21;//////// }else if(in < 728 + off){ out = 10; }else if(in < 743 + off){ out = 0;//////// }else{ out = 0;//just in case } return out; }