Go Down

Topic: Sequencer groove (Read 2010 times) previous topic - next topic

Flub

Code: [Select]

void loop() {
 if (Play) {
   if (play()) {
     Button_Check();
   }
 }
}

////////////////////////////////////////////////////////////////////////////////////
//FUNKTIONEN                              
////////////////////////////////////////////////////////////////////////////////////

//________________________________________________________________________SETLEDS()
void setLeds() {
/* if (Mode==false) {*/
   for (unsigned int i = 0; i<=15; i=i+1) {
  //   if (second) {
     /*  if (ReadValue(program_sequence,ProgramSequenceTakt,active_channel,((i*Faktor)+16), false) == 0) {
         digitalWrite((StepLedPINS[i]), LOW);
       } else {
         digitalWrite((StepLedPINS[i]), HIGH);
       }*/
    // } else {
       if (ReadValue(program_sequence,ProgramSequenceTakt,active_channel,(i*Faktor), false) == 0) {
         digitalWrite((StepLedPINS[i]), LOW);
       } else {
         digitalWrite((StepLedPINS[i]), HIGH);
       }
    // }
   }
 /*} else {    
   for (int i = 0; i <= 15; i++) {
     if (i==program_sequence || i == (Paste-1)) {
       digitalWrite((StepLedPINS[i]), HIGH);
     } else {
       if (i != play_sequence) {
         digitalWrite((StepLedPINS[i]), LOW);
       }
     }
   }
 }*/
}
//________________________________________________________________________DISPLAY_BARS()
void display_bars(unsigned int count) {
 for (unsigned int i = 0; i < 4; i = i + 1) {
   if ( i == (count-1)) {
     if (count == 1) {
       digitalWrite(TaktPINS[i],HIGH);
     } else {
       analogWrite(TaktPINS[i],100);
     }
   } else {
     digitalWrite(TaktPINS[i],LOW);
   }
 }
}
//________________________________________________________________________DISPLAY_VALUES()
void display_values(unsigned int a, unsigned int b, unsigned int c, unsigned int d) {
 digitalWrite(14, HIGH);
 for (unsigned int i = 0; i < 4; i = i+1) {
   digitalWrite(DisplayDataPIN,numbers[b][i]);
   digitalWrite(DisplayClockPIN, HIGH);
   digitalWrite(DisplayDataPIN,LOW);
   digitalWrite(DisplayClockPIN, LOW);
 }
 for (unsigned int i = 0; i < 4; i = i+1) {
   digitalWrite(DisplayDataPIN,numbers[a][i]);
   digitalWrite(DisplayClockPIN, HIGH);
   digitalWrite(DisplayDataPIN,LOW);
   digitalWrite(DisplayClockPIN, LOW);
 }
 for (unsigned int i = 0; i < 4; i = i+1) {
   digitalWrite(DisplayDataPIN,numbers[d][i]);
   digitalWrite(DisplayClockPIN, HIGH);
   digitalWrite(DisplayDataPIN,LOW);
   digitalWrite(DisplayClockPIN, LOW);
 }
 for (unsigned int i = 0; i < 4; i = i+1) {
   digitalWrite(DisplayDataPIN,numbers[c][i]);
   digitalWrite(DisplayClockPIN, HIGH);
   digitalWrite(DisplayDataPIN,LOW);
   digitalWrite(DisplayClockPIN, LOW);
 }
}
//________________________________________________________________________READVALUE()
inline boolean ReadValue(int seq, int takt, int channel, int p, boolean Switch) {
 takt--;
 int count = (seq*4*10*32)+(takt*10*32)+(channel*32)+p;
 int x = count % 8;
 int x2 = (count-x)/8;
 count=-1;
 boolean BIT = bitRead(sequenzen[x2],x);
 if (Switch) {
   bitWrite(sequenzen[x2],x,inv(BIT));
 } else {
   return BIT;
 }
}
//________________________________________________________________________WRITEVALUE()
void WriteValue(int seq, int takt, int channel, int p, boolean value) {
 takt--;
 int count = (seq*4*10*32)+(takt*10*32)+(channel*32)+p;  
 int x = count % 8;
 int x2 = (count-x)/8;
 count=-1;
 bitWrite(sequenzen[x2],x,value);
}
//________________________________________________________________________inv()
inline boolean inv(boolean x) {
 if (x==HIGH) {
   return LOW;  
 } else {
   return HIGH;
 }
}
boolean play () {
 if ((micros() - Timer) > 66000) {
   for (int i = 0; i<10; i++) {
     channelvals[i]=ReadValue(play_sequence,PlaySequenceTakt,i,Step,false);
   }
   for (int i = 0; i<10; i++) {
     digitalWrite(55+i,channelvals[i]);
   }
   Step++;
   Timer = micros();
   lastOut = micros();
   if ((micros()-lastOut) > 50) {
     for (int i = 0; i<10; i++) {
       digitalWrite(55+i,LOW);
     }
   }
   if (Step > 31) {
     Step = 0;
   } else {
     Step = Step;
   }
   if (PlaySequenceTakt == ProgramSequenceTakt) {      
       if (Faktor == 2) {
         digitalWrite(SetStepsLedPINS[3], stepper[Step/Faktor][0]);
         digitalWrite(SetStepsLedPINS[2], stepper[Step/Faktor][1]);
         digitalWrite(SetStepsLedPINS[1], stepper[Step/Faktor][2]);
         digitalWrite(SetStepsLedPINS[0], stepper[Step/Faktor][3]);
       } else {
         if (Step > 15) {
           StepSize=Step-16;        
         } else {
           StepSize = Step;
         }
           digitalWrite(SetStepsLedPINS[3], HIGH);
           digitalWrite(SetStepsLedPINS[2], HIGH);
           digitalWrite(SetStepsLedPINS[1], HIGH);
           digitalWrite(SetStepsLedPINS[0], HIGH);
       }
     } else {
       digitalWrite(SetStepsLedPINS[3], HIGH);
       digitalWrite(SetStepsLedPINS[2], HIGH);
       digitalWrite(SetStepsLedPINS[1], HIGH);
       digitalWrite(SetStepsLedPINS[0], HIGH);
     }
   return false;
 } else {
   return true;
 }  
}
//________________________________________________________________________Button_Check()
boolean Button_Check() {
 for (unsigned int i = 0; i < 16; i++) {
   button_state=digitalRead(ProgramButtonPINS[i]);  
   if (button_state==LOW) {
     if (button_ok[i]) {
       button_ok[i]= false;
       button_last = millis();
       ReadValue(program_sequence,ProgramSequenceTakt,active_channel,(i*Faktor), true);
       setLeds();
     }
   } else if ((button_ok[i]) == false) {
     if ((millis()-button_last) > 100) {
       button_ok[i] = true;
     }
   }
 }
 //________________________________________________________________ButtonA
 button_state=digitalRead(ButtonAPIN);
 if (button_state==LOW) {
   if (ButtonA_ok) {
     ButtonA_ok = false;
     button_last=millis();
     active_channel--;
     setLeds();
     display_values(0,0,0,active_channel);
   }
 } else if ((ButtonA_ok) == false) {
   if ((millis()-button_last) > 200) {
   ButtonA_ok = true;
   }
 }
 //________________________________________________________________ButtonB  
 button_state=digitalRead(ButtonBPIN);
 if (button_state==LOW) {
   if (ButtonB_ok) {
     ButtonB_ok = false;
     button_last=millis();
     active_channel++;
     setLeds();
     display_values(0,0,0,active_channel);
   }
 } else if ((ButtonB_ok) == false) {
   if ((millis()-button_last) > 200) {
   ButtonB_ok = true;
   }
 }  
}

