Author Topic: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)  (Read 452 times)

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« on: September 27, 2020, 11:43:14 PM »
I wrote a polyphonic interrupter for the Bluepill.


It uses the STM32duino core for programming.
Here's the code:

Code: (c) [Select]
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define sampling_rate 96000
#define max_playing_notes 8

float note_numerator = sampling_rate/440.0;
int notePeriod(float pitch){
    return note_numerator/pow(2, (pitch-69)/12.0);
}

typedef struct {
    byte pitch;
    int on_time;
    int off_time;
    int been_on;
} Note;

Note playing_notes[max_playing_notes];

void handleNoteOn(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0){
            int period = notePeriod(pitch);
            playing_notes[i] = {pitch, 10, period-10, 0};
            break;
        }
    }
    digitalWrite(LED_BUILTIN, LOW);
}

void handleNoteOff(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].pitch == pitch) playing_notes[i].on_time = 0;
    }
    digitalWrite(LED_BUILTIN, HIGH);
}

void sample(void){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time != 0) playing_notes[i].been_on++;
    }
}

void setup()
{
   
    pinMode(PB9, OUTPUT);
    digitalWrite(PB9, LOW);
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);

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

    MIDI.setHandleNoteOn(handleNoteOn);
    MIDI.setHandleNoteOff(handleNoteOff);
    MIDI.begin(MIDI_CHANNEL_OMNI);

    HardwareTimer *MyTim = new HardwareTimer(TIM2);
    MyTim->setOverflow(sampling_rate, HERTZ_FORMAT);
    MyTim->attachInterrupt(sample);
    MyTim->resume();
}

void loop()
{
    MIDI.read();
    bool play = false;
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0) continue;
        if(playing_notes[i].been_on > playing_notes[i].on_time) playing_notes[i].been_on = -playing_notes[i].off_time;
        if(playing_notes[i].been_on >= 0) play = true;
    }
    if(play){
        digitalWrite(PB9, HIGH);
    }else{
        digitalWrite(PB9, LOW);
    }
}
License: GPL-3

Offline TMaxElectronics

  • High Voltage Experimenter
  • **
  • Posts: 92
  • Karma: +3/-0
    • View Profile
    • My random (and very empty) electronics blog
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #1 on: September 28, 2020, 01:14:46 AM »
Cool project :D quite a bit simpler that either my MidiStick or max's synthterrupter

a few things I noticed though:

It seems to me like you don't take velocity or volume into account, since that should be a simple addition I highly recommend it, especially if you have many voices. Sometimes a song gets unexpectedly intense with the amount of notes playing at a given time, and with your code you can't really do much about it once the code is uploaded. Since you don't have adsr all you need to add is maybe a macro for the maximum ontime and then use the MIDI_VOLUME command to scale a variable from 0 to the max from the macro, which is then used as the on-time setting for the notes.

It also doesn't seem like you have any duty limiting, which is a very risky thing with a 8-voice polyphonic interrupter. If you play many high notes (or even many low ones) the duty cycle could get very high, putting a lot of thermal stress onto your IGBTs. The way I'd recommend to do this is to just add all the on-times of active notes together whenever a note event (either on or off) occurs, and if that total on-time is too much you scale back all notes by the amount by which the total value is too large. My interrupter uses a different approach that is quite complex and not really needed here. Here is how the synthterrupter does it (older code, but the idea is still the same): https://github.com/MMMZZZZ/Syntherrupter/blob/80f99ee601b220f3aca8894f0c15684e727fd0e8/Syntherrupter_Tiva/MIDI.cpp#L920

And finally the last thing that I didn't find was a note holdoff,  which isn't really that important for a SSTC but very much so if you maybe want to upgrade to drsstc at some point. With a DRSSTC the current in the primary circuit continues to oscillate a bit after the interrupter pulse goes low as the energy is slowly put back into the bus caps. If however the interrupter is triggered again during this ring down (f.E. a note pulse occurs almost immediately after the end of another), the start "kick" or start oscillator (depending on the driver) would cause hard switching of the IGBTs, which if it occurs once might be fine, but if it happens too often it will probably kill the IGBTs. I believe that SSTCs don't have that problem, but I'm not 100% sure. If you want to implement this you could just add a variable that stores the system time of the last "output off", and whenever you switch it on again you check if the time is larger than a preset value.

