' ******************************************************************** ' * PIC firmware for Klung * ' * angklung shakers * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/klung/picworks * ' * source code development directory: * ' * Klung2.bas * ' * Version 3.0 * ' ******************************************************************** ' 20.11.2015: Starting code from the model for Tinti and Zi ' needs further work! ' 21.11.2015: further code writing. ' Coded such that compatibility with existing pieces and code for Klung is guaranteed. ' This version measured and tested. ' new duration scales, tempered, calculated in PBCC ' 22.11.2015: Version for the second PIC finished. Include "18F4620.inc" ' (40MHz) ' Mapping defines for midi-events on pin outputs and inputs: ' This is very specific for the 28-Pulse board ' mapping for board 1, lowest angklungs, left side of robot. $define Ang60L PORTA.2 ' noot 60 $define Ang60R PORTA.1 $define Ang61L PORTA.0 ' noot 61 $define Ang61R PORTA.3 $define Ang62L PORTA.4 ' noot 62 $define Ang62R PORTA.5 $define Ang63L PORTE.0 ' noot 63 $define Ang63R PORTE.1 $define Ang64L PORTE.2 $define Ang64R PORTB.4 $define Ang65L PORTB.3 $define Ang65R PORTB.2 $define Ang66L PORTB.1 $define Ang66R PORTB.0 $define Ang67L PORTD.7 $define Ang67R PORTD.6 $define Ang68L PORTD.5 ' missing note $define Ang68R PORTD.4 $define Ang69L PORTC.5 ' highest note $define Ang69R PORTC.4 $define Ang70L PORTD.3 'nc $define Ang70R PORTD.2 'nc $define Ang71L PORTC.0 'nc $define Ang71R PORTC.1 'nc $define nc PORTC.2 ' PORTC.2 ' on/off only $define Lite120 PORTD.0 ' PORTC.3 ' on/off only $define Lite121 PORTC.3 ' PORTD.0 $define Video_Relais PORTD.1 ' controller 67 'red LED for debug: $define Debug_Led PORTB.5 ' for testing - red led - watchdog Declare All_Digital = True ' makes all analog pins, digital for I/O Clear SSPCON1.5 ' make sure RC3 is free for use. ' configure the input and output pins: TRISA = %11000000 'bits set to 0 are output, 1 = input - bits 6 and 7 are the clock! TRISB = %11100000 'bits 6 and 7 are for the ICP, bit 5 is the red LED TRISC = %11000000 'RC6 en RC7 zijn USART I/O and must be set to input TRISD = %00000000 'all bits can be used TRISE = %11101000 'low nibble only, bit3 (RE3) is MCLR 'bit 4 most be zero to disable PSP mode on port D - gwr 20.01.2012 'this was the bug we had! 'constant definitions: Symbol noot0 = 60 Symbol noot1 = 61 Symbol noot2 = 62 Symbol noot3 = 63 Symbol noot4 = 64 Symbol noot5 = 65 Symbol noot6 = 66 Symbol noot7 = 67 Symbol noot8 = 68 ' missing note Symbol noot9 = 69 'Symbol noot10 = 70 'Symbol noot11 = 71 Symbol lamp0 = 120 Symbol lamp1 = 121 'initialisations for the midi input parser: Symbol Midichannel = 4 ' Klung_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 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 ' faster, replaces the arrays Dim veltim8 As Dword System ' Dim veltim9 As Dword System ' velo pulse timer ' Dim veltim10 As Dword System ' Dim veltim11 As Dword System Dim Velflags As Word System ' so we can have only 16 tasks Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 ' handled on the hub board. Dim notes As Word System ' must be word as we have 10 notes Dim LRword As Word System Dim LR0 As LRword.0 ' 0= left, 1= right Dim LR1 As LRword.1 Dim LR2 As LRword.2 Dim LR3 As LRword.3 Dim LR4 As LRword.4 Dim LR5 As LRword.5 Dim LR6 As LRword.6 Dim LR7 As LRword.7 ' 0= left, 1= right Dim LR8 As LRword.8 Dim LR9 As LRword.9 ' Dim LR10 As LRword.10 ' Dim LR11 As LRword.11 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 ' set with key pressure Dim Rate6 As Word 'System Dim Rate7 As Word 'System Dim Rate8 As Word 'System Dim Rate9 As Word 'System ' Dim Rate10 As Word 'System ' set with key pressure ' Dim Rate11 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 velo10 As Word System ' Dim velo11 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 'indexes for durations lookup Dim Pres6 As Byte 'System Dim Pres7 As Byte 'System Dim Pres8 As Byte 'System Dim Pres9 As Byte 'System ' Dim Pres10 As Byte 'System 'indexes for durations lookup ' Dim Pres11 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[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 oldprog As Byte ' for program changes to modify the lookup tables '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Include "Klung_Irq.inc" ' for UART,Timer0, Timer3 Interrupt 'Clear ' clear all RAM '----------------------------------------------------------------------------------------- Dim dummy[256] As Word ' unusable memory space Dim vels[128] As Word ' velocity lookup table 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 Video_Relais ' power off !!! ' make sure all shakers are free: Low Ang60R Low Ang60L Low Ang61R Low Ang61L Low Ang62L Low Ang62R Low Ang63L Low Ang63R Low Ang64L Low Ang64R Low Ang65L Low Ang65R Low Ang66L Low Ang66R Low Ang67L Low Ang67R Low Ang68L Low Ang68R Low Ang69L Low Ang69R Low Ang70L Low Ang70R Low Ang71L Low Ang71R Low nc Low Lite120 Low Lite121 Low Video_Relais Clear LRword ' 0 = left Clear notes Clear Velflags Set TimVals Clear CC66 Clear Pres0 Clear Pres1 Clear Pres2 Clear Pres3 Clear Pres4 Clear Pres5 Clear Pres6 Clear Pres7 Clear Pres8 Clear Pres9 ' Clear Pres10 ' Clear Pres11 Clear Rate0 Clear Rate1 Clear Rate2 Clear Rate3 Clear Rate4 Clear Rate5 Clear Rate6 Clear Rate7 Clear Rate8 Clear Rate9 ' Clear Rate10 ' Clear Rate11 Clear velo0 Clear velo1 Clear velo2 Clear velo3 Clear velo4 Clear velo5 Clear velo6 Clear velo7 Clear velo8 Clear velo9 ' Clear velo10 ' Clear velo11 Clear oldprog 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 ' always start in program change 0 ' 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 ' could be used for different lookup tables statusbyte = Bytein prog = 255 ' Case Aftertouch_Status ' for fingered vibrato, freq.changes during notes ' 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 ' note 48 Clear Velflags.0 ' cancel running timer Clear notes.0 If LR0 = 0 Then ' staat naar links Clear Ang60L Else ' staat naar rechts Clear Ang60R EndIf Case noot1 ' note 49 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR0 = 0 Then Clear Ang61L Else Clear Ang61R EndIf Case noot2 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Ang62L Else Clear Ang63R EndIf Case noot3 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Ang63L Else Clear Ang63R EndIf Case noot4 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then Clear Ang64L Else Clear Ang64R EndIf Case noot5 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then Clear Ang65L Else Clear Ang65R EndIf Case noot6 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then Clear Ang66L Else Clear Ang66R EndIf Case noot7 Clear Velflags.7 ' cancel running timer Clear notes.7 If LR7 = 0 Then Clear Ang67L Else Clear Ang67R EndIf Case noot8 Clear Velflags.8 ' cancel running timer Clear notes.8 If LR8 = 0 Then Clear Ang68L Else Clear Ang68R EndIf Case noot9 Clear Velflags.9 ' cancel running timer Clear notes.9 If LR9 = 0 Then Clear Ang69L Else Clear Ang69R EndIf ' Case noot10 ' Clear Velflags.10 ' cancel running timer ' Clear notes.10 ' If LR10 = 0 Then ' Clear Ang70L ' Else ' Clear Ang70R ' EndIf ' Case noot11 ' Clear Velflags.11 ' cancel running timer ' Clear notes.11 ' If LR11 = 0 Then ' Clear Ang71L ' Else ' Clear Ang71R ' EndIf Case lamp0 Clear Lite120 Set noteUit GoTo Check_Timers Case lamp1 Clear Lite121 Set noteUit GoTo Check_Timers ' Case lamp2 ' Clear Lite121 ' 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 noot0 ' note 48 Clear Velflags.0 ' cancel running timer Clear notes.0 If LR0 = 0 Then ' staat naar links Clear Ang60L Else ' staat naar rechts Clear Ang60R EndIf Case noot1 ' note 49 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR0 = 0 Then Clear Ang61L Else Clear Ang61R EndIf Case noot2 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Ang62L Else Clear Ang63R EndIf Case noot3 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Ang63L Else Clear Ang63R EndIf Case noot4 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then Clear Ang64L Else Clear Ang64R EndIf Case noot5 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then Clear Ang65L Else Clear Ang65R EndIf Case noot6 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then Clear Ang66L Else Clear Ang66R EndIf Case noot7 Clear Velflags.7 ' cancel running timer Clear notes.7 If LR7 = 0 Then Clear Ang67L Else Clear Ang67R EndIf Case noot8 Clear Velflags.8 ' cancel running timer Clear notes.8 If LR8 = 0 Then Clear Ang68L Else Clear Ang68R EndIf Case noot9 Clear Velflags.9 ' cancel running timer Clear notes.9 If LR9 = 0 Then Clear Ang69L Else Clear Ang69R EndIf ' Case noot10 ' Clear Velflags.10 ' cancel running timer ' Clear notes.10 ' If LR10 = 0 Then ' Clear Ang70L ' Else ' Clear Ang70R ' EndIf ' Case noot11 ' Clear Velflags.11 ' cancel running timer ' Clear notes.11 ' If LR11 = 0 Then ' Clear Ang71L ' Else ' Clear Ang71R ' EndIf Case lamp0 Clear Lite120 Set noteUit GoTo Check_Timers Case lamp1 Clear Lite121 Set noteUit GoTo Check_Timers ' Case lamp2 ' Clear Lite121 ' Set noteUit ' GoTo Check_Timers End Select GoTo resort Else Select noteAan Case noot0 If LR0 = 0 Then ' we are left Clear Ang60L ' if not switched off by timer, do it now Set Ang60R ' move right Else ' we are right Clear Ang60R ' switch off if still on Set Ang60L ' move left EndIf Toggle LR0 ' reflects the position now Set Velflags.0 velo0 = vels[velo] TimVals[0] = time + velo0 If Pres0 > 0 Then ' if note repeats are programmed... Set notes.0 ' set the repeat flag Rate0 = Dur[Pres0] - velo0 'as Dur[127]=5449 is always larger than Vel[127]=2055 ' we do not need following construction: 'If Dur[Pres0] <= velo0 Then ' Rate0 = velo0 ' stick to 50% duty cycle 'Else ' Rate0 = Dur[Pres0] - velo0 'EndIf Else Clear notes.0 EndIf Case noot1 If LR1 = 0 Then ' we are left Clear Ang61L ' if not switched off by timer, do it now Set Ang61R ' move right Else ' we are right Clear Ang61R ' switch off if still on Set Ang61L ' move left EndIf Toggle LR1 ' reflects the position now Set Velflags.1 velo1 = vels[velo] TimVals[1] = time + velo1 If Pres1 > 0 Then ' if note repeats are programmed... Set notes.1 ' set the repeat flag Rate1 = Dur[Pres1] - velo1 'If Dur[Pres1] <= velo1 Then ' Rate1 = velo1 ' stick to 50% duty cycle 'Else ' Rate1 = Dur[Pres1] - velo1 'EndIf Else Clear notes.1 EndIf Case noot2 If LR2 = 0 Then ' we are left Clear Ang62L ' if not switched off by timer, do it now Set Ang62R ' move right Else ' we are right Clear Ang62R ' switch off if still on Set Ang62L ' move left EndIf Toggle LR2 ' reflects the position now Set Velflags.2 velo2 = vels[velo] TimVals[2] = time + velo2 If Pres2 > 0 Then ' if note repeats are programmed... Set notes.2 ' set the repeat flag Rate2 = Dur[Pres2] - velo2 'If Dur[Pres2] <= velo2 Then ' Rate2 = velo2 ' stick to 50% duty cycle 'Else ' Rate2 = Dur[Pres2] - velo2 'EndIf Else Clear notes.2 EndIf Case noot3 If LR3 = 0 Then ' we are left Clear Ang63L ' if not switched off by timer, do it now Set Ang63R ' move right Else ' we are right Clear Ang63R ' switch off if still on Set Ang63L ' move left EndIf Toggle LR3 ' reflects the position now Set Velflags.3 velo3 = vels[velo] TimVals[3] = time + velo3 If Pres3 > 0 Then ' if note repeats are programmed... Set notes.3 ' set the repeat flag Rate3 = Dur[Pres3] - velo3 'If Dur[Pres3] <= velo3 Then ' Rate3 = velo3 ' stick to 50% duty cycle 'Else ' Rate3 = Dur[Pres3] - velo3 'EndIf Else Clear notes.3 EndIf Case noot4 If LR4 = 0 Then ' we are left Clear Ang64L ' if not switched off by timer, do it now Set Ang64R ' move right Else ' we are right Clear Ang64R ' switch off if still on Set Ang64L ' move left EndIf Toggle LR4 ' reflects the position now Set Velflags.4 velo4 = vels[velo] TimVals[4] = time + velo4 If Pres4 > 0 Then ' if note repeats are programmed... Set notes.4 ' set the repeat flag Rate4 = Dur[Pres4] - velo4 'If Dur[Pres4] <= velo4 Then ' Rate4 = velo4 ' stick to 50% duty cycle 'Else ' Rate4 = Dur[Pres4] - velo4 'EndIf Else Clear notes.4 EndIf Case noot5 If LR5 = 0 Then ' we are left Clear Ang65L ' if not switched off by timer, do it now Set Ang65R ' move right Else ' we are right Clear Ang65R ' switch off if still on Set Ang65L ' move left EndIf Toggle LR5 ' reflects the position now Set Velflags.5 velo5 = vels[velo] TimVals[5] = time + velo5 If Pres5 > 0 Then ' if note repeats are programmed... Set notes.5 ' set the repeat flag Rate5 = Dur[Pres5] - velo5 'If Dur[Pres5] <= velo5 Then ' Rate5 = velo5 ' stick to 50% duty cycle 'Else ' Rate5 = Dur[Pres5] - velo5 'EndIf Else Clear notes.5 EndIf Case noot6 If LR6 = 0 Then ' we are left Clear Ang66L ' if not switched off by timer, do it now Set Ang66R ' move right Else ' we are right Clear Ang66R ' switch off if still on Set Ang66L ' move left EndIf Toggle LR6 ' reflects the position now Set Velflags.6 velo6 = vels[velo] TimVals[6] = time + velo6 If Pres6 > 0 Then ' if note repeats are programmed... Set notes.6 ' set the repeat flag Rate6 = Dur[Pres6] - velo6 'If Dur[Pres6] <= velo6 Then ' Rate6 = velo6 ' stick to 50% duty cycle 'Else ' Rate6 = Dur[Pres6] - velo6 'EndIf Else Clear notes.6 EndIf Case noot7 If LR7 = 0 Then ' we are left Clear Ang67L ' if not switched off by timer, do it now Set Ang67R ' move right Else ' we are right Clear Ang67R ' switch off if still on Set Ang67L ' move left EndIf Toggle LR7 ' reflects the position now Set Velflags.7 velo7 = vels[velo] TimVals[7] = time + velo7 If Pres7 > 0 Then ' if note repeats are programmed... Set notes.7 ' set the repeat flag Rate7 = Dur[Pres7] - velo7 'If Dur[Pres7] <= velo7 Then ' Rate7 = velo7 ' stick to 50% duty cycle 'Else ' Rate7 = Dur[Pres7] - velo7 'EndIf Else Clear notes.7 EndIf Case noot8 If LR8 = 0 Then ' we are left Clear Ang68L ' if not switched off by timer, do it now Set Ang68R ' move right Else ' we are right Clear Ang68R ' switch off if still on Set Ang68L ' move left EndIf Toggle LR8 ' reflects the position now Set Velflags.8 velo8 = vels[velo] TimVals[8] = time + velo8 If Pres8 > 0 Then ' if note repeats are programmed... Set notes.8 ' set the repeat flag Rate8 = Dur[Pres8] - velo8 'If Dur[Pres8] <= velo8 Then ' Rate8 = velo8 ' stick to 50% duty cycle 'Else ' Rate8 = Dur[Pres8] - velo8 'EndIf Else Clear notes.8 EndIf Case noot9 If LR9 = 0 Then ' we are left Clear Ang69L ' if not switched off by timer, do it now Set Ang69R ' move right Else ' we are right Clear Ang69R ' switch off if still on Set Ang69L ' move left EndIf Toggle LR9 ' reflects the position now Set Velflags.9 velo9 = vels[velo] TimVals[9] = time + velo9 If Pres9 > 0 Then ' if note repeats are programmed... Set notes.9 ' set the repeat flag Rate9 = Dur[Pres9] - velo9 'If Dur[Pres9] <= velo9 Then ' Rate9 = velo9 ' stick to 50% duty cycle 'Else ' Rate9 = Dur[Pres9] - velo9 'EndIf Else Clear notes.9 EndIf ' Case noot10 ' If LR10 = 0 Then ' we are left ' Clear Ang70L ' if not switched off by timer, do it now ' Set Ang70R ' move right ' Else ' we are right ' Clear Ang70R ' switch off if still on ' Set Ang70L ' move left ' EndIf ' Toggle LR10 ' reflects the position now ' Set Velflags.10 ' velo10 = vels[velo] ' TimVals[10] = time + velo10 ' If Pres10 > 0 Then ' if note repeats are programmed... ' Set notes.10 ' set the repeat flag ' Rate10 = Dur[Pres10] - velo10 ' 'If Dur[Pres10] <= velo10 Then ' ' Rate10 = velo10 ' stick to 50% duty cycle ' 'Else ' ' Rate10 = Dur[Pres10] - velo10 ' 'EndIf ' Else ' Clear notes.10 ' EndIf ' Case noot11 ' If LR11 = 0 Then ' we are left ' Clear Ang71L ' if not switched off by timer, do it now ' Set Ang71R ' move right ' Else ' we are right ' Clear Ang71R ' switch off if still on ' Set Ang71L ' move left ' EndIf ' Toggle LR11 ' reflects the position now ' Set Velflags.11 ' velo11 = vels[velo] ' TimVals[11] = time + velo11 ' If Pres11 > 0 Then ' if note repeats are programmed... ' Set notes.11 ' set the repeat flag ' Rate11 = Dur[Pres11] - velo11 ' 'If Dur[Pres11] <= velo11 Then ' ' Rate11 = velo11 ' stick to 50% duty cycle ' 'Else ' ' Rate11 = Dur[Pres11] - velo11 ' 'EndIf ' Else ' Clear notes.11 ' EndIf Case lamp0 Set Lite120 Set noteAan GoTo Check_Timers Case lamp1 Set Lite121 Set noteAan GoTo Check_Timers ' Case lamp2 ' Set Lite121 ' Set noteAan ' GoTo Check_Timers 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 lite flashing on Fa-Hub 'in used by PIC2 for fingerings !!! 'here we could use it for fingered vibrato 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 lookups If prog = 255 Then 'single byte message prog = Bytein 'weak coding... GoSub ProgChange EndIf GoTo Check_Timers ' Case Aftertouch_Status ' for changing vibrato frequency during notes ' If aft = 255 Then ' aft = Bytein ' GoSub Aftertouch ' EndIf ' GoTo Check_Timers 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 If LR0 = 0 Then ' we are left Clear Ang60L ' laat los, blijf links Else ' we are right Clear Ang60R ' laat los, blijf rechts EndIf If notes.0 = 0 Then ' note off - no repeats Clear Velflags.0 Set TimVals[0] Else ' note is active If Velflags.0 = 1 Then ' velo timer afgelopen TimVals[0] = time + Rate0 ' stel de wachttijd in Clear Velflags.0 Else ' wachttijd afgelopen If LR0 = 0 Then ' we zijn links Set Ang60R ' beweeg naar rechts Else ' we zijn rechts Set Ang60L ' beweeg naar links EndIf Toggle LR0 ' reflecting the position now TimVals[0] = time + velo0 ' velotijd gaat in Set Velflags.0 ' set velo-timer en aktiveer hem End If EndIf Case 1 If LR1 = 0 Then ' we are left Clear Ang61L ' laat los, blijf links Else ' we are right Clear Ang61R ' laat los, blijf rechts EndIf If notes.1 = 0 Then ' note off - no repeats Clear Velflags.1 Set TimVals[1] Else ' note is active If Velflags.1 = 1 Then ' velo timer afgelopen TimVals[1] = time + Rate1 ' stel de wachttijd in Clear Velflags.1 Else ' wachttijd afgelopen If LR1 = 0 Then ' we zijn links Set Ang61R ' beweeg naar rechts Else ' we zijn rechts Set Ang61L ' beweeg naar links EndIf Toggle LR1 ' reflecting the position now TimVals[1] = time + velo1 ' velotijd gaat in Set Velflags.1 ' set velo-timer en aktiveer hem End If EndIf Case 2 If LR2 = 0 Then ' we are left Clear Ang62L ' laat los, blijf links Else ' we are right Clear Ang62R ' laat los, blijf rechts EndIf If notes.2 = 0 Then ' note off - no repeats Clear Velflags.2 Set TimVals[2] Else ' note is active If Velflags.2 = 1 Then ' velo timer afgelopen TimVals[2] = time + Rate2 ' stel de wachttijd in Clear Velflags.2 Else ' wachttijd afgelopen If LR2 = 0 Then ' we zijn links Set Ang62R ' beweeg naar rechts Else ' we zijn rechts Set Ang62L ' beweeg naar links EndIf Toggle LR2 ' reflecting the position now TimVals[2] = time + velo2 ' velotijd gaat in Set Velflags.2 ' set velo-timer en aktiveer hem End If EndIf Case 3 If LR3 = 0 Then ' we are left Clear Ang63L ' laat los, blijf links Else ' we are right Clear Ang63R ' laat los, blijf rechts EndIf If notes.3 = 0 Then ' note off - no repeats Clear Velflags.3 Set TimVals[3] Else ' note is active If Velflags.3 = 1 Then ' velo timer afgelopen TimVals[3] = time + Rate3 ' stel de wachttijd in Clear Velflags.3 Else ' wachttijd afgelopen If LR3 = 0 Then ' we zijn links Set Ang63R ' beweeg naar rechts Else ' we zijn rechts Set Ang63L ' beweeg naar links EndIf Toggle LR3 ' reflecting the position now TimVals[3] = time + velo3 ' velotijd gaat in Set Velflags.3 ' set velo-timer en aktiveer hem End If EndIf Case 4 If LR4 = 0 Then ' we are left Clear Ang64L ' laat los, blijf links Else ' we are right Clear Ang64R ' laat los, blijf rechts EndIf If notes.4 = 0 Then ' note off - no repeats Clear Velflags.4 Set TimVals[4] Else ' note is active If Velflags.4 = 1 Then ' velo timer afgelopen TimVals[4] = time + Rate4 ' stel de wachttijd in Clear Velflags.4 Else ' wachttijd afgelopen If LR4 = 0 Then ' we zijn links Set Ang64R ' beweeg naar rechts Else ' we zijn rechts Set Ang64L ' beweeg naar links EndIf Toggle LR4 ' reflecting the position now TimVals[4] = time + velo4 ' velotijd gaat in Set Velflags.4 ' set velo-timer en aktiveer hem End If EndIf Case 5 If LR5 = 0 Then ' we are left Clear Ang65L ' laat los, blijf links Else ' we are right Clear Ang65R ' laat los, blijf rechts EndIf If notes.5 = 0 Then ' note off - no repeats Clear Velflags.5 Set TimVals[5] Else ' note is active If Velflags.5 = 1 Then ' velo timer afgelopen TimVals[5] = time + Rate5 ' stel de wachttijd in Clear Velflags.5 Else ' wachttijd afgelopen If LR5 = 0 Then ' we zijn links Set Ang65R ' beweeg naar rechts Else ' we zijn rechts Set Ang65L ' beweeg naar links EndIf Toggle LR5 ' reflecting the position now TimVals[5] = time + velo5 ' velotijd gaat in Set Velflags.5 ' set velo-timer en aktiveer hem End If EndIf Case 6 If LR6 = 0 Then ' we are left Clear Ang66L ' laat los, blijf links Else ' we are right Clear Ang66R ' laat los, blijf rechts EndIf If notes.6 = 0 Then ' note off - no repeats Clear Velflags.6 Set TimVals[6] Else ' note is active If Velflags.6 = 1 Then ' velo timer afgelopen TimVals[6] = time + Rate6 ' stel de wachttijd in Clear Velflags.6 Else ' wachttijd afgelopen If LR6 = 0 Then ' we zijn links Set Ang66R ' beweeg naar rechts Else ' we zijn rechts Set Ang66L ' beweeg naar links EndIf Toggle LR6 ' reflecting the position now TimVals[6] = time + velo6 ' velotijd gaat in Set Velflags.6 ' set velo-timer en aktiveer hem End If EndIf Case 7 If LR7 = 0 Then ' we are left Clear Ang67L ' laat los, blijf links Else ' we are right Clear Ang67R ' laat los, blijf rechts EndIf If notes.7 = 0 Then ' note off - no repeats Clear Velflags.7 Set TimVals[7] Else ' note is active If Velflags.7 = 1 Then ' velo timer afgelopen TimVals[7] = time + Rate7 ' stel de wachttijd in Clear Velflags.7 Else ' wachttijd afgelopen If LR7 = 0 Then ' we zijn links Set Ang67R ' beweeg naar rechts Else ' we zijn rechts Set Ang67L ' beweeg naar links EndIf Toggle LR7 ' reflecting the position now TimVals[7] = time + velo7 ' velotijd gaat in Set Velflags.7 ' set velo-timer en aktiveer hem End If EndIf Case 8 If LR8 = 0 Then ' we are left Clear Ang68L ' laat los, blijf links Else ' we are right Clear Ang68R ' laat los, blijf rechts EndIf If notes.8 = 0 Then ' note off - no repeats Clear Velflags.8 Set TimVals[8] Else ' note is active If Velflags.8 = 1 Then ' velo timer afgelopen TimVals[8] = time + Rate8 ' stel de wachttijd in Clear Velflags.8 Else ' wachttijd afgelopen If LR8 = 0 Then ' we zijn links Set Ang68R ' beweeg naar rechts Else ' we zijn rechts Set Ang68L ' beweeg naar links EndIf Toggle LR8 ' reflecting the position now TimVals[8] = time + velo8 ' velotijd gaat in Set Velflags.8 ' set velo-timer en aktiveer hem End If EndIf Case 9 If LR9 = 0 Then ' we are left Clear Ang69L ' laat los, blijf links Else ' we are right Clear Ang69R ' laat los, blijf rechts EndIf If notes.9 = 0 Then ' note off - no repeats Clear Velflags.9 Set TimVals[9] Else ' note is active If Velflags.9 = 1 Then ' velo timer afgelopen TimVals[9] = time + Rate9 ' stel de wachttijd in Clear Velflags.9 Else ' wachttijd afgelopen If LR9 = 0 Then ' we zijn links Set Ang69R ' beweeg naar rechts Else ' we zijn rechts Set Ang69L ' beweeg naar links EndIf Toggle LR9 ' reflecting the position now TimVals[9] = time + velo9 ' velotijd gaat in Set Velflags.9 ' set velo-timer en aktiveer hem End If EndIf ' Case 10 ' If LR10 = 0 Then ' we are left ' Clear Ang70L ' laat los, blijf links ' Else ' we are right ' Clear Ang70R ' laat los, blijf rechts ' EndIf ' If notes.10 = 0 Then ' note off - no repeats ' Clear Velflags.10 ' Set TimVals[10] ' Else ' note is active ' If Velflags.10 = 1 Then ' velo timer afgelopen ' TimVals[10] = time + Rate10 ' stel de wachttijd in ' Clear Velflags.10 ' Else ' wachttijd afgelopen ' If LR10 = 0 Then ' we zijn links ' Set Ang70R ' beweeg naar rechts ' Else ' we zijn rechts ' Set Ang70L ' beweeg naar links ' EndIf ' Toggle LR10 ' reflecting the position now ' TimVals[10] = time + velo10 ' velotijd gaat in ' Set Velflags.10 ' set velo-timer en aktiveer hem ' End If ' EndIf ' Case 11 ' If LR11 = 0 Then ' we are left ' Clear Ang71L ' laat los, blijf links ' Else ' we are right ' Clear Ang71R ' laat los, blijf rechts ' EndIf ' If notes.11 = 0 Then ' note off - no repeats ' Clear Velflags.11 ' Set TimVals[11] ' Else ' note is active ' If Velflags.11 = 1 Then ' velo timer afgelopen ' TimVals[11] = time + Rate11 ' stel de wachttijd in ' Clear Velflags.11 ' Else ' wachttijd afgelopen ' If LR11 = 0 Then ' we zijn links ' Set Ang71R ' beweeg naar rechts ' Else ' we zijn rechts ' Set Ang71L ' beweeg naar links ' EndIf ' Toggle LR11 ' reflecting the position now ' TimVals[11] = time + velo11 ' velotijd gaat in ' Set Velflags.11 ' set velo-timer en aktiveer hem ' End If ' 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 notes Set TimVals EndIf Else ' idx > 9, 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-shaking 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 EndIf Case noot1 Pres1 = pres If Pres1 > 0 Then Rate1 = Dur[Pres1] Else Clear Rate1 Clear notes.1 EndIf Case noot2 Pres2 = pres If Pres2 > 0 Then Rate2 = Dur[Pres2] Else Clear Rate2 Clear notes.2 EndIf Case noot3 Pres3 = pres If Pres3 > 0 Then Rate3 = Dur[Pres3] Else Clear Rate3 Clear notes.3 EndIf Case noot4 Pres4 = pres If Pres4 > 0 Then Rate4 = Dur[Pres4] Else Clear Rate4 Clear notes.4 EndIf Case noot5 Pres5 = pres If Pres5 > 0 Then Rate5 = Dur[Pres5] Else Clear Rate5 Clear notes.5 EndIf Case noot6 Pres6 = pres If Pres6 > 0 Then Rate6 = Dur[Pres6] Else Clear Rate6 Clear notes.6 EndIf Case noot7 Pres7 = pres If Pres7 > 0 Then Rate7 = Dur[Pres7] Else Clear Rate7 Clear notes.7 EndIf Case noot8 Pres8 = pres If Pres8 > 0 Then Rate8 = Dur[Pres8] Else Clear Rate8 Clear notes.8 EndIf Case noot9 Pres9 = pres If Pres9 > 0 Then Rate9 = Dur[Pres9] Else Clear Rate9 Clear notes.9 EndIf ' Case noot10 ' Pres10 = pres ' If Pres10 > 0 Then ' Rate10 = Dur[Pres10] ' Else ' Clear Rate10 ' Clear notes.10 ' EndIf ' Case noot11 ' Pres11 = pres ' If Pres11 > 0 Then ' Rate11 = Dur[Pres11] ' Else ' Clear Rate11 ' Clear notes.11 ' EndIf EndSelect ' we do not need to resort here Set notePres '= 255 Return ProgChange: Select Case prog Case 0 ' conform to prog change 0 in the 2006 version If oldprog <> 0 Then GoSub Vels_Lookup oldprog = prog EndIf Case 122 ' conform to prog change 122 in the 2006 version If oldprog <> 122 Then GoSub Vels_Lookup_122 oldprog = prog EndIf End Select Set prog '= 255 'this is not realy required Return 'Pitchbend: ' Set pblsb 'Return 'Aftertouch: ' '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 shakers ' 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 ' Clear Rate10 ' Clear Pres10 ' Clear Rate11 ' Clear Pres11 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] ' Pres10 = value ' Rate10 = Dur[value] ' Pres11 = value ' Rate11 = Dur[value] EndIf Case 66 If value = 0 Then Clear PowerOn GoSub PowerDown Else Set PowerOn EndIf Case 67 'on/off for the video If value = 0 Then Clear Video_Relais Else Set Video_Relais EndIf Case 123 GoSub NotenUit End Select Set Ctrl 'mandatory reset Return PowerDown: Clear Video_Relais Clear Velflags 'stop all running timers Clear notes ' clear all velo-bits Clear Ang60R Clear Ang61R Clear Ang62R Clear Ang63R Clear Ang64R Clear Ang65R Clear Ang66R Clear Ang67R Clear Ang68R Clear Ang69R ' Clear Ang70R ' Clear Ang71R Clear Ang60L Clear Ang61L Clear Ang62L Clear Ang63L Clear Ang64L Clear Ang65L Clear Ang66L Clear Ang67L Clear Ang68L Clear Ang69L ' Clear Ang70L ' Clear Ang71L Clear Lite120 Clear Lite121 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 ' Clear Rate10 ' Clear Pres10 ' Clear Rate11 ' Clear Pres11 Clear oldprog ' revert to program change 0 GoSub Vels_Lookup Return NotenUit: Clear Velflags 'stop all running timers Clear notes Clear Ang60R Clear Ang61R Clear Ang62R Clear Ang63R Clear Ang64R Clear Ang65R Clear Ang66R Clear Ang67R Clear Ang68R Clear Ang69R ' Clear Ang70R ' Clear Ang71R Clear Ang60L Clear Ang61L Clear Ang62L Clear Ang63L Clear Ang64L Clear Ang65L Clear Ang66L Clear Ang67L Clear Ang68L Clear Ang69L ' Clear Ang70L ' Clear Ang71L Clear Lite120 Clear Lite121 Return Dur_Lookup: '21.11.2015: for these angklungs a good range would be fastest = 16 Hz, slowest = 2 Hz ' this is a tempered distribution! Set Dur[0] ' not used Dur[1]= 43592 ' freq= 1.99999904000046 Dur[2]= 42188 ' freq= 2.06655821920214 Dur[3]= 41502 ' freq= 2.10071702934076 Dur[4]= 40828 ' freq= 2.13539625138875 Dur[5]= 40165 ' freq= 2.17064504299017 Dur[6]= 39513 ' freq= 2.20646263639056 Dur[7]= 38871 ' freq= 2.24290494589025 Dur[8]= 38240 ' freq= 2.27991522363232 Dur[9]= 37619 ' freq= 2.31755118827454 Dur[10]= 37008 ' freq= 2.35581382813716 Dur[11]= 36407 ' freq= 2.39470316564672 Dur[12]= 35816 ' freq= 2.43421817488553 Dur[13]= 35234 ' freq= 2.47442692148777 Dur[14]= 34662 ' freq= 2.51526046251515 Dur[15]= 34099 ' freq= 2.55678929445732 Dur[16]= 33545 ' freq= 2.59901499930541 Dur[17]= 33001 ' freq= 2.64185806950396 Dur[18]= 32465 ' freq= 2.68547537815186 Dur[19]= 31937 ' freq= 2.72987312996525 Dur[20]= 31419 ' freq= 2.77488010922372 Dur[21]= 30908 ' freq= 2.82075702574415 Dur[22]= 30406 ' freq= 2.86732744036375 Dur[23]= 29913 ' freq= 2.91458423266473 Dur[24]= 29427 ' freq= 2.96271988825569 Dur[25]= 28949 ' freq= 3.01163971645653 Dur[26]= 28479 ' freq= 3.06134197660382 Dur[27]= 28016 ' freq= 3.11193454282196 Dur[28]= 27561 ' freq= 3.16330895655818 Dur[29]= 27114 ' freq= 3.21545910421554 Dur[30]= 26673 ' freq= 3.26862213293218 Dur[31]= 26240 ' freq= 3.32255938078125 Dur[32]= 25814 ' freq= 3.37739049165957 Dur[33]= 25395 ' freq= 3.43311510737153 Dur[34]= 24982 ' freq= 3.48987103321192 Dur[35]= 24577 ' freq= 3.54737999559344 Dur[36]= 24178 ' freq= 3.60592100883862 Dur[37]= 23785 ' freq= 3.66550170913181 Dur[38]= 23399 ' freq= 3.72596940688491 Dur[39]= 23019 ' freq= 3.78747808991268 Dur[40]= 22645 ' freq= 3.850031271879 Dur[41]= 22277 ' freq= 3.91363101637115 Dur[42]= 21915 ' freq= 3.9782778075154 Dur[43]= 21559 ' freq= 4.04397041382718 Dur[44]= 21209 ' freq= 4.11070574528267 Dur[45]= 20865 ' freq= 4.17847870365205 Dur[46]= 20526 ' freq= 4.24748894824613 Dur[47]= 20193 ' freq= 4.31753370730947 Dur[48]= 19865 ' freq= 4.3888224591845 Dur[49]= 19542 ' freq= 4.46136312310409 Dur[50]= 19225 ' freq= 4.53492630177894 Dur[51]= 18912 ' freq= 4.60998086673541 Dur[52]= 18605 ' freq= 4.68604988721849 Dur[53]= 18303 ' freq= 4.76336983837076 Dur[54]= 18006 ' freq= 4.8419392508997 Dur[55]= 17714 ' freq= 4.92175444008694 Dur[56]= 17426 ' freq= 5.00309641637209 Dur[57]= 17143 ' freq= 5.08568851144491 Dur[58]= 16864 ' freq= 5.16982674049455 Dur[59]= 16591 ' freq= 5.25489471109036 Dur[60]= 16321 ' freq= 5.34182698068134 Dur[61]= 16056 ' freq= 5.42999241104261 Dur[62]= 15795 ' freq= 5.51971878136753 Dur[63]= 15539 ' freq= 5.61065436332454 Dur[64]= 15286 ' freq= 5.70351682269397 Dur[65]= 15038 ' freq= 5.79757668251763 Dur[66]= 14794 ' freq= 5.89319711718941 Dur[67]= 14554 ' freq= 5.99037777598599 Dur[68]= 14317 ' freq= 6.08954097588182 Dur[69]= 14085 ' freq= 6.18984438421726 Dur[70]= 13856 ' freq= 6.29214478577512 Dur[71]= 13631 ' freq= 6.39600602682856 Dur[72]= 13410 ' freq= 6.50141373241611 Dur[73]= 13192 ' freq= 6.60885067857035 Dur[74]= 12978 ' freq= 6.71782694958392 Dur[75]= 12767 ' freq= 6.82885236560665 Dur[76]= 12560 ' freq= 6.94139794201434 Dur[77]= 12356 ' freq= 7.05600179278894 Dur[78]= 12155 ' freq= 7.17268269450433 Dur[79]= 11958 ' freq= 7.29084781332163 Dur[80]= 11763 ' freq= 7.41171114100995 Dur[81]= 11572 ' freq= 7.53404408500692 Dur[82]= 11384 ' freq= 7.65846434923578 Dur[83]= 11199 ' freq= 7.78497706506832 Dur[84]= 11018 ' freq= 7.91286605116174 Dur[85]= 10839 ' freq= 8.04354259172434 Dur[86]= 10663 ' freq= 8.17630668214387 Dur[87]= 10489 ' freq= 8.31194185829918 Dur[88]= 10319 ' freq= 8.44887665003393 Dur[89]= 10152 ' freq= 8.58786033803192 Dur[90]= 9987 ' freq= 8.7297444829979 Dur[91]= 9825 ' freq= 8.87368530806108 Dur[92]= 9665 ' freq= 9.02058542697362 Dur[93]= 9508 ' freq= 9.16953703741061 Dur[94]= 9354 ' freq= 9.32050012312381 Dur[95]= 9202 ' freq= 9.47445752572268 Dur[96]= 9052 ' freq= 9.63145803708574 Dur[97]= 8905 ' freq= 9.79045010125773 Dur[98]= 8761 ' freq= 9.95137063710764 Dur[99]= 8618 ' freq= 10.1164954921908 Dur[100]= 8478 ' freq= 10.2835525066879 Dur[101]= 8341 ' freq= 10.4524587161851 Dur[102]= 8205 ' freq= 10.6257109264717 Dur[103]= 8072 ' freq= 10.8007876798439 Dur[104]= 7941 ' freq= 10.9789646331318 Dur[105]= 7812 ' freq= 11.1602609001152 Dur[106]= 7685 ' freq= 11.3446920171373 Dur[107]= 7560 ' freq= 11.5322695967857 Dur[108]= 7437 ' freq= 11.7230009616378 Dur[109]= 7317 ' freq= 11.9152601 Dur[110]= 7198 ' freq= 12.1122475898444 Dur[111]= 7081 ' freq= 12.3123793463776 Dur[112]= 6966 ' freq= 12.5156414228682 Dur[113]= 6853 ' freq= 12.7220134469138 Dur[114]= 6742 ' freq= 12.9314681328538 Dur[115]= 6632 ' freq= 13.1459526766737 Dur[116]= 6524 ' freq= 13.3635742108676 Dur[117]= 6418 ' freq= 13.5842876521814 Dur[118]= 6314 ' freq= 13.8080389850649 Dur[119]= 6212 ' freq= 14.0347646734868 Dur[120]= 6111 ' freq= 14.2667252743741 Dur[121]= 6011 ' freq= 14.5040688989686 Dur[122]= 5914 ' freq= 14.7419611348833 Dur[123]= 5818 ' freq= 14.9852110951702 Dur[124]= 5723 ' freq= 15.2339608861961 Dur[125]= 5630 ' freq= 15.4856053555418 Dur[126]= 5539 ' freq= 15.7400177201119 Dur[127]= 5449 ' freq= 15.9999923200037 Return Vels_Lookup: ' lookup table for the velocity controlled pulse durations ' in this firmware the time value of one unit is 11.47 microseconds. [tektronix measurement 21.11.2015] ' for compatibility with the code in version 2.0 from 2006 ' we should cover a range of 7ms to 22ms, so from 610 to 1918 ' range: 1918 -610 = 1308 ' increment per velo-step = 1308/127 = 10.30 ' so we can calculate it as follows: 'Vels[1] = 610 For i = 1 To 127 vels[i] = 610 + (11.47 * (i-1)) Next i ' measurement after this change: ' velo 1 = 7ms ' velo 127 = 22 ms ' Vels[127] = 2055 Return Vels_Lookup_122: ' lookup table for the velocity controlled pulse durations ' in this firmware the time value of one unit is 11.47 microseconds. [tektronix measurement 21.11.2015] ' for compatibility with the code in version 2.0 from 2006 , using prog. change 122 ' we should cover a range of 1.2ms to 55ms, so from 105 to 4795 ' range: 4795 - 105 = 4690 ' increment per velo-step = 4690/127 = 36.93 ' so we can calculate it as follows: 'Vels[1] = 105 For i = 1 To 127 vels[i] = 105 + (36.93 * (i-1)) Next i ' measurement after this change: ' velo 1 = 1.2 ms ' velo 127 = 55 ms ' Vels[127] = 4758 Return '[EOF]