electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
 Forum index » DIY Hardware and Software
MIDI to CV 555 VCO design ideas
Post new topic   Reply to topic Moderators: jksuperstar, Scott Stites, Uncle Krunkus
Page 1 of 3 [57 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Goto page: 1, 2, 3 Next
Author Message
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Sun Apr 05, 2015 9:03 pm    Post subject: MIDI to CV 555 VCO design ideas
Subject description: I'm trying to make a MIDI controlled 555 VCO
Reply with quote  Mark this post and the followings unread

Hi all --

I am trying to make a 555 VCO that is controlled by a MIDI source. Also, this oscillator will be for bass frequencies, so it only needs limited octave range.

So far, I plan to capture a MIDI signal via an optocoupler circuit, but after this, I am not sure the best way to proceed:

Should the signal go:

MIDI source --> optocoupler --> microcontroller to convert optocoupler pulse to a control voltage that would allow for linear control of a 555 VCO

For now I am going to use an Arduino for the microcontroller, but eventually once I get the prototype working I'll use my own set of discrete parts.

However, please advise:

1) Is the block diagram above appropriate to achieve a MIDI-CV controlled 555 VCO?
2) Will the 555 stay in tune well enough, for say three octaves in standard bass frequency range?
3) Please direct me to any other relevant links for this project. I've searched through this forum and didn't quite find what I was looking for.

Thanks!
Back to top
View user's profile Send private message Visit poster's website
Boerge



Joined: Sep 02, 2009
Posts: 80
Location: Germany

PostPosted: Mon Apr 06, 2015 3:30 am    Post subject: Re: MIDI to CV 555 VCO design ideas
Subject description: I'm trying to make a MIDI controlled 555 VCO
Reply with quote  Mark this post and the followings unread

Hi,

xiphocoleon wrote:

For now I am going to use an Arduino for the microcontroller


Seems a bit oversized - any little PIC or ATTiny should do the trick Wink


xiphocoleon wrote:

1) Is the block diagram above appropriate to achieve a MIDI-CV controlled 555 VCO?


Hm, no diagram there Wink

xiphocoleon wrote:

2) Will the 555 stay in tune well enough, for say three octaves in standard bass frequency range?


Should work. Look at the PAiA FatMan, has MIDI and uses 555 for VCO.

xiphocoleon wrote:

3) Please direct me to any other relevant links for this project. I've searched through this forum and didn't quite find what I was looking for.


Use your favorite search engine too look vor "PIC MIDI2CV" or "Atmel MIDI2CV", have a look at the FatMan-schemo. Should be enough for the start
Wink

greetings


Boerge

_________________
...ich will doch nur löten...
Back to top
View user's profile Send private message
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Mon Apr 06, 2015 8:52 am    Post subject: Reply with quote  Mark this post and the followings unread

Thank you so much. Yes, I plan to use a non-Arduino microcontroller for the final project. Thanks for the recommendations, because I've never used non-Arduino microcontrollers.

Ah yes, the "block diagram" I was referring to was just my text-based diagram:

MIDI source --> optocoupler --> microcontroller to convert optocoupler pulse to a control voltage that would allow for linear control of a 555 VCO

If anyone thinks this is not the appropriate way to process the signals, please let me know.

And I will check out the FATMAN and other search terms you've recommended.

I'll post some updates here as I progress and will post the final version so that it may help others.
Back to top
View user's profile Send private message Visit poster's website
gdavis



Joined: Feb 27, 2013
Posts: 359
Location: San Diego
Audio files: 1

PostPosted: Tue Apr 07, 2015 12:28 pm    Post subject: Reply with quote  Mark this post and the followings unread

I'm not familiar with the PIC family but I've done midi to CV with arduino. Hooking up a midi receiver circuit to the arduino is simple, just connect the output of the optocoupler circuit to the serial RX pin. There is a midi library that makes handling midi messages easy. Check the Arduino website for information.

The trickier part is generating the CV output. Some people have reported success using the PWM output of the micro-controller but personally I think using a SPI DAC is easier, especially for pitch CV. There has been a fair amount of discussion about this, probably in the microcontrollers section.

BTW, Arduino isn't a microcontroller, it's a platform that utilizes a few of the Atmel AVR microcontrollers. There's even an Arduino addon for Atmel Studio. I use Atmel Studio with AVR Dragon to download my Arduino code through ICSP to my custom microcontroller board.

_________________
My synth build blog: http://gndsynth.blogspot.com/

Last edited by gdavis on Tue Apr 07, 2015 12:52 pm; edited 1 time in total
Back to top
View user's profile Send private message
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Tue Apr 07, 2015 12:34 pm    Post subject: Reply with quote  Mark this post and the followings unread

Thanks for your input. I have studied the PAIA Fatman circuit and I am now going to consider the best way for me to set up the 555 to receive MIDI pitch data.