Not so say of course that the interrupter is no good or anything like that, everybody starts somewhere and my intention is to tell you what I would have liked to read when starting work on my first one :D

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #2 on: September 28, 2020, 01:27:07 AM »
This is still the first version. I just coded this quickly to see if the Bluepill is powerful enough for the job and I can say it very much is.

I still have to add pitchbend and velocity. I'll also try to figure something out to make lower notes louder because the low duty cycle makes them almost inaudible when higher notes play. Perhaps some kind of duty cycle sharing.

As for the note holdoff, I think that's a little too complicated for me. I'm still new to C.

Offline Max

  • High Voltage Technician
  • ***
  • Posts: 108
  • Karma: +10/-0
  • "With the first link, the chain is forged. [...]"
    • View Profile
    • My Youtube Channel
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #3 on: September 28, 2020, 04:44:56 PM »
Less than 80 lines of code - okay that's minimalistic! Now no one can say anymore that polyphony would be hard to do.  ;D Anyways, sounds already pretty good!

Note holdoff is really not that difficult at all. Add one more variable that you increment in your ISR just like the notes. It will be the holdoff. Then, in the if (been_on > ontime) section, you reset the holdoff to 0. Why? Well, if you enter that if, an ontime has ended and thus we want to wait for the holdoff time before the next ontime plays. Third change: replace the "if (play)" by "if (play && holdoff >= minHoldoff)". And you're done :)

This is a very simple approach but it has one disadvantage: the holdoff does not increase the time "between" ontimes but effectively omits a part of the next ontime. If two ontimes follow each other closely, the second one will be shortened by the holdoff time. This will probably be quite audible since 10-50us less ontime do make a big difference. On the other side, since there was an ontime just before this one it might not matter that much.
How to fix this? You could try the following. Only increment the been_on counters if the holdoff is above its threshold (and increment the holdoff otherwise). This does cause some jitter in the frequency of the notes but I'd guess this is less audible than the changing ontime. I'd definitely try both! ;)

Considering your issue with lower notes. In your video the very lowest note - even when playing alone is almost not audible at all (at 0:08 f.ex.). Are you 100% sure that it did really play at the same, constant ontime as the other notes? Your code looks like it should but the way it sounds would make me check it with a scope.
That aside, I thought about something similar for my Syntherrupter and came up with this: low notes play at constant duty, high notes at constant ontime, both values can be specified by the user. Crossover between modes happens at the frequency where both result in the same ontime. I explained it in details here: https://highvoltageforum.net/index.php?topic=1020.msg8564#msg8564
The code for this is not hard at all. You calculate the crossover frequency (or the MIDI pitch value corresponding to that frequency) once when the duty and/or ontime settings change. Then, in your handleNoteOn: if the note's frequency is above the crossover frequency, set ontime to the given value, otherwhise set the ontime to the given percentage of the notes period.
Here's the source code for the crossover frequency (line 433-445): https://github.com/MMMZZZZ/Syntherrupter/blob/d52c01bdb566ff2c13969cbc9f7b3510c9f22e47/Syntherrupter_Tiva/MIDI.cpp#L433
And here's the calculation of the ontime (line 691-699): https://github.com/MMMZZZZ/Syntherrupter/blob/d52c01bdb566ff2c13969cbc9f7b3510c9f22e47/Syntherrupter_Tiva/MIDI.cpp#L691


Kind regards,
Max

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #4 on: September 28, 2020, 06:28:50 PM »
I cooked up some new code. It uses duty cycle per note instead of a fixed pulse width. It ranges from 0.5% to 2.5% duty cycle per note depending on velocity. This increases the quality of low notes drastically.
Code: (c) [Select]
// GPL-3.0
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define sampling_rate 96000
#define max_playing_notes 5
#define max_pitch 104

float note_numerator = sampling_rate/440.0;
int notePeriod(float pitch){
    while(pitch > max_pitch){
        pitch -= 12;
    }
    return note_numerator/pow(2, (pitch-69)/12.0);
}

