Author Topic: Working on a polyphonic interrupter for atmega328p / Arduino UNO  (Read 1318 times)

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 143
  • Karma: +1/-0
    • View Profile
    • Zipdox
Code: [Select]
#include <MIDI.h>

#define samplingRate 62500
#define maxPlayingNotes 2

MIDI_CREATE_DEFAULT_INSTANCE();

float midiNotes[] = {8.18, 8.66, 9.18, 9.72, 10.3, 10.91, 11.56, 12.25, 12.98, 13.75, 14.57, 15.43, 16.35, 17.32, 18.35, 19.45, 20.6, 21.83, 23.12, 24.5, 25.96, 27.5, 29.14, 30.87, 32.7, 34.65, 36.71, 38.89, 41.2, 43.65, 46.25, 49, 51.91, 55, 58.27, 61.74, 65.41, 69.3, 73.42, 77.78, 82.41, 87.31, 92.5, 98, 103.83, 110, 116.54, 123.47, 130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94, 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392, 415.3, 440, 466.16, 493.88, 523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880, 932.33, 987.77, 1046.5, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 1567.98, 1661.22, 1760, 1864.66, 1975.53, 2093, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520, 3729.31, 3951.07, 4186.01, 4434.92, 4698.64, 4978.03, 5274.04, 5587.65, 5919.91, 6271.93, 6644.88, 7040, 7458.62, 7902.13, 8372.02, 8869.84, 9397.27, 9956.06, 10548.08, 11175.3, 11839.82, 12543.85};

typedef struct {
    byte pitch;
    int onTime;
    int offTime;
    int hasBeenOn;
} Note;

Note getNoteTimes(byte pitch, float dutyCycle){
  float period = samplingRate/midiNotes[pitch];
  Note finalNote = {pitch, round(dutyCycle*period), round((1-dutyCycle)*period), 0};
  return finalNote;
}

volatile Note playingNotes[maxPlayingNotes];


void handleNoteOn(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < maxPlayingNotes; i++){
        if(playingNotes[i].onTime == 0){ // 0 onTime means this note isn't in use
            playingNotes[i] = getNoteTimes(pitch, 0.1);
            break;
        }
    }
    digitalWrite(13, HIGH);
}

void handleNoteOff(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < maxPlayingNotes; i++){
        if(playingNotes[i].pitch == pitch){
            playingNotes[i] = {0,0,0,0}; // 0 onTime means it doesn't play
        }
    }
    digitalWrite(13, LOW);
}

void handlePitchBend(byte channel, int bend){
  float bendfactor = (1+ (float) bend/8190);
  float dutyCycle = 0.1;
  for(int i = 0; i < maxPlayingNotes; i++){
      if(playingNotes[i].onTime == 0) continue;
      float period = samplingRate/(bendfactor * midiNotes[playingNotes[i].pitch]);
      playingNotes[i].onTime = round(dutyCycle*period);
      playingNotes[i].offTime = round((1-dutyCycle)*period);
  }
}




