Midi polyphonic synth help with code or new approach

Status
Not open for further replies.

OldMan

Member
Hi

I was hoping someone might be able to help me please

I'm working on a midi controlled polyphonic synth(not paraphonic) using 2 x teensy 3.1 and midi library 3.2 (4 voice for the moment).
what i'm trying to achieve is using one teensy to generate the oscillator voices Then each of the voices goes through analogue filters and processing then through a digitally controlled VCA.
The setup is as follows:
I have one teensy generating four oscillator voices using phase accumulation wavetables. it is also responsible for velocity. Then the individual oscillator voices are outputted to 4 channels
of MCP4922. DAC
At this point each voice will be then going through digitally controlled analogue filters and processing.(which is left out of the design at the moment while i try to work out the polyphonic side of things)
From there each voice passes through a MCP41010 which is controlled by a second midi controlled teensy, this implements an individual ADSR for each voice.
From there all voices are combined using a analogue mixer circuit
I've adapted the midi code side of things using this excellent https://forum.pjrc.com/archive/index.php/t-27896.html and both teensy are fed the same midi signal from a midi in circuit

The problem is with the Release stage of the ADSR and here is where i'm up to at the moment .
I have disabled the code inside the note Off that releases the voice to be used by the next key strike on teensy 1
Instead the second teensy is running an almost identical midi solution except the ISR runs a simple ADSR for each Digital Pot (at the moment).
When the envelope is triggered it takes pin D3 D4 D5 D6 HIGH and when the END of the release stage is finished i.e. the volume is at zero it takes D3 D4 D5 D6 LOW
These digital outs are connected to Teensy 1 with wires and pull down resistors to digital in pins D3 D4 D5 D6
On teensy one the pins D3 D4 D5 D6 are read with digital read from inside the ISR. I have check this setup and indeed it does read ok. (these are called MPC1 to MCP4.)
My initial thought was that when a key is struck D3 to D5 are read and if HIGH don't reset the voice but if are LOW and the release is finished allow the next part of the code Quote "try to find a free voice to play a note"
to use that voice. Obviously this doesn't work and i can't figure out why ?? I have spent the last week moving things around and am now getting so frustrated i could *4£-??`@%$ and i'm normally such a patient person.
I really really hoping someone might shed some light on a solution.

If you got this far thanks for reading

PS there is printStuff(); which displays the contents of the typedef struct.
In an ideal world…..if 4 keys are held down and you press a fifth note nothing will sound …if 4 keys are hit and the voices are in release then if another key is struck it would steal a voice .
This is how the roland Juno 106 works.

thanks again and here is the code for each teensy

CODE FOR TEENSY ONE
Code:
#include <TimerOne.h>
#include <MIDI.h>
#include <spi4teensy3.h>  // include the SPI library:
// how many voices do we have?
#define VOICES 4
// note struct
// contains a pitch, a velocity, and a sequence number
typedef struct
{
  uint8_t myPitch;
  uint8_t myVelocity;
  uint8_t mySequence;
  uint8_t myOutput;//My addition
}
note;
// array of notes
// four notes since we have four voices
note notes[VOICES];
// array of frearduinoquencies corresponding to MIDI notes 0 to 128
const float noteFreqs[128] = {8.176, 8.662, 9.177, 9.723, 10.301, 10.913, 11.562, 12.25, 12.978, 13.75, 14.568, 15.434, 16.352, 17.324, 18.354, 19.445, 20.602, 21.827, 23.125, 24.5, 25.957, 27.5, 29.135, 30.868, 32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520, 3729.31, 3951.066, 4186.009, 4434.922, 4698.636, 4978.032, 5274.041, 5587.652, 5919.911, 6271.927, 6644.875, 7040, 7458.62, 7902.133, 8372.018, 8869.844, 9397.273, 9956.063, 10548.08, 11175.3, 11839.82, 12543.85};
volatile float oscAFreq;
const int sine1024[1024] = {//SINE WAVE
  0 , 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 12 , 13 , 14 , 16 , 18 , 19 , 21 , 23 , 25 , 27 , 29 , 31 , 33 , 35 , 38 , 40 , 43 , 45 , 48 , 51 , 53 , 56 , 59 , 62 , 66 , 69 , 72 , 75 , 79 , 82 , 86 , 89 , 93 , 97 , 101 , 105 , 109 , 113 , 117 , 121 , 125 , 130 , 134 , 139 , 143 , 148 , 153 , 158 , 162 , 167 , 172 , 177 , 183 , 188 , 193 , 199 , 204 , 209 , 215 , 221 , 226 , 232 , 238 , 244 , 250 , 256 , 262 , 268 , 275 , 281 , 287 , 294 , 300 , 307 , 313 , 320 , 327 , 334 , 341 , 348 , 355 , 362 , 369 , 376 , 384 , 391 , 398 , 406 , 413 , 421 , 429 , 436 , 444 , 452 , 460 , 468 , 476 , 484 , 492 , 500 , 509 , 517 , 525 , 534 , 542 , 551 , 559 , 568 , 577 , 585 , 594 , 603 , 612 , 621 , 630 , 639 , 648 , 658 , 667 , 676 , 686 , 695 , 704 , 714 , 724 , 733 , 743 , 753 , 762 , 772 , 782 , 792 , 802 , 812 , 822 , 832 , 842 , 852 , 863 , 873 , 883 , 893 , 904 , 914 , 925 , 935 , 946 , 957 , 967 , 978 , 989 , 999 , 1010 , 1021 , 1032 , 1043 , 1054 , 1065 , 1076 , 1087 , 1098 , 1109 , 1121 , 1132 , 1143 , 1154 , 1166 , 1177 , 1188 , 1200 , 1211 , 1223 , 1234 , 1246 , 1257 , 1269 , 1281 , 1292 , 1304 , 1316 , 1328 , 1339 , 1351 , 1363 , 1375 , 1387 , 1399 , 1411 , 1423 , 1434 , 1446 , 1459 , 1471 , 1483 , 1495 , 1507 , 1519 , 1531 , 1543 , 1556 , 1568 , 1580 , 1592 , 1604 , 1617 , 1629 , 1641 , 1654 , 1666 , 1678 , 1691 , 1703 , 1716 , 1728 , 1740 , 1753 , 1765 , 1778 , 1790 , 1803 , 1815 , 1828 , 1840 , 1853 , 1865 , 1878 , 1890 , 1903 , 1915 , 1928 , 1940 , 1953 , 1966 , 1978 , 1991 , 2003 , 2016 , 2028 , 2041 , 2054 , 2066 , 2079 , 2091 , 2104 , 2116 , 2129 , 2141 , 2154 , 2167 , 2179 , 2192 , 2204 , 2217 , 2229 , 2242 , 2254 , 2267 , 2279 , 2292 , 2304 , 2317 , 2329 , 2342 , 2354 , 2367 , 2379 , 2391 , 2404 , 2416 , 2428 , 2441 , 2453 , 2465 , 2478 , 2490 , 2502 , 2515 , 2527 , 2539 , 2551 , 2563 , 2575 , 2588 , 2600 , 2612 , 2624 , 2636 , 2648 , 2660 , 2672 , 2684 , 2696 , 2708 , 2720 , 2732 , 2743 , 2755 , 2767 , 2779 , 2790 , 2802 , 2814 , 2825 , 2837 , 2849 , 2860 , 2872 , 2883 , 2895 , 2906 , 2918 , 2929 , 2940 , 2952 , 2963 , 2974 , 2985 , 2996 , 3007 , 3019 , 3030 , 3041 , 3052 , 3063 , 3073 , 3084 , 3095 , 3106 , 3117 , 3127 , 3138 , 3149 , 3159 , 3170 , 3180 , 3191 , 3201 , 3211 , 3222 , 3232 , 3242 , 3252 , 3263 , 3273 , 3283 , 3293 , 3303 , 3313 , 3322 , 3332 , 3342 , 3352 , 3361 , 3371 , 3381 , 3390 , 3400 , 3409 , 3418 , 3428 , 3437 , 3446 , 3455 , 3464 , 3473 , 3482 , 3491 , 3500 , 3509 , 3518 , 3527 , 3535 , 3544 , 3552 , 3561 , 3569 , 3578 , 3586 , 3594 , 3603 , 3611 , 3619 , 3627 , 3635 , 3643 , 3651 , 3658 , 3666 , 3674 , 3681 , 3689 , 3696 , 3704 , 3711 , 3718 , 3726 , 3733 , 3740 , 3747 , 3754 , 3761 , 3768 , 3775 , 3781 , 3788 , 3795 , 3801 , 3808 , 3814 , 3820 , 3826 , 3833 , 3839 , 3845 , 3851 , 3857 , 3863 , 3868 , 3874 , 3880 , 3885 , 3891 , 3896 , 3902 , 3907 , 3912 , 3917 , 3922 , 3927 , 3932 , 3937 , 3942 , 3947 , 3951 , 3956 , 3961 , 3965 , 3969 , 3974 , 3978 , 3982 , 3986 , 3990 , 3994 , 3998 , 4002 , 4005 , 4009 , 4013 , 4016 , 4020 , 4023 , 4026 , 4029 , 4032 , 4036 , 4038 , 4041 , 4044 , 4047 , 4050 , 4052 , 4055 , 4057 , 4060 , 4062 , 4064 , 4066 , 4068 , 4070 , 4072 , 4074 , 4076 , 4077 , 4079 , 4081 , 4082 , 4083 , 4085 , 4086 , 4087 , 4088 , 4089 , 4090 , 4091 , 4092 , 4092 , 4093 , 4093 , 4094 , 4094 , 4095 , 4095 , 4095 , 4095 , 4095 , 4095 , 4095 , 4094 , 4094 , 4094 , 4093 , 4093 , 4092 , 4091 , 4091 , 4090 , 4089 , 4088 , 4087 , 4086 , 4084 , 4083 , 4082 , 4080 , 4079 , 4077 , 4075 , 4073 , 4072 , 4070 , 4068 , 4066 , 4063 , 4061 , 4059 , 4056 , 4054 , 4051 , 4049 , 4046 , 4043 , 4041 , 4038 , 4035 , 4032 , 4028 , 4025 , 4022 , 4019 , 4015 , 4012 , 4008 , 4004 , 4001 , 3997 , 3993 , 3989 , 3985 , 3981 , 3977 , 3972 , 3968 , 3964 , 3959 , 3955 , 3950 , 3945 , 3941 , 3936 , 3931 , 3926 , 3921 , 3916 , 3911 , 3905 , 3900 , 3895 , 3889 , 3884 , 3878 , 3872 , 3867 , 3861 , 3855 , 3849 , 3843 , 3837 , 3831 , 3825 , 3818 , 3812 , 3806 , 3799 , 3793 , 3786 , 3779 , 3773 , 3766 , 3759 , 3752 , 3745 , 3738 , 3731 , 3724 , 3716 , 3709 , 3702 , 3694 , 3687 , 3679 , 3671 , 3664 , 3656 , 3648 , 3640 , 3632 , 3624 , 3616 , 3608 , 3600 , 3592 , 3584 , 3575 , 3567 , 3558 , 3550 , 3541 , 3533 , 3524 , 3515 , 3507 , 3498 , 3489 , 3480 , 3471 , 3462 , 3453 , 3443 , 3434 , 3425 , 3416 , 3406 , 3397 , 3387 , 3378 , 3368 , 3359 , 3349 , 3339 , 3329 , 3320 , 3310 , 3300 , 3290 , 3280 , 3270 , 3260 , 3249 , 3239 , 3229 , 3219 , 3208 , 3198 , 3188 , 3177 , 3167 , 3156 , 3145 , 3135 , 3124 , 3113 , 3103 , 3092 , 3081 , 3070 , 3059 , 3048 , 3037 , 3026 , 3015 , 3004 , 2993 , 2982 , 2971 , 2959 , 2948 , 2937 , 2926 , 2914 , 2903 , 2891 , 2880 , 2868 , 2857 , 2845 , 2834 , 2822 , 2810 , 2799 , 2787 , 2775 , 2763 , 2752 , 2740 , 2728 , 2716 , 2704 , 2692 , 2680 , 2668 , 2656 , 2644 , 2632 , 2620 , 2608 , 2596 , 2584 , 2572 , 2560 , 2548 , 2535 , 2523 , 2511 , 2499 , 2486 , 2474 , 2462 , 2449 , 2437 , 2425 , 2412 , 2400 , 2388 , 2375 , 2363 , 2350 , 2338 , 2325 , 2313 , 2301 , 2288 , 2276 , 2263 , 2251 , 2238 , 2226 , 2213 , 2200 , 2188 , 2175 , 2163 , 2150 , 2138 , 2125 , 2113 , 2100 , 2087 , 2075 , 2062 , 2050 , 2037 , 2025 , 2012 , 1999 , 1987 , 1974 , 1962 , 1949 , 1937 , 1924 , 1912 , 1899 , 1887 , 1874 , 1861 , 1849 , 1836 , 1824 , 1811 , 1799 , 1786 , 1774 , 1762 , 1749 , 1737 , 1724 , 1712 , 1699 , 1687 , 1675 , 1662 , 1650 , 1638 , 1625 , 1613 , 1601 , 1589 , 1576 , 1564 , 1552 , 1540 , 1528 , 1515 , 1503 , 1491 , 1479 , 1467 , 1455 , 1443 , 1431 , 1419 , 1407 , 1395 , 1383 , 1371 , 1359 , 1348 , 1336 , 1324 , 1312 , 1301 , 1289 , 1277 , 1266 , 1254 , 1242 , 1231 , 1219 , 1208 , 1196 , 1185 , 1174 , 1162 , 1151 , 1140 , 1128 , 1117 , 1106 , 1095 , 1084 , 1073 , 1062 , 1051 , 1040 , 1029 , 1018 , 1007 , 996 , 985 , 975 , 964 , 953 , 943 , 932 , 922 , 911 , 901 , 890 , 880 , 870 , 859 , 849 , 839 , 829 , 819 , 809 , 799 , 789 , 779 , 769 , 759 , 750 , 740 , 730 , 721 , 711 , 702 , 692 , 683 , 673 , 664 , 655 , 646 , 637 , 627 , 618 , 609 , 601 , 592 , 583 , 574 , 565 , 557 , 548 , 540 , 531 , 523 , 514 , 506 , 498 , 490 , 482 , 473 , 465 , 457 , 450 , 442 , 434 , 426 , 419 , 411 , 404 , 396 , 389 , 381 , 374 , 367 , 360 , 353 , 346 , 339 , 332 , 325 , 318 , 311 , 305 , 298 , 292 , 285 , 279 , 273 , 266 , 260 , 254 , 248 , 242 , 236 , 230 , 225 , 219 , 213 , 208 , 202 , 197 , 192 , 186 , 181 , 176 , 171 , 166 , 161 , 156 , 151 , 147 , 142 , 137 , 133 , 129 , 124 , 120 , 116 , 112 , 108 , 104 , 100 , 96 , 92 , 88 , 85 , 81 , 78 , 74 , 71 , 68 , 65 , 61 , 58 , 56 , 53 , 50 , 47 , 44 , 42 , 39 , 37 , 35 , 32 , 30 , 28 , 26 , 24 , 22 , 20 , 19 , 17 , 15 , 14 , 13 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 2 , 1 , 1 , 1 , 0 , 0 , 0 ,
};
volatile unsigned long delta;

//VARIABLES FOR ISR DAC
volatile unsigned long phaccu0;
volatile unsigned long phaccu1;
volatile unsigned long phaccu2;
volatile unsigned long phaccu3;
volatile unsigned long tword0;
volatile unsigned long tword1;
volatile unsigned long tword2;
volatile unsigned long tword3;
volatile int fromarray0;
volatile int fromarray1;
volatile int fromarray2;
volatile int fromarray3;
float dfreq0 = 2000;
float dfreq1 = 2000;
float dfreq2 = 2000;
float dfreq3 = 2000;
const double refclk = 43470.00;
//mcp4922
const int CS1 = 9; // chip Select MCP zero & one
const int CS2 = 10; // chip Select MCP two & three
int i = 0;
volatile byte myvoiceUsed;
float voice0Freq;
float voice1Freq;
float voice2Freq;
float voice3Freq;
float myFreq;
volatile unsigned long level0;
volatile unsigned long level1;
volatile unsigned long level2;
volatile unsigned long level3;
volatile int MCP0 = 0;
volatile int MCP1 = 0;
volatile int MCP2 = 0;
volatile int MCP3 = 0;

void setup() {
  pinMode (CS1, OUTPUT);//mcp4922 ONE
  pinMode (CS2, OUTPUT);//mcp4922 TWO
  pinMode(3, INPUT);//From 2nd Teensy
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(13, OUTPUT);
  Serial.begin(31250);
  MIDI.begin(MIDI_CHANNEL_OMNI);
  //MIDI.turnThruOff();
  MIDI.setHandleNoteOn(HandleNoteOn);
  //MIDI.setHandleNoteOff(HandleNoteOff);
  analogWriteResolution(12);
  analogReadRes(12);
  analogReadAveraging (1);//maximum is 32 minimum is one
  spi4teensy3::init(); // initialize SPI:
  Timer1.initialize (23);// Timer1.setPeriod(38);//23 is working
  Timer1.attachInterrupt(fourOSC);
}

void fourOSC() {//ISR

  MCP0 = digitalRead(3);//Read from 2nd Teensy  zero when release ends
  MCP1 = digitalRead(4);//Read from 2nd Teensy  zero when release ends
  MCP2 = digitalRead(5);//Read from 2nd Teensy  zero when release ends
  MCP3 = digitalRead(6);//Read from 2nd Teensy  zero when release ends


  //Oscillator / Voice Zero
  phaccu0 = phaccu0 + tword0;
  int i0 = phaccu0 >> 22;
  fromarray0 = ((sine1024[i0] * level0) / 1261);// to sort out -31

  //Oscillator / Voice One
  phaccu1 = phaccu1 + tword1;
  int i1 = phaccu1 >> 22;
  fromarray1 = ((sine1024[i1] * level1) / 1261);// to sort out -31

  //Oscillator / Voice Tw0
  phaccu2 = phaccu2 + tword2;
  int i2 = phaccu2 >> 22;
  fromarray2 = ((sine1024[i2] * level2) / 1261);// to sort out -31

  //Oscillator / Voice Three
  phaccu3 = phaccu3 + tword3;
  int i3 = phaccu3 >> 22;
  fromarray3 = ((sine1024[i3] * level3) / 1261);// to sort out -31

  mcpZero(fromarray0); //OUT to DAC
  mcpOne(fromarray1);  //OUT to DAC
  mcpTwo(fromarray2);  //OUT to DAC
  mcpThree(fromarray3); //OUT to DAC
} //EO four OSC

void HandleNoteOn(byte channel, byte pitch, byte velocity)
{

  if (channel == 1) {
    if (velocity > 0) { ///if its a real note
      digitalWrite(13, HIGH);
      // flag if a free voice was found
      byte voicesFree = 0;
      // the voice to be used
      byte voiceUsed = 0;
      // temporary variable for finding oldest note
      uint8_t seqNo = 0;
      int i;


      //MY INITIAL IDEA MY INITIAL IDEA code repeated for each voice i've taken the other 3 out
      //to keep the code size down for reading
/*
      if (notes[0].myOutput == 100 && MCP0 == 0) {
        int i = 0;
        Serial.println(notes[i].myPitch);
        notes[i].myPitch = 0;
        notes[i].myVelocity = 0;
        notes[i].mySequence = 0;
        notes[i].myOutput = 0;
        printStuff();
      }
      */

      //IS THIS THE PLACE TO RELEASE NOTE AFTER GETTING ZERO FROM DIGITAL READ

      //**************************************************************************************************
      // try to find a free voice to play the note
      for (i = 0; i < VOICES; i++)
      {
        // if a free voice is found, use it
        if (notes[i].mySequence == 0)
        {
          notes[i].myPitch = pitch;
          notes[i].myVelocity = velocity;
          // store the time
          notes[i].mySequence = 1;
          // flag it
          voicesFree = 1;
          // store the voice used so the right oscillators can be turned on
          voiceUsed = i;
          break;
        }
        // increment the sequence number if the note is being used
        else {
          notes[i].mySequence = notes[i].mySequence + 1;
        }// eo else
      }//eo  for i = 0; i < VOICES; i++
      // assign seqNo to mySequence
      notes[voiceUsed].mySequence = 1;
      // assign pitch and velocity to myPitch and myVelocity
      notes[voiceUsed].myPitch = pitch;
      notes[voiceUsed].myVelocity = velocity;
      notes[voiceUsed].myOutput = i + 100;
    
      if (voicesFree > -1) //this is for test printing to see whats going on
      {
        //  printStuff();
      }

      // voiceUsed is now the voice that will play the note
      oscAFreq = noteFreqs[pitch];

      // start the appropriate waveforms
      switch (voiceUsed)
      {
        case 0:
          phaccu0 = 0;
          myvoiceUsed = 0;
          myFreq = oscAFreq;
          level0 = velocity * 10;
          //   kill0 = 1;
          break;

        case 1:
          phaccu1 = 0;
          myvoiceUsed = 1;
          myFreq = oscAFreq;
          level1 = velocity * 10;
          break;

        case 2:
          phaccu2 = 0;
          myvoiceUsed = 2;
          myFreq = oscAFreq;
          level2 = velocity * 10;
          break;

        case 3:
          phaccu3 = 0;
          myvoiceUsed = 3;
          myFreq = oscAFreq;
          level3 = velocity * 10;
          break;
      }//eo case
    }//eo if Its a Real Note

    //   **************************************************************
    //    END OF NOTE ON .. AND START OFF NOTE OFF USING ZERO VELOCITY

    if (velocity == 0) //IF its a note with zero velocity ie a note off
    {
      printStuff();
      // holds the voice playing the pitch
      byte voiceUsedInRelease = 0;
      // find the voice which is playing the note
      for (int i = 0; i < VOICES; i++)
      {
        if (pitch == notes[i].myPitch)
        {
          voiceUsedInRelease = i;
          // reset the voice values
          // THIS IS THE SECTION I THINK NEEDS TO BE TRIGGERED BY DIGITAL READS FROM 2ND TEENSY
          //notes[i].myPitch = 0;
          // notes[i].myVelocity = 0;
          //  notes[i].mySequence = 0;
          //  notes[i].myOutput = 0;
        }//eo if
      }//eo for

      // signal the EGs to go to release mode (NOT USED)
      // but if used will kill voice after sustain
      /*
      switch (voiceUsedInRelease)
      {
        case 0:
           level0 = 0;
          break;

        case 1:
          level1 = 0;
          break;

        case 2:
           level2 = 0;
          break;

        case 3:
          level3 = 0;
          break;
      }//eo switch
      */

    }// EO if velocity == 0
  }//  if channel == 1
}//eo void HandleNoteOn

void loop() {

  MIDI.read();

  if (myvoiceUsed == 0) {
    dfreq0 = myFreq;
    tword0 = 4294967296 * dfreq0 / refclk; 
  }

  if (myvoiceUsed == 1) {
    dfreq1 = myFreq;
    tword1 = 4294967296 * dfreq1 / refclk;
  }

  if (myvoiceUsed == 2) {
    dfreq2 = myFreq;
    tword2 = 4294967296 * dfreq2 / refclk;
  }

  if (myvoiceUsed == 3) {
    dfreq3 = myFreq;
    tword3 = 4294967296 * dfreq3 / refclk; 
  }
  /*
   Serial.print(" MCP0 = "); Serial.print(MCP0);
   Serial.print(" MCP1 = "); Serial.print(MCP1);
  Serial.print(" MCP2 = "); Serial.print(MCP2);
  Serial.print(" MCP3 = "); Serial.println(MCP3);delay(20);
  */
}//eo void loop


void mcpZero(int value) {
  uint16_t out = (0 << 15) | (1 << 14) | (1 << 13) | (1 << 12) | ( value );
  digitalWriteFast(CS1, LOW);
  spi4teensy3::send(out >> 8);
  spi4teensy3::send(out & 0xFF);
  digitalWriteFast(CS1, HIGH);
}

void mcpOne(int value) {
  uint16_t out = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12) | ( value );
  digitalWriteFast(CS1, LOW);
  spi4teensy3::send(out >> 8);
  spi4teensy3::send(out & 0xFF);
  digitalWriteFast(CS1, HIGH);
}

void mcpTwo(int value) {
  uint16_t out = (0 << 15) | (1 << 14) | (1 << 13) | (1 << 12) | ( value );
  digitalWriteFast(CS2, LOW);
  spi4teensy3::send(out >> 8);
  spi4teensy3::send(out & 0xFF);
  digitalWriteFast(CS2, HIGH);
}

void mcpThree(int value) {
  uint16_t out = (1 << 15) | (1 << 14) | (1 << 13) | (1 << 12) | ( value );
  digitalWriteFast(CS2, LOW);
  spi4teensy3::send(out >> 8);
  spi4teensy3::send(out & 0xFF);
  digitalWriteFast(CS2, HIGH);
}

void printStuff() {

  int s0 =  notes[0].mySequence;
  int s1 =  notes[1].mySequence;
  int s2 =  notes[2].mySequence;
  int s3 =  notes[3].mySequence;
  int p0 =  notes[0].myPitch;
  int p1 =  notes[1].myPitch;
  int p2 =  notes[2].myPitch;
  int p3 =  notes[3].myPitch;
  int v0 =  notes[0].myVelocity;
  int v1 =  notes[1].myVelocity;
  int v2 =  notes[2].myVelocity;
  int v3 =  notes[3].myVelocity;
  int o0 =  notes[0].myOutput;
  int o1 =  notes[1].myOutput;
  int o2 =  notes[2].myOutput;
  int o3 =  notes[3].myOutput;

  Serial.print("index = ");
  Serial.print("\t");
  Serial.print("0");
  Serial.print("\t");
  Serial.print("1");
  Serial.print("\t");
  Serial.print("2");
  Serial.print("\t");
  Serial.println("3");
  Serial.print("mySequence = ");
  Serial.print("\t");
  Serial.print(s0);
  Serial.print("\t");
  Serial.print(s1);
  Serial.print("\t");
  Serial.print(s2);
  Serial.print("\t");
  Serial.println(s3);
  Serial.print("myPitch = ");
  Serial.print("\t");
  Serial.print(p0);
  Serial.print("\t");
  Serial.print(p1);
  Serial.print("\t");
  Serial.print(p2);
  Serial.print("\t");
  Serial.println(p3);
  Serial.print("myVelocity = ");
  Serial.print("\t");
  Serial.print(v0);
  Serial.print("\t");
  Serial.print(v1);
  Serial.print("\t");
  Serial.print(v2);
  Serial.print("\t");
  Serial.println(v3);
  Serial.print("myOutput = ");
  Serial.print("\t");
  Serial.print(o0);
  Serial.print("\t");
  Serial.print(o1);
  Serial.print("\t");
  Serial.print(o2);
  Serial.print("\t");
  Serial.println(o3);
 
  Serial.println("___________________________________________");
}

CODE FOR TEENSY TWO

Code:
#include <TimerOne.h>
#include <MIDI.h>
#include <SPI.h> //for MCP41
byte address = 0x11; //for MCP41
// how many voices do we have?
#define VOICES 4
// note struct contains a pitch, a velocity, and a sequence number
volatile typedef struct
{
  uint8_t myPitch;
  uint8_t myVelocity;
  uint8_t mySequence;
}
note;
// array of notes four notes since we have four voices
note notes[VOICES];

volatile unsigned long delta;
//VARIABLES FOR ISR ADSR
volatile unsigned long phaccu0;
volatile unsigned long phaccu1;
volatile unsigned long phaccu2;
volatile unsigned long phaccu3;
volatile unsigned long tword0;
volatile unsigned long tword1;
volatile unsigned long tword2;
volatile unsigned long tword3;
const double refclk = 43470.00; //////was 43470
int i = 0;
volatile int i0;//value for MCP41100  0
volatile int i1;//value for MCP41100  1
volatile int i2;//value for MCP41100  2
volatile int i3;//value for MCP41100  2
volatile float speed0 = 2;
volatile float speed1 = 2;
volatile float speed2 = 2;
volatile float speed3 = 2;
volatile byte flag0 = 0;
volatile byte flag1 = 0;
volatile byte flag2 = 0;
volatile byte flag3 = 0;
volatile byte trigger0 = 0;
volatile byte trigger1 = 0;
volatile byte trigger2 = 0;
volatile byte trigger3 = 0;

void setup() {
  pinMode (7, OUTPUT);//chip Select MCP0
  pinMode (8, OUTPUT);//chip Select MCP1
  pinMode (9, OUTPUT);//chip Select MCP2
  pinMode (10, OUTPUT);//chip Select MCP3
  pinMode(3, OUTPUT);   //release 
  pinMode(4, OUTPUT);   //release 
  pinMode(5, OUTPUT);   //release 
  pinMode(6, OUTPUT);   //release 
  pinMode(17, OUTPUT);   //release LED just for testing
  pinMode(18, OUTPUT);   //release LED just for testing
  pinMode(19, OUTPUT);   //release LED just for testing
  pinMode(20, OUTPUT);   //release LED just for testing

  pinMode(13, OUTPUT);
  Serial.begin(31250);
  MIDI.begin(MIDI_CHANNEL_OMNI);
  // MIDI.turnThruOff();
  MIDI.setHandleNoteOn(HandleNoteOn);
  // MIDI.setHandleNoteOff(HandleNoteOff);
  analogWriteResolution(12);
  analogReadRes(12);
  analogReadAveraging (1);//maximum is 32 minimum is one
  SPI.begin();//for MCP41
  MCP0(0x00); MCP0(0x80); MCP0(0xFF); //for MCP0
  MCP1(0x00); MCP1(0x80); MCP1(0xFF); //for MCP1
  MCP2(0x00); MCP2(0x80); MCP2(0xFF); //for MCP2
  MCP3(0x00); MCP3(0x80); MCP3(0xFF); //for MCP3
  Timer1.initialize (100);
  Timer1.attachInterrupt(VCAISR);
}//eo setup

void VCAISR() {
  ADSR0();
  ADSR1();
  ADSR2();
  ADSR3();
} //EO VCAISR

void ADSR0() {
  //ATTACK
  if (trigger0 == 1 && flag0 == 1) {
    speed0 = 1;
    phaccu0 = phaccu0 + tword0;
    i0 = phaccu0 >> 24;
    if (i0 > 200) {
      flag0 = 2;
    }
    if (trigger0 == 2) {
      flag0 = 3;
    }
  }//eo attack

  //DECAY AND SUSTAIN
  if (trigger0 == 1 && flag0 == 2) {
    speed0 = 9;
    phaccu0 = phaccu0 - tword0;
    i0 = phaccu0 >> 24;
    if (i0 < 60) {
      flag0 = 3;
    }
    if (trigger0 == 2) {
      flag0 = 3;
    }
  }//eo decay sustain

  //RELEASE
  if (trigger0 == 2 && flag0 == 3) {
    speed0 = 0.01;
    phaccu0 = phaccu0 - tword0;
    i0 = phaccu0 >> 24;
    if (i0 < 1) {
      digitalWrite(3, LOW); //out to Teensy 1
        digitalWrite(17, LOW);
      flag0 = 0;
    }
  }//eo release

  MCP0(i0);//Write value to MCP41010
}//EO void ADSR0

void ADSR1() {
  //ATTACK
  if (trigger1 == 1 && flag1 == 1) {
    speed1 = 1;
    phaccu1 = phaccu1 + tword1;
    i1 = phaccu1 >> 24;
    if (i1 > 200) {
      flag1 = 2;
    }
    if (trigger1 == 2) {
      flag1 = 3;
    }
  }//eo attack

  //DECAY AND SUSTAIN
  if (trigger1 == 1 && flag1 == 2) {
    speed1 = 9;
    phaccu1 = phaccu1 - tword1;
    i1 = phaccu1 >> 24;
    if (i1 < 60) {
      flag1 = 3;
    }
    if (trigger1 == 2) {
      flag1 = 3;
    }
  }//eo decay sustain

  //RELEASE
  if (trigger1 == 2 && flag1 == 3) {
    speed1 = 0.01;
    phaccu1 = phaccu1 - tword1;
    i1 = phaccu1 >> 24;
    if (i1 < 1) {
      digitalWrite(4, LOW); //out to Teensy 1
         digitalWrite(18, LOW);
      flag1 = 0;
    }
  }//eo release
  MCP1(i1);//Write value to MCP41010
}//eo void ADSR1

void ADSR2() {
  //ATTACK
  if (trigger2 == 1 && flag2 == 1) {
    speed2 = 1;
    phaccu2 = phaccu2 + tword2;
    i2 = phaccu2 >> 24;
    if (i2 > 200) {
      flag2 = 2;
    }
    if (trigger2 == 2) {
      flag2 = 3;
    }
  }//eo attack

  //DECAY AND SUSTAIN
  if (trigger2 == 1 && flag2 == 2) {
    speed2 = 9;
    phaccu2 = phaccu2 - tword2;
    i2 = phaccu2 >> 24;
    if (i2 < 60) {
      flag2 = 3;
    }
    if (trigger2 == 2) {
      flag2 = 3;
    }
  }//eo decay sustain

  //RELEASE
  if (trigger2 == 2 && flag2 == 3) {
    speed2 = 0.01;
    phaccu2 = phaccu2 - tword2;
    i2 = phaccu2 >> 24;
    if (i2 < 1) {
      digitalWrite(5, LOW); //out to Teensy 1
            digitalWrite(19, LOW);
      flag2 = 0;
    }
  }//eo release
  MCP2(i2);//Write value to MCP41010
}//eo void ADSR2

void ADSR3(){
//ATTACK 
  if (trigger3 == 1 && flag3 == 1) {
    speed3 = 1;
    phaccu3 = phaccu3 + tword3;
    i3 = phaccu3 >> 24;
    if (i3 > 200) {
      flag3 = 2;
    }
    if (trigger3 == 2) {
      flag3 = 3;
    }
  }//eo attack

  //DECAY AND SUSTAIN
  if (trigger3 == 1 && flag3 == 2) {
    speed3 = 9;
    phaccu3 = phaccu3 - tword3;
    i3 = phaccu3 >> 24;
    if (i3 < 60) {
      flag3 = 3;
    }
    if (trigger3 == 2) {
      flag3 = 3;
    }
  }//eo decay sustain

  //RELEASE
  if (trigger3 == 2 && flag3 == 3) {
    speed3 = 0.01;
    phaccu3 = phaccu3 - tword3;
    i3 = phaccu3 >> 24;
    if (i3 < 1) {
      digitalWrite(6, LOW); //out to Teensy 1
            digitalWrite(20, LOW);
      flag3 = 0; 
    }
  }//eo release
 MCP3(i3); //Write value to MCP41010 
}//eo void ADSR3


void HandleNoteOn(byte channel, byte pitch, byte velocity)
{
  if (channel == 1) {
    if (velocity > 0) { ///if its a real note
      digitalWrite(13, HIGH);
      // flag if a free voice was found
      byte voicesFree = 0;
      // the voice to be used
      byte voiceUsed = 0;
      // temporary variable for finding oldest note
      uint8_t seqNo = 0;
      int i;
      //**************************************************************************************************
      // try to find a free voice to play the note
      for (i = 0; i < VOICES; i++)
      {
        // if a free voice is found, use it
        if (notes[i].mySequence == 0)
        {
          notes[i].myPitch = pitch;
          notes[i].myVelocity = velocity;
          // store the time
          notes[i].mySequence = 1;
          // flag it
          voicesFree = 1;
          // store the voice used so the right ADSR's can be turned on
          voiceUsed = i;
          break;
        }
        // increment the sequence number if the note is being used
        else
        {
          notes[i].mySequence = notes[i].mySequence + 1;
        }// eo else
      }//eo  for i = 0; i < VOICES; i++
      // voiceUsed is now the voice that will trigger the ADSR so start the appropriate ADSR
      switch (voiceUsed)
      {
        case 0:
          phaccu0 = 0;
          trigger0 = 1;
          flag0 = 1;
          digitalWrite(3, HIGH);//out to Teensy 1
            digitalWrite(17, HIGH);
          break;

        case 1:
          phaccu1 = 0;
          trigger1 = 1;
          flag1 = 1;
          digitalWrite(4, HIGH);//out to Teensy 1
            digitalWrite(18, HIGH);
          break;

        case 2:
          phaccu2 = 0;
          trigger2 = 1;
          flag2 = 1;
          digitalWrite(5, HIGH);//out to Teensy 1
            digitalWrite(19, HIGH);
          break;

        case 3:
          phaccu3 = 0;
          trigger3 = 1;
          flag3 = 1;
          digitalWrite(6, HIGH);//out to Teensy 1
            digitalWrite(20, HIGH);
          break;
      }//eo SWITCH CASE
    }//eo if Its a Real Note


    //   **************************************************************

    //    END OF NOTE ON .. AND START OFF NOTE OFF USING ZERO VELOCITY

    if (velocity == 0) { //IF its a note with zero velocity ie a note off
      digitalWrite(13, LOW);
      // holds the voice playing the pitch
      byte voiceUsed = 0;
      // find the voice which is playing the note
      for (int i = 0; i < VOICES; i++)
      {
        // Serial.println(notes[i].myPitch);
        if (pitch == notes[i].myPitch)
        {
          voiceUsed = i;
          // reset the voice values
          notes[i].myPitch = 0;
          notes[i].myVelocity = 0;
          notes[i].mySequence = 0;
        }
      }//eo for

      // signal the EGs to go to release mode
      switch (voiceUsed)
      {
        case 0:
          speed0 = 0.001;
          trigger0 = 2;
          flag0 = 3;
          break;

        case 1:
          speed1 = 0.001;
          trigger1 = 2;
          flag1 = 3;
          break;

        case 2:
          speed2 = 0.001;
          trigger2 = 2;
          flag2 = 3;
          break;

        case 3:
          speed3 = 0.001;
          trigger3 = 2;
          flag3 = 3;
          break;
      }//eo switch
    }// EO if velocity == 0
  }//  if channel == 1
}//eo void HandleNoteOn

void loop() {

  MIDI.read();

  if (trigger0 == 1) {
    tword0 = 4294967296 * speed0 / refclk;
  }
  if (trigger1 == 1) {
    tword1 = 4294967296 * speed1 / refclk;
  }
  if (trigger2 == 1) {
    tword2 = 4294967296 * speed2 / refclk;
  }
  if (trigger3 == 1) {
    tword3 = 4294967296 * speed3 / refclk;
  }

}//eo void loop

//MCP41100
void MCP0(int value) {
  digitalWrite(7, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(7, HIGH);
}
void MCP1(int value) {
  digitalWrite(8, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(8, HIGH);
}
void MCP2(int value) {
  digitalWrite(9, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(9, HIGH);
}
void MCP3(int value) {
  digitalWrite(10, LOW);
  SPI.transfer(address);
  SPI.transfer(value);
  digitalWrite(10, HIGH);
}
 
Status
Not open for further replies.
Back
Top