Initially, I wanted to set up the 555 in a quasi-astable mode, where reset would be low except when MIDI data is sent to the 555, thereby turning the 555 on and controlling its pitch at the same time. However, I have a sense that using the Reset on the 555 in this way is not the best idea.
Back to top
View user's profile Send private message Visit poster's website
gdavis



Joined: Feb 27, 2013
Posts: 359
Location: San Diego
Audio files: 1

PostPosted: Tue Apr 07, 2015 1:24 pm    Post subject: Reply with quote  Mark this post and the followings unread

Oh, when I saw 555 VCO I was thinking the Thomas Henry 555 VCO circuit. Doing a good stable VCO right out of the 555 might be trickier than you think. I haven't seen the PAIA circuit though. Edit: found the PAIA circuit, that should get you started on the right track for a 555 VCO.
_________________
My synth build blog: http://gndsynth.blogspot.com/
Back to top
View user's profile Send private message
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Tue Apr 07, 2015 4:18 pm    Post subject: Reply with quote  Mark this post and the followings unread

I have now modified an Arduino sketch so that I can generate different pulse widths in response to different MIDI data.

If I were able to construct a VCO that could be voltage controlled by varied pulse widths, I'd be in a good spot. I am going to try and do this with a 555.

I am going to examine more closely if this is possible with the PAIA FATMAN 555 VCO.
Back to top
View user's profile Send private message Visit poster's website
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Tue Apr 07, 2015 4:26 pm    Post subject: Reply with quote  Mark this post and the followings unread

I'm thinking I want to convert the pulses output by the microcontroller to a steady DC voltage, which the 555 would respond to. The important question would be: could this be tuned accurately?

A sample pulse-width to voltage circuit: http://m.eet.com/media/1144833/178105f1.pdf
Back to top
View user's profile Send private message Visit poster's website
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue Apr 07, 2015 7:57 pm    Post subject: Reply with quote  Mark this post and the followings unread

That was alluded to earlier in the thread; some folks do do PWM -> CV circuits, and you should be able to find a few examples. Whether that's precise enough for voltage control is a different matter. I think you need to look into how you can voltage control your 555 before you get too much farther.
Back to top
View user's profile Send private message
gdavis



Joined: Feb 27, 2013
Posts: 359
Location: San Diego
Audio files: 1

PostPosted: Tue Apr 07, 2015 9:50 pm    Post subject: Reply with quote  Mark this post and the followings unread

xiphocoleon wrote:
I'm thinking I want to convert the pulses output by the microcontroller to a steady DC voltage, which the 555 would respond to. The important question would be: could this be tuned accurately?

A sample pulse-width to voltage circuit: http://m.eet.com/media/1144833/178105f1.pdf

That circuit looks like it's meant for a servo pulse train which has long periods of inactivity between each pulse, hence the sample and hold.

The microcontroller output is going to be a continuous PWM signal, all you really need is a low pass filter. The trade off is going to be accuracy vs. response time. You'll have to find a cuttoff frequency that gives you the balance you need.

I've seen discussions that mentioned things like using higher order filters and combining 2 outputs to increase the accuracy and response. This muffwiggler thread I think is where I saw both mentioned, discusses a couple different low pass filters, claims he got a decent response out of it.

_________________
My synth build blog: http://gndsynth.blogspot.com/
Back to top
View user's profile Send private message
comrade_zero



Joined: Mar 05, 2009
Posts: 66
Location: arizona
Audio files: 4

PostPosted: Thu Apr 09, 2015 1:54 am    Post subject: Reply with quote  Mark this post and the followings unread

I don't know about using a 555 osc, but I did something very similar using an optocoupler, Arduino, and the super-simple sawtooth oscillator from Nicolas (see sticky.) Added a manual Sallen-Key filter and a simple voltage-controlled attenuator (using an LED/LDR pair driven by an Arduino pin for "envelope"). Used an extra op-amp as a comparator to tap a square wave off the original osc. Made a nice poor-man's bass monosynth. Samples on my original post here: http://electro-music.com/forum/topic-48046.html
For cv I used two PWM outs into two passive low-pass filters (something like 10k resistors into 10uF caps) and summed them at the cv in. I think I got a total of three octaves out of it. The "fun" part of this approach is that you get to manually tune each note. I set up a test circuit with the Arduino and the oscillator and manually determined each appropriate pwm output value for each note, then stuck those in an array that could be looked up for each corresponding MIDI value. I wound up using two PWM outputs because a single output (0-127) did not have good enough resolution, so I added the second as a "fine" control. Note: using this (admittedly inelegant) approach results in "settling" time for the oscillator, so it may not respond as quickly/accurately as you need.
Back to top
View user's profile Send private message
JovianPyx



Joined: Nov 20, 2007
Posts: 1988
Location: West Red Spot, Jupiter
Audio files: 224

PostPosted: Thu Apr 09, 2015 8:06 am    Post subject: Reply with quote  Mark this post and the followings unread