void setup(){
    for(int i = 0; i<(sizeof(playingNotes)/sizeof(playingNotes[0])); i++){
        playingNotes[i] = {0,0,0,0};
    }

    pinMode(9, OUTPUT);
    pinMode(13, OUTPUT);

  cli(); //stop interrupts
  // set Timer/Counter Control Register to 0
  TCCR2B = 0;
 
  OCR2A = 0; // = 16000000 / (freq*prescaler) - 1 (must be <256)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS01 and CS00 bits for 64 prescaler
  TCCR2B |= (1 << CS20);
  // enable timer compare interrupt
  TIMSK2 |= (1 << OCIE2A);
  sei(); //allow interrupts


  MIDI.setHandleNoteOn(handleNoteOn);
  MIDI.setHandleNoteOff(handleNoteOff);
  MIDI.setHandlePitchBend(handlePitchBend);
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop(){
    MIDI.read();
}

volatile bool shouldPlay;
ISR(TIMER2_COMPA_vect){

  shouldPlay = false;
 
  for(int i = 0; i < maxPlayingNotes; i++){
    if(playingNotes[i].onTime == 0) continue;
    playingNotes[i].hasBeenOn++;
    if(playingNotes[i].hasBeenOn > playingNotes[i].onTime){
      playingNotes[i].hasBeenOn = -playingNotes[i].offTime;
    }
    if(playingNotes[i].hasBeenOn >= 0){
        shouldPlay = true;
    }
  }

  if(shouldPlay){
    PORTB |= 1 << 1;
  }else{
    PORTB &= ~(1 << 1);
  }

}

Currently it can only play 2 notes at the same time or else it gets stuck unable to receiver MIDI commands to turn off. I'm nut sure why but I'm guessing because the lack of CPU time to process Serial data because of interrupts.

Offline Netzpfuscher

  • High Voltage Technician
  • ***
  • Posts: 124
  • Karma: +10/-0
    • View Profile
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #1 on: March 24, 2020, 05:35:24 PM »
Your code is full of float calculations. It's possible that you ran out of CPU time. Float calculations on a 8bit micro without floating point unit is extremely expensive.
If you make your calculations with integer arithmetic you save a lot CPU.

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 143
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #2 on: March 24, 2020, 06:10:09 PM »
Your code is full of float calculations. It's possible that you ran out of CPU time. Float calculations on a 8bit micro without floating point unit is extremely expensive.
If you make your calculations with integer arithmetic you save a lot CPU.
The float calculations are for higher accuracy so it's not as out tune. But I'll try and see if I can get better performance with int.

Offline Netzpfuscher

  • High Voltage Technician
  • ***
  • Posts: 124
  • Karma: +10/-0
    • View Profile
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #3 on: March 24, 2020, 06:47:08 PM »
You simply need fixed point  ;)

Take a look at the function after line 130:
https://github.com/Netzpfuscher/UD3/blob/master/common/ud3core/tasks/tsk_midi.c

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 143
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #4 on: March 24, 2020, 08:24:49 PM »
You simply need fixed point  ;)

Take a look at the function after line 130:
https://github.com/Netzpfuscher/UD3/blob/master/common/ud3core/tasks/tsk_midi.c
I'm not very experienced with C, what do you mean?

Offline Netzpfuscher

  • High Voltage Technician
  • ***
  • Posts: 124
  • Karma: +10/-0
    • View Profile
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #5 on: March 24, 2020, 09:09:40 PM »
To make it simple.
Let's use your MIDI-Table and pick a number: 18.35 you also can represent it with 1835 if you multiply it by 100 or 12543.85 which is the "same" as 1254385. Both numbers fit in a uint32. And calculations with int/uint are fast on a Atmel. Floats needs emulation in Software which is extremely slow. So you can multiply all of your numbers by 100 make your calculations and at the end you can divide by 100 to get the integer part and make modulo operation to get the fraction. You need to care yourself not to overflow the variables ;)
But this is not so fast than another way (which I use) the first example is decimal, a decimal division or multiplication on a system without a hardware multiplier/divider is slow. But a binary multiplication/division is very fast. It's a shift operation. Divide by 2 is a right shift multiply by 2 is a left shift which takes only one clock cycle ;)

Lets use the number 12543.85 you can use 16 bits to store the 12543 and 16 bits to store the .85.
fixed_point_number = (12543<<16) + ((85*65535)/100) = 822073752 = ‭‭0011000011111111 1101100110011000‬

The conversion only needs to be done once at the beginning and at the end of the calculation. Or use precalculated values for the frequency in this format ;) And is has another advantage. Lets say you need to put the result in a 16 bit PWM Block or a 16 Bit DAC. Then you need no back calculation to decimal. You take your 32bit fixed point value shift it right value = value >>16 and you have it for your PWM block  8) But that everything works right all numbers in a calculation needs to be in this format. For integers it is simple just shift left and right and you have it.