typedef struct {
    byte channel;
    byte pitch;
    int on_time;
    int off_time;
    int been_on;
} Note;

Note playing_notes[max_playing_notes];

const float min_duty_cycle = 127/4.0;
const float duty_cycle_multiplier = 1/(min_duty_cycle+127)*0.025;
void handleNoteOn(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0){
            int period = notePeriod(pitch);
            float duty_cycle = (min_duty_cycle+velocity)*duty_cycle_multiplier;
            int on_time = duty_cycle*period;
            playing_notes[i] = {channel, pitch, on_time, period-on_time, 0};
            break;
        }
    }
}

void handleNoteOff(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].pitch == pitch) playing_notes[i].on_time = 0;
    }
}

void handlePitchBend(byte channel, int bend){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].channel != channel) continue;
        int period = notePeriod(playing_notes[i].pitch + bend/4096.0);
        playing_notes[i].off_time = period-10;
    }
}

void sample(void){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time != 0) playing_notes[i].been_on++;
    }
}

void handleStop(){
    for(int i = 0; i < max_playing_notes; i++){
        playing_notes[i].on_time = 0;
    }
}

void setup(){
    pinMode(PB9, OUTPUT);
    digitalWrite(PB9, LOW);

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

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

    HardwareTimer *MyTim = new HardwareTimer(TIM2);
    MyTim->setOverflow(sampling_rate, HERTZ_FORMAT);
    MyTim->attachInterrupt(sample);
    MyTim->resume();
}

void loop(){
    MIDI.read();
    bool play = false;
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0) continue;
        if(playing_notes[i].been_on > playing_notes[i].on_time) playing_notes[i].been_on = -playing_notes[i].off_time;
        if(playing_notes[i].been_on >= 0) play = true;
    }
    if(play){
        digitalWrite(PB9, HIGH);
    }else{
        digitalWrite(PB9, LOW);
    }
}
I'm thinking about using some sort of lookup table for the pulse width depending on pitch. I'll have to figure out how to take velocity into account.

Only a slight problem; higher notes fail to make the SSTC pulse properly, because the pulses are too short, and so they are very hard to hear.

« Last Edit: September 28, 2020, 06:33:49 PM by Zipdox »

Offline Max

  • High Voltage Technician
  • ***
  • Posts: 108
  • Karma: +10/-0
  • "With the first link, the chain is forged. [...]"
    • View Profile
    • My Youtube Channel
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #5 on: September 28, 2020, 11:48:25 PM »
Hi,


I'm thinking about using some sort of lookup table for the pulse width depending on pitch.
Uhm... don't think this would be necessary...? LUTs are useful if the calculation of the right value would take too much time but currently you don't face such a lag of processing time I think?

I'll have to figure out how to take velocity into account.
As a factor. You have the nominal ontime, f.ex. based on the period of the note, and then multiply it with velocity/128. So your velocity scales the ontime between 0 and the nominal value. Note: Your microcontroller doesn't have an FPU, meaning you should avoid floating point calculations whereever possible.

Only a slight problem; higher notes fail to make the SSTC pulse properly, because the pulses are too short, and so they are very hard to hear.
Of course they are! That's exactly what I described and linked from my previous post, including a quite simple solution.


Kind regards,
Max

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #6 on: October 02, 2020, 10:56:24 PM »
Code: (c) [Select]
#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

#define sampling_rate 96000
#define max_playing_notes 5
#define max_pitch 104