A word about the 555 timer and VCOs - You should be aware that the 555 timer is a bipolar part with a TTL type totem pole output structure. As such, when the device switches from high to low or low to high, both of the totem pole transistors are on for an instant while the switching occurs. This causes a current spike that propagates easily to other parts of the circuit.

This is a well documented problem with the Fatman VCO, but it is easily remedied. (I have built two Fatman synths). The problem manifests by causing "soft synch" which is where the 2 VCOs will lock together when the pitch controls bring the VCOs close together in pitch. Normally, we want that difference to remain (without locking) because it produces a pleasant phasing sound that we all enjoy. The first such remedy was called the "Lee Diode Modification" which is to replace the 100 ohm resistor (see the PAiA Fatman schematic) that feeds -12V to the 555 timer IC with an LED. The LED will not illuminate, but it does remove most of the problem of the current spike. The second remedy is to simply replace the 555 timer with a 7555 timer which is pin and function compatible, but the 7555 being constructed out of CMOS will not "crowbar" the PSU like the 555 part will.

My advice is to start off with the 7555 timer instead of the bipolar 555 part to avoid the soft synch problem.

Note that the original 555 (biploar) part was designed as an "industrial timer" which was made to withstand a very noisy electrical environment.

_________________
FPGA, dsPIC and Fatman Synth Stuff

Time flies like a banana.
Fruit flies when you're having fun.
BTW, Do these genes make my ass look fat?
corruptio optimi pessima
Back to top
View user's profile Send private message Visit poster's website
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Fri May 01, 2015 6:26 am    Post subject: Reply with quote  Mark this post and the followings unread

comrade_zero wrote:
I don't know about using a 555 osc, but I did something very similar using an optocoupler, Arduino, and the super-simple sawtooth oscillator from Nicolas (see sticky.) Added a manual Sallen-Key filter and a simple voltage-controlled attenuator (using an LED/LDR pair driven by an Arduino pin for "envelope"). Used an extra op-amp as a comparator to tap a square wave off the original osc. Made a nice poor-man's bass monosynth. Samples on my original post here: http://electro-music.com/forum/topic-48046.html
For cv I used two PWM outs into two passive low-pass filters (something like 10k resistors into 10uF caps) and summed them at the cv in. I think I got a total of three octaves out of it. The "fun" part of this approach is that you get to manually tune each note. I set up a test circuit with the Arduino and the oscillator and manually determined each appropriate pwm output value for each note, then stuck those in an array that could be looked up for each corresponding MIDI value. I wound up using two PWM outputs because a single output (0-127) did not have good enough resolution, so I added the second as a "fine" control. Note: using this (admittedly inelegant) approach results in "settling" time for the oscillator, so it may not respond as quickly/accurately as you need.


Hi Comrade -- I really like your approach and I am going to check out your ideas. I have been working on another project recently and had to pause this one, but in the next weeks I am back to the MIDI to CV synth. I have been studying in the Fatman schematic a bit and it looks like it is also in the same vein of what I'm doing. I'm uncomfortable with the 8031 microcontroller because I think it's prorammed in Assembly (I think?) and I only know C++ and would be more comfortable writing my own code and modifying examples for a microcontroller that could accept that -- maybe the ATTINY 85?
Back to top
View user's profile Send private message Visit poster's website
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Fri May 01, 2015 7:03 am    Post subject: Reply with quote  Mark this post and the followings unread

There are lots of MIDI to CV projects out there using Arduino of various sorts, and also a few using PIC microcontrollers which are programmed in various languages including C or C++. Arduino's dev environment is a little easier to make "just work", but that assumes you have the whole Arduino "thang". Programming an AVR (ATtiny etc) directly seems to be more or less a wash versus a PIC.

One note on an existing project out there: http://www.acxsynth.com/midi2cvlite/midi2cvlitefr.htm

I like this one, it's simple but it has one flaw -- it uses floating point math in scaling, and this means that for some types of synths (I believe those doing "running status" MIDI messages) it drops bytes and will get stuck at fast key speeds (e.g. a fast sequence). The solution is pretty simple, just convert the two multiplies here:

