' ******************************************************************** ' * PIC firmware for Klung * ' * angklung shakers * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/klung/picworks * ' * source code development directory: * ' * Klung1.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 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 Ang48L PORTA.2 ' noot 48 - niet gemonteerd $define Ang48R PORTA.1 $define Ang49L PORTA.0 ' noot 49 $define Ang49R PORTA.3 $define Ang50L PORTA.4 ' noot 50 $define Ang50R PORTA.5 $define Ang51L PORTE.0 ' noot 51 $define Ang51R PORTE.1 $define Ang52L PORTE.2 $define Ang52R PORTB.4 $define Ang53L PORTB.3 $define Ang53R PORTB.2 $define Ang54L PORTB.1 $define Ang54R PORTB.0 $define Ang55L PORTD.7 $define Ang55R PORTD.6 $define Ang56L PORTD.5 $define Ang56R PORTD.4 $define Ang57L PORTC.5 $define Ang57R PORTC.4 $define Ang58L PORTD.3 $define Ang58R PORTD.2 $define Ang59L PORTC.0 $define Ang59R PORTC.1 $define Lite122 PORTC.2 ' PORTC.2 ' on/off only $define Lite123 PORTD.0 ' PORTC.3 ' on/off only $define Lite124 PORTC.3 ' PORTD.0 ' on/off only - not connected. $define Power_Relais PORTD.1 ' controller 66 '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 = 48 ' missing note Symbol noot1 = 49 Symbol noot2 = 50 Symbol noot3 = 51 Symbol noot4 = 52 Symbol noot5 = 53 Symbol noot6 = 54 Symbol noot7 = 55 Symbol noot8 = 56 Symbol noot9 = 57 Symbol noot10 = 58 Symbol noot11 = 59 Symbol lamp0 = 122 Symbol lamp1 = 123 Symbol lamp2 = 124 '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 12 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[12] 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 Power_Relais ' power off !!! ' make sure all shakers are free: Low Ang48R Low Ang48L Low Ang49R Low Ang49L Low Ang50L Low Ang50R Low Ang51L Low Ang51R Low Ang52L Low Ang52R Low Ang53L Low Ang53R Low Ang54L Low Ang54R Low Ang55L Low Ang55R Low Ang56L Low Ang56R Low Ang57L Low Ang57R Low Ang58L Low Ang58R Low Ang59L Low Ang59R Low Lite122 Low Lite123 Low Lite124 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 Ang48L Else ' staat naar rechts Clear Ang48R EndIf Case noot1 ' note 49 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR0 = 0 Then Clear Ang49L Else Clear Ang49R EndIf Case noot2 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Ang50L Else Clear Ang51R EndIf Case noot3 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Ang51L Else Clear Ang51R EndIf Case noot4 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then Clear Ang52L Else Clear Ang52R EndIf Case noot5 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then Clear Ang53L Else Clear Ang53R EndIf Case noot6 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then Clear Ang54L Else Clear Ang54R EndIf Case noot7 Clear Velflags.7 ' cancel running timer Clear notes.7 If LR7 = 0 Then Clear Ang55L Else Clear Ang55R EndIf Case noot8 Clear Velflags.8 ' cancel running timer Clear notes.8 If LR8 = 0 Then Clear Ang56L Else Clear Ang56R EndIf Case noot9 Clear Velflags.9 ' cancel running timer Clear notes.9 If LR9 = 0 Then Clear Ang57L Else Clear Ang57R EndIf Case noot10 Clear Velflags.10 ' cancel running timer Clear notes.10 If LR10 = 0 Then Clear Ang58L Else Clear Ang58R EndIf Case noot11 Clear Velflags.11 ' cancel running timer Clear notes.11 If LR11 = 0 Then Clear Ang59L Else Clear Ang59R EndIf Case lamp0 Clear Lite122 Set noteUit GoTo Check_Timers Case lamp1 Clear Lite123 Set noteUit GoTo Check_Timers Case lamp2 Clear Lite124 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 Ang48L Else ' staat naar rechts Clear Ang48R EndIf Case noot1 ' note 49 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR0 = 0 Then Clear Ang49L Else Clear Ang49R EndIf Case noot2 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Ang50L Else Clear Ang51R EndIf Case noot3 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Ang51L Else Clear Ang51R EndIf Case noot4 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then Clear Ang52L Else Clear Ang52R EndIf Case noot5 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then Clear Ang53L Else Clear Ang53R EndIf Case noot6 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then Clear Ang54L Else Clear Ang54R EndIf Case noot7 Clear Velflags.7 ' cancel running timer Clear notes.7 If LR7 = 0 Then Clear Ang55L Else Clear Ang55R EndIf Case noot8 Clear Velflags.8 ' cancel running timer Clear notes.8 If LR8 = 0 Then Clear Ang56L Else Clear Ang56R EndIf Case noot9 Clear Velflags.9 ' cancel running timer Clear notes.9 If LR9 = 0 Then Clear Ang57L Else Clear Ang57R EndIf Case noot10 Clear Velflags.10 ' cancel running timer Clear notes.10 If LR10 = 0 Then Clear Ang58L Else Clear Ang58R EndIf Case noot11 Clear Velflags.11 ' cancel running timer Clear notes.11 If LR11 = 0 Then Clear Ang59L Else Clear Ang59R EndIf Case lamp0 Clear Lite122 Set noteUit GoTo Check_Timers Case lamp1 Clear Lite123 Set noteUit GoTo Check_Timers Case lamp2 Clear Lite124 Set noteUit GoTo Check_Timers End Select GoTo resort Else Select noteAan Case noot0 If LR0 = 0 Then ' we are left Clear Ang48L ' if not switched off by timer, do it now Set Ang48R ' move right Else ' we are right Clear Ang48R ' switch off if still on Set Ang48L ' 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 Ang49L ' if not switched off by timer, do it now Set Ang49R ' move right Else ' we are right Clear Ang49R ' switch off if still on Set Ang49L ' 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 Ang50L ' if not switched off by timer, do it now Set Ang50R ' move right Else ' we are right Clear Ang50R ' switch off if still on Set Ang50L ' 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 Ang51L ' if not switched off by timer, do it now Set Ang51R ' move right Else ' we are right Clear Ang51R ' switch off if still on Set Ang51L ' 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 Ang52L ' if not switched off by timer, do it now Set Ang52R ' move right Else ' we are right Clear Ang52R ' switch off if still on Set Ang52L ' 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 Ang53L ' if not switched off by timer, do it now Set Ang53R ' move right Else ' we are right Clear Ang53R ' switch off if still on Set Ang53L ' 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 Ang54L ' if not switched off by timer, do it now Set Ang54R ' move right Else ' we are right Clear Ang54R ' switch off if still on Set Ang54L ' 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 Ang55L ' if not switched off by timer, do it now Set Ang55R ' move right Else ' we are right Clear Ang55R ' switch off if still on Set Ang55L ' 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 Ang56L ' if not switched off by timer, do it now Set Ang56R ' move right Else ' we are right Clear Ang56R ' switch off if still on Set Ang56L ' 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 Ang57L ' if not switched off by timer, do it now Set Ang57R ' move right Else ' we are right Clear Ang57R ' switch off if still on Set Ang57L ' 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 Ang58L ' if not switched off by timer, do it now Set Ang58R ' move right Else ' we are right Clear Ang58R ' switch off if still on Set Ang58L ' 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 Ang59L ' if not switched off by timer, do it now Set Ang59R ' move right Else ' we are right Clear Ang59R ' switch off if still on Set Ang59L ' 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 Lite122 Set noteAan GoTo Check_Timers Case lamp1 Set Lite123 Set noteAan GoTo Check_Timers Case lamp2 Set Lite124 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 < 12 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 Ang48L ' laat los, blijf links Else ' we are right Clear Ang48R ' 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 Ang48R ' beweeg naar rechts Else ' we zijn rechts Set Ang48L ' 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 Ang49L ' laat los, blijf links Else ' we are right Clear Ang49R ' 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 Ang49R ' beweeg naar rechts Else ' we zijn rechts Set Ang49L ' 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 Ang50L ' laat los, blijf links Else ' we are right Clear Ang50R ' 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 Ang50R ' beweeg naar rechts Else ' we zijn rechts Set Ang50L ' 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 Ang51L ' laat los, blijf links Else ' we are right Clear Ang51R ' 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 Ang51R ' beweeg naar rechts Else ' we zijn rechts Set Ang51L ' 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 Ang52L ' laat los, blijf links Else ' we are right Clear Ang52R ' 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 Ang52R ' beweeg naar rechts Else ' we zijn rechts Set Ang52L ' 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 Ang53L ' laat los, blijf links Else ' we are right Clear Ang53R ' 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 Ang53R ' beweeg naar rechts Else ' we zijn rechts Set Ang53L ' 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 Ang54L ' laat los, blijf links Else ' we are right Clear Ang54R ' 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 Ang54R ' beweeg naar rechts Else ' we zijn rechts Set Ang54L ' 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 Ang55L ' laat los, blijf links Else ' we are right Clear Ang55R ' 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 Ang55R ' beweeg naar rechts Else ' we zijn rechts Set Ang55L ' 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 Ang56L ' laat los, blijf links Else ' we are right Clear Ang56R ' 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 Ang56R ' beweeg naar rechts Else ' we zijn rechts Set Ang56L ' 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 Ang57L ' laat los, blijf links Else ' we are right Clear Ang57R ' 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 Ang57R ' beweeg naar rechts Else ' we zijn rechts Set Ang57L ' 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 Ang58L ' laat los, blijf links Else ' we are right Clear Ang58R ' 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 Ang58R ' beweeg naar rechts Else ' we zijn rechts Set Ang58L ' 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 Ang59L ' laat los, blijf links Else ' we are right Clear Ang59R ' 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 Ang59R ' beweeg naar rechts Else ' we zijn rechts Set Ang59L ' 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 > 11, 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 11 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 12 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 'on/off for the robot If value = 0 Then Clear PowerOn 'CC66.0 =0 GoSub PowerDown Else Set PowerOn 'CC66.0 =1 Set Power_Relais EndIf Case 123 GoSub NotenUit End Select Set Ctrl 'mandatory reset Return PowerDown: Clear Power_Relais Clear Velflags 'stop all running timers Clear notes ' clear all velo-bits Clear Ang48R Clear Ang49R Clear Ang50R Clear Ang51R Clear Ang52R Clear Ang53R Clear Ang54R Clear Ang55R Clear Ang56R Clear Ang57R Clear Ang58R Clear Ang59R Clear Ang48L Clear Ang49L Clear Ang50L Clear Ang51L Clear Ang52L Clear Ang53L Clear Ang54L Clear Ang55L Clear Ang56L Clear Ang57L Clear Ang58L Clear Ang59L Clear Lite122 Clear Lite123 Clear Lite124 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 Ang48R Clear Ang49R Clear Ang50R Clear Ang51R Clear Ang52R Clear Ang53R Clear Ang54R Clear Ang55R Clear Ang56R Clear Ang57R Clear Ang58R Clear Ang59R Clear Ang48L Clear Ang49L Clear Ang50L Clear Ang51L Clear Ang52L Clear Ang53L Clear Ang54L Clear Ang55L Clear Ang56L Clear Ang57L Clear Ang58L Clear Ang59L Clear Lite122 Clear Lite123 Clear Lite124 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]