float note_periods[128] = {11741.9717620882, 11082.9455264689, 10460.9075912845, 9873.78196275034, 9319.60916365988, 8796.53969381148, 8302.82785747354, 7836.82593728726, 7396.97869516308, 6981.81818181818, 6589.95883763219, 6220.09286847073, 5870.98588104412, 5541.47276323444, 5230.45379564223, 4936.89098137517, 4659.80458182994, 4398.26984690574, 4151.41392873677, 3918.41296864363, 3698.48934758154, 3490.90909090909, 3294.97941881609, 3110.04643423537, 2935.49294052206, 2770.73638161722, 2615.22689782112, 2468.44549068758, 2329.90229091497, 2199.13492345287, 2075.70696436839, 1959.20648432181, 1849.24467379077, 1745.45454545455, 1647.48970940805, 1555.02321711768, 1467.74647026103, 1385.36819080861, 1307.61344891056, 1234.22274534379, 1164.95114545748, 1099.56746172643, 1037.85348218419, 979.603242160907, 924.622336895385, 872.727272727273, 823.744854704023, 777.511608558842, 733.873235130515, 692.684095404305, 653.806724455279, 617.111372671896, 582.475572728742, 549.783730863217, 518.926741092097, 489.801621080454, 462.311168447692, 436.363636363636, 411.872427352012, 388.755804279421, 366.936617565257, 346.342047702153, 326.90336222764, 308.555686335948, 291.237786364371, 274.891865431609, 259.463370546048, 244.900810540227, 231.155584223846, 218.181818181818, 205.936213676006, 194.37790213971, 183.468308782629, 173.171023851076, 163.45168111382, 154.277843167974, 145.618893182186, 137.445932715804, 129.731685273024, 122.450405270113, 115.577792111923, 109.090909090909, 102.968106838003, 97.1889510698552, 91.7341543913143, 86.5855119255382, 81.7258405569099, 77.138921583987, 72.8094465910928, 68.7229663579022, 64.8658426365121, 61.2252026350567, 57.7888960559616, 54.5454545454546, 51.4840534190015, 48.5944755349276, 45.8670771956572, 43.2927559627691, 40.862920278455, 38.5694607919935, 36.4047232955464, 34.3614831789511, 32.432921318256, 30.6126013175284, 28.8944480279808, 27.2727272727273, 25.7420267095007, 24.2972377674638, 22.9335385978286, 21.6463779813845, 20.4314601392275, 19.2847303959968, 18.2023616477732, 17.1807415894755, 16.216460659128, 15.3063006587642, 14.4472240139904, 13.6363636363636, 12.8710133547504, 12.1486188837319, 11.4667692989143, 10.8231889906923, 10.2157300696137, 9.64236519799838, 9.1011808238866, 8.59037079473777, 8.10823032956401, 7.65315032938209};
float note_numerator = sampling_rate/440.0;
float notePeriod(float pitch){
    while(pitch > max_pitch){
        pitch -= 12;
    }
    return note_numerator/pow(2, (pitch-69)/12.0);
}

typedef struct {
    byte channel;
    byte pitch;
    int on_time;
    int off_time;
    int been_on;
    byte velocity;
} Note;

Note playing_notes[max_playing_notes];

const float min_duty_cycle = 127/4.0;
const float duty_cycle_multiplier = 1/(min_duty_cycle+127)*0.025;
void handleNoteOn(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0){
            float period = note_periods[pitch];
            float duty_cycle = (min_duty_cycle+velocity)*duty_cycle_multiplier;
            int on_time = duty_cycle*period;
            if(on_time < 5 && pitch >= 80){
                on_time = 5;
            }else if(on_time < 6 && pitch < 80){
                on_time = 6;
            }
            playing_notes[i] = {channel, pitch, on_time, period-on_time, 0, velocity};
            break;
        }
    }
}

void handleNoteOff(byte channel, byte pitch, byte velocity){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].pitch == pitch) playing_notes[i].on_time = 0;
    }
}

void handlePitchBend(byte channel, int bend){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].channel != channel) continue;
        float period = notePeriod(playing_notes[i].pitch + bend/4096.0);
        float duty_cycle = (min_duty_cycle+playing_notes[i].velocity)*duty_cycle_multiplier;
        int on_time = duty_cycle*period;
        if(on_time < 5 && playing_notes[i].pitch >= 80){
            on_time = 5;
        }else if(on_time < 6 && playing_notes[i].pitch < 80){
            on_time = 6;
        }
        playing_notes[i].on_time = on_time;
        playing_notes[i].off_time = period-on_time;
    }
}

void sample(void){
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time != 0) playing_notes[i].been_on++;
    }
}