Code:
switch(MIDI_Byte1){
            case 0x90:           // Note On
            if(MIDI_Byte3==0) FinNote();
            else {
            Note_VAL = MIDI_Byte2-24;      //Le do grave a la valeur 24 et pas 0
            Note_VAL = Note_VAL * 83.3333;   //83.3333 = 1 V/oct /12
               PlayNote();   //on joue la note
               Gate();
               }
            break;                                     
                case 0x80:          // Note Off
                FinNote();
                break;                                   
                case 0xE0:          // pitch wheel
                Pitch_Wheel_VAL = MIDI_Byte3 * 2.644;
                PlayNote();


To use equivalent integer operations -- an integer multiply then divide is much faster than a FP multiply.
Back to top
View user's profile Send private message
jackdamery



Joined: Apr 26, 2010
Posts: 75
Location: UK

PostPosted: Thu May 07, 2015 5:56 am    Post subject: Reply with quote  Mark this post and the followings unread

I investigated the very thing you are doing. I found 555s are unstable (turn 555 on, measure frequency. Leave running for half an hour, measure frequency again.).

You might have more luck with the TLC555 (lincmos version of the 555).
Back to top
View user's profile Send private message
xiphocoleon



Joined: Oct 04, 2013
Posts: 40
Location: Brooklyn

PostPosted: Mon May 18, 2015 4:44 pm    Post subject: Reply with quote  Mark this post and the followings unread

Hi comrade_zero -- which is the Nicolas design you're referring to? http://electro-music.com/wiki/pmwiki.php?n=Schematics.NicolasSuperSimpleVPerHzVCO -- this design says it produces a triangle wave, and I know you mentioned a sawtooth wave. Could you post a link to the Nicolas design you mentioned? Thanks.

comrade_zero wrote:
I don't know about using a 555 osc, but I did something very similar using an optocoupler, Arduino, and the super-simple sawtooth oscillator from Nicolas (see sticky.)
Back to top
View user's profile Send private message Visit poster's website
comrade_zero



Joined: Mar 05, 2009
Posts: 66
Location: arizona
Audio files: 4

PostPosted: Mon May 18, 2015 10:23 pm    Post subject: Reply with quote  Mark this post and the followings unread

http://electro-music.com/forum/post-292718.html

you can use another op-amp as a comparator to generate a pulse/square off of the output, but the circuit as-is puts out a nice sawtooth. I used tl082's in my build, but I've breadboarded it with 358's. Needs bipolar supply as drawn (i've run it off of +/- 12v), but you could run it off a single supply using a "virtual ground."
The response to cv is not perfectly linear, so you will have to manually tune each desires note (using a DAC or PWM output or whatever) and build an array of desired outputs that yield the desired notes.
Like I said, I think I got three or four in-tune octaves out of it driving it from an arduino pwm.
Good luck, hope this helps.
c_z
Back to top
View user's profile Send private message
isak



Joined: Dec 13, 2009
Posts: 847
Location: Israel
Audio files: 18

PostPosted: Tue May 19, 2015 3:19 pm    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:
There are lots of MIDI to CV projects out there using Arduino of various sorts, and also a few using PIC microcontrollers which are programmed in various languages including C or C++. Arduino's dev environment is a little easier to make "just work", but that assumes you have the whole Arduino "thang". Programming an AVR (ATtiny etc) directly seems to be more or less a wash versus a PIC.

One note on an existing project out there: http://www.acxsynth.com/midi2cvlite/midi2cvlitefr.htm

I like this one, it's simple but it has one flaw -- it uses floating point math in scaling, and this means that for some types of synths (I believe those doing "running status" MIDI messages) it drops bytes and will get stuck at fast key speeds (e.g. a fast sequence). The solution is pretty simple, just convert the two multiplies here:

