'**************************************************************** '* Name : Chi_US.BAS * '* Author : Godfried-Willem RAES * '* Notice : Copyleft (c) 2016 Logosoft Public Domain * '* Date : 16.03.2016 * '* Version : 1.1 * '* Last update : 28.03.2016 * '**************************************************************** ' PIC: 18F2525 ' ctrl 7 @ PWM RC1 for volume control via VCA ' pitch bend @ PWM RC2 frequency ' ctrl 8 @ PWM RC2 = carrier PWM amplitude (0-50%) ' uses sorting routine for timers. ' ctrl 31 added to support changing the settings for the lowest ultrasonic frequency ' ctrl 65 added for muting the amplifier (on/off) ' 16.03.2016: Version 1.0, flashed and debugged. ' 17.03.2016: Lookup table added for PWM frequencies ' Version 1.1, flashed. ' 27.03.2016: First tests in Chi: ' US hardware clipping. needs corrections and revision ' Lite code o.k ' Mute works ' 28.03.2016: Hardware debugged and solved. ' demodulation circuitry now functioning. ' This code not yet flashed. Include "18F2525.inc" 'version for the Chi-US board. (40MHz) 'Include "18F2520.inc" 'also possible. (40MHz) 'Include "18F25K20.inc" 'for test & debug on an Amicus board. (64MHz) ' Mapping defines for midi-events on pin outputs and inputs: $define GreenLed PORTC.5 ' groene LED $define YellowLed PORTC.4 ' gele LED $define BlueLed PORTB.2 ' lights up when the carrier frequency was changed with CC31 $define US_Carrier PORTC.2 ' pwm - HPWM1 - 0-50% CC8 $define Volume PORTC.1 ' pwm - HPWM2 - 0-100% CC7 $define Mute PORTA.5 ' amplifier muting $define Lamp1 PORTA.4 $define Lamp2 PORTA.3 'red LED for debug: $define Debug_Led PORTB.5 ' for testing - red led - watchdog ' configure the input and output pins: Clear SSPCON1.5 'RC3 must be available for I/O TRISA = %01000011 'bits set to 0 are output, 1 = input TRISB = %11100000 TRISC = %11000000 'RC1 en RC2 zijn pwm outputs and must be set to output 'RC6 en RC7 zijn USART I/O and must be set to input 'constant definitions: 'initialisations for the midi input parser: Symbol Midichannel = 9 ' Chi_Channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel ' 2 bytes follow Symbol Control_Status = 176 + Midichannel Symbol ProgChange_Status = 192 + Midichannel ' 1 byte message Symbol Aftertouch_Status = 208 + Midichannel ' 1 byte follows Symbol Pitchbend_Status = 224 + Midichannel ' lsb msb follow 'application specific constants Symbol NrTasks = 2 ' maximum 16 'Symbol fPWM = 16384 ' lowest pwm frequency for ultrasonic emitter ' must be >= PWMminF ' seems the upper limit is 39065 Hz (Tektronix measurement) ' after the manual it is 32767 Hz 'Symbol fPwm = 21000 ' gives range 21000Hz to 37383Hz ' Textronix measurement confirms the range as 21000 to 38881 Hz ' ultrasound start frequencies: (>=2442) 'Symbol fPWM99 = 2489 ' Mib 'Symbol fPWM100 = 2637 'Symbol fPWM101 = 2793 'Symbol fPWM102 = 2910 'Symbol fPWM103 = 3136 'Symbol fPWM104 = 3322 'Symbol fPWM105 = 3620 'Symbol fPWM106 = 3729 'Symbol fPWM107 = 3901 'Symbol fPWM108 = 4186 'Symbol fPWM109 = 4435 'Symbol fPWM110 = 4698 'Symbol fPWM111 = 4978 'Symbol fPWM112 = 5274 'Symbol fPWM113 = 5587 'Symbol fPWM114 = 5820 'Symbol fPWM115 = 6272 'Symbol fPWM116 = 6644 'Symbol fPWM117 = 7040 'Symbol fPWM118 = 7458 'Symbol fPWM119 = 7802 ' end extended range for Chi 'Symbol fPWM120 = 8372 'Symbol fPWM121 = 8870 'Symbol fPWM122 = 9397 'Symbol fPWM123 = 9956 'Symbol fPWM124 = 10548 'Symbol fPWM125 = 11175 'Symbol fPWM126 = 11840 'Symbol fPWM127 = 12544 ' highest possible midi note 'Symbol fPWM128 = 13289 'Symbol fPWM129 = 14080 'Symbol fPWM130 = 14917 'Symbol fPWM131 = 15804 'Symbol fPWM132 = 16744 'Symbol fPWM133 = 17739 'Symbol fPWM134 = 18794 'Symbol fPWM135 = 19912 'Symbol fPWM136 = 21096 ' Setup the USART Declare Hserial_Baud = 31250 ' Set baud rate for the USART to MIDI specs. Declare Hserial_TXSTA = 0x24 ' instead of the normal 0x20 - ?? 0x24 Declare All_Digital = True ' Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables ' Dim Cnt As Dword System ' Dim CntHw As Cnt.Word1 'used in the timer0 interrupt, to create a 32 bit timer Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H 'it makes Cntlw the low word of cnt 'We still have to copy the contents of Lw to Cnt Dim Tim3 As TMR3L.Word Dim Bytein As Byte System ' midi byte read from buffer Dim StBit As Bytein.7 ' highest bit of ByteIn Dim i As Byte System ' general purpose counter ' midi variables Dim statusbyte As Byte System Dim noteUit As Byte System ' note off + release value Dim release As Byte System Dim noteAan As Byte System ' note on + release value Dim velo As Byte System Dim notePres As Byte System ' note pressure + pressure value Dim pres As Byte System Dim Ctrl As Byte System ' continuous controller + value Dim value As Byte System Dim prog As Byte System ' program change + program-byte Dim aft As Byte System ' channel aftertouch Dim pblsb As Byte System ' pitch bend lsb Dim pbmsb As Byte System ' pitch bend msb Dim BendVal As Word System ' 14 bit pitchbend value Dim fPWM As Word System ' lowest US-frequency ' Dim veltim As Dword System ' 32 bit velo Dim VelFlags As Byte System ' byte in enough here. bits 0 - 15 used as flags for active timers ' Dim Velflags0 As VelFlags.Byte0 ' alias for bits 0-7 ' Dim VelFlags1 As VelFlags.Byte1 ' bits 8-15 - not used in this code. Dim CC66 As Byte System ' global on/off switch Dim st As Byte System Dim b1 As Byte System Dim b2 As Byte System Dim Lites As Byte System ' bits used as flags Dim USfreq As Word System ' must be 16 bits Dim CC7 As Byte System ' VCA volume Dim CC8 As Byte System ' US-pwm Dim CC30 As Byte System Dim CC31 As Byte System Dim CC65 As Byte System Dim Rate0 As Word System ' set with key pressure Dim Rate1 As Word System Dim Pres0 As Byte System 'indexes for durations lookup Dim Pres1 As Byte System Dim time As Dword System ' 32-bit, incremented in loopcounter Dim maxtim As time.31 ' overflow bit, will cause timer reset after 1h45 Dim t As Byte System ' loopcounter, running at 4 times time-clock Dim tog As Byte System Dim tg As tog.0 ' divide by 4 bit Dim TimVals[2] As Dword ' lijst met timer waarden - de kleinste is eerst aan de beurt Dim Nxt As Dword System ' waarde voor de eerstvolgende timer Dim idx As Byte System ' index voor de eerstvolgende timer '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler And buffer read subroutines into memory Dim Ringbuffer[256] As Byte Include "Chi_Irq.inc" ' our own version for UART And Timer0/3 Interrupt 'Dim vels[128] As Word ' velocity lookup table 'Dim Vels0[128] As Word Dim Frq[128] As Word ' chromatic frequency lookup Dim Dur[128] As Word ' duration lookup for repetitions 'make sure we initialize the used pins on start up: Low Volume Low Mute Low Lamp1 Low Lamp2 Low Debug_Led Low GreenLed Low YellowLed Low BlueLed Clear CC66 Clear CC65 Set CC7 Clear CC8 GoSub Dur_Lookup GoSub Frq_Lookup fPWM = Frq[76] 'fPWM136 BendVal = 8192 USfreq = fPWM + BendVal ' default frequency 29288Hz CC31 = 76 ' set to fPWM136 HPWM 1, CC8, USfreq ' connected to RC2 US-carrier HPWM 2, CC7, USfreq ' connected to RC1 volume '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High Debug_Led DelayMS 50 ' wait for stability Low Debug_Led Clear VelFlags Clear Lites Init_Usart_Interrupt ' Initiate the USART serial buffer interrupt ' this procedure is in the include file Clear_Serial_Buffer ' Clear the serial buffer and reset its pointers ' in the include as well ' Configure Timer0 for: ' Clear TMR0L and TMR0H registers ' Interrupt on Timer0 overflow ' 16-bit operation ' Internal clock source 40MHz ' 1:256 Prescaler : thus 40MHz / 256 = 156.250kHz ' Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) in macro file. Clear T1CON Clear IntConBits_T0IF ' clear interrupt flag Set INTCONBITS_T0IE ' enable interrupt on overflow T0CON = %10000111 ' bit 7 = enable/disable ' bit 6 = 1=8 bit, 0=16 bit ' bit 5 = 1 pin input, 0= Internal Clk0 ' bit 4 = HL or LH transition when bit5 =1 ' bit 3 = 1= bypass prescaler, 0= input from prescaler ' bit 2-0 = prescaler select: 111= 1:256 ' Setup the High priorities for the interrupts ' open and start timer3 for sampling: Clear T3CON Clear PIR2BITS_TMR3IF ' clear IRQ flag Set PIE2BITS_TMR3IE ' irq on Clear Tim3 ' Clear TMR3L And TMR3H registers Set RCONbits_IPEN ' Enable priority interrupts Clear IPR2bits_TMR3IP ' Set Timer3 as a low priority interrupt source ' we can also set T3Con in one instruction as: T3CON = %10110000 ' oef, now it works... ' bit 7 = 16 bit mode ' bit 6,3 = 0, 0 ' bit 5,4 = 1:8 prescale ' bit 2 = 0 ' bit 1 = 0 Internal clock = Fosc/4 ' bit 0 : 1= enable timer 3, 0= disable set to 0 for Whisper! ' maximum count = 52.42ms, 1 tick =0.8uS, lowest freq.=19Hz ' reset all timers on startup: Set TimVals Set idx Set Nxt.31 Clear time ' so we start from 0 ' start the main program loop: LOOP: Inc t ' byte If t.1 = tg Then Btg tg Inc time ' dword EndIf ' Create an infinite loop Bytein = HRSIn ' Read data from the serial buffer, with no timeout ' Start the midi parser. Midi_Parse: If Bytein > Pitchbend_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) GoTo Check_Timers 'throw away... Else Clear statusbyte 'reset the status byte GoTo Check_Timers 'throw away End If EndIf If StBit =1 Then 'should be faster than If Bytein > 127 Then 'status byte received, bit 7 is set Clear statusbyte 'if on another channel, the statusbyte needs a reset Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Case Keypres_Status ' used for lights statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Case Control_Status ' only 66 and 123 statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 Case ProgChange_Status statusbyte = Bytein prog = 255 Case Aftertouch_Status statusbyte = Bytein aft = 255 Case Pitchbend_Status statusbyte = Bytein Set pblsb '= 255 Set pbmsb '= 255 End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel GoTo Check_Timers 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else 'release = Bytein 'message complete, so we can do the action... Select noteUit Case 120 Clear Lamp1 Clear Lites.0 Clear VelFlags.0 Case 121 Clear Lamp2 Clear Lites.1 Clear VelFlags.1 Case Else Set noteUit GoTo Check_Timers End Select Set noteUit '= 255 'reset GoTo resort EndIf GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then Select noteAan Case 120 Clear Lamp1 Clear Lites.0 Clear VelFlags.0 Case 121 Clear Lamp2 Clear Lites.1 Clear VelFlags.1 Case Else Set noteAan GoTo Check_Timers End Select Set noteAan 'reset !!! GoTo resort 'jump out EndIf If CC66 > 0 Then Select noteAan Case 120 Set Lamp1 ' stroom aan If velo < 127 Then Rate0 = Dur[velo] ' word var's Set VelFlags.0 TimVals[0] = time + Rate0 Set Lites.0 Else ' licht aan zonder flashing Clear VelFlags.0 Set Lites.0 '??? EndIf Case 121 Set Lamp2 If velo < 127 Then Rate1 = Dur[velo] ' word var's Set VelFlags.1 TimVals[1] = time + Rate1 Set Lites.1 Else ' licht aan zonder flashing Clear VelFlags.1 Set Lites.1 EndIf Case Else Set noteAan GoTo Check_Timers End Select Set noteAan '= 255 'reset GoTo resort EndIf EndIf 'for CC66 condition GoTo Check_Timers Case Keypres_Status 'used for lite flashing speed modulation If notePres = 255 Then notePres = Bytein GoTo Check_Timers Else Select notePres Case 120 Pres0 = Bytein If Pres0 > 0 Then Rate0 = Dur[Pres0] ' note that we set Lites.0 only on reception of a note-on ' this way we can program the repeats prior to playing. Else Clear Rate0 Clear Lites.0 EndIf Case 121 Pres1 = Bytein If Pres1 > 0 Then Rate1 = Dur[Pres1] Else Clear Rate1 Clear Lites.1 EndIf EndSelect Set notePres '= 255 GoTo Check_Timers ' we do not need to resort here EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf GoTo Check_Timers ' no resorting Case ProgChange_Status ' not used on Chi If prog = 255 Then 'single byte message prog = Bytein 'weak coding... GoSub ProgChange EndIf GoTo Check_Timers Case Pitchbend_Status ' used for USfreq If pblsb = 255 Then pblsb = Bytein Else pbmsb = Bytein GoSub Pitchbend End If GoTo Check_Timers End Select EndIf resort: GoSub SortTimers ' so we resort only if an incoming midi command changed something Check_Timers: ' here we check the Task counters and compare them with the 32 bit cnt value ' copied in time using the TimVals[] dword variables: If idx < 2 Then ' we moeten alleen checken wanneer er een timer loopt If time >= Nxt Then ' nagaan of de eerstvolgende timer afgelopen is... ' in dit geval is de eerste timer afgelopen en moeten we de juiste aktie ondernemen: Set Nxt.31 ' timer reset, is immers afgelopen ' aan de hand van idx weten we welke timer dit is Select idx Case 0 If Lites.0 = 0 Then Clear VelFlags.0 Clear Lamp1 Set TimVals[0] Else ' moet knipperen Btg Lamp1 TimVals[0] = time + Rate0 EndIf Case 1 If Lites.1 = 0 Then Clear VelFlags.1 Clear Lamp2 Set TimVals[1] Else Btg Lamp2 TimVals[1] = time + Rate1 EndIf 'Case Else ' ' in dit geval is idx geset ' GoTo jumpout End Select GoSub SortTimers ' find a new nxt and idx EndIf ' beveiliging tegen overflow crashes... If maxtim = 1 Then Clear time Clear VelFlags Clear Lites Set TimVals HPWM 1, 0, USfreq ' connected to US carrier HPWM 2, 255, USfreq ' connected to volume vca EndIf Else ' idx > 2, no timers running, so to avoid overflows, we can reset the loop timer If maxtim = 1 Then Clear time ' 16.06.2015 EndIf Btg PORTB.0 ' average loop-speed: 4.5 microseconds, 5.45 us under full load. (Tektronix measurement) GoTo LOOP ' end of the main loop SortTimers: 'look up the next smallest timer value in the Timvals array ' zoek de de volgende kleinste timer waarde: Set idx ' makes it 255 Set Nxt.31 ' nxt is set on entry. - for speed, we just set the highest bit For i = 0 To 1 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 5 dword comparisons idx = i EndIf Next i Return ProgChange: Set prog '= 255 'this is not realy required Return Pitchbend: 'steers the frequency of the ultrasonic carrier and demodulation wave ' adapted to Chi 15.03.2016 BendVal = pbmsb << 7 BendVal = BendVal + pblsb USfreq = fPWM + BendVal HPWM 2, CC7, USfreq ' vca HPWM 1, CC8, USfreq ' carrier Set pblsb '= 255 so that we can receive more pitchbends in running status Return Aftertouch: 'this is the channel aftertouch, affecting all notes. Not used on Chi Set aft '= 255 'not mandatory Return Controller: Select Ctrl Case 7 If value = 0 Then Set CC7 ' = 255 Else CC7 = value << 1 ' make 8 bit 0-100% - 2->254 'bug: CC7 = 264 - CC7 ' invert PWM CC7 = 254 - CC7 ' 252 -> 0 EndIf HPWM 2, CC7, USfreq ' volume - vca Case 8 CC8 = value ' 7-bit, 0-50% HPWM 1, CC8, USfreq ' carrier duty cycle Case 30 ' controller to set all repeat frequencies to one and the same value at once If value = 0 Then Clear Lites Clear Rate0 Clear Pres0 Clear Rate1 Clear Pres1 Else Pres0 = value Rate0 = Dur[value] Pres1 = value Rate1 = Dur[value] EndIf Case 31 ' sets the lowest ultrasonic frequency in fPWM ' new coding using lookup table: fPWM = Frq[value] If fPWM > 16000 Then Set BlueLed Else Clear BlueLed EndIf USfreq = fPWM + BendVal ' bendval range = 0 - 16383 CC31 = value HPWM 2, CC7, USfreq HPWM 1, CC8, USfreq Case 65 ' muting on amplifier on/off controller If value = 0 Then Clear Mute Clear YellowLed Clear CC65 Else If CC66 > 0 Then Set Mute CC65 = value Set YellowLed EndIf EndIf Case 66 'on/off for the robot If value = 0 Then GoSub PowerDown ' must also reset controllers Clear CC66 Else Set GreenLed Set CC66 EndIf Case 123 GoSub AllNotesOff End Select Set Ctrl '= 255 'mandatory reset Return AllNotesOff: Clear VelFlags Clear Lamp1 Clear Lamp2 Clear Lites Return PowerDown: Clear VelFlags 'stop all running timers Clear Lamp1 Clear Lamp2 Clear Lites ' reset controllers: Set CC7 Clear CC8 Clear CC31 fPWM = Frq[76] '21096Hz ' default to > 20kHz BendVal = 8192 USfreq = fPWM + BendVal HPWM 1, CC8, USfreq ' connected to RC2 - Carrier HPWM 2, CC7, USfreq ' connected to RC1 - VCA Set BlueLed ' US by default Clear GreenLed Clear CC65 Clear Mute Clear YellowLed Return Dur_Lookup: ' a good range would be fastest = 30 Hz, slowest = 1 Hz ' this is a tempered distribution! ' same look-up as on the pulse boards. Set Dur[0] ' not used Dur[1]= 41667 ' freq= .999992000063999 Dur[2]= 39494 ' freq= 1.0550125757499 Dur[3]= 38450 ' freq= 1.08365843086259 Dur[4]= 37434 ' freq= 1.11307011451265 Dur[5]= 36445 ' freq= 1.14327525495038 Dur[6]= 35482 ' freq= 1.17430434210774 Dur[7]= 34544 ' freq= 1.20619113787247 Dur[8]= 33631 ' freq= 1.23893629885126 Dur[9]= 32743 ' freq= 1.27253662360403 Dur[10]= 31877 ' freq= 1.30710752789367 Dur[11]= 31035 ' freq= 1.34257021642232 Dur[12]= 30215 ' freq= 1.37900601246621 Dur[13]= 29416 ' freq= 1.41646269603844 Dur[14]= 28639 ' freq= 1.45489251254117 Dur[15]= 27882 ' freq= 1.49439303732396 Dur[16]= 27146 ' freq= 1.53490999287802 Dur[17]= 26428 ' freq= 1.57661066545583 Dur[18]= 25730 ' freq= 1.61938074880166 Dur[19]= 25050 ' freq= 1.66333998669328 Dur[20]= 24388 ' freq= 1.70849051446066 Dur[21]= 23743 ' freq= 1.75490319953951 Dur[22]= 23116 ' freq= 1.8025033166061 Dur[23]= 22505 ' freq= 1.85144042064726 Dur[24]= 21910 ' freq= 1.90171915411532 Dur[25]= 21331 ' freq= 1.95333864641445 Dur[26]= 20768 ' freq= 2.006291730868 Dur[27]= 20219 ' freq= 2.06076792455941 Dur[28]= 19685 ' freq= 2.11667090000847 Dur[29]= 19164 ' freq= 2.17421554303207 Dur[30]= 18658 ' freq= 2.23317969057062 Dur[31]= 18165 ' freq= 2.29378842095605 Dur[32]= 17685 ' freq= 2.35604561304307 Dur[33]= 17218 ' freq= 2.41994811631239 Dur[34]= 16763 ' freq= 2.48563304102289 Dur[35]= 16320 ' freq= 2.5531045751634 Dur[36]= 15888 ' freq= 2.62252433702585 Dur[37]= 15469 ' freq= 2.69355916133342 Dur[38]= 15060 ' freq= 2.76671093404161 Dur[39]= 14662 ' freq= 2.84181330423316 Dur[40]= 14274 ' freq= 2.91906029610948 Dur[41]= 13897 ' freq= 2.99824902257082 Dur[42]= 13530 ' freq= 3.07957625030796 Dur[43]= 13172 ' freq= 3.16327563518575 Dur[44]= 12824 ' freq= 3.24911624038262 Dur[45]= 12485 ' freq= 3.33733813910025 Dur[46]= 12155 ' freq= 3.42794460441519 Dur[47]= 11834 ' freq= 3.52092839840009 Dur[48]= 11522 ' freq= 3.61627032343922 Dur[49]= 11217 ' freq= 3.71459986330272 Dur[50]= 10921 ' freq= 3.81527943106553 Dur[51]= 10632 ' freq= 3.91898670679709 Dur[52]= 10351 ' freq= 4.02537597011561 Dur[53]= 10078 ' freq= 4.13441820467024 Dur[54]= 9811 ' freq= 4.24693371385859 Dur[55]= 9552 ' freq= 4.36208821887214 Dur[56]= 9300 ' freq= 4.48028673835125 Dur[57]= 9054 ' freq= 4.60201752448273 Dur[58]= 8815 ' freq= 4.72679145396105 Dur[59]= 8582 ' freq= 4.85512312592247 Dur[60]= 8355 ' freq= 4.9870337123479 Dur[61]= 8134 ' freq= 5.12253094008688 Dur[62]= 7919 ' freq= 5.26160710527423 Dur[63]= 7710 ' freq= 5.40423692174665 Dur[64]= 7506 ' freq= 5.5511146638245 Dur[65]= 7308 ' freq= 5.70151432220398 Dur[66]= 7115 ' freq= 5.85617240571562 Dur[67]= 6927 ' freq= 6.01510995621 Dur[68]= 6744 ' freq= 6.1783313562673 Dur[69]= 6565 ' freq= 6.34678852500635 Dur[70]= 6392 ' freq= 6.51856487275761 Dur[71]= 6223 ' freq= 6.69559162247576 Dur[72]= 6059 ' freq= 6.87682235792485 Dur[73]= 5898 ' freq= 7.06454165253758 Dur[74]= 5743 ' freq= 7.25520924023449 Dur[75]= 5591 ' freq= 7.45245334764204 Dur[76]= 5443 ' freq= 7.65509216730969 Dur[77]= 5299 ' freq= 7.86311882745172 Dur[78]= 5159 ' freq= 8.07650061381405 Dur[79]= 5023 ' freq= 8.29517552591413 Dur[80]= 4890 ' freq= 8.52079072937969 Dur[81]= 4761 ' freq= 8.75166281593503 Dur[82]= 4635 ' freq= 8.98957209636821 Dur[83]= 4513 ' freq= 9.23258734027624 Dur[84]= 4393 ' freq= 9.48478640261021 Dur[85]= 4277 ' freq= 9.74203101862676 Dur[86]= 4164 ' freq= 10.0064040986231 Dur[87]= 4054 ' freq= 10.277914816642 Dur[88]= 3947 ' freq= 10.5565408326999 Dur[89]= 3843 ' freq= 10.842223956978 Dur[90]= 3741 ' freq= 11.1378419317473 Dur[91]= 3642 ' freq= 11.4406004027091 Dur[92]= 3546 ' freq= 11.7503290092122 Dur[93]= 3452 ' freq= 12.0702974121282 Dur[94]= 3361 ' freq= 12.3971040364971 Dur[95]= 3272 ' freq= 12.7343113284434 Dur[96]= 3186 ' freq= 13.0780498012136 Dur[97]= 3102 ' freq= 13.4321942832581 Dur[98]= 3020 ' freq= 13.7969094922737 Dur[99]= 2940 ' freq= 14.172335600907 Dur[100]= 2862 ' freq= 14.5585837409737 Dur[101]= 2787 ' freq= 14.9503647889008 Dur[102]= 2713 ' freq= 15.3581521071385 Dur[103]= 2641 ' freq= 15.7768522024486 Dur[104]= 2571 ' freq= 16.2064047711656 Dur[105]= 2504 ' freq= 16.640042598509 Dur[106]= 2437 ' freq= 17.0975242784845 Dur[107]= 2373 ' freq= 17.5586458772299 Dur[108]= 2310 ' freq= 18.037518037518 Dur[109]= 2249 ' freq= 18.5267526307989 Dur[110]= 2190 ' freq= 19.0258751902588 Dur[111]= 2132 ' freq= 19.5434646654159 Dur[112]= 2076 ' freq= 20.0706486833654 Dur[113]= 2021 ' freq= 20.616856341745 Dur[114]= 1967 ' freq= 21.182850364345 Dur[115]= 1915 ' freq= 21.7580504786771 Dur[116]= 1865 ' freq= 22.3413762287757 Dur[117]= 1815 ' freq= 22.9568411386593 Dur[118]= 1767 ' freq= 23.5804565176382 Dur[119]= 1721 ' freq= 24.2107301956227 Dur[120]= 1675 ' freq= 24.8756218905473 Dur[121]= 1631 ' freq= 25.5466993664418 Dur[122]= 1588 ' freq= 26.2384550797649 Dur[123]= 1546 ' freq= 26.9512721000431 Dur[124]= 1505 ' freq= 27.6854928017719 Dur[125]= 1465 ' freq= 28.4414106939704 Dur[126]= 1427 ' freq= 29.1987853305302 Dur[127]= 1389 ' freq= 29.9976001919846 Return Frq_Lookup: For i = 0 To 38 Frq[i] = 21096 Next i Frq[39] = 2489 ' midi noot 99 = Mib Frq[40] = 2637 Frq[41] = 2793 Frq[42] = 2910 Frq[43] = 3136 Frq[44] = 3322 Frq[45] = 3620 Frq[46] = 3729 Frq[47] = 3901 Frq[48] = 4186 Frq[49] = 4435 Frq[50] = 4698 Frq[51] = 4978 Frq[52] = 5274 Frq[53] = 5587 Frq[54] = 5820 Frq[55] = 6272 Frq[56] = 6644 Frq[57] = 7040 Frq[58] = 7458 Frq[59] = 7802 ' end extended range for Chi Frq[60] = 8372 ' here we started for Frq[61] = 8870 Frq[62] = 9397 Frq[63] = 9956 Frq[64] = 10548 Frq[65] = 11175 Frq[66] = 11840 Frq[67] = 12544 ' highest possible midi note Frq[68] = 13289 Frq[69] = 14080 Frq[70] = 14917 Frq[71] = 15804 Frq[72] = 16744 Frq[73] = 17739 Frq[74] = 18794 Frq[75] = 19912 Frq[76] = 21096 For i = 77 To 127 Frq[i] = 21096 Next i Return Vels_Lookup: ' lookup table for the velocity controlled pulse durations ' if we state that the longest pulse (for fortissimo) should not exceed 16ms (=666 24us units) ' and we set the minimum pulse duration at 1ms (=42 24us units) then we can calculate the lookup ' as follows: ' vels[1] = 42 ' minimum velocity 1ms ' For i = 2 To 127 ' vels[i] = vels[i-1] + 5 ' Next i ' Velocity lookup tables for board 0 - after measurements 06.04.2015 ' Noot= 61 Out0 Output= 1 'Vels0[1]= 184 'Vels0[2]= 186 'Vels0[3]= 187 'Vels0[4]= 188 'Vels0[5]= 189 'Vels0[6]= 190 'Vels0[7]= 191 'Vels0[8]= 193 'Vels0[9]= 194 'Vels0[10]= 195 'Vels0[11]= 196 'Vels0[12]= 197 'Vels0[13]= 198 'Vels0[14]= 200 'Vels0[15]= 201 'Vels0[16]= 202 'Vels0[17]= 203 'Vels0[18]= 204 'Vels0[19]= 205 'Vels0[20]= 207 'Vels0[21]= 208 'Vels0[22]= 209 'Vels0[23]= 210 'Vels0[24]= 211 'Vels0[25]= 212 'Vels0[26]= 214 'Vels0[27]= 215 'Vels0[28]= 216 'Vels0[29]= 217 'Vels0[30]= 218 'Vels0[31]= 219 'Vels0[32]= 220 'Vels0[33]= 222 'Vels0[34]= 223 'Vels0[35]= 224 'Vels0[36]= 225 'Vels0[37]= 226 'Vels0[38]= 227 'Vels0[39]= 229 'Vels0[40]= 230 'Vels0[41]= 231 'Vels0[42]= 232 'Vels0[43]= 233 'Vels0[44]= 234 'Vels0[45]= 236 'Vels0[46]= 237 'Vels0[47]= 238 'Vels0[48]= 239 'Vels0[49]= 240 'Vels0[50]= 241 'Vels0[51]= 243 'Vels0[52]= 244 'Vels0[53]= 245 'Vels0[54]= 246 'Vels0[55]= 247 'Vels0[56]= 248 'Vels0[57]= 249 'Vels0[58]= 251 'Vels0[59]= 252 'Vels0[60]= 253 'Vels0[61]= 254 'Vels0[62]= 255 'Vels0[63]= 256 'Vels0[64]= 258 'Vels0[65]= 259 'Vels0[66]= 260 'Vels0[67]= 261 'Vels0[68]= 262 'Vels0[69]= 263 'Vels0[70]= 265 'Vels0[71]= 266 'Vels0[72]= 267 'Vels0[73]= 268 'Vels0[74]= 269 'Vels0[75]= 270 'Vels0[76]= 272 'Vels0[77]= 273 'Vels0[78]= 274 'Vels0[79]= 275 'Vels0[80]= 276 'Vels0[81]= 277 'Vels0[82]= 279 'Vels0[83]= 280 'Vels0[84]= 281 'Vels0[85]= 282 'Vels0[86]= 283 'Vels0[87]= 284 'Vels0[88]= 285 'Vels0[89]= 287 'Vels0[90]= 288 'Vels0[91]= 289 'Vels0[92]= 290 'Vels0[93]= 291 'Vels0[94]= 292 'Vels0[95]= 294 'Vels0[96]= 295 'Vels0[97]= 296 'Vels0[98]= 297 'Vels0[99]= 298 'Vels0[100]= 299 'Vels0[101]= 301 'Vels0[102]= 302 'Vels0[103]= 303 'Vels0[104]= 304 'Vels0[105]= 305 'Vels0[106]= 306 'Vels0[107]= 308 'Vels0[108]= 309 'Vels0[109]= 310 'Vels0[110]= 311 'Vels0[111]= 312 'Vels0[112]= 313 'Vels0[113]= 314 'Vels0[114]= 316 'Vels0[115]= 317 'Vels0[116]= 318 'Vels0[117]= 319 'Vels0[118]= 320 'Vels0[119]= 321 'Vels0[120]= 323 'Vels0[121]= 324 'Vels0[122]= 325 'Vels0[123]= 326 'Vels0[124]= 327 'Vels0[125]= 328 'Vels0[126]= 330 'Vels0[127]= 331 Return '[EOF]