Thank you  for the modulo stuff !
I now started to rearrange and improve the code. Thats what ive got yet. Do you see anything to improve?

montecito


Thank you  for the modulo stuff !
I now started to rearrange and improve the code. Thats what ive got yet. Do you see anything to improve?


What actually are your goals ?? Are you trying to reduce the amount of C code you have to write/debug/maintain, trying to reduce final program size, trying to have the code run faster, or something else ??

Flub

I want the code to go faster, because the sequenzer triggers a Drumsynth I built and when the code was still basic to test if it worked, the rhythm had much more groove then it had after I added all the functions, display options and button combinations That I want the sequencer to have. This is the reason why I want to be as effiecient as possible to keep the beat tight. ( the difference is not really big tecnically but the whole feel is very different, when it is fast you feel your body wants to move, when it is slow it just doesnt make you feel like that.

It is very important that the trigger pulses come at the same point in time and this in a very strict time interval , so the generated sounds really clash together if you know what i mean. Perhaps I could try to set all trigger voltages up right connected to a 4066 analog switch which is later opened by a slightly delayed clock pulse from the sequencer so the trigger pulses really come out at the same time.

sorry for my bad english, if it is bad
-Flo

AWOL

If you want to squeeze some more cycles, you could look at replacing the "digitalWrite"s with direct port manipulation.
I'd check what the compiler is doing with the division and modulo ops, then if it really is doing division, replace them with mask and shift operations.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Flub

how can i check this?
i use the arduino ide

montecito


how can i check this?
i use the arduino ide


I haven't analyzed your program in detail, I will try to do this and I'll comment later if I see anything.

However, It may be useful to look at disassembled output of your program to see the exact assembly language instructions being generated to see if your division/modulus is being done efficiently by the compiler.  You can generate that output by (IIRC) by the compiler option -S. I don't know how to change compiler options using the Arduino IDE. 

I am building my sketches the old fashion way via command-line 'make' commands.  There is a good article on how to do this:

http://pragprog.com/magazines/2011-04/advanced-arduino-hacking

and here

http://bleaklow.com/2010/06/04/a_makefile_for_arduino_sketches.html

The latter article has a link to a google code project where you can download his examples.

Additionally, IIRC, the Arduino IDE uses compiler optimization flag -O0.  This optimizes for program size.  If you want to have the compiler optimize for speed you can try -O1 or -O2 or -O3.  However, these optimizations may be at the expense of increasing program size.

AWOL

...or you can run "avr-objdump" with a "-d" option on your compiled code to get a disassembly listing.
To find where the IDE leaves your compiled code, hold down the "shift" key when compiling.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

montecito


...or you can run "avr-objdump" with a "-d" option on your compiled code to get a disassembly listing.


I did not know about this.  Good to know. Thanks.

Flub

Am i right that running avrobjdump works like this:

open the console
avrobjdump -d PATH TO FILE

I am using windows xp right now, is it possible to run this program on windows ?

Flub

#24
Jul 02, 2011, 07:19 pm Last Edit: Jul 02, 2011, 07:23 pm by Flub Reason: 1
I now did it with the ubuntu on my netbook:

this is the commands output :
http://www.murderers.de/file.txt

if the function readfile goes to the hexnumber bc which is 188 in the decimal system does it mean that the time the function takes is

(1/16000000)*188 = 0,01175 milliseconds

AWOL

Quote
if the function readfile goes to the hexnumber bc which is 188 in the decimal system does it mean that the time the function takes is

(1/16000000)*188 = 0,01175 milliseconds


No, some instructions take more than one cycle,.
(I can't see "readfile" anywhere on that page - what is the source?)
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Flub

i meant readvalue instead of readfile. it is the the last code i posted here. what can i see in this assembler code? do i have to learn assembler first?

Anders 2009

I think you need to restructure and break up your code first. When that is done, you can go into more advanced optimizations if needed.

As mentioned early on in this thread, you should restructure your code so that reading inputs is a separate step from acting on the inputs. This way you can easily gain cycles just by skipping some actions and performing them only every N:th loop, or every N:th millis (better).






Flub

#28
Jul 28, 2011, 09:13 am Last Edit: Jul 28, 2011, 10:04 am by Flub Reason: 1
I now restructured the code like Anders proposed
i uploaded it http://murderers.de/NEu.pde


i want it as efficent as possible

Flub

#29
Feb 12, 2012, 01:14 pm Last Edit: Feb 12, 2012, 01:16 pm by Flub Reason: 1
Hey there,
I began to work again on the sequencer :

this is the loop function:
Code: [Select]
    if (play()) {
    } else {
      Button_Check();
      Button_Process();
    }


this is the play function:
Code: [Select]
   Time = micros()-lastOut;
   if (Time >= 4000 && clock == true) {    
     PORTK = 0b00000000;
     clock = false;
   } else if (Time >= step_intervall) {
     for (int i = 0; i<8; i++) {
       bitWrite(outputs,i,ReadValue(play_sequence,PlaySequenceTakt,i,Step,false));
     }
     PORTK = outputs;
 clock = true;
 lastOut = micros();  
     if (Step < 31) {
       Step++;
     } else {
       Step=0;
     }
     return true;
   } else {
     return false;    
   }
 }


Now it seems like the step_intervall isnt constant, so perhaps the board (Mega 1280) gets interuppted because i used almost every Pin on it and there are more interuppting pins i readed some where.

What can I do to create the Outputsignal in a very constant time intervall (my variable for this intervall in micro seconds is "step_intervall")

Please help me = )

-Flo

Go Up