void handleStop(){
    for(int i = 0; i < max_playing_notes; i++){
        playing_notes[i].on_time = 0;
    }
}

void setup(){
    pinMode(PB9, OUTPUT);
    digitalWrite(PB9, LOW);

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

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

    HardwareTimer *MyTim = new HardwareTimer(TIM2);
    MyTim->setOverflow(sampling_rate, HERTZ_FORMAT);
    MyTim->attachInterrupt(sample);
    MyTim->resume();
}

void loop(){
    MIDI.read();
    bool play = false;
    for(int i = 0; i < max_playing_notes; i++){
        if(playing_notes[i].on_time == 0) continue;
        if(playing_notes[i].been_on > playing_notes[i].on_time) playing_notes[i].been_on = -playing_notes[i].off_time;
        if(playing_notes[i].been_on >= 0) play = true;
    }
    if(play){
        digitalWrite(PB9, HIGH);
    }else{
        digitalWrite(PB9, LOW);
    }
}

Offline TMaxElectronics

  • High Voltage Experimenter
  • **
  • Posts: 92
  • Karma: +3/-0
    • View Profile
    • My random (and very empty) electronics blog
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #7 on: October 03, 2020, 01:36:46 AM »
Interesting idea with that LUT, but I'm not convinced to be honest (might be because I don't really understand it :P). My Midistick doesn't do any pulse stretching at lower frequencies and sounds fine (in my opinion). But I tend to use midi files that have backing and melody on separate tracks and then use the volume adjust for each to get the mixing right, at least something where my experience mixing bands comes in handy these days...

It also seems a little like the notes are being drowned out by another. Polyphony is great, but it puts a lot of responsibility on the user to select the right tracks to be played. If there are too many different notes playing it gets a little confusing ;) It also makes a difference whether the notes are harmonic to another (in a chord) or a completely different melody. I usually try to keep it to two tracks per synth/coil that play notes at any given moment in time (with a maximum of four simultaneous notes), everything else gets too messy in my opinion. Another thing that could help with that is sustain (where the note volume constantly drops off as it is played), but that would be a major addition to the code, so maybe a long term goal :D You can read up on the envelope of a note if you are interested: https://en.wikipedia.org/wiki/Envelope_(music)

I'm also curious which midi player you use. Everybody seems to have a different preference there :D

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #8 on: October 03, 2020, 02:36:03 AM »
I use my phone with an OTG dongle and one of those cheap USB MIDI cables and this app. The MIDI cable is suboptimal because it has a shitty connector loose that can cause messages dropping. Also I patched the app with lucky patcher to remove the ads  ;)

Offline TMaxElectronics

  • High Voltage Experimenter
  • **
  • Posts: 92
  • Karma: +3/-0
    • View Profile
    • My random (and very empty) electronics blog
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #9 on: October 03, 2020, 02:38:57 PM »
I guess you use the app because you don't have a laptop and don't want to carry your desktop around right? It might be worth looking into using the usb module of the STM32 to do direct USB-Midi conversion. That would circumvent any issues with midi cables and make it easier to use. I didn't read everything but this seems like a god place to start: https://stm32duinoforum.com/forum/viewtopic_f_28_t_4442.html

My MidiStick also communicates this way, and it is actually pretty simple, as long as you don't want to dynamically rename devices or use multiple of them. The dynamic device name stuff took me best part of a month to get working properly ::)

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #10 on: October 06, 2020, 12:41:33 AM »
I can use my laptop but I's slightly inconvenient.
Regarding using USB, I looked into it but I couldn't find any USB libraries that are compatible with the STM32Duino core. USBComposite requires a different core that I was unable to get working. I might try again when I have more time on my hands. I'm kinda busy this week.
« Last Edit: October 06, 2020, 12:43:55 AM by Zipdox »

