' ******************************************************************** ' * PIC firmware for player piano pp2 * ' * pulse and hold coding * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/playerpiano/picworks * ' * source code development directory: * ' * pp2-5.bas * ' ******************************************************************** ' 22.01.2016: Starting from the code model for Zi (nov.2015) ' note repetitions not yet implemented. ' 23.01.2016: first prototype coded. ' Prog.change lookups recalculated after measurements on board 8. (pp2-8-V2) ' 24.01.2016: extensive testing on LED-board. ' note repetitions fully implemented now. ' Version 1.0 firmware upload in PIC ' 25.01.2016: PIC2 found molten as well. So replaced with this code. ' decided to replace all PIC's. ' this is the source code for PIC5 ' Chips labeled PP2.x-V3 Include "18F2525.inc" ' (40MHz) ' Mapping defines for midi-events on pin outputs and inputs: $define Vel0 PORTA.1 ' velocity bit - strobe $define Hol0 PORTA.2 $define Vel1 PORTA.3 $define Hol1 PORTA.0 $define Vel2 PORTA.5 $define Hol2 PORTA.4 $define Vel3 PORTB.6 $define Hol3 PORTB.7 $define Vel4 PORTB.4 $define Hol4 PORTB.5 $define Vel5 PORTB.2 $define Hol5 PORTB.3 $define Vel6 PORTB.0 $define Hol6 PORTB.1 $define Vel7 PORTC.4 $define Hol7 PORTC.5 $define Vel8 PORTC.1 $define Hol8 PORTC.0 $define Vel9 PORTC.3 $define Hol9 PORTC.2 'red LED for debug: ' $define Debug_Led PORTC.6 ' for testing - red led - watchdog ' this conflicts with serial out!!! Declare All_Digital = True ' makes all analog pins, digital for I/O ' configure the input and output pins: Clear SSPCON1.5 'RC3 must be available for I/O TRISA = %01000000 'bits set to 0 are output, 1 = input TRISB = %00000000 'no ICD possible. 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: Symbol noot0 = 61 ' board 5 Symbol noot1 = 62 Symbol noot2 = 63 Symbol noot3 = 64 Symbol noot4 = 65 Symbol noot5 = 66 Symbol noot6 = 67 Symbol noot7 = 68 Symbol noot8 = 69 Symbol noot9 = 70 'initialisations for the midi input parser: Symbol Midichannel = 0 ' Piano_Channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel 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 ' 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 Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables: ' Dim Cnt As Dword System '32 bit counter ' Dim CntHw As Cnt.Word1 ' Word System 'used in the timer0 interrupt, where it is incremented ' Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H 'it makes Cntlw the low word of cnt, when we use cnt.word0=CntLw ' Dim Tim1 As TMR1L.Word 'not used here ' Dim Tim2 As TMR2 'not used here ' Dim Cnt3 As Dword System ' Dim Cnt3Hw As Cnt3.Word1 ' Dim Tim3 As TMR3L.Word ' same trick for timer3 ' Dim Sr as TMR0L.7 '512 S/s - this works but these DO NOT WORK!!!: ' Dim Sr as CntLw.Byte1 does not ' Dim Sr As TMR0H.0 'sampling rate bit, 256 S/s ' DIM Sr as CntLw.8 ' As TMR0H.1 would be 128 S/s ' As TMR0H.2 would be 64 S/s ' As TMR0H.3 would be 32 S/s ' As TMR0H.4 would be 16 S/s 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 veltim As Dword System ' 32 bit velo Dim veltim0 As Dword System ' faster, replaces the arrays Dim veltim1 As Dword System ' Dim veltim2 As Dword System ' velo pulse timer Dim veltim3 As Dword System Dim veltim4 As Dword System Dim veltim5 As Dword System Dim veltim6 As Dword System Dim veltim7 As Dword System Dim veltim8 As Dword System Dim veltim9 As Dword System Dim Velflags As Word System ' so we can have only 16 tasks Dim Holdflags As Word System ' added 24.01.2016 Dim Waitflags As Word System ' Dim CC66 As Byte System ' global on/off switch ' Dim PowerOn As CC66.0 ' handled on the hub board. Dim notes As Word System ' for note repetition mechanism Dim Rate0 As Word 'System ' set with key pressure Dim Rate1 As Word 'System Dim Rate2 As Word 'System Dim Rate3 As Word 'System Dim Rate4 As Word 'System Dim Rate5 As Word 'System Dim Rate6 As Word 'System Dim Rate7 As Word 'System Dim Rate8 As Word 'system Dim Rate9 As Word 'system Dim velo0 As Word System Dim velo1 As Word System Dim velo2 As Word System Dim velo3 As Word System Dim velo4 As Word System Dim velo5 As Word System Dim velo6 As Word System Dim velo7 As Word System Dim velo8 As Word System Dim velo9 As Word System Dim Pres0 As Byte 'System 'indexes for durations lookup Dim Pres1 As Byte 'System Dim Pres2 As Byte 'System Dim Pres3 As Byte 'System Dim Pres4 As Byte 'System Dim Pres5 As Byte 'System Dim Pres6 As Byte 'System Dim Pres7 As Byte 'System Dim Pres8 As Byte Dim Pres9 As Byte 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[10] 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 Dim Ringbuffer[256] As Byte 'System '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Include "pp2_Irq.inc" ' for UART,Timer0, Timer3 Interrupt 'Clear ' clear all RAM '----------------------------------------------------------------------------------------- 'Dim dummy[256] As Word ' unusable memory space ' must overlap with Dim Ringbuffer[256] As Byte At __Start_Of_Reserve_Ram ' in the interrupt handler Dim vels[128] As Word ' velocity lookup table in use Dim Dur[128] As Word ' duration lookup for repetitions ' Main program starts here MAIN: ' High Debug_Led DelayMS 10 ' wait for stability ' Low Debug_Led Low Vel0 Low Vel1 Low Vel2 Low Vel3 Low Vel4 Low Vel5 Low Vel6 Low Vel7 Low Vel8 Low Vel9 Low Hol0 Low Hol1 Low Hol2 Low Hol3 Low Hol4 Low Hol5 Low Hol6 Low Hol7 Low Hol8 Low Hol9 Clear notes Clear Velflags Clear Holdflags Clear Waitflags Set TimVals Clear Pres0 Clear Pres1 Clear Pres2 Clear Pres3 Clear Pres4 Clear Pres5 Clear Pres6 Clear Pres7 Clear Pres8 Clear Pres9 Clear Rate0 Clear Rate1 Clear Rate2 Clear Rate3 Clear Rate4 Clear Rate5 Clear Rate6 Clear Rate7 Clear Rate8 Clear Rate9 Clear velo0 Clear velo1 Clear velo2 Clear velo3 Clear velo4 Clear velo5 Clear velo6 Clear velo7 Clear velo8 Clear velo9 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 ' 6.4 us per clock-tick ' Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) ' replacing above macro with in-line coding: 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 bot, 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 ' TIMER1: if enabled, all midi-in is blocked, so it must interfere with the UART ' Configure Timer1 for: ' Clear TMR1L and TMR1H registers ' Interrupt on Timer1 overflow ' 16-bit read/write mode ' Internal clock source ' 1:8 Prescaler ' ' OpenTimer1(TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_8) ' dit kompileert o.k. ' TIMER2: if enabled, the UART stops working... ' Opentimer2 (Timer_Int_On & T2_POST_1_16 & T2_PS_1_16) ' dit lukt... maar de timer is nodig voor de UART... ' TIMER3: ' Configure Timer3 for: ' Interrupt on Timer3 overflow ' 16-bit read/write mode ' Internal clock source ' 1:8 Prescaler ' Don’t sync external clock input ' T3_OSC1En_On () ' macro ' OpenTimer3(TIMER_INT_ON & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_8 & T3_SYNC_EXT_OFF) ' fout, but == voorbeeld??? ' Opentimer3 (Timer_Int_On & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_8 & T3_SYNC_EXT_OFF & T3_SOURCE_CCP) ' fout ' OpenTimer3 (Timer_INT_ON & T3_16BIT_RW & T3_PS_1_8 & T3_SYNC_EXT_OFF) ' fout ' OpenTimer3 (0xFFFF & Timer_INT_On & T3_16BIT_RW) ' OpenTimer3(T3_8BIT_RW & T3_SOURCE_EXT & T3_PS_1_1 & T3_SYNC_EXT_OFF) ' copied from manual, fout!!! ' OpenTimer3(TIMER_INT_OFF & T3_16BIT_RW & T3_SOURCE_INT & T3_PS_1_8) ' doing it this way seems to work: Clear T3CON Clear PIR2BITS_TMR3IF ' clear IRQ flag Set PIE2BITS_TMR3IE ' irq on 'T3_OSC1En_On () ' macro - sets T3CON ' 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 = %10110001 ' 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 ' maximum count = 52.42ms, 1 tick =0.8uS, freq.=19Hz ' Set up priority interrupts. ' IPR1bits_TMR1IP = 0 ' Set Timer1 as a low priority interrupt source ' INTCONbits_PEIE = 1 ' Enable peripheral interrupts ' INTCONbits_GIE = 1 ' Enable global interrupts ' Open the ADC: ' not used on this board. ' Fosc/32 ' Right justified for 10-bit operation ' Tad value of 0 ' Vref+ at Vcc : Vref- at Gnd ' Make AN0 an analogue input ' OpenADC(ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_0_TAD, ADC_REF_VDD_VSS, ADC_1ANA) GoSub Dur_Lookup GoSub Vels_Lookup_0 ' read the default lookup table ' start the main program loop: LOOP: ' Create an infinite loop Inc t ' byte If t.1 = tg Then Btg tg Inc time ' dword EndIf Bytein = HRSIn ' Read data from the serial buffer, with no timeout ' Start the midi parser. Midi_Parse: If Bytein > ProgChange_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. Else Clear statusbyte 'reset the status byte End If GoTo Check_Timers 'throw away... 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 'reset value. Cannot be 0 !!! Set release '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Case Keypres_Status 'not used here statusbyte = Bytein notePres = 255 pres = 255 Case Control_Status ' controllers and switches statusbyte = Bytein Set Ctrl Set value Case ProgChange_Status ' used for different lookup tables statusbyte = Bytein prog = 255 ' Case Aftertouch_Status ' statusbyte = Bytein ' Set aft ' Case Pitchbend_Status ' not on this board. ' statusbyte = Bytein ' pblsb = 255 ' 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 noot0 Clear Velflags.0 ' cancel running velo timer Clear notes.0 ' cancel note repetitions Clear Holdflags.0 Clear Waitflags.0 Set TimVals[0] Clear Vel0 Clear Hol0 Case noot1 Clear Velflags.1 ' cancel running timer Clear Holdflags.1 Clear Waitflags.1 Clear notes.1 Set TimVals[1] Clear Vel1 Clear Hol1 Case noot2 Clear Velflags.2 ' cancel running timer Clear Holdflags.2 Clear Waitflags.2 Clear notes.2 Set TimVals[2] Clear Vel2 Clear Hol2 Case noot3 Clear Velflags.3 ' cancel running timer Clear Holdflags.3 Clear Waitflags.3 Clear notes.3 Set TimVals[3] Clear Vel3 Clear Hol3 Case noot4 Clear Velflags.4 ' cancel running timer Clear Holdflags.4 Clear Waitflags.4 Clear notes.4 Set TimVals[4] Clear Vel4 Clear Hol4 Case noot5 Clear Velflags.5 Clear Holdflags.5 Clear Waitflags.5 Clear notes.5 Set TimVals[5] Clear Vel5 Clear Hol5 Case noot6 Clear Velflags.6 Clear Holdflags.6 Clear Waitflags.6 Clear notes.6 Set TimVals[6] Clear Vel6 Clear Hol6 Case noot7 Clear Velflags.7 Clear Holdflags.7 Clear Waitflags.7 Clear notes.7 Set TimVals[7] Clear Vel7 Clear Hol7 Case noot8 Clear Velflags.8 Clear Holdflags.8 Clear Waitflags.8 Clear notes.8 Set TimVals[8] Clear Vel8 Clear Hol8 Case noot9 Clear Velflags.9 Clear Holdflags.9 Clear Waitflags.9 Clear notes.9 Set TimVals[9] Clear Vel9 Clear Hol9 End Select Set noteUit '= 255 'reset GoTo resort ' mandatory, as we changed timers! EndIf GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then Select noteAan Case noot0 Clear Velflags.0 ' cancel running timer Clear Holdflags.0 Clear Waitflags.0 Clear notes.0 ' cancel repeats Set TimVals[0] Clear Vel0 Clear Hol0 Case noot1 Clear Velflags.1 ' cancel running timer Clear Holdflags.1 Clear Waitflags.1 Clear notes.1 Set TimVals[1] Clear Vel1 Clear Hol1 Case noot2 Clear Velflags.2 ' cancel running timer Clear Holdflags.2 Clear Waitflags.2 Clear notes.2 Set TimVals[2] Clear Vel2 Clear Hol2 Case noot3 Clear Velflags.3 ' cancel running timer Clear Holdflags.3 Clear Waitflags.3 Clear notes.3 Set TimVals[3] Clear Vel3 Clear Hol3 Case noot4 Clear Velflags.4 ' cancel running timer Clear Holdflags.4 Clear Waitflags.4 Clear notes.4 Set TimVals[4] Clear Vel4 Clear Hol4 Case noot5 Clear Velflags.5 Clear Holdflags.5 Clear Waitflags.5 Clear notes.5 Set TimVals[5] Clear Vel5 Clear Hol5 Case noot6 Clear Velflags.6 Clear Holdflags.6 Clear Waitflags.6 Clear notes.6 Set TimVals[6] Clear Vel6 Clear Hol6 Case noot7 Clear Velflags.7 Clear Holdflags.7 Clear Waitflags.7 Clear notes.7 Set TimVals[7] Clear Vel7 Clear Hol7 Case noot8 Clear Velflags.8 Clear Holdflags.8 Clear Waitflags.8 Clear notes.8 Set TimVals[8] Clear Vel8 Clear Hol8 Case noot9 Clear Velflags.9 Clear Holdflags.9 Clear Waitflags.9 Clear notes.9 Set TimVals[9] Clear Vel9 Clear Hol9 Case Else Set noteAan GoTo Check_Timers End Select Set noteAan GoTo resort ' mandatory as we changed timers Else Select noteAan Case noot0 ' in principle is could be that Hol0 is still on. ' this is not a problem for the hardware however. Set Velflags.0 velo0 = vels[velo] ' read velo lookup TimVals[0] = time + velo0 ' set the timer value Set Vel0 ' set the velo bit high If Pres0 > 0 Then ' if note repeats are programmed... Set notes.0 ' set the repeat flag 'if velo0 > Dur[Pres0]>>1 then velo0 = Dur[Pres0] ' safety! Rate0 = Dur[Pres0] '- velo0 ' dur's must be > velo Else Clear notes.0 ' clear the note repeat flag EndIf Case noot1 Set Velflags.1 velo1 = vels[velo] ' read lookup TimVals[1] = time + velo1 Set Vel1 If Pres1 > 0 Then ' if note repeats are programmed... Set notes.1 'if velo1 > Dir[Pres1] then velo1 = Dur[Pres1] Rate1 = Dur[Pres1] '- velo1 Else Clear notes.1 EndIf Case noot2 Set Velflags.2 velo2 = vels[velo] ' read lookup TimVals[2] = time + velo2 Set Vel2 If Pres2 > 0 Then ' if note repeats are programmed... Set notes.2 'If velo2 > Dir[Pres2] Then velo2 = Dur[Pres2] Rate2 = Dur[Pres2] '- velo2 Else Clear notes.2 EndIf Case noot3 Set Velflags.3 velo3 = vels[velo] ' read lookup TimVals[3] = time + velo3 Set Vel3 If Pres3 > 0 Then ' if note repeats are programmed... Set notes.3 'If velo3 > Dir[Pres3] Then velo3 = Dur[Pres3] Rate3 = Dur[Pres3] '- velo3 Else Clear notes.3 EndIf Case noot4 Set Velflags.4 velo4 = vels[velo] ' read lookup TimVals[4] = time + velo4 Set Vel4 If Pres4 > 0 Then ' if note repeats are programmed... Set notes.4 Rate4 = Dur[Pres4] '- velo4 Else Clear notes.4 EndIf Case noot5 Set Velflags.5 velo5 = vels[velo] ' read lookup TimVals[5] = time + velo5 Set Vel5 If Pres5 > 0 Then ' if note repeats are programmed... Set notes.5 Rate5 = Dur[Pres5] '- velo5 Else Clear notes.5 EndIf Case noot6 Set Velflags.6 velo6 = vels[velo] ' read lookup TimVals[6] = time + velo6 Set Vel6 If Pres6 > 0 Then ' if note repeats are programmed... Set notes.6 Rate6 = Dur[Pres6] '- velo6 Else Clear notes.6 EndIf Case noot7 Set Velflags.7 velo7 = vels[velo] ' read lookup TimVals[7] = time + velo7 Set Vel7 If Pres7 > 0 Then ' if note repeats are programmed... Set notes.7 Rate7 = Dur[Pres7] '- velo7 Else Clear notes.7 EndIf Case noot8 Set Velflags.8 velo8 = vels[velo] ' read lookup TimVals[8] = time + velo8 Set Vel8 If Pres8 > 0 Then ' if note repeats are programmed... Set notes.8 Rate8 = Dur[Pres8] '- velo8 Else Clear notes.8 EndIf Case noot9 Set Velflags.9 velo9 = vels[velo] ' read lookup TimVals[9] = time + velo9 Set Vel9 If Pres9 > 0 Then ' if note repeats are programmed... Set notes.9 Rate9 = Dur[Pres9] '- velo9 Else Clear notes.9 EndIf Case Else Set noteAan GoTo Check_Timers End Select Set noteAan '= 255 'reset !!! GoTo resort EndIf EndIf GoTo Check_Timers Case Keypres_Status 'used for note repetitions If notePres = 255 Then notePres = Bytein Else pres = Bytein GoSub KeyPres EndIf GoTo Check_Timers Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller ' fingerings implemented here EndIf GoTo Check_Timers Case ProgChange_Status ' could be used to select alternative fingering lookups If prog = 255 Then 'single byte message prog = Bytein 'weak coding... GoSub ProgChange EndIf GoTo Check_Timers Case Else GoTo Check_Timers ' no sorting End Select EndIf resort: GoSub SortTimers ' so we resort only if an incoming midi command changed something Check_Timers: If idx < 10 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 ' noot0 If notes.0 = 0 Then ' in dit geval zijn er geen repeats Clear Vel0 ' cut velo-voltage Set Hol0 ' switch hold voltage on Clear Velflags.0 ' cancel timer Set TimVals[0] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.0 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.0 TimVals[0] = time + velo0 Set Vel0 Clear Waitflags.0 ElseIf Holdflags.0 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol0 TimVals[0] = time + Dur[Pres0] ' waittime Clear Holdflags.0 Set Waitflags.0 ElseIf Velflags.0 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel0 TimVals[0] = time + Rate0 ' rate0 = Dur(Pres0) - velo Set Hol0 Set Holdflags.0 Clear Velflags.0 EndIf EndIf Case 1 If notes.1 = 0 Then ' in dit geval zijn er geen repeats Clear Vel1 ' cut velo-voltage Set Hol1 ' switch hold voltage on Clear Velflags.1 ' cancel timer Set TimVals[1] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.1 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.1 TimVals[1] = time + velo1 Set Vel1 Clear Waitflags.1 ElseIf Holdflags.1 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol1 TimVals[1] = time + Dur[Pres1] ' waittime Clear Holdflags.1 Set Waitflags.1 ElseIf Velflags.1 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel1 TimVals[1] = time + Rate1 ' rate1 = Dur(Pres0) - velo Set Hol1 Set Holdflags.1 Clear Velflags.1 EndIf EndIf Case 2 ' noot2 If notes.2 = 0 Then ' in dit geval zijn er geen repeats Clear Vel2 ' cut velo-voltage Set Hol2 ' switch hold voltage on Clear Velflags.2 ' cancel timer Set TimVals[2] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.2 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.2 TimVals[2] = time + velo2 Set Vel2 Clear Waitflags.2 ElseIf Holdflags.2 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol2 TimVals[2] = time + Dur[Pres2] ' waittime Clear Holdflags.2 Set Waitflags.2 ElseIf Velflags.2 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel2 TimVals[2] = time + Rate2 ' rate2 = Dur(Pres2) - velo Set Hol2 Set Holdflags.2 Clear Velflags.2 EndIf EndIf Case 3 ' noot3 If notes.3 = 0 Then ' in dit geval zijn er geen repeats Clear Vel3 ' cut velo-voltage Set Hol3 ' switch hold voltage on Clear Velflags.3 ' cancel timer Set TimVals[3] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.3 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.3 TimVals[3] = time + velo3 Set Vel3 Clear Waitflags.3 ElseIf Holdflags.3 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol3 TimVals[3] = time + Dur[Pres3] ' waittime Clear Holdflags.3 Set Waitflags.3 ElseIf Velflags.3 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel3 TimVals[3] = time + Rate3 ' rate3 = Dur(Pres3) - velo Set Hol3 Set Holdflags.3 Clear Velflags.3 EndIf EndIf Case 4 ' noot4 If notes.4 = 0 Then ' in dit geval zijn er geen repeats Clear Vel4 ' cut velo-voltage Set Hol4 ' switch hold voltage on Clear Velflags.4 ' cancel timer Set TimVals[4] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.4 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.4 TimVals[4] = time + velo4 Set Vel4 Clear Waitflags.4 ElseIf Holdflags.4 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol4 TimVals[4] = time + Dur[Pres4] ' waittime Clear Holdflags.4 Set Waitflags.4 ElseIf Velflags.4 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel4 TimVals[4] = time + Rate4 ' rate4 = Dur(Pres4) - velo Set Hol4 Set Holdflags.4 Clear Velflags.4 EndIf EndIf Case 5 ' noot5 If notes.5 = 0 Then ' in dit geval zijn er geen repeats Clear Vel5 ' cut velo-voltage Set Hol5 ' switch hold voltage on Clear Velflags.5 ' cancel timer Set TimVals[5] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.5 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.5 TimVals[5] = time + velo5 Set Vel5 Clear Waitflags.5 ElseIf Holdflags.5 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol5 TimVals[5] = time + Dur[Pres5] ' waittime Clear Holdflags.5 Set Waitflags.5 ElseIf Velflags.5 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel5 TimVals[5] = time + Rate5 ' rate5 = Dur(Pres5) - velo Set Hol5 Set Holdflags.5 Clear Velflags.5 EndIf EndIf Case 6 ' noot6 If notes.6 = 0 Then ' in dit geval zijn er geen repeats Clear Vel6 ' cut velo-voltage Set Hol6 ' switch hold voltage on Clear Velflags.6 ' cancel timer Set TimVals[6] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.6 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.6 TimVals[6] = time + velo6 Set Vel6 Clear Waitflags.6 ElseIf Holdflags.6 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol6 TimVals[6] = time + Dur[Pres6] ' waittime Clear Holdflags.6 Set Waitflags.6 ElseIf Velflags.6 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel6 TimVals[6] = time + Rate6 ' rate6 = Dur(Pres6) - velo Set Hol6 Set Holdflags.6 Clear Velflags.6 EndIf EndIf Case 7 ' noot7 If notes.7 = 0 Then ' in dit geval zijn er geen repeats Clear Vel7 ' cut velo-voltage Set Hol7 ' switch hold voltage on Clear Velflags.7 ' cancel timer Set TimVals[7] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.7 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.7 TimVals[7] = time + velo7 Set Vel7 Clear Waitflags.7 ElseIf Holdflags.7 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol7 TimVals[7] = time + Dur[Pres7] ' waittime Clear Holdflags.7 Set Waitflags.7 ElseIf Velflags.7 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel7 TimVals[7] = time + Rate7 ' rate7 = Dur(Pres7) - velo Set Hol7 Set Holdflags.7 Clear Velflags.7 EndIf EndIf Case 8 ' noot8 If notes.8 = 0 Then ' in dit geval zijn er geen repeats Clear Vel8 ' cut velo-voltage Set Hol8 ' switch hold voltage on Clear Velflags.8 ' cancel timer Set TimVals[8] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.8 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.8 TimVals[8] = time + velo8 Set Vel8 Clear Waitflags.8 ElseIf Holdflags.8 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol8 TimVals[8] = time + Dur[Pres8] ' waittime Clear Holdflags.8 Set Waitflags.8 ElseIf Velflags.8 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel8 TimVals[8] = time + Rate8 ' rate8 = Dur(Pres8) - velo Set Hol8 Set Holdflags.8 Clear Velflags.8 EndIf EndIf Case 9 ' noot9 If notes.9 = 0 Then ' in dit geval zijn er geen repeats Clear Vel9 ' cut velo-voltage Set Hol9 ' switch hold voltage on Clear Velflags.9 ' cancel timer Set TimVals[9] ' set to infinite= disable Else ' in dit geval moet de noot worden herhaald: If Waitflags.9 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.9 TimVals[9] = time + velo9 Set Vel9 Clear Waitflags.9 ElseIf Holdflags.9 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Hol9 TimVals[9] = time + Dur[Pres9] ' waittime Clear Holdflags.9 Set Waitflags.9 ElseIf Velflags.9 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Vel9 TimVals[9] = time + Rate9 ' rate9 = Dur(Pres9) - velo Set Hol9 Set Holdflags.9 Clear Velflags.9 EndIf 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 Holdflags Clear Waitflags Clear notes Set TimVals EndIf Else ' idx > 7, 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.2 ' average loop-speed: 4.5 microseconds, 5.45 us under full load. (Tektronix measurement) GoTo 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 9 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 10 dword comparisons idx = i EndIf Next i Return KeyPres: ' used for auto-repeat in Select notePres Case noot0 Pres0 = pres If Pres0 > 0 Then Rate0 = Dur[Pres0] ' note that we set notes.0 only on reception of a note-on ' this way we can program the repeats prior to playing. Else Clear Rate0 Clear notes.0 ' we have to cancel running timers here: Clear Velflags.0 Clear Holdflags.0 Clear Waitflags.0 Set TimVals[0] Clear Hol0 Clear Vel0 GoSub SortTimers EndIf Case noot1 Pres1 = pres If Pres1 > 0 Then Rate1 = Dur[Pres1] Else Clear Rate1 Clear notes.1 ' we have to cancel running timers here: Clear Velflags.1 Clear Holdflags.1 Clear Waitflags.1 Set TimVals[1] Clear Hol1 Clear Vel1 GoSub SortTimers EndIf Case noot2 Pres2 = pres If Pres2 > 0 Then Rate2 = Dur[Pres2] Else Clear Rate2 Clear notes.2 Clear Velflags.2 Clear Holdflags.2 Clear Waitflags.2 Set TimVals[2] Clear Hol2 Clear Vel2 GoSub SortTimers EndIf Case noot3 Pres3 = pres If Pres3 > 0 Then Rate3 = Dur[Pres3] Else Clear Rate3 Clear notes.3 Clear Velflags.3 Clear Holdflags.3 Clear Waitflags.3 Set TimVals[3] Clear Hol3 Clear Vel3 GoSub SortTimers EndIf Case noot4 Pres4 = pres If Pres4 > 0 Then Rate4 = Dur[Pres4] Else Clear Rate4 Clear notes.4 Clear Velflags.4 Clear Holdflags.4 Clear Waitflags.4 Set TimVals[4] Clear Hol4 Clear Vel4 GoSub SortTimers EndIf Case noot5 Pres5 = pres If Pres5 > 0 Then Rate5 = Dur[Pres5] Else Clear Rate5 Clear notes.5 Clear Velflags.5 Clear Holdflags.5 Clear Waitflags.5 Set TimVals[5] Clear Hol5 Clear Vel5 GoSub SortTimers EndIf Case noot6 Pres6 = pres If Pres6 > 0 Then Rate6 = Dur[Pres6] Else Clear Rate6 Clear notes.6 Clear Velflags.6 Clear Holdflags.6 Clear Waitflags.6 Set TimVals[6] Clear Hol6 Clear Vel6 GoSub SortTimers EndIf Case noot7 Pres7 = pres If Pres7 > 0 Then Rate7 = Dur[Pres7] Else Clear Rate7 Clear notes.7 Clear Velflags.7 Clear Holdflags.7 Clear Waitflags.7 Set TimVals[7] Clear Hol7 Clear Vel7 GoSub SortTimers EndIf Case noot8 Pres8 = pres If Pres8 > 0 Then Rate8 = Dur[Pres8] Else Clear Rate8 Clear notes.8 Clear Velflags.8 Clear Holdflags.8 Clear Waitflags.8 Set TimVals[8] Clear Hol8 Clear Vel8 GoSub SortTimers EndIf Case noot9 Pres9 = pres If Pres9 > 0 Then Rate9 = Dur[Pres9] Else Clear Rate9 Clear notes.9 Clear Velflags.9 Clear Holdflags.9 Clear Waitflags.9 Set TimVals[9] Clear Hol9 Clear Vel9 GoSub SortTimers EndIf EndSelect ' we do not need to resort here if pres changed ' as timers are only reprogrammed after reception of a note-on ' however on note-pressure zero we perform a full noteoff. Set notePres '= 255 Return ProgChange: ' here we have to change the velo lookup ' implemented prog. changes: 0, 122, 123 prog = prog & 7 ' bit mask to preserve only the 3 lowest bits Select prog Case 0 GoSub Vels_Lookup_0 Case 2 '122 GoSub Vels_Lookup_2 Case 3 '123 GoSub Vels_Lookup_3 EndSelect Set prog '= 255 Return 'Pitchbend: ' Set pblsb 'Return 'Aftertouch: ' not implemented on the player piano ' 'this is the channel aftertouch, affecting any playing note ' 'used for fingered vibrato in instruments such as ' 'the value of aft is used to set or modify the vibrato speed. Minimum freq=19Hz/2 = 9.54Hz ' coding using timer3: ' If aft > 0 Then ' Clear T3CONBITS_TMR3ON ' stop timer ' CC31 = aft ' VibratoPeriod = CC31 << 9 '* CC31 ' Tim3 = VibratoPeriod ' Set T3CONBITS_TMR3ON ' restart timer ' Else ' Clear CC31 ' Clear VibratoPeriod ' Clear T3CONBITS_TMR3ON ' stop timer ' EndIf ' Set aft ' reset 'Return Controller: Select Ctrl Case 30 ' can be used for global repeat frequency of the notes ' controller to set all repeat frequencies to one and the same value at once If value = 0 Then Clear notes Clear Rate0 Clear Pres0 Clear Rate1 Clear Pres1 Clear Rate2 Clear Pres2 Clear Rate3 Clear Pres3 Clear Rate4 Clear Pres4 Clear Rate5 Clear Pres5 Clear Rate6 Clear Pres6 Clear Rate7 Clear Pres7 Clear Rate8 Clear Pres8 Clear Rate9 Clear Pres9 ' should'nt we also cancel all running timers and ' perform an all-notes off: Clear Velflags Clear Holdflags Clear Waitflags Set TimVals Clear Vel0 Clear Vel1 Clear Vel2 Clear Vel3 Clear Vel4 Clear Vel5 Clear Vel6 Clear Vel7 Clear Vel8 Clear Vel9 Clear Hol0 Clear Hol1 Clear Hol2 Clear Hol3 Clear Hol4 Clear Hol5 Clear Hol6 Clear Hol7 Clear Hol8 Clear Hol9 GoSub SortTimers Else Pres0 = value Rate0 = Dur[value] Pres1 = value Rate1 = Dur[value] Pres2 = value Rate2 = Dur[value] Pres3 = value Rate3 = Dur[value] Pres4 = value Rate4 = Dur[value] Pres5 = value Rate5 = Dur[value] Pres6 = value Rate6 = Dur[value] Pres7 = value Rate7 = Dur[value] Pres8 = value Rate8 = Dur[value] Pres9 = value Rate9 = Dur[value] EndIf Case 66 'on/off for the robot If value = 0 Then GoSub PowerDown EndIf Case 123 Clear Velflags Clear Holdflags Clear Waitflags Clear notes Set TimVals Clear Vel0 Clear Vel1 Clear Vel2 Clear Vel3 Clear Vel4 Clear Vel5 Clear Vel6 Clear Vel7 Clear Vel8 Clear Vel9 Clear Hol0 Clear Hol1 Clear Hol2 Clear Hol3 Clear Hol4 Clear Hol5 Clear Hol6 Clear Hol7 Clear Hol8 Clear Hol9 GoSub SortTimers End Select Set Ctrl 'mandatory reset Return PowerDown: ' must perform a controller reset!!! Clear Velflags 'stop all running timers Clear Holdflags Clear Waitflags Clear notes Set TimVals Clear Vel0 Clear Vel1 Clear Vel2 Clear Vel3 Clear Vel4 Clear Vel5 Clear Vel6 Clear Vel7 Clear Vel8 Clear Vel9 Clear Hol0 Clear Hol1 Clear Hol2 Clear Hol3 Clear Hol4 Clear Hol5 Clear Hol6 Clear Hol7 Clear Hol8 Clear Hol9 ' we should also reset all programmed repeat frequencies. Clear Rate0 Clear Pres0 Clear Rate1 Clear Pres1 Clear Rate2 Clear Pres2 Clear Rate3 Clear Pres3 Clear Rate4 Clear Pres4 Clear Rate5 Clear Pres5 Clear Rate6 Clear Pres6 Clear Rate7 Clear Pres7 Clear Rate8 Clear Pres8 Clear Rate9 Clear Pres9 GoSub SortTimers Return Dur_Lookup: Set Dur[0] ' not used ' durations for note repetition on pp2 ' the dur values are for a half period ! ' the frequencies are for the full period. Dur[1]= 23674 ' freq= 2.01144916866806 Dur[2]= 22917 ' freq= 2.07789185404056 Dur[3]= 22548 ' freq= 2.11189673669716 Dur[4]= 22185 ' freq= 2.14645245071208 Dur[5]= 21827 ' freq= 2.18165792912666 Dur[6]= 21475 ' freq= 2.21741781695216 Dur[7]= 21129 ' freq= 2.25372935865624 Dur[8]= 20789 ' freq= 2.29058865837932 Dur[9]= 20454 ' freq= 2.32810441082662 Dur[10]= 20124 ' freq= 2.36628143604888 Dur[11]= 19800 ' freq= 2.4050024050024 Dur[12]= 19481 ' freq= 2.44438414963542 Dur[13]= 19167 ' freq= 2.48442884223132 Dur[14]= 18858 ' freq= 2.52513774626406 Dur[15]= 18554 ' freq= 2.56651113609182 Dur[16]= 18255 ' freq= 2.60854821249234 Dur[17]= 17961 ' freq= 2.65124701403305 Dur[18]= 17672 ' freq= 2.69460432430102 Dur[19]= 17387 ' freq= 2.73877308443364 Dur[20]= 17107 ' freq= 2.78360014140689 Dur[21]= 16831 ' freq= 2.82924648678318 Dur[22]= 16560 ' freq= 2.87554635380722 Dur[23]= 16293 ' freq= 2.92266909832736 Dur[24]= 16030 ' freq= 2.97062056263553 Dur[25]= 15772 ' freq= 3.01921427967586 Dur[26]= 15518 ' freq= 3.06863304672301 Dur[27]= 15268 ' freq= 3.11887919957084 Dur[28]= 15022 ' freq= 3.16995390887016 Dur[29]= 14780 ' freq= 3.22185707842 Dur[30]= 14542 ' freq= 3.27458723827862 Dur[31]= 14307 ' freq= 3.32837405598991 Dur[32]= 14077 ' freq= 3.38275538957502 Dur[33]= 13850 ' freq= 3.43819838404676 Dur[34]= 13627 ' freq= 3.49446302333952 Dur[35]= 13407 ' freq= 3.55180484963434 Dur[36]= 13191 ' freq= 3.60996494724036 Dur[37]= 12978 ' freq= 3.66921310055845 Dur[38]= 12769 ' freq= 3.7292699208276 Dur[39]= 12564 ' freq= 3.79011840329892 Dur[40]= 12361 ' freq= 3.85236207580678 Dur[41]= 12162 ' freq= 3.91539612062552 Dur[42]= 11966 ' freq= 3.97952930127424 Dur[43]= 11773 ' freq= 4.04476748654104 Dur[44]= 11583 ' freq= 4.11111522222633 Dur[45]= 11397 ' freq= 4.17820896894337 Dur[46]= 11213 ' freq= 4.24677139204919 Dur[47]= 11032 ' freq= 4.3164473911392 Dur[48]= 10855 ' freq= 4.38683073413612 Dur[49]= 10680 ' freq= 4.45871232388086 Dur[50]= 10508 ' freq= 4.53169467253974 Dur[51]= 10338 ' freq= 4.60621470487982 Dur[52]= 10172 ' freq= 4.68138494092092 Dur[53]= 10008 ' freq= 4.75809828327814 Dur[54]= 9846 ' freq= 4.83638509232659 Dur[55]= 9688 ' freq= 4.91526090204868 Dur[56]= 9532 ' freq= 4.99570369482245 Dur[57]= 9378 ' freq= 5.07774020250028 Dur[58]= 9227 ' freq= 5.16083750070962 Dur[59]= 9078 ' freq= 5.24554391044807 Dur[60]= 8932 ' freq= 5.33128611946346 Dur[61]= 8788 ' freq= 5.41864447189891 Dur[62]= 8646 ' freq= 5.50763909542536 Dur[63]= 8507 ' freq= 5.59763108252588 Dur[64]= 8370 ' freq= 5.68925300108096 Dur[65]= 8235 ' freq= 5.78251944372163 Dur[66]= 8102 ' freq= 5.87744354715473 Dur[67]= 7972 ' freq= 5.97328745848565 Dur[68]= 7843 ' freq= 6.07153482328798 Dur[69]= 7717 ' freq= 6.17066834508846 Dur[70]= 7593 ' freq= 6.2714404871655 Dur[71]= 7470 ' freq= 6.37470516988589 Dur[72]= 7350 ' freq= 6.47878198898607 Dur[73]= 7231 ' freq= 6.58540279616203 Dur[74]= 7115 ' freq= 6.692768463675 Dur[75]= 7000 ' freq= 6.80272108843537 Dur[76]= 6888 ' freq= 6.91333443946684 Dur[77]= 6777 ' freq= 7.02656745153425 Dur[78]= 6667 ' freq= 7.14250001785625 Dur[79]= 6560 ' freq= 7.25900116144019 Dur[80]= 6454 ' freq= 7.37822243865008 Dur[81]= 6350 ' freq= 7.49906261717285 Dur[82]= 6248 ' freq= 7.62148649472593 Dur[83]= 6147 ' freq= 7.74671345681595 Dur[84]= 6048 ' freq= 7.87351977828168 Dur[85]= 5951 ' freq= 8.00185643069192 Dur[86]= 5855 ' freq= 8.13305680940181 Dur[87]= 5760 ' freq= 8.26719576719577 Dur[88]= 5668 ' freq= 8.40138454817354 Dur[89]= 5576 ' freq= 8.54000136640022 Dur[90]= 5486 ' freq= 8.68010346683332 Dur[91]= 5398 ' freq= 8.82160941442157 Dur[92]= 5311 ' freq= 8.96611704369189 Dur[93]= 5225 ' freq= 9.11369332421964 Dur[94]= 5141 ' freq= 9.26260408851344 Dur[95]= 5058 ' freq= 9.41460016193112 Dur[96]= 4977 ' freq= 9.56782150272204 Dur[97]= 4897 ' freq= 9.72412653033441 Dur[98]= 4818 ' freq= 9.88357152740714 Dur[99]= 4740 ' freq= 10.0462125778581 Dur[100]= 4664 ' freq= 10.2099158702932 Dur[101]= 4589 ' freq= 10.3767809150245 Dur[102]= 4515 ' freq= 10.546854400675 Dur[103]= 4442 ' freq= 10.7201818142836 Dur[104]= 4370 ' freq= 10.89680723548 Dur[105]= 4300 ' freq= 11.0741971207087 Dur[106]= 4231 ' freq= 11.2547973573736 Dur[107]= 4162 ' freq= 11.4413857806458 Dur[108]= 4095 ' freq= 11.6285830571545 Dur[109]= 4029 ' freq= 11.8190736210096 Dur[110]= 3964 ' freq= 12.012877805007 Dur[111]= 3901 ' freq= 12.206882240207 Dur[112]= 3838 ' freq= 12.4072557631703 Dur[113]= 3776 ' freq= 12.6109765940274 Dur[114]= 3715 ' freq= 12.8180478113183 Dur[115]= 3655 ' freq= 13.0284672008338 Dur[116]= 3596 ' freq= 13.2422268128608 Dur[117]= 3538 ' freq= 13.4593124983176 Dur[118]= 3481 ' freq= 13.6797034240298 Dur[119]= 3425 ' freq= 13.9033715676051 Dur[120]= 3370 ' freq= 14.1302811925957 Dur[121]= 3316 ' freq= 14.3603883048998 Dur[122]= 3262 ' freq= 14.5981139236811 Dur[123]= 3210 ' freq= 14.8345942738466 Dur[124]= 3158 ' freq= 15.0788624506167 Dur[125]= 3107 ' freq= 15.3263751590111 Dur[126]= 3057 ' freq= 15.5770518871598 Dur[127]= 3008 ' freq= 15.8308004052685 Return Vels_Lookup_0: ' lookup table for the velocity controlled pulse durations ' first test: ' resolution is 6.2 us. ' 21 = 130 us (meting 21.01.2016) ' vels[1] = 88 ' should be 550 microseconds ' maxvel = 44ms, or 44ms / 6.2us = 7096 units ' stepsize = (7096 - 88) / 126 = 55.6 ' For i = 2 To 127 ' vels[i] = vels[i-1] + 55 ' Next i ' resultaat: ' 1 = 88 units = 1ms ' 127 = 7096 units = 70ms ' benadering 2: resolution = 10.5 us (op grond van vorige meting) vels[1] = 52 ' maxvel = 44ms or 44000/10.5 = 4190 units ' stepsize = (4190 - 52) / 126 = 32.8 For i = 2 To 127 vels[i] = vels[i-1] + 32.8 Next i ' resultaat: [23.01.2016, 18u10] ' 1 = 52 => 550 us ' 127 = 4190 => 44ms ' dit komt overeen met prog change 0 to boards 1 tot 9 in pp2-firmware versie 2005. Return Vels_Lookup_2: ' lookup table for the velocity controlled pulse durations ' minvel = 500us or, 500us / 10.5us = 47.6 units ' maxvel = 27ms or, 27000us / 10.5us = 2571 units ' stepsize = (2571 - 47.6) / 126 = 20.02 vels[1] = 47 For i = 2 To 127 vels[i] = vels[i-1] + 20 Next i Return Vels_Lookup_3: ' lookup table for the velocity controlled pulse durations ' minvel = 480 us or, 45.7 units ' maxvel = 17ms or, 17000us / 10.5us = 1619 units ' stepsize = (1619 - 45) / 126 = 12.49 vels[1] = 46 For i = 2 To 127 vels[i] = vels[i-1] + 12.49 Next i Return '[EOF]