Go Down

Topic: Playing around with timers and tones. (Read 8919 times) previous topic - next topic

WilliamK Govinda

I was wondering on using a timer to call an interrupt and have it drive multiple output ports and multiple tones. Its easy to do it draft, but I was hoping to get some good hz with tune and fine control. Any ideas? ;-)

The code below uses a single pin and Timer1, plus analog input on pin A2 just to showcase a high to low frequency range.

I did this quickly, so don't expect much.  :smiley-red:

Code: [Select]
int sensorPin = A2;
int soundPin = 9;
int hzOSC = 0;
uint8_t pinValue = 0;
int posValue[2] = {0,0};

void setup() {
  pinMode(soundPin, OUTPUT); 
 
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  ICR1 = 200;
  TIMSK1 = _BV(TOIE1);
 
  sei(); // enable global interrupts
}

void loop()
{
  hzOSC++;
  if (hzOSC > 800) hzOSC = 0;
  delay(map(analogRead(sensorPin), 0, 1023, 0, 10));
}

ISR(TIMER1_OVF_vect)
{
  if (pinValue == 0) PORTB &= B11111101; else PORTB |= B00000010;
 
  if (posValue[1] > hzOSC)
  {
    pinValue = !pinValue;
    posValue[1] = 0;
  }
 
  posValue[0]++;
  if (posValue[0] > 2)
  {
    posValue[0] = 0;
    posValue[1]++;
  }
}

robtillaart

What did you connect to the soundpin?

looking at the code:

* for a draft exercise I would use   delay(analogRead(sensorPin)/100);



* if (pinValue == 0)   pinvalue is 0 or 1; that equals true/false 
==> if (pinvalue) PORTB |= B00000010; else PORTB &= B11111101;

as they are in an IRQ some vars need to be volatile
volatile int hzOSC = 0;
volatile int posValue[2] = {0,0};

every 3 IRQ's posValue [1] is increased. for this posValue[0] is used to count to 3.
why not:
Code: [Select]

  if (posValue > hzOSC * 3)
  {
    pinValue = !pinValue;
    posValue = 0;
  }

is it slower?
optionally let hzOSC go from 0..2400 in steps of 3 within loop() than you can do   if (posValue > hzOSC) in the IRQ again

Rob



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

WilliamK Govinda

Since I need HZ with fraction format, for fine-tune, I created the non-optimized code, which works great. Just need to find a way to optimize it...  :smiley-fat:

Code: [Select]
#define soundPin 9
uint8_t pinValue[4] = {0,0,0,0};
float freqtab[128];
float oscPos[4] = {0.0f,0.0f,0.0f,0.0f};
float oscRate[4] = {1.0f,1.0f,1.0f,1.0f};

void setup()
{
  Serial.begin(38400);
 
  // make frequency (Hz) table
  double k = 1.059463094359; // 12th root of 2;
  double a = 6.875; // a
  a *= k; // b
  a *= k; // bb
  a *= k; // c, frequency of midi note 0
  for (int i = 0; i < 128; i++)
  {
    freqtab[i] = (float)a;
    Serial.print(i, DEC); Serial.print(" - "); Serial.println(freqtab[i]);
    a *= k;
  }

  pinMode(soundPin, OUTPUT);
   
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  ICR1 = 2000-1;
  TIMSK1 = _BV(TOIE1);
 
  sei(); // enable global interrupts
}

void loop()
{
  ICR1 = 2000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/8000.0f) * freqtab[60];
  delay(2000);
  oscRate[0] = (1.0f/8000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 1000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/16000.0f) * freqtab[60];
  delay(2000);
  oscRate[0] = (1.0f/16000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/20000.0f) * freqtab[60];
  delay(2000);
  //oscRate[0] = (1.0f/20000.0f) * freqtab[72];
  //delay(150);
 
  //ICR1 = 400-1;
  //oscRate[0] = oscRate[1] = (1.0f/40000.0f) * freqtab[60];
  //delay(2000);
 
  oscRate[0] = (1.0f/40000.0f) * freqtab[72];
  delay(100);
  oscRate[0] = (1.0f/40000.0f) * freqtab[84];
  delay(100);
  oscRate[0] = (1.0f/40000.0f) * freqtab[96];
  delay(100);
}

