//glitchbox //by Amanda Ghassaei 2012 ////todo //led data //audio storage //send out audio //trigger audio //pot control //switches //timers //turn off midi-send clear when mute /*********************************************************************** if you want to add your own audio samples, compress them to 8 bit 8kHz using these instructions: and paste the data into the memory below. the buttons are arranged as follows: 0 1 2 3 4 5 6 7 8 ***********************************************************************/ //AUDIO STORAGE boolean on1 = 0; boolean on2 = 0; boolean on3 = 0; boolean on4 = 0; boolean on5 = 0; boolean on6 = 0; boolean on7 = 0; boolean on8 = 0; boolean on9 = 0; //variables for loops byte i; byte j; byte k; //position variables byte x; byte y; //states byte state = 0; //position variables byte xseq; byte yseq; //states byte stateseq = 0; //data storage for buttons boolean button_current[9];//current state boolean button_last[9];//last state boolean button_state[9];//current debounced state byte button_debounce_count[9];//debounce counter boolean button_event[9];//event signal byte buttonData;//used for reading portc int kButtonUpDefaultDebounceCount = 12; // Used in button debouncing /*********************************************************************** change the number following "#define steps" to set the number of steps in your sequencer. default is 16 ***********************************************************************/ //sequencer #define steps 16 byte sequencer[steps][9];//32 step sequencer storage //REC- turn sequencer on/off boolean currentrec = 0; boolean prevrec = 0; boolean recdebounce = 0; byte recdebouncecount;//debounce rec switch //variables for loops byte recdebouncesteps; byte recdebouncei; int seqTimer = 0; boolean seqONcurrent = 1;//optional mute recorded sequences boolean seqONprev = 1; boolean seqON = 1; byte seqONcounter;//debounce mute switch boolean initonoff; //BPM int BPMvalcurrent; int BPMvalstored; void buttonInit() { byte i; for (i = 0; i <9; i++) { button_current[i] = 0; button_last[i] = 0; button_state[i] = 0; button_event[i] = 0; } PORTB = 0xFF;//set all pins high } //MUCH OF THIS BUTTON DEBOUNCING FUNCTION WAS COPIED FROM THE MONOME 40H FIRMWARE BY JOE LAKE AND BRIAN CRABTREE // buttonCheck - checks the state of a given button. void buttonCheck(byte index) { if ((button_current[index] ^ button_last[index]) && // if the current physical button state is different from the (button_current[index] ^ button_state[index])) { // last physical button state AND the current debounced state if (button_current[index]) { // if the current physical button state is depressed button_event[index] = 1; // queue up a new button event immediately button_state[index] = 1; // and set the debounced state to down. } else{ button_debounce_count[index] = kButtonUpDefaultDebounceCount; } // otherwise the button was previously depressed and now // has been released so we set our debounce counter. } else if ((button_current[index] ^ button_last[index]) == 0 && // if the current physical button state is the same as (button_current[index] ^ button_state[index])) { // the last physical button state but the current physical // button state is different from the current debounce // state... if (button_debounce_count[index] > 0 && --button_debounce_count[index] == 0) { // if the the debounce counter has // been decremented to 0 (meaning the // the button has been up for // kButtonUpDefaultDebounceCount // iterations/// button_event[index] = 1; // queue up a button state change event if (button_current[index]){ // and toggle the buttons debounce state. button_state[index] = 1; } else{ button_state[index] = 0; } } } } void buttonpress() { // digitalWrite(8,HIGH); // digitalWrite(9,HIGH); // digitalWrite(10,HIGH); PORTB |= 0x07;//set pins 8, 9, 10 high for (i=0; i<9; i++) { button_last[i] = button_current[i]; } //THE FOLLOWING CODE CHECKS THE STATES OF THE BUTTONS digitalWrite(8,LOW); button_current[2] = 1^digitalRead(A0); button_current[1] = 1^digitalRead(A1); button_current[0] = 1^digitalRead(A2); digitalWrite(8,HIGH); digitalWrite(9,LOW); button_current[5] = 1^digitalRead(A0); button_current[4] = 1^digitalRead(A1); button_current[3] = 1^digitalRead(A2); digitalWrite(9,HIGH); digitalWrite(10,LOW); button_current[8] = 1^digitalRead(A0); button_current[7] = 1^digitalRead(A1); button_current[6] = 1^digitalRead(A2); digitalWrite(10, HIGH); ////SAME AS THE CODE ABOVE- WITHOUT ARDUINO LIBRARY COMMANDS //for (j=0; j<3; j++){ // PORTB &= ~(1<> k);//load data into button_current //// } // // button_current[3] = 1^digitalRead(A0); // button_current[4] = 1^digitalRead(A1); // button_current[5] = 1^digitalRead(A2); // PORTB |= (1< 0 && --recdebouncecount == 0) {//decrease debounce counter and check to see if = 0 if (currentrec){//if debounce counter = 0 toggle debounced state recdebounce = 1; for (recdebouncesteps=0; recdebouncesteps 0 && --seqONcounter == 0) {//decrease debounce counter and check to see if = 0 Serial.print(1,BYTE);//end current MIDI if (seqONcurrent){//if debounce counter = 0 toggle debounced state seqON = 1; } else{ seqON = 0; } } } } void checkBPM(){ BPMvalcurrent=analogRead(A5); if (abs(BPMvalcurrent-BPMvalstored)>8){//if change exceeds noise tolerance BPMvalstored = BPMvalcurrent; OCR1A = 31250/(BPMvalstored/100); // compare match register 16MHz/256/2Hz } } ISR(TIMER1_COMPA_vect){ if (seqTimer==2*steps-1){ seqTimer=0; } else{ seqTimer+=1;//increase seqTimer by 1 } if (seqON==initonoff){//if mute is off if (seqTimer%2==0){//every other tick PORTB&=B11100111;//turn off LEDs //Serial.print(1, BYTE);//clear out midi from last time step for (byte iseq=0; iseq<9; iseq++) { stateseq = sequencer[seqTimer/2][iseq]; xseq = iseq % 3;//x coordinate yseq = iseq / 3;//y coordinate if ((stateseq==1)|(stateseq==2)){ Serial.print(((xseq << 6) | (yseq << 4)), BYTE);//byte [xxyy(off)---]//clear out midi Serial.print(((xseq << 6) | (yseq << 4)) | ((stateseq-1) << 3), BYTE);//byte [xxyy(on/off)---] } } if (seqTimer%(steps/2) ==0) {//turn led on every forth tick if (recdebounce){ PORTB|=B00001000;//turn on amber LED } else{ PORTB|=B00010000;//turn on white LED } } } } else{ if (seqTimer%2==0){//every other tick PORTB&=B11100111;//turn off LEDs } if (seqTimer%(steps/2) ==0) {//turn led on every forth tick if (recdebounce){ PORTB|=B00001000;//turn on amber LED } else{ PORTB|=B00010000;//turn on white LED } } } } void setup() { //button data out on pins 8, 9, 10 DDRB = 0xFF; //button data in on pins A0, A1, A2 DDRC = 0x00; BPMvalstored = analogRead(A5); // //SETUP TIMER2 FOR SEQUENCER cli();//stop interrupts // TCNT2=0x00; // OCR2A = 250; // 1 ms @ Fosc = 16 MHz // TCCR2A=0x02; // WGM: No wave generation // TCCR2B=0x04; // START Timer, prescaler = 64 // TIMSK2 = (1 << TOIE2); // Enable interrupt when Timer reaches OCRA // set up Timer 2 // Timer 2 - gives us our 1 mS counting interval // 16 MHz clock (62.5 nS per tick) - prescaled by 128 // counter increments every 8 uS. // So we count 125 of them, giving exactly 1000 uS (1 mS) // TCCR2A = 0; // stop timer 2 // TCCR2B = 0; // TCNT2 = 0; // reset counter // // OCR2A = 124; // count up to 125 (zero relative!!!!) // TCCR2A = _BV (WGM21) ; // CTC mode // TCCR2B = _BV (CS20) | _BV (CS22) ; // start Timer with a prescaler of 128 // TIMSK2 = _BV (OCIE2A); // enable Timer2 Interrupt (ie. every 1 mS) // // TCCR2A = 0; // TCCR2B = 0; // TCNT2 = 0; // // OCR2A = 255; // compare match register 16MHz/256/2Hz // TCCR2B |= (1 << WGM21); // CTC mode // TCCR2B |= (1 << CS20); // 256 prescaler // TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 31250/(BPMvalstored/100); // compare match register 16MHz/256/2Hz TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt sei();//allow interrupts //initialize mute switch so that it allows playback on startup initonoff=digitalRead(A4); PORTB = 0x07;//set pins 8, 9, 10 high, 11, 12 low Serial.begin(57600);//not initializing properly when unplugged and replugged buttonInit(); Serial.print(1,BYTE);//clear message } void loop() { buttonpress(); checkBPM(); checkSwitches(); checkBPM(); }