For all of this there are premade librarys just google a bit for fixed point math.
« Last Edit: March 24, 2020, 09:15:06 PM by Netzpfuscher »

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 143
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #6 on: March 24, 2020, 09:32:09 PM »
To make it simple.
Let's use your MIDI-Table and pick a number: 18.35 you also can represent it with 1835 if you multiply it by 100 or 12543.85 which is the "same" as 1254385. Both numbers fit in a uint32. And calculations with int/uint are fast on a Atmel. Floats needs emulation in Software which is extremely slow. So you can multiply all of your numbers by 100 make your calculations and at the end you can divide by 100 to get the integer part and make modulo operation to get the fraction. You need to care yourself not to overflow the variables ;)
But this is not so fast than another way (which I use) the first example is decimal, a decimal division or multiplication on a system without a hardware multiplier/divider is slow. But a binary multiplication/division is very fast. It's a shift operation. Divide by 2 is a right shift multiply by 2 is a left shift which takes only one clock cycle ;)

Lets use the number 12543.85 you can use 16 bits to store the 12543 and 16 bits to store the .85.
fixed_point_number = (12543<<16) + ((85*65535)/100) = 822073752 = ‭‭0011000011111111 1101100110011000‬

The conversion only needs to be done once at the beginning and at the end of the calculation. Or use precalculated values for the frequency in this format ;) And is has another advantage. Lets say you need to put the result in a 16 bit PWM Block or a 16 Bit DAC. Then you need no back calculation to decimal. You take your 32bit fixed point value shift it right value = value >>16 and you have it for your PWM block  8) But that everything works right all numbers in a calculation needs to be in this format. For integers it is simple just shift left and right and you have it.

For all of this there are premade librarys just google a bit for fixed point math.
I will try to convert it to fixed point.

High Voltage Forum

Re: Working on a polyphonic interrupter for atmega328p / Arduino UNO
« Reply #6 on: March 24, 2020, 09:32:09 PM »

 


* Recent Topics and Posts