#define calcOsc(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= 1.0f) { pinValue[a] = !pinValue[a]; oscPos[a] -= 1.0f; }
ISR(TIMER1_OVF_vect)
{
  if (pinValue[0] == 0) PORTB &= B11111101; else PORTB |= B00000010; // D9  (PB1)
  if (pinValue[1] == 0) PORTB &= B11110111; else PORTB |= B00001000; // D11 (PB3)
  if (pinValue[2] == 0) PORTD &= B11101111; else PORTD |= B00010000; // D4  (PD4)
 
  calcOsc(0);
  calcOsc(1);
  calcOsc(2);
}

WilliamK Govinda

And here's a new code. Now you can modulate the angle of the square waveform, I also added a simple modulation to PWM, like the Alpha Juno had. :-) Just use 2 buttons, analog input, and analog output. So far I got 2 voices at 20khz, but I want more and at 40khz, so I need to optimize the code. I added a test-samplerate code to check if the code is overrunning or not.

Code: [Select]
#define soundPin1 9 // See below for direct port manipulation
#define soundPin2 4 // See below for direct port manipulation
#define analogInput A2
#define buttonPin 12
#define buttonPinPWM 8

float freqtab[128];
float oscPos[4] = {0.0f,0.0f,0.0f,0.0f};
float oscRate[4] = {1.0f,1.0f,1.0f,1.0f};
float oscPWM[4] = {0.5f,0.5f,0.5f,0.5f};

void setup()
{
  Serial.begin(38400);
 
  // make frequency (Hz) table
  double k = 1.059463094359; // 12th root of 2;
  double a = 6.875; // a
  a *= k; // b
  a *= k; // bb
  a *= k; // c, frequency of midi note 0
  for (int i = 0; i < 128; i++)
  {
    freqtab[i] = (float)a;
    a *= k;
  }

  pinMode(soundPin1, OUTPUT);
  pinMode(soundPin2, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(buttonPinPWM, INPUT);
   
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  ICR1 = 2000-1;
  TIMSK1 = _BV(TOIE1);
 
  sei(); // enable global interrupts 

  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/20000.0f) * freqtab[60];
  oscPWM[0] = 0.9f; 
}

void loop()
{
  if (!digitalRead(buttonPin)) testSampleRate(); else testPWM();
}

#define calcOSC(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= 1.0f) oscPos[a] -= 1.0f;
ISR(TIMER1_OVF_vect)
{
  if (oscPos[0] <= oscPWM[0]) PORTB &= B11111101; else PORTB |= B00000010;
  if (oscPos[1] <= oscPWM[1]) PORTD &= B11101111; else PORTD |= B00010000;
 
  calcOSC(0);
  calcOSC(1);
}

uint8_t isUp = true;
float pwmRate = 0.0001f;
void testPWM()
{
  if (!digitalRead(buttonPinPWM))
  {
    oscPWM[0] = 0.1f + (float(analogRead(analogInput))/1023.0f)/2.5f;
  }
  else
  {

    pwmRate = (float(analogRead(analogInput))/1023.0f) / 1000.0f;

    if (isUp)
    {
      oscPWM[0] += pwmRate;
      if (oscPWM[0] >= 0.5f) isUp = false;
    }
    else
    {
      oscPWM[0] -= pwmRate;
      if (oscPWM[0] <= 0.1f) isUp = true;
    }
  }
}


