' ******************************************************************** ' * PIC firmware for Tinti * ' * Tintinabuli shakers * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/tinti/picworks * ' * source code development directory: * ' * Tinti_4.bas * ' ******************************************************************** ' this board was board6 in the version 1.0 of the robot. ' PortD seems to give problems. Something wrong with the initialisation? ' TrisE, bit 4 must be cleared !!! otherwize, port D works in PSP mode!!! ' 28.06.2014: Starting from the coding for Synchrochord, coding for ' We need 6 pulse/hold boards for this robot. ' 30.06.2014: First version for board1 ready for testing: 5 string pluckers implemented. ' 02.07.2014: Pin assignment error found and repaired. ' Performance of code measured with Tektronics scope. ' CC14 added to set the mimimum force required to pluck the strings. ' 03.07.2014: Version made for board6 ' 05.07.2014: velo's rescaled and string map changed ' 25.08.2015: Code rewriting for use in ' For tinti, note hold's are not required. ' 29.08.2015: This board serves the five lowest bells, 89 to 93 ' after LED board, everything seems to work fine now. ' Starting from the code for board 6 (Tinti_1.bas), extending for board 5 ' compiles o.k., to be tested. ' For boards 4,3,2 we just need to change the midi map. ' board 1 requires some special attention with the mapping!!! ' 30.08.2015: Tinti_3 firmware. Notes 101-107 ' Tinti_4 firmware. Notes 108-114 ' 12.09.2015: Cleanup. Include "18F4620.inc" ' (40MHz) ' Mapping defines for midi-events on pin outputs and inputs: ' This is very specific for the Pulse/Hold board Rev.2,2006 ' mapping for board 2, second lowest bells, left side of robot. $define Bel7HoldL PORTA.2 ' Bel7 - noot 114 $define Bel7VeloL PORTA.1 $define Bel7HoldR PORTA.0 $define Bel7VeloR PORTA.3 $define Bel6HoldL PORTA.4 ' Bel6 - noot 113 $define Bel6VeloL PORTA.5 $define Bel6HoldR PORTE.0 $define Bel6VeloR PORTE.1 $define Bel5HoldL PORTE.2 ' Bel5 - noot 112 $define Bel5VeloL PORTB.4 $define Bel5HoldR PORTB.3 $define Bel5VeloR PORTB.2 $define Bel4HoldL PORTB.1 ' Bel4 - noot 111 $define Bel4VeloL PORTB.0 $define Bel4HoldR PORTD.7 $define Bel4VeloR PORTD.6 $define Bel3HoldL PORTD.5 ' Bel3 - noot 110 $define Bel3VeloL PORTD.4 $define Bel3HoldR PORTC.5 $define Bel3VeloR PORTC.4 $define Bel2HoldL PORTD.3 ' wordt nu bel 2 noot 109 $define Bel2VeloL PORTD.2 $define Bel2HoldR PORTC.0 $define Bel2VeloR PORTC.1 $define Bel1HoldL PORTC.2 ' wordt nu bel 1 noot 108 $define Bel1VeloL PORTC.3 $define Bel1HoldR PORTD.0 $define Bel1VeloR PORTD.1 ' $define lite1 PORTC.2 ' $define lite2 PORTD.0 ' $define nc5 PORTC.3 ' $define nc6 PORTD.1 '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 Bel1 = 108 ' @7 Symbol Bel2 = 109 ' @6 Symbol Bel3 = 110 ' @5 Symbol Bel4 = 111 ' @4 Symbol Bel5 = 112 ' @3 Symbol Bel6 = 113 ' @2 Symbol Bel7 = 114 ' @1 'Symbol lite17 = 17 'Symbol lite18 = 18 'initialisations for the midi input parser: Symbol Midichannel = 11 ' Tinti_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 Velflags As Byte System ' so we can have only 8 tasks Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 ' handled on the hub board. Dim notes As Byte System Dim LRbyte As Byte Dim LR0 As LRbyte.0 ' 0= left, 1= right Dim LR1 As LRbyte.1 Dim LR2 As LRbyte.2 Dim LR3 As LRbyte.3 Dim LR4 As LRbyte.4 Dim LR5 As LRbyte.5 Dim LR6 As LRbyte.6 ' Dim minvel As Word System ' Dim varvel As Word System ' Dim st As Byte System ' Dim b1 As Byte System ' Dim b2 As Byte System ' Dim Idx As Byte System ' Dim CC30 As Byte System ' valve hold down time, midi value ' Dim ReleaseTime As Word System ' calculated from CC30 ' Dim VibratoPeriod As Word System ' claculated from CC31 ' Dim CC31 As Byte System ' vibrato controller, midi value ' Dim CC32 As Byte System ' PulseTime controller ' Dim PulseTime As Word System ' calculated from CC32 ' Dim solenoid As Byte ' solenoid active at any moment (0= none, 1-12=solenoid number) ' Dim oldsolenoid As Byte ' previously active solenoid. ' Dim NoteSolenoid[49] As Byte ' lookup table 0-48, 4 octaves ' index = midinote - lowtes 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 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 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 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[7] As Dword ' lijst met timer waarden - de kleinste is eerst aan de beurt Dim Nxt As Dword System ' waarde voor de eerstvolgende timer Dim idx As Byte System ' index voor de eerstvolgende timer '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Include "Tinti_Irq.inc" ' for UART,Timer0, Timer3 Interrupt 'Clear ' clear all RAM '----------------------------------------------------------------------------------------- Dim dummy[128] As Word ' unusable memory space Dim vels[128] As Word ' velocity lookup tables Dim Vels0[128] As Word Dim Vels1[128] As Word Dim Vels2[128] As Word Dim Vels3[128] As Word Dim Vels4[128] As Word Dim Vels5[128] As Word Dim Vels6[128] As Word 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 ' make sure all shakers are free: Low Bel7VeloR Low Bel6VeloR Low Bel5VeloR Low Bel4VeloR Low Bel3VeloR Low Bel2VeloR Low Bel1VeloR Low Bel7VeloL Low Bel6VeloL Low Bel5VeloL Low Bel4VeloL Low Bel3VeloL Low Bel2VeloL Low Bel1VeloL Low Bel7HoldR Low Bel6HoldR Low Bel5HoldR Low Bel4HoldR Low Bel3HoldR Low Bel2HoldR Low Bel1HoldR Low Bel7HoldL Low Bel6HoldL Low Bel5HoldL Low Bel4HoldL Low Bel3HoldL Low Bel2HoldL Low Bel1HoldL Clear LRbyte ' 0 = left ' minvel = 0 '2048 '8 << 3 ' =2048 ' default value for controller 14 Clear CC66 Clear notes Clear Velflags Set TimVals Clear Pres0 Clear Pres1 Clear Pres2 Clear Pres3 Clear Pres4 Clear pres5 Clear Pres6 Clear Rate0 Clear Rate1 Clear Rate2 Clear Rate3 Clear Rate4 Clear Rate5 Clear Rate6 Clear velo0 Clear velo1 Clear velo2 Clear velo3 Clear velo4 Clear velo5 Clear velo6 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 ' 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 > Pitchbend_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in. 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 Bel1 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then ' staat naar links Clear Bel1VeloL Clear Bel1HoldL Else ' staat naar rechts Clear Bel1VeloR Clear Bel1HoldR EndIf Case Bel2 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then ' staat naar links Clear Bel2VeloL Clear Bel2HoldL Else ' staat naar rechts Clear Bel2VeloR Clear Bel2HoldR EndIf Case Bel3 ' note 89 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then ' staat naar links Clear Bel3VeloL Clear Bel3HoldL Else ' staat naar rechts Clear Bel3VeloR Clear Bel3HoldR EndIf Case Bel4 ' note 90 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Bel4VeloL Clear Bel4HoldL Else Clear Bel4VeloR Clear Bel4HoldR EndIf Case Bel5 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Bel5VeloL Clear Bel5HoldL Else Clear Bel5VeloR Clear Bel5HoldR EndIf Case Bel6 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR1 = 0 Then Clear Bel6VeloL Clear Bel6HoldL Else Clear Bel6VeloR Clear Bel6HoldR EndIf Case Bel7 Clear Velflags.0 ' cancel running timer Clear notes.0 If LR0 = 0 Then Clear Bel7VeloL Clear Bel7HoldL Else Clear Bel7VeloR Clear Bel7HoldR EndIf 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 Bel1 Clear Velflags.6 ' cancel running timer Clear notes.6 If LR6 = 0 Then ' staat naar links Clear Bel1VeloL Clear Bel1HoldL Else ' staat naar rechts Clear Bel1VeloR Clear Bel1HoldR EndIf Case Bel2 Clear Velflags.5 ' cancel running timer Clear notes.5 If LR5 = 0 Then ' staat naar links Clear Bel2VeloL Clear Bel2HoldL Else ' staat naar rechts Clear Bel2VeloR Clear Bel2HoldR EndIf Case Bel3 ' note 89 Clear Velflags.4 ' cancel running timer Clear notes.4 If LR4 = 0 Then ' staat naar links Clear Bel3VeloL Clear Bel3HoldL Else ' staat naar rechts Clear Bel3VeloR Clear Bel3HoldR EndIf Case Bel4 ' note 90 Clear Velflags.3 ' cancel running timer Clear notes.3 If LR3 = 0 Then Clear Bel4VeloL Clear Bel4HoldL Else Clear Bel4VeloR Clear Bel4HoldR EndIf Case Bel5 Clear Velflags.2 ' cancel running timer Clear notes.2 If LR2 = 0 Then Clear Bel5VeloL Clear Bel5HoldL Else Clear Bel5VeloR Clear Bel5HoldR EndIf Case Bel6 Clear Velflags.1 ' cancel running timer Clear notes.1 If LR1 = 0 Then Clear Bel6VeloL Clear Bel6HoldL Else Clear Bel6VeloR Clear Bel6HoldR EndIf Case Bel7 Clear Velflags.0 ' cancel running timer Clear notes.0 If LR0 = 0 Then Clear Bel7VeloL Clear Bel7HoldL Else Clear Bel7VeloR Clear Bel7HoldR EndIf Case Else GoTo Check_Timers End Select GoTo resort Else Select noteAan Case Bel1 If LR6 = 0 Then Clear Bel1HoldL Set Bel1VeloR ' move right Else Clear Bel1HoldR Set Bel1VeloL EndIf Toggle LR6 ' reflects the position now Set Velflags.6 velo6 = Vels6[velo] TimVals[6] = time + velo6 If Pres6 > 0 Then ' if note repeat are programmed... Set notes.6 If Dur[Pres6] <= velo6 Then Rate6 = velo6 ' stick to 50% duty cycle Else Rate6 = Dur[Pres6] - velo6 EndIf EndIf Case Bel2 If LR5 = 0 Then Clear Bel2HoldL Set Bel2VeloR ' move right Else Clear Bel2HoldR Set Bel2VeloL EndIf Toggle LR5 ' reflects the position now Set Velflags.5 velo5 = Vels5[velo] TimVals[5] = time + velo5 If pres5 > 0 Then ' if note repeat are programmed... Set notes.5 If Dur[pres5] <= velo5 Then Rate5 = velo5 ' stick to 50% duty cycle Else Rate5 = Dur[pres5] - velo5 EndIf EndIf Case Bel3 If LR4 = 0 Then Clear Bel3HoldL Set Bel3VeloR ' move right Else Clear Bel3HoldR Set Bel3VeloL EndIf Toggle LR4 ' reflects the position now Set Velflags.4 velo4 = Vels4[velo] TimVals[4] = time + velo4 If Pres4 > 0 Then ' if note repeat are programmed... Set notes.4 If Dur[Pres4] <= velo4 Then Rate4 = velo4 ' stick to 50% duty cycle Else Rate4 = Dur[Pres4] - velo4 EndIf EndIf Case Bel4 If LR3 = 0 Then Clear Bel4HoldL Set Bel4VeloR ' move right Else Clear Bel4HoldR Set Bel4VeloL EndIf Toggle LR3 Set Velflags.3 velo3= Vels3[velo] TimVals[3] = time + velo3 If Pres3 > 0 Then ' if note repeat are programmed... Set notes.3 If Dur[Pres3] <= velo3 Then Rate3 = velo3 ' stick to 50% duty cycle Else Rate3 = Dur[Pres3] - velo3 EndIf EndIf Case Bel5 If LR2 = 0 Then Clear Bel5HoldL Set Bel5VeloR ' move right Else Clear Bel5HoldR Set Bel5VeloL EndIf Toggle LR2 Set Velflags.2 velo2= Vels2[velo] TimVals[2] = time + velo2 If Pres2 > 0 Then ' if note repeat are programmed... Set notes.2 If Dur[Pres2] <= velo2 Then Rate2 = velo2 ' stick to 50% duty cycle Else Rate2 = Dur[Pres2] - velo2 EndIf EndIf Case Bel6 If LR1 = 0 Then Clear Bel6HoldL Set Bel6VeloR ' move right Else Clear Bel6HoldR Set Bel6VeloL EndIf Toggle LR1 Set Velflags.1 velo1= Vels1[velo] TimVals[1] = time + velo1 If Pres1 > 0 Then ' if note repeat are programmed... Set notes.1 If Dur[Pres1] <= velo1 Then Rate1 = velo1 ' stick to 50% duty cycle Else Rate1 = Dur[Pres1] - velo1 EndIf EndIf Case Bel7 If LR0 = 0 Then Clear Bel7HoldL Set Bel7VeloR ' move right Else Clear Bel7HoldR Set Bel7VeloL EndIf Toggle LR0 'should we do this here? Set Velflags.0 velo0= Vels0[velo] TimVals[0] = time + velo0 If Pres0 > 0 Then ' if note repeats are programmed... Set notes.0 If Dur[Pres0] <= velo0 Then Rate0 = velo0 ' stick to 50% duty cycle Else Rate0 = Dur[Pres0] - velo0 EndIf 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 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 fingering 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 < 7 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 6 If notes.6 = 0 Then ' note off Clear Velflags.6 Clear Bel1HoldL Clear Bel1HoldR Clear Bel1VeloL Clear Bel1VeloR Set TimVals[6] Else ' note is active If Velflags.6 = 1 Then ' velo timer afgelopen If LR6 = 0 Then ' staat links Clear Bel1VeloL Set Bel1HoldL ' hold is switched off on reception of a note off command ' blijft links Else Clear Bel1VeloR Set Bel1HoldR ' blijft rechts EndIf TimVals[6] = time + Rate6 ' wachttijd gaat in Clear Velflags.6 Else ' wachttijd is afgelopen If LR6 = 0 Then ' staat links Clear Bel1HoldL ' maak links los Set Bel1VeloR ' ga naar rechts Else ' staat rechts Clear Bel1HoldR ' maak rechts los Set Bel1VeloL ' ga naar links EndIf Toggle LR6 ' huidige positie TimVals[6] = time + velo6 ' stel een nieuwe velo-timer in Set Velflags.6 ' aktiveer hem ook EndIf EndIf Case 5 If notes.5 = 0 Then ' note off Clear Velflags.5 Clear Bel2HoldL Clear Bel2HoldR Clear Bel2VeloL Clear Bel2VeloR Set TimVals[5] Else ' note is active If Velflags.5 = 1 Then ' velo timer afgelopen If LR5 = 0 Then ' staat links Clear Bel2VeloL Set Bel2HoldL ' hold is switched off on reception of a note off command ' blijft links Else Clear Bel2VeloR Set Bel2HoldR ' blijft rechts EndIf TimVals[5] = time + Rate5 ' wachttijd gaat in Clear Velflags.5 Else ' wachttijd is afgelopen If LR5 = 0 Then ' staat links Clear Bel2HoldL ' maak links los Set Bel2VeloR ' ga naar rechts Else ' staat rechts Clear Bel2HoldR ' maak rechts los Set Bel2VeloL ' ga naar links EndIf Toggle LR5 ' huidige positie TimVals[5] = time + velo5 ' stel een nieuwe velo-timer in Set Velflags.5 ' aktiveer hem ook EndIf EndIf Case 4 ' Bel3 - note 89 If notes.4 = 0 Then ' note off Clear Velflags.4 Clear Bel3HoldL Clear Bel3HoldR Clear Bel3VeloL Clear Bel3VeloR Set TimVals[4] Else ' note is active If Velflags.4 = 1 Then ' velo timer afgelopen If LR4 = 0 Then ' staat links Clear Bel3VeloL Set Bel3HoldL ' hold is switched off on reception of a note off command ' blijft links Else Clear Bel3VeloR Set Bel3HoldR ' blijft rechts EndIf TimVals[4] = time + Rate4 ' wachttijd gaat in Clear Velflags.4 Else ' wachttijd is afgelopen If LR4 = 0 Then ' staat links Clear Bel3HoldL ' maak links los Set Bel3VeloR ' ga naar rechts Else ' staat rechts Clear Bel3HoldR ' maak rechts los Set Bel3VeloL ' ga naar links EndIf Toggle LR4 ' huidige positie TimVals[4] = time + velo4 ' stel een nieuwe velo-timer in Set Velflags.4 ' aktiveer hem ook EndIf EndIf Case 3 ' note 90 If notes.3 = 0 Then ' note off Clear Velflags.3 Clear Bel4HoldL Clear Bel4HoldR Clear Bel4VeloL Clear Bel4VeloR Set TimVals[3] Else ' note is active If Velflags.3 = 1 Then ' velo timer afgelopen If LR3 = 0 Then Clear Bel4VeloL Set Bel4HoldL ' hold is switched off on reception of a note off command Else Clear Bel4VeloR Set Bel4HoldR EndIf TimVals[3] = time + Rate3 ' wachttijd gaat in Clear Velflags.3 Else ' wachttijd is afgelopen If LR3 = 0 Then ' is inmiddels omgekeerd! Clear Bel4HoldL Set Bel4VeloR Else Clear Bel4HoldR Set Bel4VeloL EndIf Toggle LR3 TimVals[3] = time + velo3 ' stel een nieuwe velo-timer in Set Velflags.3 ' aktiveer hem ook EndIf EndIf Case 2 ' note 91 If notes.2 = 0 Then ' note off Clear Velflags.2 Clear Bel5HoldL Clear Bel5HoldR Clear Bel5VeloL Clear Bel5VeloR Set TimVals[2] Else ' note is active If Velflags.2 = 1 Then ' velo timer afgelopen If LR2 = 0 Then Clear Bel5VeloL Set Bel5HoldL ' hold is switched off on reception of a note off command Else Clear Bel5VeloR Set Bel5HoldR EndIf TimVals[2] = time + Rate2 ' wachttijd gaat in Clear Velflags.2 Else ' wachttijd is afgelopen If LR2 = 0 Then ' is inmiddels omgekeerd! Clear Bel5HoldL Set Bel5VeloR Else Clear Bel5HoldR Set Bel5VeloL EndIf Toggle LR2 TimVals[2] = time + velo2 ' stel een nieuwe velo-timer in Set Velflags.2 ' aktiveer hem ook EndIf EndIf Case 1 If notes.1 = 0 Then ' note off Clear Velflags.1 Clear Bel6HoldL Clear Bel6HoldR Clear Bel6VeloL Clear Bel6VeloR Set TimVals[1] Else ' note is active If Velflags.1 = 1 Then ' velo timer afgelopen If LR1 = 0 Then Clear Bel6VeloL Set Bel6HoldL ' hold is switched off on reception of a note off command Else Clear Bel6VeloR Set Bel6HoldR EndIf TimVals[1] = time + Rate1 ' wachttijd gaat in Clear Velflags.1 Else ' wachttijd is afgelopen If LR1 = 0 Then ' is inmiddels omgekeerd! Clear Bel6HoldL Set Bel6VeloR Else Clear Bel6HoldR Set Bel6VeloL EndIf Toggle LR1 TimVals[1] = time + velo1 ' stel een nieuwe velo-timer in Set Velflags.1 ' aktiveer hem ook EndIf EndIf Case 0 If notes.0 = 0 Then ' note off Clear Velflags.0 Clear Bel7HoldL Clear Bel7HoldR Clear Bel7VeloL Clear Bel7VeloR Set TimVals[0] Else ' note is active If Velflags.0 = 1 Then ' velo timer afgelopen If LR0 = 0 Then Clear Bel7VeloL Set Bel7HoldL ' hold is switched off on reception of a note off command Else Clear Bel7VeloR Set Bel7HoldR EndIf TimVals[0] = time + Rate0 ' wachttijd gaat in Clear Velflags.0 Else ' wachttijd is afgelopen If LR0 = 0 Then ' is inmiddels omgekeerd! Clear Bel7HoldL Set Bel7VeloR Else Clear Bel7HoldR Set Bel7VeloL EndIf Toggle LR0 TimVals[0] = time + velo0 ' stel een nieuwe velo-timer in Set Velflags.0 ' aktiveer hem ook 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 notes Set TimVals EndIf Else ' idx > 6, 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 6 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 7 dword comparisons idx = i EndIf Next i Return KeyPres: ' used for auto-shaking in Select notePres Case Bel7 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 Bel6 Pres1 = pres If Pres1 > 0 Then Rate1 = Dur[Pres1] Else Clear Rate1 Clear notes.1 EndIf Case Bel5 Pres2 = pres If Pres2 > 0 Then Rate2 = Dur[Pres2] Else Clear Rate2 Clear notes.2 EndIf Case Bel4 Pres3 = pres If Pres3 > 0 Then Rate3 = Dur[Pres3] Else Clear Rate3 Clear notes.3 EndIf Case Bel3 Pres4 = pres If Pres4 > 0 Then Rate4 = Dur[Pres4] Else Clear Rate4 Clear notes.4 EndIf Case Bel2 pres5 = pres If pres5 > 0 Then Rate5 = Dur[pres5] Else Clear Rate5 Clear notes.5 EndIf Case Bel1 Pres6 = pres If Pres6 > 0 Then Rate6 = Dur[Pres6] Else Clear Rate6 Clear notes.6 EndIf EndSelect ' we do not need to resort here Set notePres '= 255 Return ProgChange: Set prog '= 255 'this is not realy required Return Pitchbend: Set pblsb '= 255 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 14 ' minvel = value '<< 8 ' sets minimum velocity for plucking a string. 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 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] 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 EndIf Case 123 GoSub PowerDown End Select Set Ctrl 'mandatory reset Return PowerDown: Clear Velflags 'stop all running timers Clear notes ' clear all velo-bits Clear Bel7VeloL Clear Bel7VeloR Clear Bel6VeloL Clear Bel6VeloR Clear Bel5VeloL Clear Bel5VeloR Clear Bel4VeloL Clear Bel4VeloR Clear Bel3VeloL Clear Bel3VeloR Clear Bel2VeloL Clear Bel2VeloR Clear Bel1VeloR Clear Bel1VeloL Clear Bel7HoldR Clear Bel7HoldL Clear Bel6HoldR Clear Bel6HoldL Clear Bel5HoldR Clear Bel5HoldL Clear Bel4HoldR Clear Bel4HoldL Clear Bel3HoldR Clear Bel3HoldL Clear Bel2HoldR Clear Bel2HoldL Clear Bel1HoldR Clear Bel1HoldL Return Dur_Lookup: '09.06.2015: for these bells a good range would be fastest = 30 Hz, slowest = 1 Hz ' this is a tempered distribution! ' same look-up as on the pulse boards in bello Set Dur[0] ' not used Dur[1]= 41667 ' freq= .999992000063999 Dur[2]= 39494 ' freq= 1.0550125757499 Dur[3]= 38450 ' freq= 1.08365843086259 Dur[4]= 37434 ' freq= 1.11307011451265 Dur[5]= 36445 ' freq= 1.14327525495038 Dur[6]= 35482 ' freq= 1.17430434210774 Dur[7]= 34544 ' freq= 1.20619113787247 Dur[8]= 33631 ' freq= 1.23893629885126 Dur[9]= 32743 ' freq= 1.27253662360403 Dur[10]= 31877 ' freq= 1.30710752789367 Dur[11]= 31035 ' freq= 1.34257021642232 Dur[12]= 30215 ' freq= 1.37900601246621 Dur[13]= 29416 ' freq= 1.41646269603844 Dur[14]= 28639 ' freq= 1.45489251254117 Dur[15]= 27882 ' freq= 1.49439303732396 Dur[16]= 27146 ' freq= 1.53490999287802 Dur[17]= 26428 ' freq= 1.57661066545583 Dur[18]= 25730 ' freq= 1.61938074880166 Dur[19]= 25050 ' freq= 1.66333998669328 Dur[20]= 24388 ' freq= 1.70849051446066 Dur[21]= 23743 ' freq= 1.75490319953951 Dur[22]= 23116 ' freq= 1.8025033166061 Dur[23]= 22505 ' freq= 1.85144042064726 Dur[24]= 21910 ' freq= 1.90171915411532 Dur[25]= 21331 ' freq= 1.95333864641445 Dur[26]= 20768 ' freq= 2.006291730868 Dur[27]= 20219 ' freq= 2.06076792455941 Dur[28]= 19685 ' freq= 2.11667090000847 Dur[29]= 19164 ' freq= 2.17421554303207 Dur[30]= 18658 ' freq= 2.23317969057062 Dur[31]= 18165 ' freq= 2.29378842095605 Dur[32]= 17685 ' freq= 2.35604561304307 Dur[33]= 17218 ' freq= 2.41994811631239 Dur[34]= 16763 ' freq= 2.48563304102289 Dur[35]= 16320 ' freq= 2.5531045751634 Dur[36]= 15888 ' freq= 2.62252433702585 Dur[37]= 15469 ' freq= 2.69355916133342 Dur[38]= 15060 ' freq= 2.76671093404161 Dur[39]= 14662 ' freq= 2.84181330423316 Dur[40]= 14274 ' freq= 2.91906029610948 Dur[41]= 13897 ' freq= 2.99824902257082 Dur[42]= 13530 ' freq= 3.07957625030796 Dur[43]= 13172 ' freq= 3.16327563518575 Dur[44]= 12824 ' freq= 3.24911624038262 Dur[45]= 12485 ' freq= 3.33733813910025 Dur[46]= 12155 ' freq= 3.42794460441519 Dur[47]= 11834 ' freq= 3.52092839840009 Dur[48]= 11522 ' freq= 3.61627032343922 Dur[49]= 11217 ' freq= 3.71459986330272 Dur[50]= 10921 ' freq= 3.81527943106553 Dur[51]= 10632 ' freq= 3.91898670679709 Dur[52]= 10351 ' freq= 4.02537597011561 Dur[53]= 10078 ' freq= 4.13441820467024 Dur[54]= 9811 ' freq= 4.24693371385859 Dur[55]= 9552 ' freq= 4.36208821887214 Dur[56]= 9300 ' freq= 4.48028673835125 Dur[57]= 9054 ' freq= 4.60201752448273 Dur[58]= 8815 ' freq= 4.72679145396105 Dur[59]= 8582 ' freq= 4.85512312592247 Dur[60]= 8355 ' freq= 4.9870337123479 Dur[61]= 8134 ' freq= 5.12253094008688 Dur[62]= 7919 ' freq= 5.26160710527423 Dur[63]= 7710 ' freq= 5.40423692174665 Dur[64]= 7506 ' freq= 5.5511146638245 Dur[65]= 7308 ' freq= 5.70151432220398 Dur[66]= 7115 ' freq= 5.85617240571562 Dur[67]= 6927 ' freq= 6.01510995621 Dur[68]= 6744 ' freq= 6.1783313562673 Dur[69]= 6565 ' freq= 6.34678852500635 Dur[70]= 6392 ' freq= 6.51856487275761 Dur[71]= 6223 ' freq= 6.69559162247576 Dur[72]= 6059 ' freq= 6.87682235792485 Dur[73]= 5898 ' freq= 7.06454165253758 Dur[74]= 5743 ' freq= 7.25520924023449 Dur[75]= 5591 ' freq= 7.45245334764204 Dur[76]= 5443 ' freq= 7.65509216730969 Dur[77]= 5299 ' freq= 7.86311882745172 Dur[78]= 5159 ' freq= 8.07650061381405 Dur[79]= 5023 ' freq= 8.29517552591413 Dur[80]= 4890 ' freq= 8.52079072937969 Dur[81]= 4761 ' freq= 8.75166281593503 Dur[82]= 4635 ' freq= 8.98957209636821 Dur[83]= 4513 ' freq= 9.23258734027624 Dur[84]= 4393 ' freq= 9.48478640261021 Dur[85]= 4277 ' freq= 9.74203101862676 Dur[86]= 4164 ' freq= 10.0064040986231 Dur[87]= 4054 ' freq= 10.277914816642 Dur[88]= 3947 ' freq= 10.5565408326999 Dur[89]= 3843 ' freq= 10.842223956978 Dur[90]= 3741 ' freq= 11.1378419317473 Dur[91]= 3642 ' freq= 11.4406004027091 Dur[92]= 3546 ' freq= 11.7503290092122 Dur[93]= 3452 ' freq= 12.0702974121282 Dur[94]= 3361 ' freq= 12.3971040364971 Dur[95]= 3272 ' freq= 12.7343113284434 Dur[96]= 3186 ' freq= 13.0780498012136 Dur[97]= 3102 ' freq= 13.4321942832581 Dur[98]= 3020 ' freq= 13.7969094922737 Dur[99]= 2940 ' freq= 14.172335600907 Dur[100]= 2862 ' freq= 14.5585837409737 Dur[101]= 2787 ' freq= 14.9503647889008 Dur[102]= 2713 ' freq= 15.3581521071385 Dur[103]= 2641 ' freq= 15.7768522024486 Dur[104]= 2571 ' freq= 16.2064047711656 Dur[105]= 2504 ' freq= 16.640042598509 Dur[106]= 2437 ' freq= 17.0975242784845 Dur[107]= 2373 ' freq= 17.5586458772299 Dur[108]= 2310 ' freq= 18.037518037518 Dur[109]= 2249 ' freq= 18.5267526307989 Dur[110]= 2190 ' freq= 19.0258751902588 Dur[111]= 2132 ' freq= 19.5434646654159 Dur[112]= 2076 ' freq= 20.0706486833654 Dur[113]= 2021 ' freq= 20.616856341745 Dur[114]= 1967 ' freq= 21.182850364345 Dur[115]= 1915 ' freq= 21.7580504786771 Dur[116]= 1865 ' freq= 22.3413762287757 Dur[117]= 1815 ' freq= 22.9568411386593 Dur[118]= 1767 ' freq= 23.5804565176382 Dur[119]= 1721 ' freq= 24.2107301956227 Dur[120]= 1675 ' freq= 24.8756218905473 Dur[121]= 1631 ' freq= 25.5466993664418 Dur[122]= 1588 ' freq= 26.2384550797649 Dur[123]= 1546 ' freq= 26.9512721000431 Dur[124]= 1505 ' freq= 27.6854928017719 Dur[125]= 1465 ' freq= 28.4414106939704 Dur[126]= 1427 ' freq= 29.1987853305302 Dur[127]= 1389 ' freq= 29.9976001919846 Return Vels_Lookup: ' lookup table for the velocity controlled pulse durations ' notes 108-114 Vels0[1]= 47 Vels0[2]= 52 Vels0[3]= 57 Vels0[4]= 62 Vels0[5]= 66 Vels0[6]= 71 Vels0[7]= 76 Vels0[8]= 81 Vels0[9]= 86 Vels0[10]= 91 Vels0[11]= 96 Vels0[12]= 101 Vels0[13]= 105 Vels0[14]= 110 Vels0[15]= 115 Vels0[16]= 120 Vels0[17]= 125 Vels0[18]= 130 Vels0[19]= 135 Vels0[20]= 140 Vels0[21]= 144 Vels0[22]= 149 Vels0[23]= 154 Vels0[24]= 159 Vels0[25]= 164 Vels0[26]= 169 Vels0[27]= 174 Vels0[28]= 179 Vels0[29]= 183 Vels0[30]= 188 Vels0[31]= 193 Vels0[32]= 198 Vels0[33]= 203 Vels0[34]= 208 Vels0[35]= 213 Vels0[36]= 218 Vels0[37]= 222 Vels0[38]= 227 Vels0[39]= 232 Vels0[40]= 237 Vels0[41]= 242 Vels0[42]= 247 Vels0[43]= 252 Vels0[44]= 257 Vels0[45]= 261 Vels0[46]= 266 Vels0[47]= 271 Vels0[48]= 276 Vels0[49]= 281 Vels0[50]= 286 Vels0[51]= 291 Vels0[52]= 296 Vels0[53]= 300 Vels0[54]= 305 Vels0[55]= 310 Vels0[56]= 315 Vels0[57]= 320 Vels0[58]= 325 Vels0[59]= 330 Vels0[60]= 335 Vels0[61]= 339 Vels0[62]= 344 Vels0[63]= 349 Vels0[64]= 354 Vels0[65]= 359 Vels0[66]= 364 Vels0[67]= 369 Vels0[68]= 374 Vels0[69]= 378 Vels0[70]= 383 Vels0[71]= 388 Vels0[72]= 393 Vels0[73]= 398 Vels0[74]= 403 Vels0[75]= 408 Vels0[76]= 413 Vels0[77]= 417 Vels0[78]= 422 Vels0[79]= 427 Vels0[80]= 432 Vels0[81]= 437 Vels0[82]= 442 Vels0[83]= 447 Vels0[84]= 452 Vels0[85]= 456 Vels0[86]= 461 Vels0[87]= 466 Vels0[88]= 471 Vels0[89]= 476 Vels0[90]= 481 Vels0[91]= 486 Vels0[92]= 491 Vels0[93]= 495 Vels0[94]= 500 Vels0[95]= 505 Vels0[96]= 510 Vels0[97]= 515 Vels0[98]= 520 Vels0[99]= 525 Vels0[100]= 530 Vels0[101]= 534 Vels0[102]= 539 Vels0[103]= 544 Vels0[104]= 549 Vels0[105]= 554 Vels0[106]= 559 Vels0[107]= 564 Vels0[108]= 569 Vels0[109]= 573 Vels0[110]= 578 Vels0[111]= 583 Vels0[112]= 588 Vels0[113]= 593 Vels0[114]= 598 Vels0[115]= 603 Vels0[116]= 608 Vels0[117]= 612 Vels0[118]= 617 Vels0[119]= 622 Vels0[120]= 627 Vels0[121]= 632 Vels0[122]= 637 Vels0[123]= 642 Vels0[124]= 647 Vels0[125]= 651 Vels0[126]= 656 Vels0[127]= 661 ' rescale velocities: For i = 1 To 127 Vels0[i] = Vels0[i] * 2.6 Vels1[i] = Vels0[i] Vels2[i] = Vels0[i] Vels3[i] = Vels0[i] Vels4[i] = Vels0[i] Vels5[i] = Vels0[i] Vels6[i] = Vels0[i] Next i Return '[EOF]