post Re: Tesla Coil Show Controller Project
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Max
Today at 11:13:18 AM
post Re: repair of Panasonic microwave inverter
[Electronic Circuits]
Weston
Today at 10:08:34 AM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
davekni
Today at 03:20:42 AM
post Re: repair of Panasonic microwave inverter
[Electronic Circuits]
Twospoons
Today at 03:16:27 AM
post 3kW Cisco Server Supply teardown and help needed
[Electronic Circuits]
Da_Stier
July 23, 2021, 09:23:11 PM
post Re: IGBT question
[Dual Resonant Solid State Tesla coils (DRSSTC)]
thedoc298
July 23, 2021, 08:05:58 PM
post Re: IGBT question
[Dual Resonant Solid State Tesla coils (DRSSTC)]
futurist
July 23, 2021, 07:02:18 PM
post Re: IGBT question
[Dual Resonant Solid State Tesla coils (DRSSTC)]
thedoc298
July 23, 2021, 05:33:57 PM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
GKnapp
July 23, 2021, 04:51:37 PM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
davekni
July 23, 2021, 03:52:46 AM
post Re: IGBT question
[Dual Resonant Solid State Tesla coils (DRSSTC)]
thedoc298
July 22, 2021, 10:59:32 PM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
GKnapp
July 22, 2021, 08:50:34 PM
post Re: IGBT question
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Mads Barnkob
July 22, 2021, 08:47:23 PM
post Help needed - which IGBT module to buy
[Dual Resonant Solid State Tesla coils (DRSSTC)]
thedoc298
July 22, 2021, 07:01:24 PM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
davekni
July 22, 2021, 06:50:07 AM
post Re: Proper phase lead adjustment at the input
[Dual Resonant Solid State Tesla coils (DRSSTC)]
davekni
July 22, 2021, 06:39:37 AM
post Re: Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
alan sailer
July 21, 2021, 07:55:03 PM
post Horrible waveforms advice--just bad test setup?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
GKnapp
July 21, 2021, 06:34:13 PM
post Re: Global shutter synchronized to arcs?
[DSLR]
Uspring
July 21, 2021, 05:10:18 PM
post Re: Tesla Coil Show Controller Project
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Mads Barnkob
July 21, 2021, 12:42:29 PM
post Re: Proper phase lead adjustment at the input
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Chrisader
July 21, 2021, 08:15:00 AM
post Re: Proper phase lead adjustment at the input
[Dual Resonant Solid State Tesla coils (DRSSTC)]
davekni
July 21, 2021, 04:57:04 AM
post Re: Micro-power continuity checker.
[Electronic Circuits]
davekni
July 21, 2021, 03:50:33 AM
post Re: Skm flyback destroyer 🤗
[Transformer (Ferrite Core)]
oneKone
July 21, 2021, 01:50:19 AM
post Proper phase lead adjustment at the input
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Chrisader
July 20, 2021, 10:06:14 PM
post Re: Micro-power continuity checker.
[Electronic Circuits]
klugesmith
July 20, 2021, 06:24:29 PM
post Micro-power continuity checker.
[Electronic Circuits]
davekni
July 20, 2021, 05:37:36 AM
post Re: Help needed with SSTC. First TC build
[Solid State Tesla Coils (SSTC)]
davekni
July 20, 2021, 05:08:24 AM
post Re: Global shutter synchronized to arcs?
[DSLR]
davekni
July 20, 2021, 04:43:05 AM
post Re: Global shutter synchronized to arcs?
[DSLR]
TMaxElectronics
July 20, 2021, 12:09:36 AM
post Re: Help needed with SSTC. First TC build
[Solid State Tesla Coils (SSTC)]
AstRii
July 19, 2021, 11:13:13 PM
post Another question on CT Feedback
[Solid State Tesla Coils (SSTC)]
Maverikie
July 19, 2021, 08:56:04 PM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
newage
July 19, 2021, 07:09:56 PM
post Re: Global shutter synchronized to arcs?
[DSLR]
klugesmith
July 19, 2021, 06:49:08 PM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
klugesmith
July 19, 2021, 04:39:05 PM
post Global shutter synchronized to arcs?
[DSLR]
davekni
July 19, 2021, 06:32:35 AM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
MRMILSTAR
July 19, 2021, 05:22:51 AM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
newage
July 19, 2021, 04:24:38 AM
post Re: a typical sstc half bridge design, any considerations or tips?
[Solid State Tesla Coils (SSTC)]
eli
July 19, 2021, 12:35:18 AM
post Re: a typical sstc half bridge design, any considerations or tips?
[Solid State Tesla Coils (SSTC)]
Mads Barnkob
July 19, 2021, 12:15:43 AM
post a typical sstc half bridge design, any considerations or tips?
[Solid State Tesla Coils (SSTC)]
eli
July 18, 2021, 11:44:03 PM
post Re: HFSSTC design help and questions
[Solid State Tesla Coils (SSTC)]
eli
July 18, 2021, 09:33:40 PM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
johnf
July 18, 2021, 09:07:15 PM
post Re: Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
MRMILSTAR
July 18, 2021, 03:38:01 PM
post Best and stable version of video
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Transgarp
July 18, 2021, 03:33:31 PM
post Sync RSG motor problems - help and thoughts needed
[Spark Gap Tesla Coils (SGTC)]
newage
July 18, 2021, 01:30:46 PM
post Re: DRSSTC design advise / Primary peak current calculation
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Mads Barnkob
July 17, 2021, 10:05:39 AM
post Re: DRSSTC design advise / Primary peak current calculation
[Dual Resonant Solid State Tesla coils (DRSSTC)]
alan sailer
July 16, 2021, 11:01:43 PM
post Re: DRSSTC design advise / Primary peak current calculation
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Martin
July 16, 2021, 09:55:50 AM
post Re: Skm flyback destroyer 🤗
[Transformer (Ferrite Core)]
Patrick
July 16, 2021, 09:54:50 AM

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
SimplePortal 2.3.6 © 2008-2014, SimplePortal