Code:
switch(MIDI_Byte1){
            case 0x90:           // Note On
            if(MIDI_Byte3==0) FinNote();
            else {
            Note_VAL = MIDI_Byte2-24;      //Le do grave a la valeur 24 et pas 0
            Note_VAL = Note_VAL * 83.3333;   //83.3333 = 1 V/oct /12
               PlayNote();   //on joue la note
               Gate();
               }
            break;                                     
                case 0x80:          // Note Off
                FinNote();
                break;                                   
                case 0xE0:          // pitch wheel
                Pitch_Wheel_VAL = MIDI_Byte3 * 2.644;
                PlayNote();


To use equivalent integer operations -- an integer multiply then divide is much faster than a FP multiply.


Hi elmegil

i got the same problem you mention above, with my x0xb0x seq and also with my DAW, i work with cubase and every time when i'm trying to move the midi note with the mouse the sound got stuck, only after pressing reset to the lite midi2cv it comes back to work normal.
can you please show how/where i need to replace it on the code?
should i insert the fix instead the whole lines below...? (its from the original code)

Code:
 switch(Rx_DATA){          
             case 0x90:         // Note On
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;                                                            
                case 0x80:          // Note Off
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;                                   
                case 0xE0:          // pitch bend
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;
                case 0xB0:;         //Modulation
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
            break;
            case 0xFE:         //Active Sensing
            break;
            default:
            MIDI_Byte1 = 0;                                                                                             
                  }


thanks in advance,
Isak E.

_________________
http://www.myspace.com/mgmtrance
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue May 19, 2015 3:38 pm    Post subject: Reply with quote  Mark this post and the followings unread

It doesn't appear to be the same problem to me, nothing in the code fragment you've included does a multiply.

It may be the same symptom, but I don't see anything in the fragment of code you've included that leads me to any conclusion about the cause.

Sorry Sad
Back to top
View user's profile Send private message
isak



Joined: Dec 13, 2009
Posts: 847
Location: Israel
Audio files: 18

PostPosted: Tue May 19, 2015 3:46 pm    Post subject: Reply with quote  Mark this post and the followings unread

elmegil wrote:
It doesn't appear to be the same problem to me, nothing in the code fragment you've included does a multiply.

It may be the same symptom, but I don't see anything in the fragment of code you've included that leads me to any conclusion about the cause.

Sorry Sad


thank you for replying Smile

sorry, i dont understand... Confused
didnt you said its a fix for the ACX lite midi2cv?
if yes, where should i put it on the code?

this is the whole code :
Code:

/*
Logiciel de gestion du module MIDI CV/Gate ACS  Lite version

Alain COUPEL  11 novembre 2008


PORT A :   0= output,  1= input

RA0   TRIGGER      0   
RA1   Select DAC2 0
RA2   SDI       0
RA3   Select DAC1 0
RA4   SCK        0
RA5   MCLR      1   input pour reset
RA6   LED       0
RA7   GATE       0

TRISA = 0b00100000

PORT B :

RB0 NC         0
RB1 NC         0
RB2 Rx         1   INPUT Rx MIDI
RB3 NC         0
RB4 NC         0
RB5 NC         0
RB6   NC         1
RB7 NC         1

TRISB = 0b11000100

*/
 
 #include<htc>      //Compilateur Hi-Tech PICC std

__CONFIG(INTIO &WDTDIS & PWRTEN &MCLREN & UNPROTECT & BORDIS & FCMDIS );

#define      TRIG RA0   //Trigger output
#define      SDI RA2      //SPI Data
#define      CI1 RA3      // DAC select
#define      SCK RA4      //SPI Clock
#define    LED RA6      //LED output
#define      GATE RA7   //Gate output

#define      DACa 0b0001000000000000         // = 0x1000 DACa select
#define      DACb 0b1001000000000000         // = 0x9000 DACb select
   

int
Note_VAL,   //
Tx_DATA,   // Data to transfer
Pitch_Wheel_VAL;

unsigned char
 k, n,
nb_Byte,      //Bytes number of the MIDI message
nb_Notes,      // Number of notes played simultaneously
Rx_DATA,
MIDI_Chnl,      // Numéro de canal MIDI
MIDI_Byte1,
MIDI_Byte2,
MIDI_Byte3;      // groupe de 3 octets MIDI


void delai(void){
   char i, j;
   for(i=0;i<255;i++)
   for(j=0;j<120;j++);
}

void clignote(void){
   for(k=0;k<3;k++){
      RA6 = 1;
      delai();
      RA6=0;
      delai();
      }      
}   

void Init_PIC(void){
   OSCCON = 0b01111100;      //osc  8 MHz
   TRISA = 0b00100000;         //port A  output
   PORTA = 0b00001010;         // unselect DAC
   TRISB = 0b11000100;
   ANSEL = 0;               //désactivation des convertisseurs A/N            
   OPTION = 0b00000011;      //RBPU/INTEDG/T0CS/T0SE/PSA/PS2/PS1/PS0   
}

void Init_Interrupt(void){
   GIE = 1;      //enables global interrupts
   PEIE = 1;      //enables all periph interrupts
   RBIE = 0;      // 0 = disables port change interrupt
   RCIE = 0;      //disable rx interrupts
   TXIE=0;         //disable tx interrupts
}         

void Init_Serial(void){      
   SPBRG=15;         //Value for 31250 bauds:((CLK/(16 * BAUD) -1))
   BRGH=1;            //High Speed
   SYNC=0;            //asynchronous
   SPEN=1;            //enable serial port pin
   CREN=1;            //enable reception
   SREN=0;            //no effect
   RX9=0;            //8-bit reception
}


void Send_SPI(void){   
   for(n=0;n<16;n++){
   SCK = 0;
   Tx_DATA = Tx_DATA <<1> 4095) Tx_DATA = 4095;
   Tx_DATA = Tx_DATA + DACa;
      RA3 = 0;         
      Send_SPI();
      RA3 = 1;
}   
   
void PlayCTRL(void){
   Tx_DATA = MIDI_Byte3 << 5; //only the first 6 bits are used (0-5V)
   Tx_DATA = Tx_DATA + DACb;
      RA3 = 0;         
      Send_SPI();
      RA3 = 1;

}   

void Gate(void){
   nb_Notes++;
   LED  = 1;
   TRIG = 1;
   GATE = 1;
   TMR0IF = 0;         //disable interrupt flag
   TMR0 = 0;
   TMR0IE = 1;      //enable Timer0 interrupt
}

void FinNote(void){
      nb_Notes--;
   if(nb_Notes==0){
      LED  = 0;
      TRIG = 0;
      GATE = 0;
      }   
}

void interrupt Timer(void){
   TMR0IE = 0;         //disable Timer0 interrupt
   TMR0IF = 0;         //disable interrupt flag
   TRIG = 0;
}
      
void TestsMIDI(void){

      switch(MIDI_Byte1){
            case 0x90:           // Note On
            if(MIDI_Byte3==0) FinNote();
            else {
            Note_VAL = MIDI_Byte2-24;      //Le do grave a la valeur 24 et pas 0
            Note_VAL = Note_VAL * 83.3333;   //83.3333 = 1 V/oct /12
               PlayNote();   //on joue la note
               Gate();
               }
            break;                                     
                case 0x80:          // Note Off
                FinNote();
                break;                                   
                case 0xE0:          // pitch wheel
                Pitch_Wheel_VAL = MIDI_Byte3 * 2.644;
                PlayNote();
                break;                 
                case 0xB0:         //Modulation
            if(MIDI_Byte2==1)   // Est ce bien la molette de modulation ?
                PlayCTRL();                                         
        }

}   
void clear_usart_errors(void){
   if (OERR){                                                                                 
   CREN=0;                                       
   CREN=1;                                                                                 
   }                                             
   if (FERR){                                             
   Rx_DATA=RCREG;                                 
   TXEN=0;                                       
   TXEN=1;                                    
   }
}
      
main(){
   Init_PIC();
   Init_Serial();
   Init_Interrupt();
   nb_Byte=0;
   nb_Notes = 0;
   Pitch_Wheel_VAL = 167;

   clignote();   


while(MIDI_Byte1!=0x90){            //Autolearn MIDI Channel
   PlayNote();
      if(RCIF){          
      clear_usart_errors();
        Rx_DATA=RCREG;
      MIDI_Byte1 = Rx_DATA&0xF0;
      MIDI_Chnl = Rx_DATA&0x0F;
      }
}

for (;;){         // boucle infinie : on peut jouer tant qu'on veut !!
   
        if(RCIF){          
      clear_usart_errors();
        Rx_DATA=RCREG;

      switch(nb_Byte){
            case 0:
         if(!(Rx_DATA&0x80)&& MIDI_Byte1){      //Test de Running Status
         nb_Byte = 2;
         MIDI_Byte2 = Rx_DATA;
      }
      else{
         Rx_DATA = Rx_DATA - MIDI_Chnl;
            switch(Rx_DATA){          
             case 0x90:         // Note On
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;                                                            
                case 0x80:          // Note Off
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;                                   
                case 0xE0:          // pitch bend
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
                break;
                case 0xB0:;         //Modulation
                MIDI_Byte1=Rx_DATA;
                nb_Byte++;
            break;
            case 0xFE:         //Active Sensing
            break;
            default:
            MIDI_Byte1 = 0;                                                                                             
                  }
}//if running status
              break;
            case 1:
            MIDI_Byte2=Rx_DATA;
            nb_Byte++;
             break;
            case 2:
            MIDI_Byte3=Rx_DATA;
            nb_Byte = 0;
            TestsMIDI();
                           
         }//switch(nb_Byte)
   }//if(RCIF)

}//for
   
}//main


i hope we understand each other Smile
sorry if were not Rolling Eyes

_________________
http://www.myspace.com/mgmtrance
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue May 19, 2015 7:17 pm    Post subject: Reply with quote  Mark this post and the followings unread

I see the confusion Smile

The fragment I posted is from the TestMIDI routine, and I did not post the actual correction, I just noted it needed to be made an integer operation.

Note that I did make some other minor changes because I am compiling with the free XC8 compiler rather than Hi-Tech C.

Here is the corrected code, in its entirety:

Code:

/*
Logiciel de gestion du module MIDI CV/Gate ACS  Lite version

Alain COUPEL  11 novembre 2008


PORT A :   0= output,  1= input

RA0   TRIGGER      0
RA1   Select DAC2 0
RA2   SDI       0
RA3   Select DAC1 0
RA4   SCK        0
RA5   MCLR      1   input pour reset
RA6   LED       0
RA7   GATE       0

TRISA = 0b00100000

PORT B :

RB0 NC         0
RB1 NC         0
RB2 Rx         1   INPUT Rx MIDI
RB3 NC         0
RB4 NC         0
RB5 NC         0
RB6   NC         1
RB7 NC         1

TRISB = 0b11000100

 */

//#include<htc>      //Compilateur Hi-Tech PICC std
#include <stdio>
#include <stdlib>
#include <xc>

#include <pic16f88>

// options are different between Hi-Tech C & XC8, in particular complaining about not having FOSC_INTOSCIO
//__CONFIG(INTIO &WDTDIS & PWRTEN &MCLREN & UNPROTECT & BORDIS & FCMDIS);
__CONFIG(MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & WDTE_OFF & PWRTE_ON & LVP_OFF & DEBUG_OFF & FOSC_INTOSCIO);

#define      TRIG RA0   //Trigger output
#define      SDI RA2      //SPI Data
#define      CI1 RA3      // DAC select
#define      SCK RA4      //SPI Clock
#define    LED RA6      //LED output
#define      GATE RA7   //Gate output

#define      DACa 0b0001000000000000         // = 0x1000 DACa select
#define      DACb 0b1001000000000000         // = 0x9000 DACb select


int
Note_VAL, //
Tx_DATA, // Data to transfer
Pitch_Wheel_VAL;

unsigned char
k, n,
nb_Byte, //Bytes number of the MIDI message
nb_Notes, // Number of notes played simultaneously
Rx_DATA,
MIDI_Chnl, // Num?ro de canal MIDI
MIDI_Byte1,
MIDI_Byte2,
MIDI_Byte3; // groupe de 3 octets MIDI

void delai(void) {
    char i, j;
    for (i = 0; i < 255; i++)
        for (j = 0; j < 120; j++);
}

void clignote(void) {
    for (k = 0; k < 3; k++) {
        RA6 = 1;
        delai();
        RA6 = 0;
        delai();
    }
}

void Init_PIC(void) {
    OSCCON = 0b01111100; //osc  8 MHz
    TRISA = 0b00100000; //port A  output
    PORTA = 0b00001010; // unselect DAC
    TRISB = 0b11000100;
    PORTB = 0b00000000;
    ANSEL = 0; //d?sactivation des convertisseurs A/N
    OPTION_REG = 0b00000011; //RBPU/INTEDG/T0CS/T0SE/PSA/PS2/PS1/PS0
}

void Init_Interrupt(void) {
    GIE = 1; //enables global interrupts
    PEIE = 1; //enables all periph interrupts
    RBIE = 0; // 0 = disables port change interrupt
    RCIE = 0; //disable rx interrupts
    TXIE = 0; //disable tx interrupts
}

void Init_Serial(void) {
    SPBRG = 15; //Value for 31250 bauds:((CLK/(16 * BAUD) -1))
    BRGH = 1; //High Speed
    SYNC = 0; //asynchronous
    SPEN = 1; //enable serial port pin
    CREN = 1; //enable reception
    SREN = 0; //no effect
    RX9 = 0; //8-bit reception
}

void Send_SPI(void) {
    for (n = 0; n < 16; n++) {
        SCK = 0;
        Tx_DATA = Tx_DATA <<1> 4095) Tx_DATA = 4095;
    Tx_DATA = Tx_DATA + DACa;
    RA3 = 0;
    Send_SPI();
    RA3 = 1;
}

void PlayCTRL(void) {
    Tx_DATA = MIDI_Byte3 << 5; //only the first 6 bits are used (0-5V)
    Tx_DATA = Tx_DATA + DACb;
    RA3 = 0;
    Send_SPI();
    RA3 = 1;

}

void Gate(void) {
    nb_Notes++;
    LED = 1;
    TRIG = 1;
    GATE = 1;
    TMR0IF = 0; //disable interrupt flag
    TMR0 = 0;
    TMR0IE = 1; //enable Timer0 interrupt
}

void FinNote(void) {
    nb_Notes--;
    if (nb_Notes == 0) {
        LED = 0;
        TRIG = 0;
        GATE = 0;
    }
}

void interrupt Timer(void) {
    TMR0IE = 0; //disable Timer0 interrupt
    TMR0IF = 0; //disable interrupt flag
    TRIG = 0;
}

void TestsMIDI(void) {

    switch (MIDI_Byte1) {
        case 0x90: // Note On
            if (MIDI_Byte3 == 0) FinNote();
            else {

Code:

                Note_VAL = MIDI_Byte2 - 24; //Le do grave a la valeur 24 et pas 0
                //Note_VAL = Note_VAL * 83.3333;   //83.3333 = 1 V/oct /12
                // use integer math instead; the slowdown causes dropped notes and hanging gates
                // with some MIDI sources
                Note_VAL = Note_VAL * 250;
                Note_VAL = (int) (Note_VAL / 3);

Code:

                PlayNote(); //on joue la note
                Gate();
            }
            break;
        case 0x80: // Note Off
            FinNote();
            break;
        case 0xE0: // pitch wheel
            Pitch_Wheel_VAL = MIDI_Byte3 * 2.644;
            PlayNote();
            break;
        case 0xB0: //Modulation
            if (MIDI_Byte2 == 1) // Est ce bien la molette de modulation ?
                PlayCTRL();
    }

}

void clear_usart_errors(void) {
    if (OERR) {
        CREN = 0;
        CREN = 1;
    }
    if (FERR) {
        Rx_DATA = RCREG;
        TXEN = 0;
        TXEN = 1;
    }
}

main() {
    Init_PIC();
    Init_Serial();
    Init_Interrupt();
    nb_Byte = 0;
    nb_Notes = 0;
    Pitch_Wheel_VAL = 167;

    clignote();


    while (MIDI_Byte1 != 0x90) { //Autolearn MIDI Channel
        PlayNote();
        if (RCIF) {
            clear_usart_errors();
            Rx_DATA = RCREG;
            MIDI_Byte1 = Rx_DATA & 0xF0;
            MIDI_Chnl = Rx_DATA & 0x0F;
        }
    }

    for (;;) { // boucle infinie : on peut jouer tant qu'on veut !!

        if (RCIF) {
            clear_usart_errors();
            Rx_DATA = RCREG;

            switch (nb_Byte) {
                case 0:
                    if (!(Rx_DATA & 0x80) && MIDI_Byte1) { //Test de Running Status
                        nb_Byte = 2;
                        MIDI_Byte2 = Rx_DATA;
                    } else {
                        Rx_DATA = Rx_DATA - MIDI_Chnl;
                        switch (Rx_DATA) {
                            case 0x90: // Note On
                                MIDI_Byte1 = Rx_DATA;
                                nb_Byte++;
                                break;
                            case 0x80: // Note Off
                                MIDI_Byte1 = Rx_DATA;
                                nb_Byte++;
                                break;
                            case 0xE0: // pitch bend
                                MIDI_Byte1 = Rx_DATA;
                                nb_Byte++;
                                break;
                            case 0xB0:; //Modulation
                                MIDI_Byte1 = Rx_DATA;
                                nb_Byte++;
                                break;
                            case 0xFE: //Active Sensing
                                break;
                            default:
                                MIDI_Byte1 = 0;
                        }
                    }//if running status
                    break;
                case 1:
                    MIDI_Byte2 = Rx_DATA;
                    nb_Byte++;
                    break;
                case 2:
                    MIDI_Byte3 = Rx_DATA;
                    nb_Byte = 0;
                    TestsMIDI();

            }//switch(nb_Byte)
        }//if(RCIF)

    }//for

}//main
Back to top
View user's profile Send private message
isak



Joined: Dec 13, 2009
Posts: 847
Location: Israel
Audio files: 18

PostPosted: Tue May 19, 2015 8:15 pm    Post subject: Reply with quote  Mark this post and the followings unread

Ok, got it Smile

So your minor changes of the code is fixing what exactly?

_________________
http://www.myspace.com/mgmtrance
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Tue May 19, 2015 10:52 pm    Post subject: Reply with quote  Mark this post and the followings unread

A floating point math operation (83.333 * whatever it was) is very expensive on a PIC because there is no floating point coprocessor. So it has to link in a library that has (probably) dozens of instructions to accomplish the multiplication, plus time to do a subroutine call and return. This takes some significant time to run (in processor time), and while I haven't looked at the code I wouldn't be surprised if it also takes measures to ensure it isn't interrupted, for example, by the serial port service routine.

So the reason you're getting stuck notes is that the processor is busy doing floating point math when it needs to be accepting incoming serial messages, and so those incoming messages occasionally get dropped.

If you instead do the math strictly as integers (and in the end, you have to end up with an integer anyway, the DAC doesn't understand floating point math), it can be done in-line, and with relatively few instructions. For example multiply times 250 can be done as multiply times 125 then left shift one bit. Similarly integer division can be done in line, efficiently, and often with shifts. And if we guess that there are things blocking interrupts int he FP library, there definitely would not be in any in-line integer math.

It goes faster and is less prone to possible bad interactions with the interrupts driving the UART, and in my testing I was entirely unable to get any notes to get stuck the same way I could with the floating point math.

Trust me, this insight was hard-won, I spent quite a while trying to figure out where it was dropping the incoming stream, and initially it was just a lucky guess as to what would be tying up the CPU enough to drop bytes. Once I found it, the explanation seemed obvious, but until I made the leap it was far from it.
Back to top
View user's profile Send private message
isak



Joined: Dec 13, 2009
Posts: 847
Location: Israel
Audio files: 18

PostPosted: Tue May 19, 2015 11:57 pm    Post subject: Reply with quote  Mark this post and the followings unread

WOW Shocked
You really got to the bottom of this stuck notes, haa? Very Happy
Ok, I got it.

Last 2 questions please.
1.Why you divide the code to 3 parts? the middle small code, is it the correction?
2. Can you please upload the whole code in one piece so I won't make mistakes trying to understand what goes where?


Thanks man Smile

_________________
http://www.myspace.com/mgmtrance
Back to top
View user's profile Send private message
elmegil



Joined: Mar 20, 2012
Posts: 2177
Location: Chicago
Audio files: 16

PostPosted: Wed May 20, 2015 5:22 am    Post subject: Reply with quote  Mark this post and the followings unread

isak wrote:

Last 2 questions please.
1.Why you divide the code to 3 parts? the middle small code, is it the correction?


Yes. I tried to color code but that did not work.

isak wrote:

2. Can you please upload the whole code in one piece so I won't make mistakes trying to understand what goes where?


Thanks man Smile


You're welcome.

Here it is as an attachment.... It's named "newmain.c" because that's how I created it in the MPLAB-X IDE.


newmain.c
 Description:

Download
 Filename:  newmain.c
 Filesize:  6.7 KB
 Downloaded:  206 Time(s)

Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic Moderators: jksuperstar, Scott Stites, Uncle Krunkus
Page 1 of 3 [57 Posts]
View unread posts
View new posts in the last week
Goto page: 1, 2, 3 Next
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use