Offline profdc9

  • High Voltage Engineer
  • ****
  • Posts: 248
  • Karma: +12/-0
    • View Profile
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #11 on: October 07, 2020, 04:43:20 AM »
I used the USBComposite library for my vector network analyzer ( http://www.github.com/profdc9/VNA ) and Roger's stm32duino core.  You can use it in place of the built-in USB serial if you compile without it.    For example:


void usb_init_serial()
{
  if (usb_initialized)
    USBComposite.end();
  usb_initialized = 1;
  usb_reenumerate();
  USBComposite.clear();
  USBComposite.setProductId(VENDOR_ID);
  USBComposite.setProductId(SERIAL_CDC_PRODUCT_ID);
  CompositeSerial.registerComponent();
  console_setMainSerial(&CompositeSerial);
  USBComposite.begin();
  //while (!USBComposite.isReady());
}

bool usb_init_mass_storage()
{
  DWORD sectors;
  flash_mount_fs_card();
  if (!flash_fs_mounted) return false;
  if (disk_ioctl(0, GET_SECTOR_COUNT, &sectors) != RES_OK) return false;
 
  if (usb_initialized)
    USBComposite.end();
  usb_initialized = 1;
  usb_reenumerate();
  USBComposite.clear();
  USBComposite.setProductId(VENDOR_ID);
  USBComposite.setProductId(MASS_STORAGE_PRODUCT_ID);
  MassStorage.setDriveData(0, sectors, sd_read, sd_write);
  MassStorage.registerComponent();
  console_setMainSerial(NULL);
  USBComposite.begin();
  while (!USBComposite.isReady());
  return true;
}


I have not tried the MIDI support, however, but the USBSerial and USBMassStorage works for me.

I can use my laptop but I's slightly inconvenient.
Regarding using USB, I looked into it but I couldn't find any USB libraries that are compatible with the STM32Duino core. USBComposite requires a different core that I was unable to get working. I might try again when I have more time on my hands. I'm kinda busy this week.
« Last Edit: October 07, 2020, 04:45:34 AM by profdc9 »

Offline TMaxElectronics

  • High Voltage Experimenter
  • **
  • Posts: 92
  • Karma: +3/-0
    • View Profile
    • My random (and very empty) electronics blog
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #12 on: October 07, 2020, 02:35:18 PM »
The biggest trouble is setting the USB config descriptor for midi... that took me a few days to get right on the midiStick, the best info I found is the original spec (from 1999 :P). Just google "midi10.pdf".

Once you have that working and manage to receive packets, you deal with them just like normal midi packets, but keep in mind that the actual packet starts at data[1] as the data[0] is the virtual cable ID.

Offline Zipdox

  • High Voltage Technician
  • ***
  • Posts: 104
  • Karma: +1/-0
    • View Profile
    • Zipdox
Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #13 on: October 24, 2020, 07:02:13 PM »
I fixed pitch bend and made the program calculate the lookup tables at startup. I also uploaded the code to GitHub.
https://github.com/Zipdox/STM32_Interrupter
Pitch bend demo

High Voltage Forum

Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
« Reply #13 on: October 24, 2020, 07:02:13 PM »

 


* Recent Topics and Posts

post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
Today at 09:41:48 AM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
plasma
Today at 01:46:20 AM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 24, 2020, 11:12:37 PM
post Re: CM600DU-24NF availability or substitute?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
October 24, 2020, 11:07:33 PM
post Re: Welcome new members, come say hello and tell a little about yourself :)
[General Chat]
Daniel Uhrenholt
October 24, 2020, 10:45:41 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
October 24, 2020, 10:12:37 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Mads Barnkob
October 24, 2020, 09:29:06 PM
post Re: Welcome new members, come say hello and tell a little about yourself :)
[General Chat]
Mads Barnkob
October 24, 2020, 09:20:37 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 24, 2020, 09:07:24 PM
post Re: Software for playing MIDIs
[Computers, Microcontrollers, Programmable Logic, Interfaces and Displays]
Zipdox
October 24, 2020, 07:29:57 PM
post Re: Polyphonic Interrupter with STM32F103C8T6 (Bluepill)
[Computers, Microcontrollers, Programmable Logic, Interfaces and Displays]
Zipdox
October 24, 2020, 07:02:13 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
October 24, 2020, 06:38:42 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 24, 2020, 05:42:49 PM
post Software for playing MIDIs
[Computers, Microcontrollers, Programmable Logic, Interfaces and Displays]
Max
October 24, 2020, 04:37:26 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
October 24, 2020, 03:51:52 PM
post Re: DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 24, 2020, 02:25:00 PM
post Re: Welcome new members, come say hello and tell a little about yourself :)
[General Chat]
Daniel Uhrenholt
October 24, 2020, 12:12:41 PM
post MOVED: DIY current transformer for scoping primary current?
[Solid State Tesla Coils (SSTC)]
Kizmo
October 24, 2020, 11:45:58 AM
post DIY current transformer for measuring primary current?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Daniel Uhrenholt
October 24, 2020, 11:22:24 AM
post Re: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Science, Research and News In Other Fields Than Electronics]
davekni
October 24, 2020, 04:16:06 AM
post Re: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Science, Research and News In Other Fields Than Electronics]
davekni
October 24, 2020, 04:07:24 AM
post Re: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Science, Research and News In Other Fields Than Electronics]
Twospoons
October 23, 2020, 11:39:35 PM
post Re: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Science, Research and News In Other Fields Than Electronics]
Hydron
October 23, 2020, 07:10:22 PM
post Re: QCW with replaceable ferrite-core primary
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 23, 2020, 05:36:02 PM
post Re: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Science, Research and News In Other Fields Than Electronics]
klugesmith
October 23, 2020, 05:34:39 PM
post MOVED: Ping pong (and pumpkin?) cannons - split from ferrite-core QCW topic
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Hydron
October 23, 2020, 05:27:45 PM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
Uspring
October 23, 2020, 03:03:28 PM
post Re: RC snubbers
[Solid State Tesla Coils (SSTC)]
davekni
October 23, 2020, 12:27:42 AM
post Re: RC snubbers
[Solid State Tesla Coils (SSTC)]
AstRii
October 22, 2020, 10:06:59 PM
post Re: RC snubbers
[Solid State Tesla Coils (SSTC)]
Mads Barnkob
October 22, 2020, 09:05:22 PM
post Re: RC snubbers
[Solid State Tesla Coils (SSTC)]
davekni
October 22, 2020, 07:17:16 PM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
klugesmith
October 22, 2020, 05:33:39 PM
post Re: RC snubbers
[Solid State Tesla Coils (SSTC)]
T3sl4co1l
October 22, 2020, 02:07:27 PM
post RC snubbers
[Solid State Tesla Coils (SSTC)]
AstRii
October 22, 2020, 11:42:26 AM
post Re: CM600DU-24NF availability or substitute?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
SAMGO
October 22, 2020, 11:21:19 AM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
johnf
October 22, 2020, 09:14:24 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
klugesmith
October 22, 2020, 06:19:28 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
davekni
October 22, 2020, 04:21:50 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
klugesmith
October 22, 2020, 01:23:15 AM
post Re: Tesla coil circuit draws lots of current but the spark size is small.
[Solid State Tesla Coils (SSTC)]
davekni
October 21, 2020, 08:31:51 PM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
davekni
October 21, 2020, 08:21:55 PM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
Uspring
October 21, 2020, 07:17:07 PM
post Re: Tesla coil circuit draws lots of current but the spark size is small.
[Solid State Tesla Coils (SSTC)]
SalinsLV
October 21, 2020, 01:30:19 PM
post Re: QCW with replaceable ferrite-core primary
[Science, Research and News In Other Fields Than Electronics]
davekni
October 21, 2020, 05:00:34 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
plasma
October 21, 2020, 04:46:55 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
davekni
October 21, 2020, 04:42:19 AM
post Re: Current transformer for narrow spaces
[Laboratories, Equipment and Tools]
klugesmith
October 21, 2020, 02:29:54 AM
post Re: CM600DU-24NF availability or substitute?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
Mads Barnkob
October 20, 2020, 11:50:25 PM
post CM600DU-24NF availability or substitute?
[Dual Resonant Solid State Tesla coils (DRSSTC)]
SAMGO
October 20, 2020, 10:50:25 PM
post Variable transformer, reverse engineering of 3A electronic fuse
[Laboratories, Equipment and Tools]
Mads Barnkob
October 20, 2020, 09:38:42 PM

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