void testSampleRate()
{
  oscPWM[0] = 0.5f;
 
  ICR1 = 2000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/8000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (1.0f/8000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 1000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/16000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (1.0f/16000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/20000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (1.0f/20000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 400-1;
  oscRate[0] = oscRate[1] = (1.0f/40000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
 
  oscRate[0] = (1.0f/40000.0f) * freqtab[72];
  delay(100);
  oscRate[0] = (1.0f/40000.0f) * freqtab[84];
  delay(100);
  oscRate[0] = (1.0f/40000.0f) * freqtab[96];
  delay(100);
}

robtillaart

These comments are focussed on the freq table:

For generating a frequency table you better begin at the high end and do divisions - maybe not as fast, but errors don't add up.

Furthermore if you have the highest octave, you only need divisions by 2.
C8 = C8 /1;
C7 = C8 /2;
C6 = C8 /4;
C5 = C8 /8;
etc. ..

This means a smaller table is possible -  12 elements instead of 128 floats  (464 bytes of precious RAM) - comparison sketch below

Top down generation is 0.1 hz better compared to - http://www.phy.mtu.edu/~suits/notefreqs.html -

Code: [Select]

float ft[12];
float freqtab[128];

float FREQ(uint8_t t)
{
  uint8_t n = t/12;
  uint8_t o = t - n*12;
  return (ft[o]/(1 << (10-(n))));
}

void setup()
{
 Serial.begin(38400);

 // make frequency (Hz) table
 double k = 1.059463094359; // 12th root of 2;
 double A9 = 14080;
 A9*=k;
 A9*=k; // a
 for (int i = 11; i >=0; i--)
 {
   ft[i] = A9;
   A9 /= k;
 }

 // make frequency (Hz) table
 double a = 6.875; // a
 a *= k; // b
 a *= k; // bb
 a *= k; // c, frequency of midi note 0
 for (int i = 0; i < 128; i++)
 {
   freqtab[i] = (float)a;
   a *= k;
 }

 for (int i = 0; i<128; i++)
 {
   Serial.print(i, DEC);
   Serial.print(" - ");
   Serial.print(FREQ(i));
   Serial.print(" - ");
   Serial.println(freqtab[i]);
 }
}

void loop()
{
}

Disadvantage will be that the access takes more time than with full table, don't know if that is acceptable

another trick to make the table smaller is to use  uint16_t  to hold the frequency  multiplied by 8.0   (divide by 8.0 when read)
* formula :  f = (freqtab * 8 + 0.5);  // 0.5 for rounding
* Error in frequency is max 0.63%   (lowest octave)
* works for  freqtab(0..119) so not the full range - 127    
  => to get full range use factor 5.0 but error goes up to 0.96%

timing in micros
accessing all 128 elements in a loop assigning to a float.
                 total    per item
full  table:  196       1.53   factor 1
calc table: 5688      44.44  factor 29.0
int  table:  1652      12.90  factor 8.44    (multiplier 8 - other multipliers tested did worse)

Conclusion:

It is clear that memory and its access has its price.



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#5
Aug 12, 2011, 08:36 pm Last Edit: Aug 12, 2011, 08:44 pm by robtillaart Reason: 1
Quote
but I want more and at 40khz,

(OK my freq table remarks make no sense for speed up ;)

To optimize speed you need to get rid of the float math or at least optimize it.


some oneliners:

oscPWM[0] = 0.1f + (float(analogRead(analogInput))/1023.0f)/2.5f;
==>
oscPWM[0] = 0.1 + analogRead(analogInput) * 3,9100e-4;  // multiplication is cheaper than division

oscRate[2] = (1.0f/20000.0f) * freqtab[60];
==>
oscRate[2] = freqtab[60] * 0,00005;

pwmRate = (float(analogRead(analogInput))/1023.0f) / 1000.0f;
==>
pwmRate = analogRead(analogInput) * 9,775171e-7;


oscRate[0] = oscRate[1] = oscRate[2] = (1.0f/8000.0f) * freqtab[60];
==>
oscRate[0] = oscRate[1] = oscRate[2] =  0,000125 * freqtab[60];

etc



as I see in your code that entries of the freq table are divided by 4000,8000,16000, 20000, 40000.

Why not multiplying the freq table with the Greatest Common Divider 80000?  // do this in advance when generating the table
That would give a multiplications by 20, 10, 5, 4, and 2 which might be faster



You have some PWM calculation with values between 0 and 1.
Try to make unsigned longs of it and do the math in microseconds iso seconds
Maybe working in milliseconds is good enough  - multiply all floats with 512 and the error will be in the order of 0.5% max.

my 2 cents,
Rob

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

WilliamK Govinda

Thanks for the ideas, I will check each individually tomorrow.  8)

The real-time interrupt is where things needs optimization, everything else is not real-time, so its ok if its slow.

Code: [Select]
#define calcOSC(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= 1.0f) oscPos[a] -= 1.0f;
ISR(TIMER1_OVF_vect)
{
  if (oscPos[0] <= oscPWM[0]) PORTB &= B11111101; else PORTB |= B00000010;
  if (oscPos[1] <= oscPWM[1]) PORTD &= B11101111; else PORTD |= B00010000;
 
  calcOSC(0);
  calcOSC(1);
}


This is where I need to optimize as much as possible. So far I can get 2 voices at 20khz, which is not bad, but I want 4 voices at 40khz instead.  :smiley-fat: Them I can go crazy and see if I could do another thing with this, but that's for later on. ;-)

Wk

robtillaart

Code: [Select]
 
#define calcOSC(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= 1.0f) oscPos[a] -= 1.0f;
ISR(TIMER1_OVF_vect)
{
  if (oscPos[0] <= oscPWM[0]) PORTB &= B11111101; else PORTB |= B00000010;
  if (oscPos[1] <= oscPWM[1]) PORTD &= B11101111; else PORTD |= B00010000;
 
  calcOSC(0);
  calcOSC(1);
}


you are comparing floats, that takes time. See sketch below:
Code: [Select]

volatile float x = 1.0f;
volatile float y = 2.0f;
volatile long  k = 1;
volatile long  l = 2;
volatile int  p = 1;
volatile int  q = 2;
int a;

void setup()
{
  Serial.begin(115200);

  uint32_t before = millis();
  for(int i=0; i< 10000; i++)
  {
    if (x < y) a = 15;
    else a = 10;
  }
  Serial.println(millis()- before);

  before = millis();
  for(int i=0; i< 10000; i++)
  {
    if (k < l) a = 15;
    else a = 10;
  }
  Serial.println(millis()- before);

  before = millis();
  for(int i=0; i< 10000; i++)
  {
    if (p < q) a = 15;
    else a = 10;
  }
  Serial.println(millis()- before);
}

void loop()
{
}

my output (A2009)
47 - float compare
20 - long compare
13 - int compare

So there is a factor 2 or 3 to be gained.


Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart


OK, here is your code patched so the critical part is using int iso float. Hope I got all points patched, give it a try...
Rob

Code: [Select]

#define soundPin1 9 // See below for direct port manipulation
#define soundPin2 4 // See below for direct port manipulation
#define analogInput A2
#define buttonPin 12
#define buttonPinPWM 8

float freqtab[128];
// all multiplied by 10000
int oscPos[4] = {0,0,0,0};
int oscRate[4] = {10000,10000,10000,10000};
int oscPWM[4] = {5000,5000,5000,5000};

void setup()
{
  Serial.begin(38400);
 
  // make frequency (Hz) table
  double k = 1.059463094359; // 12th root of 2;
  double a = 6.875; // a
  a *= k; // b
  a *= k; // bb
  a *= k; // c, frequency of midi note 0
  for (int i = 0; i < 128; i++)
  {
    freqtab[i] = (float)a;
    a *= k;
  }

  pinMode(soundPin1, OUTPUT);
  pinMode(soundPin2, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(buttonPinPWM, INPUT);
   
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  ICR1 = 2000-1;
  TIMSK1 = _BV(TOIE1);
 
  sei(); // enable global interrupts 

  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (int) 10000 * (1.0f/20000.0f) * freqtab[60];
  oscPWM[0] = (int) 9000; // * 0.9f; 
}

void loop()
{
  if (!digitalRead(buttonPin)) testSampleRate(); else testPWM();
}

#define calcOSC(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= 10000) oscPos[a] -= 10000;
ISR(TIMER1_OVF_vect)
{
  if (oscPos[0] <= oscPWM[0]) PORTB &= B11111101; else PORTB |= B00000010;
  if (oscPos[1] <= oscPWM[1]) PORTD &= B11101111; else PORTD |= B00010000;
 
  calcOSC(0);
  calcOSC(1);
}

uint8_t isUp = true;
//float pwmRate = 0.0001f;
int pwmRate = 1; // 10000 * 0.0001f;
void testPWM()
{
  if (!digitalRead(buttonPinPWM))
  {
    oscPWM[0] = (int) 10000 * (0.1f + (float(analogRead(analogInput))/1023.0f)/2.5f);
  }
  else
  {

    pwmRate = (int) 10000 * (float(analogRead(analogInput))/1023.0f) / 1000.0f;

    if (isUp)
    {
      oscPWM[0] += pwmRate;
      // if (oscPWM[0] >= 0.5f) isUp = false;
      if (oscPWM[0] >= 5000) isUp = false;
    }
    else
    {
      oscPWM[0] -= pwmRate;
      // if (oscPWM[0] <= 0.1f) isUp = true;
      if (oscPWM[0] <= 1000) isUp = true;
    }
  }
}


void testSampleRate()
{
  oscPWM[0] = 5000; //0.5f;
 
  ICR1 = 2000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (int) 10000 * (1.0f/8000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (int) 10000 * (1.0f/8000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 1000-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (int) 10000 * (1.0f/16000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (int) 10000 * (1.0f/16000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = (int) 10000 * (1.0f/20000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
  oscRate[0] = (int) 10000 * (1.0f/20000.0f) * freqtab[72];
  delay(150);
 
  ICR1 = 400-1;
  oscRate[0] = oscRate[1] = (int) 10000 * (1.0f/40000.0f) * freqtab[60];
  delay(2000);
  if (digitalRead(buttonPin)) return;
 
  oscRate[0] = (int) 10000 * (1.0f/40000.0f) * freqtab[72];
  delay(100);
  oscRate[0] = (int) 10000 * (1.0f/40000.0f) * freqtab[84];
  delay(100);
  oscRate[0] = (int) 10000 * (1.0f/40000.0f) * freqtab[96];
  delay(100);
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

WilliamK Govinda

Oh, thank you so much, it works perfectly at 40khz and 4 Voices!!!!  8) <hug>

I have to check the final waveform if its good and the resolution of the fine-tune, but I understood what you did, and I agree with the math, should work.

I was googling like nuts on float to int differences, I know what each is, but to be honest, I never converted a float to int code before, this is the first time. I'm impressed on how simple that is, thanks again!

My project is open-source, so as soon as I have it ready, I will post videos and info here at the forum.  8)

Wk

WilliamK Govinda

Sadly Int won't do, I need to use Long, otherwise I can't make smooth fine-tune transitions. ;-)

Here's the code I'm testing, I bump up the resolution and still can get 40khz and 4 voices. But now there's a heck load of aliasing on some situations, something I will need to address at some other time.

Keep in mind that I didn't add the other 3 outputs correctly, but they are computed, so I can check for speed. Its just a change on the interrupt area. I will now check which PWM outputs I will use for the envelope and them decide the outputs for the 4 voices. I need to leave something to use for communication with another chip, so I have to check my options: I2C, SPI, UART, ...

Code: [Select]
#define soundPin1 9 // See below for direct port manipulation
#define soundPin2 4 // See below for direct port manipulation
#define analogInput A2
#define buttonPin 12
#define buttonPinPWM 8

float freqtab[128];
#define MULT 1000000
#define MULT2 500000
#define MTYPE long
MTYPE oscPos[4] = {0,0,0,0};
MTYPE oscRate[4] = {MULT,MULT,MULT,MULT};
MTYPE oscPWM[4] = {MULT2,MULT2,MULT2,MULT2};

void setup()
{
  // make frequency (Hz) table
  double k = 1.059463094359; // 12th root of 2;
  double a = 6.875; // a
  a *= k; // b
  a *= k; // bb
  a *= k; // c, frequency of midi note 0
  for (int i = 0; i < 128; i++)
  {
    freqtab[i] = (float)a;
    a *= k;
  }

  pinMode(soundPin1, OUTPUT);
  pinMode(soundPin2, OUTPUT);
  pinMode(buttonPin, INPUT);
  pinMode(buttonPinPWM, INPUT);
   
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10);
  ICR1 = 2000-1;
  TIMSK1 = _BV(TOIE1);
  sei();

  ICR1 = 800-1;
  oscRate[0] = oscRate[1] = oscRate[2] = oscRate[3] = (MTYPE) MULT * (1.0f/20000.0f) * freqtab[60];
  oscPWM[0] = MULT2;
}

void loop()
{
  if (!digitalRead(buttonPin)) testSampleRate(); else testPWM();
}

#define calcOSC(a) oscPos[a] += oscRate[a]; if (oscPos[a] >= MULT) oscPos[a] -= MULT;
ISR(TIMER1_OVF_vect)
{
  if (oscPos[0] <= oscPWM[0]) PORTB &= B11111101; else PORTB |= B00000010;
  if (oscPos[1] <= oscPWM[1]) PORTD &= B11101111; else PORTD |= B00010000;
  if (oscPos[2] <= oscPWM[2]) PORTD &= B11101111; else PORTD |= B00010000;
  if (oscPos[3] <= oscPWM[3]) PORTD &= B11101111; else PORTD |= B00010000;
 
  calcOSC(0);
  calcOSC(1);
  calcOSC(2);
  calcOSC(3);
}

uint8_t isUp = true;
MTYPE pwmRate = 1;
void testPWM()
{
  if (!digitalRead(buttonPinPWM))
  {
    oscPWM[0] = (MTYPE) MULT * (0.1f + (float(analogRead(analogInput))/1023.0f)/2.5f);
  }
  else
  {
    pwmRate = (MTYPE) MULT * (float(analogRead(analogInput))/1023.0f) / 1000.0f;
    if (isUp)
    {
      oscPWM[0] += pwmRate;
      if (oscPWM[0] >= MULT2) isUp = false;
    }
    else
    {
      oscPWM[0] -= pwmRate;
      if (oscPWM[0] <= 1000) isUp = true;
    }
  }
}

uint8_t firstPitchSwp = true;
void testSampleRate()
{
  oscPWM[0] = MULT2;
 
  if (!digitalRead(buttonPinPWM))
  {
    if (firstPitchSwp)
    {
      ICR1 = 400-1;
      firstPitchSwp = false;
      oscRate[0] = (MTYPE) MULT * (1.0f/40000.0f) * freqtab[60];
    }
   
    oscRate[0]++;
    delay(1);
  }
  else
  { 
    firstPitchSwp = true;
   
    ICR1 = 2000-1;
    oscRate[0] = oscRate[1] = oscRate[2] = oscRate[3] = (MTYPE) MULT * (1.0f/8000.0f) * freqtab[60];
    delay(2000);
    if (digitalRead(buttonPin)) return;
    oscRate[0] = (MTYPE) MULT * (1.0f/8000.0f) * freqtab[72];
    delay(150);
   
    ICR1 = 1000-1;
    oscRate[0] = oscRate[1] = oscRate[2] = oscRate[3] = (MTYPE) MULT * (1.0f/16000.0f) * freqtab[60];
    delay(2000);
    if (digitalRead(buttonPin)) return;
    oscRate[0] = (MTYPE) MULT * (1.0f/16000.0f) * freqtab[72];
    delay(150);
   
    ICR1 = 800-1;
    oscRate[0] = oscRate[1] = oscRate[2] = oscRate[3] = (MTYPE) MULT * (1.0f/20000.0f) * freqtab[60];
    delay(2000);
    if (digitalRead(buttonPin)) return;
    oscRate[0] = (MTYPE) MULT * (1.0f/20000.0f) * freqtab[72];
    delay(150);
   
    ICR1 = 400-1;
    oscRate[0] = oscRate[1] = oscRate[2] = oscRate[3] = (MTYPE) MULT * (1.0f/40000.0f) * freqtab[60];
    delay(2000);
   
    oscRate[0] = (MTYPE) MULT * (1.0f/40000.0f) * freqtab[72];
    delay(100);
    oscRate[0] = (MTYPE) MULT * (1.0f/40000.0f) * freqtab[84];
    delay(100);
    oscRate[0] = (MTYPE) MULT * (1.0f/40000.0f) * freqtab[96];
    delay(100);
  }
}

robtillaart

#11
Aug 12, 2011, 11:09 pm Last Edit: Aug 12, 2011, 11:35 pm by robtillaart Reason: 1
You are welcome,

Think you can get rid of all the floating point math as MULT = 1.000.000 you can savely rewrite this:

pwmRate = (MTYPE) MULT * (float(analogRead(analogInput))/1023.0f) / 1000.0f;
to
pwmRate = (1000 * analogRead())/1023;

// and as pwmRate will allways be between 0..1000 an int would be large enough.
etc

And it will be even faster too..

update --
a float has 6 or 7 digits of precision,  a long has 9....
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

WilliamK Govinda

Oh, indeed, tomorrow I will try some more, thank you so much. Should I put your name on the code now? ;-)

Wk

robtillaart

Quote
Should I put your name on the code now? ;-)

No definitely not, it's your idea, I only gave some optimizing tips

Now you use long and use a factor 1.000.000 as an int and factor 10.000 was not enough for finetuning

Consider the option of using an unsigned int. (0..65535) and scale a factor 50.000 -
==> gives you 5x as much room for finetuning and still the speed of int. (faster and smaller footprint than longs)



Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

WilliamK Govinda

I was wondering about that too, need to run some tests, txs again.

Wk

Go Up