' ******************************************************************** ' * PIC firmware for * ' * valve solenoids * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/bug/picworks * ' * source code development directory: * ' * Bug_Valves.bas * ' * Version 1.2 * ' ******************************************************************** ' PortD seems to give problems. Something wrong with the initialisation? ' TrisE, bit 4 must be cleared !!! otherwize, port D works in PSP mode!!! ' 05.07.2014: real world data for this code: ' loopspeed of the multitasker: 4us to 12us ' time resolution for the timer-tasks: 25us ' 05.08.2014: code adapted to new 10 output pulse hold board. (Experimental) ' ----------------------------------------------------------------------------------- ' 24.11.2016: This board used for the robot. ' The board should handle the valve solenoids and the lights. ' Valve coding can be modelled after Horny. ' 01.12.2016: Further coding. ' first sketch ready. compiles o.k. tests and measurement required. ' 04.12.2016: debug and measurement session. ' CC25 (valve attack force) and CC26 (release time for the valves) implemented. ' CC13 for user fingerings. ' LED board test passed. ' 16.12.2016: We had a short between the underside for the PCB and the +24/-48V connector... ' We blew the +24V supply by wrongly poling the -48V supply. New SMPS ordered. ' 18.12.2016: SMPS replaced. ' 19.12.2016: The 10-output board seems not to work at all. ' The PIC runs fine though... ' Strange observation: the resonance is a lot better with all valves a semitone lower... ' Shifted lookup table added. ' This code could be improved by using priority timers, with sorting. ' This PCB gets midi from the hub board. Make sure the parser transmits all ' required controllers! (Checked 20.12.2016) ' 20.12.2016: Further debugging on the actual robot. Now it works. ' 28.12.2016: Strange behaviour: after boot, lights (eyes) start flashing without receiving a command... ' we forgot the eye-left clear command in allnotes off and power down here ' Sorted timers to be implemented! ' Prog.change for different lookups to be done. ' 31.12.2016: sorted priority timers implemented. ' 01.01.2017: Version 1.1 ready ' Range for ctrl 25 is now 4.9ms to 38ms ' 02.01.2017: Port assignment bug killed for light 125 ' PIC on Bug flashed. ' 03.01.2017: The PIC seems to crash under some conditions... ' 09.12.2020: code rechecked to be in tune with upgrades of other pics and compiler. ' also we want automated eye lights now. Done: eyes go with note-on's. ' CC69 implemented. ' A single HRSOUT command is required to make the UART system work... ' Tested o.k. This be version 1.2 Include "18F4620.inc" ' (40MHz) ' Mapping defines for midi-events on pin outputs and inputs: ' This is very specific for the unique Pulse/Hold board 2014 ' mapping: $define HoldValve1 PORTA.0 ' all valves are on port A $define VeloValve1 PORTA.1 ' out 1 weidnueller $define HoldValve2 PORTA.2 ' out 2 weidmueller $define VeloValve2 PORTA.3 $define HoldValve3 PORTA.4 ' out 3 weidmueller $define VeloValve3 PORTA.5 ' lights: $define Eye_Right PORTE.0 ' out 4 weidmueller - pin8 midi 120 $define Eye_Left PORTE.2 ' out 5 weidmueller - pin 10 midi 121 $define Tube1 PORTC.1 ' out 6 - pin 16 midi 122 $define Tube2 PORTC.3 ' out 7 - pin 18 midi 123 $define Tube3 PORTD.1 ' out 8 - pin 20 midi 124 $define RedStrip PORTC.5 ' out 9 - pin 24 midi 125 $define Light PORTD.3 ' out 10 - pin 22 midi 126 ' this was a bug: (killed 02.01.2017) ' $define RedStrip PORTD.3 ' $define Light PORTC.5 ' not used: $define Velo2R PORTE.1 'nc velo out4 $define Velo3L PORTC.0 'nc velo out5 $define Velo3R PORTC.2 'nc velo out6 $define Velo4L PORTD.0 'nc velo out7 $define Velo4R PORTD.2 'nc velo out10 $define Velo5L PORTC.4 'nc velo out9 $define Velo5R PORTD.4 'nc velo out8 'red LED for debug: $define Debug_Led PORTB.3 ' for testing - red led - watchdog $define Blue_Led PORTB.1 ' PH10 board - power on/off led 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 must be zero to disable PSP mode on port D - gwr 20.01.2012 'this was the bug we had! 'constant definitions: ' midi-mappings: Symbol Lowtes = 52 Symbol Hightes = 94 Symbol M_Eye_Right = 120 'PORTE.0 Symbol M_Eye_Left = 121 'PORTE.2 Symbol M_Tube1 = 122 'PORTC.1 Symbol M_Tube2 = 123 'PORTC.3 Symbol M_Tube3 = 124 'PORTD.1 Symbol M_RedStrip = 125 'PORTD.3 Symbol M_Light = 126 'PORTC.5 not yet mounted ' 127 is on the hub board. 'initialisations for the midi input parser: Symbol Midichannel = 12 ' Bug_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 Symbol NrTasks = 8 Symbol LastTask = NrTasks - 1 ' default startup parameters: Symbol force_default = 74 ' value to be determined on Symbol releasetime_default = 64 ' value to be determined on ' 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 time As Cnt 'Dword 'frozen copy of Cnt - now alias Dim MaxTim As time.30 ' overflow flag used to reset timer Dim Nxt As Dword Dim idx As Byte 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 Ringbuffer[256] As Byte ' Array for holding received midi messages 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 Dim b As Byte ' 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 VelFlags0 As Byte System ' so we can have only 8 tasks ' Dim VelFlags1 As Byte System Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim minvel As Word System ' may become symbol Dim varvel As Word System Dim Fingers[128] As Byte ' valve fingering lookup table Dim HoldFingers[128] As Byte Dim Valves As Byte ' reflects the bits on porta at any time Dim VeloValves As Byte Dim Holdvalves As Byte Dim playingnote As Byte Dim velo2 As Byte ' used for lights Dim velo3 As Byte Dim velo4 As Byte Dim velo5 As Byte Dim velo6 As Byte Dim velo7 As Byte Dim Timvals[NrTasks] As Dword Dim Resort As Byte Dim Resort_flag As Resort.0 ' flag to signal the requirement to resort timers Dim releasetime As Byte System ' cc26 Dim Dur[128] As Word ' for valve pulsing and holdtime Dim Dur5[128] As Word ' for light repetitions Dim force As Byte System ' cc25 Dim CC69 As Byte ' only bit 0 is used: CC69.0 '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Include "Bug_Valves_Irq.inc" ' for UART,Timer0, Timer3 Interrupt 'Clear ' clear all RAM '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High Debug_Led DelayMS 10 ' wait for stability Low Debug_Led Low VeloValve1 Low VeloValve3 Low VeloValve2 ' make sure all outputs to the velo pulses are off for the lights! Low Velo5R Low Velo5L Low Velo4R Low Velo4L Low Velo3R Low Velo3L Low Velo2R Low HoldValve1 Low HoldValve3 Low HoldValve2 Low Eye_Right Low Tube1 Low Tube3 Low Light Low Eye_Left Low Tube2 Low RedStrip Low Blue_Led ' on board LED GoSub Bug_Valve_Lookup_2 ' read fingering table ' in theory we should use the first lookup, but ' shifted a semitone lower it gives much better ' resonances. [19.12.2016] GoSub Dur_Lookup Set idx Set Timvals Clear CC66 Set CC69.0 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) ' set controllers to default values on cold boot: force = force_default releasetime = releasetime_default Clear Valves HRSOut Control_Status, 66, 64 ' dummy - without this, nothing works! 09.12.2020 ' start the main program loop: Do ' Create an infinite loop Cnt.Word0 = CntLw ' read timer 0 ' was: time = Cnt , make copy (dword!) - now time is declared as an alias for Cnt GetMidiIn () ' in Bug_Valves_Irq.inc Bytein = MidiIn ' 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 Set notePres Set pres Case Control_Status ' controllers and switches statusbyte = Bytein Set Ctrl Set value Case ProgChange_Status ' could be used for different lookup tables statusbyte = Bytein Set prog Case Aftertouch_Status ' for fingered vibrato, freq.changes during notes statusbyte = Bytein Set aft Case Pitchbend_Status ' not on this board. statusbyte = Bytein Set pblsb Set pbmsb 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 Lowtes To Hightes If Valves > 0 Then ' clear all velo bits: PORTA = PORTA & %11010101 ' and-mask, so we do not touch the hold bits Set Timvals[0] ' clear force timer Timvals[1] = time + Dur5[releasetime] 'add the timeout duration Set Resort_flag EndIf Clear playingnote If CC69.0 = 1 Then Clear Eye_Left ' automated eyes... 09.12.2020 Clear Eye_Right EndIf Case M_Eye_Left Set Timvals[2] Clear Eye_Left Set Resort_flag Case M_Eye_Right Set Timvals[3] Clear Eye_Right Set Resort_flag Case M_Tube1 Set Timvals[4] Clear Tube1 Set Resort_flag Case M_Tube2 Set Timvals[5] Clear Tube2 Set Resort_flag Case M_Tube3 Set Timvals[6] Clear Tube3 Set Resort_flag Case M_RedStrip Set Timvals[7] Clear RedStrip Set Resort_flag Case M_Light 'no flashing Clear Light End Select Set noteUit '= 255 'reset EndIf 'GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then Select noteAan Case Lowtes To Hightes If Valves > 0 Then ' clear all velo bits: PORTA = PORTA & %11010101 ' and-mask, so we do not touch the hold bits Set Timvals[0] ' set the release timer Timvals[1] = time + Dur5[releasetime] Set Resort_flag EndIf Clear playingnote If CC69.0 = 1 Then Clear Eye_Left Clear Eye_Right EndIf Case M_Eye_Left Set Timvals[2] Clear Eye_Left Set Resort_flag Case M_Eye_Right Set Timvals[3] Clear Eye_Right Set Resort_flag Case M_Tube1 Set Timvals[4] Clear Tube1 Set Resort_flag Case M_Tube2 Set Timvals[5] Clear Tube2 Set Resort_flag Case M_Tube3 Set Timvals[6] Clear Tube3 Set Resort_flag Case M_RedStrip Clear RedStrip Set Timvals[7] Set Resort_flag Case M_Light Clear Light End Select Else Select noteAan Case Lowtes To Hightes If HoldFingers[noteAan] <> Valves Then Valves = Fingers[noteAan] ' clear all valve bits: (velo and hold) PORTA = PORTA & %11000000 ' and-mask ' here we have to set a velo-timer! PORTA = PORTA | Valves ' =Fingers[noteAan] ' or-mask ' on hold we do PortA = PORTA | HoldFingers[playingnote] ' setting the hold bits ' and: PORTA = PORTA & ~ Fingers[] ' clearing the velo bits Timvals[0] = time + Dur[force] ' Else ' ' no change of valve settings required ' ' we could also drop this ' Set Timvals[0] EndIf playingnote = noteAan 'clear release timer Set Timvals[1] Set Resort_flag If CC69.0 = 1 Then Set Eye_Left 'automates eyes with notes playing. Set Eye_Right EndIf Case M_Eye_Left Set Eye_Left If velo < 127 Then ' velo is 1 to 126 Timvals[2] = time + Dur5[velo] velo2 = velo Else ' velo = 127 Set Timvals[2] End If Set Resort_flag Case M_Eye_Right Set Eye_Right If velo < 127 Then Timvals[3] = time + Dur5[velo] velo3 = velo Else Set Timvals[3] End If Set Resort_flag Case M_Tube1 Set Tube1 If velo < 127 Then Timvals[4] = time + Dur5[velo] velo4 = velo Else Set Timvals[4] End If Set Resort_flag Case M_Tube2 Set Tube2 If velo < 127 Then Timvals[5] = time + Dur5[velo] velo5 = velo Else Set Timvals[5] End If Set Resort_flag Case M_Tube3 Set Tube3 If velo < 127 Then Timvals[6] = time + Dur5[velo] velo6 = velo Else Set Timvals[6] End If Set Resort_flag Case M_RedStrip Set RedStrip If velo < 127 Then Timvals[7] = time + Dur5[velo] velo7 = velo Else Set Timvals[7] End If Set Resort_flag Case M_Light Set Light End Select Set noteAan 'reset !!! EndIf EndIf Case Keypres_Status 'could be used for lite flashing on Bug-valves 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 Case ProgChange_Status ' could be used to select alternative fingering lookups If prog = 255 Then 'single byte message prog = Bytein >> 4 ' the lowest 4 bits are in use on the PIC24 board If prog > 0 Then ' so prog is now 1,2,3,4,5,6 or 7 GoSub ProgChange ' should not happen when a note is playing! EndIf EndIf ' Case Aftertouch_Status ' for changing vibrato frequency during notes ' If aft = 255 Then ' not implemented on this board ' aft = Bytein ' GoSub Aftertouch ' EndIf End Select EndIf If Resort_flag = 1 Then GoSub SortTimers ' so we resort only if an incoming midi command changed something EndIf Check_Timers: If idx < NrTasks 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 ' one shot PORTA = PORTA & %11000000 ' clear all valve bits Valves = Valves >> 1 ' velo bits become hold bits PORTA = PORTA | Valves Set Timvals[0] Case 1 PORTA = PORTA & %11000000 Clear playingnote Clear Valves Set Timvals[1] Case 2 Btg Eye_Left ' toggle Timvals[2] = time + Dur5[velo2] Case 3 Btg Eye_Right [ Timvals[3] = time + Dur5[velo3] Case 4 Btg Tube1 Timvals[4] = time + Dur5[velo4] Case 5 Btg Tube2 Timvals[5] = time + Dur5[velo5] Case 6 Btg Tube3 Timvals[6] = time + Dur5[velo6] Case 7 Btg RedStrip Timvals[7] = time + Dur5[velo7] 'Case Else ' ' in dit geval is idx geset ' GoTo jumpout EndSelect GoSub SortTimers ' find a new nxt and idx EndIf Else ' idx >= NrTasks, no timers running, so to avoid overflows, we can reset the timer If MaxTim = 1 Then Clear Cnt Set Timvals EndIf EndIf ' here we can insert a bit toggle command to measure the loop speed ' btg PORTA.4 ' =nc3 ' Hold pin ' with no midi coming in, the square wave frequency measured here is 125kHz ' thus the idle loop time is 4 microseconds ' with fast midi in, and commands for all 5 strings and lights, the loop time becomes 7.4 microseconds. ' Measurements taken with Tektronix TDS2024C oscilloscope. (200MHz, 2GS/s) Loop ' end of the main loop SortTimers: 'look up the next smallest timer value in the Timvals array ' zoek de de volgende kleinste timer waarde: Set idx ' makes it 255 Set Nxt.31 ' nxt is set on entry. - for speed, we just set the highest bit For i = 0 To LastTask ' = NrTasks -1 If Timvals[i] < Nxt Then Nxt = Timvals[i] ' NrTasks dword comparisons idx = i EndIf Next i Clear Resort_flag Return KeyPres: Set notePres '= 255 Return ProgChange: Select prog Case 1 ' 16 in midi GoSub Bug_Valve_Lookup Case 2 ' 32 in midi - this is default GoSub Bug_Valve_Lookup_2 Case 3 ' 48 in midi Case 4 ' 64 in midi Case 5 ' 80 in midi Case 6 ' 96 in midi Case 7 ' 112 in midi EndSelect Set prog 'this is not realy required Return Pitchbend: 'only implemented on dsPIC based robots, irrelevant here Set pblsb Return Aftertouch: ' 'this is the channel aftertouch, affecting any playing note ' 'used for fingered vibrato ' '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 13 ' fingering controller ' bit 0 = valve 1 ' bit 1 = valve 2 ' bit 3 = valve 3 If playingnote > 0 Then ' fingering changes are only valid if a note is played! ' stop the release timer Set Timvals[1] Clear Valves Valves.1 = value.0 Valves.3 = value.1 Valves.5 = value.2 ' clear all valve bits: PORTA = PORTA & %11000000 ' and-mask ' here we have to set a velo-timer! PORTA = PORTA | Valves ' or-mask Timvals[0] = time + Dur[force] Set Resort_flag EndIf Case 25 ' valve attack force controller 5ms to 38ms force = 128 - value ' runs 128 --> 1 If force > 127 Then force = 127 ' 127 --> 1 can never be zero! ' uses Dur[] lookup Case 26 ' valve release time controller releasetime = 128 - value If releasetime > 127 Then releasetime = 127 ' uses Dur5[] lookup 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 CC69.0 Set Blue_Led EndIf Case 69 'enables/disables automation of the eyes. If value = 0 Then Clear CC69.0 Clear Eye_Left Clear Eye_Right Else Set CC69.0 EndIf Case 123 ' clear all output ports used: Clear VeloValve1 Clear VeloValve2 Clear VeloValve3 Clear HoldValve1 Clear HoldValve2 Clear HoldValve3 Clear Tube1 Clear Eye_Left Clear Eye_Right Clear Tube3 Clear Tube2 Clear Light Clear RedStrip 'Clear Blue_Led - this can stay on! Clear playingnote Clear Valves Set Timvals Set Resort_flag End Select Set Ctrl 'mandatory reset Return PowerDown: 'stop all running timers Set Timvals ' clear all velo-bits Clear VeloValve1 Clear VeloValve2 Clear VeloValve3 Clear Velo2R Clear Velo3L Clear Velo3R Clear Velo4L Clear Velo4R Clear Velo5L Clear Velo5R Clear HoldValve1 Clear HoldValve2 Clear HoldValve3 Clear Tube1 Clear Eye_Left Clear Eye_Right Clear Tube3 Clear Tube2 Clear Light Clear RedStrip Clear Blue_Led ' reset controllers to default values: force = force_default releasetime = releasetime_default Clear playingnote Clear Valves Set Resort_flag Set CC69.0 ' automated eyes ON by default. Return Bug_Valve_Lookup: ' bit0 = valve 1, semitone down (central valve) ' bit1 = valve 2 tone down (valve closest to mouthpiece) ' bit2 = valve 3 3 half tones down (valve closest to horn) ' this is the data set used for : '52 0111 ' alle ventielen ingedrukt - eerste oktaaftoon - Mi '53 0110 ' Fa '54 0101 ' Fa# '55 0100 ' sol '56 0010 ' sol# '57 0001 ' la '58 0000 ' eerste oktaafharmoniek op grondtoon - sib '59 0111 ' kwint op mi = si '60 0110 ' do '61 0101 ' do# '62 0100 ' re '63 0010 ' mib '64 0001 ' mi '65 0000 ' fa kwint op grondtoon '66 0101 ' fa# '67 0100 ' sol '68 0010 ' lab '69 0001 ' la '70 0000 ' sib tweede oktaaf boven grondtoon '71 0010 ' si terts '72 0001 ' do terts '73 0000 ' do# terts '74 0100 ' re - dubbelkwint '75 0010 ' mib - dubbelkwint '76 0001 ' mi - dubbelkwint '77 0000 ' fa - dubbelkwint '78 0010 ' fa# - septiem '79 0001 ' sol - septiem '80 0000 ' lab - septiem '81 0001 ' la - triple oktaaf '82 0000 ' sib - triple oktaaf For i = 0 To 53 Fingers[i] = 0 Next i Fingers[52] = %111 Fingers[53] = %110 Fingers[54] = %101 Fingers[55] = %100 Fingers[56] = %010 Fingers[57] = %001 Fingers[58] = 0 ' sounds Bb - The flugelhorn plays C Fingers[59] = %111 ' kwint boven 111 Fingers[60] = %110 Fingers[61] = %101 Fingers[62] = %100 Fingers[63] = %010 Fingers[64] = %001 Fingers[65] = %000 ' or Fingers[65] = %110 Fingers[66] = %101 Fingers[67] = %100 ' okt Fingers[68] = %010 Fingers[69] = %001 Fingers[70] = 0 ' oktaaf Bb Fingers[71] = %010 Fingers[72] = %001 Fingers[73] = %000 Fingers[74] = %100 Fingers[75] = %010 Fingers[76] = %001 Fingers[77] = 0 Fingers[78] = %010 ' fa# septiem Fingers[79] = %100 ' or 001, septiem Fingers[80] = %010 ' or 0, septiem Fingers[81] = %001 Fingers[82] = 0 'dubbeloktaaf Bb Fingers[83] = %010 Fingers[84] = %001 Fingers[85] = %000 Fingers[86] = %100 Fingers[87] = %010 Fingers[88] = %001 Fingers[89] = %000 Fingers[90] = %010 Fingers[91] = %100 Fingers[92] = %010 Fingers[93] = %001 Fingers[94] = 0 'triple oktaaf Bb For i = 95 To 127 Fingers[i] = 0 Next i ' now perform some bit swapping, to have the velo bits on odd places: ' this way the bit order corresponds to the port mapping on portA For i = 0 To 127 b = Fingers[i] If b.2 = 1 Then b.5 = 1 b.2 = 0 EndIf If b.1 = 1 Then b.3 = 1 b.1 = 0 EndIf If b.0 = 1 Then b.1 = 1 b.0 = 0 EndIf Fingers[i] = b ' thus this array contains the bits to be pulsed. Next i ' now fill the bits for the hold-positions: For i = 0 To 127 ' b = Fingers[i] ' if b.1 then ' clear b.1 ' set b.0 ' endif ' if b.3 then ' clear b.3 ' set b.2 ' endif ' if b.5 then ' clear b.5 ' set b.4 ' endif ' HoldFingers[i] = b ' much faster coding: HoldFingers[i] = Fingers[i] >> 1 Next i Return Bug_Valve_Lookup_2: ' everything shifted a semitone down, as this seems ' to gibe much better resonance ' bit0 = valve 1, semitone down (central valve) ' bit1 = valve 2 tone down (valve closest to mouthpiece) ' bit2 = valve 3 3 half tones down (valve closest to horn) ' this is the data set used for : '52 0111 ' alle ventielen ingedrukt - eerste oktaaftoon - Mi '53 0110 ' Fa '54 0101 ' Fa# '55 0100 ' sol '56 0010 ' sol# '57 0001 ' la '58 0000 ' eerste oktaafharmoniek op grondtoon - sib '59 0111 ' kwint op mi = si '60 0110 ' do '61 0101 ' do# '62 0100 ' re '63 0010 ' mib '64 0001 ' mi '65 0000 ' fa kwint op grondtoon '66 0101 ' fa# '67 0100 ' sol '68 0010 ' lab '69 0001 ' la '70 0000 ' sib tweede oktaaf boven grondtoon '71 0010 ' si terts '72 0001 ' do terts '73 0000 ' do# terts '74 0100 ' re - dubbelkwint '75 0010 ' mib - dubbelkwint '76 0001 ' mi - dubbelkwint '77 0000 ' fa - dubbelkwint '78 0010 ' fa# - septiem '79 0001 ' sol - septiem '80 0000 ' lab - septiem '81 0001 ' la - triple oktaaf '82 0000 ' sib - triple oktaaf For i = 0 To 51 Fingers[i] = 0 Next i Fingers[51] = %000 Fingers[52] = %111 Fingers[53] = %110 Fingers[54] = %101 Fingers[55] = %100 Fingers[56] = %010 Fingers[57] = %001 Fingers[58] = 0 ' sounds Bb - The flugelhorn plays C Fingers[59] = %111 ' kwint boven 111 Fingers[60] = %110 Fingers[61] = %101 Fingers[62] = %100 Fingers[63] = %010 Fingers[64] = %001 Fingers[65] = %000 ' or Fingers[65] = %110 Fingers[66] = %101 Fingers[67] = %100 ' okt Fingers[68] = %010 Fingers[69] = %001 Fingers[70] = 0 ' oktaaf Bb Fingers[71] = %010 Fingers[72] = %001 Fingers[73] = %000 Fingers[74] = %100 Fingers[75] = %010 Fingers[76] = %001 Fingers[77] = 0 Fingers[78] = %010 ' fa# septiem Fingers[79] = %100 ' or 001, septiem Fingers[80] = %010 ' or 0, septiem Fingers[81] = %001 Fingers[82] = 0 'dubbeloktaaf Bb Fingers[83] = %010 Fingers[84] = %001 Fingers[85] = %000 Fingers[86] = %100 Fingers[87] = %010 Fingers[88] = %001 Fingers[89] = %000 Fingers[90] = %010 Fingers[91] = %100 Fingers[92] = %010 Fingers[93] = %001 Fingers[94] = 0 'triple oktaaf Bb For i = 95 To 127 Fingers[i] = 0 Next i ' shift the whole array a semitone down: [19.12.2016] For i = 1 To 127 Fingers[i-1] = Fingers[i] Next i ' now perform some bit swapping, to have the velo bits on odd places: ' this way the bit order corresponds to the port mapping on portA For i = 0 To 127 b = Fingers[i] If b.2 = 1 Then b.5 = 1 b.2 = 0 EndIf If b.1 = 1 Then b.3 = 1 b.1 = 0 EndIf If b.0 = 1 Then b.1 = 1 b.0 = 0 EndIf Fingers[i] = b ' thus this array contains the bits to be pulsed. Next i ' now fill the bits for the hold-positions: For i = 0 To 127 ' much faster coding: HoldFingers[i] = Fingers[i] >> 1 Next i Return Dur_Lookup: Set Dur[0] ' lookup for valve force (ctrl 25) ' 1 time unit here is 26us (measured 04.12.2016) Dur[1]= 23674 ' period = 616ms or freq = 1.622Hz Dur[2]= 22917 Dur[3]= 22548 ' freq= 2.21749157353202 Dur[4]= 22185 ' freq= 2.25377507324769 Dur[5]= 21827 ' freq= 2.29074082558299 Dur[6]= 21475 ' freq= 2.32828870779977 Dur[7]= 21129 ' freq= 2.36641582658905 Dur[8]= 20789 ' freq= 2.40511809129828 Dur[9]= 20454 ' freq= 2.44450963136795 Dur[10]= 20124 ' freq= 2.48459550785132 Dur[11]= 19800 ' freq= 2.52525252525252 Dur[12]= 19481 ' freq= 2.56660335711719 Dur[13]= 19167 ' freq= 2.60865028434288 Dur[14]= 18858 ' freq= 2.65139463357726 Dur[15]= 18554 ' freq= 2.69483669289641 Dur[16]= 18255 ' freq= 2.73897562311695 Dur[17]= 17961 ' freq= 2.7838093647347 Dur[18]= 17672 ' freq= 2.82933454051607 Dur[19]= 17387 ' freq= 2.87571173865532 Dur[20]= 17107 ' freq= 2.92278014847723 Dur[21]= 16831 ' freq= 2.97070881112233 Dur[22]= 16560 ' freq= 3.01932367149758 Dur[23]= 16293 ' freq= 3.06880255324372 Dur[24]= 16030 ' freq= 3.11915159076731 Dur[25]= 15772 ' freq= 3.17017499365965 Dur[26]= 15518 ' freq= 3.22206469905916 Dur[27]= 15268 ' freq= 3.27482315954938 Dur[28]= 15022 ' freq= 3.32845160431367 Dur[29]= 14780 ' freq= 3.382949932341 Dur[30]= 14542 ' freq= 3.43831660019254 Dur[31]= 14307 ' freq= 3.4947927587894 Dur[32]= 14077 ' freq= 3.55189315905378 Dur[33]= 13850 ' freq= 3.6101083032491 Dur[34]= 13627 ' freq= 3.66918617450649 Dur[35]= 13407 ' freq= 3.72939509211606 Dur[36]= 13191 ' freq= 3.79046319460238 Dur[37]= 12978 ' freq= 3.85267375558638 Dur[38]= 12769 ' freq= 3.91573341686898 Dur[39]= 12564 ' freq= 3.97962432346386 Dur[40]= 12361 ' freq= 4.04498017959712 Dur[41]= 12162 ' freq= 4.1111659266568 Dur[42]= 11966 ' freq= 4.17850576633796 Dur[43]= 11773 ' freq= 4.24700586086809 Dur[44]= 11583 Dur[45]= 11397 ' freq= 4.38711941739054 Dur[46]= 11213 ' freq= 4.45910996165165 Dur[47]= 11032 ' freq= 4.53226976069616 Dur[48]= 10855 ' freq= 4.60617227084293 Dur[49]= 10680 ' freq= 4.6816479400749 Dur[50]= 10508 ' freq= 4.75827940616673 Dur[51]= 10338 ' freq= 4.83652544012381 Dur[52]= 10172 ' freq= 4.91545418796697 Dur[53]= 10008 ' freq= 4.99600319744204 Dur[54]= 9846 ' freq= 5.07820434694292 Dur[55]= 9688 ' freq= 5.16102394715111 Dur[56]= 9532 ' freq= 5.24548887956357 Dur[57]= 9378 ' freq= 5.33162721262529 Dur[58]= 9227 ' freq= 5.4188793757451 Dur[59]= 9078 ' freq= 5.50782110597048 Dur[60]= 8932 ' freq= 5.59785042543663 Dur[61]= 8788 ' freq= 5.68957669549385 Dur[62]= 8646 ' freq= 5.78302105019662 Dur[63]= 8507 Dur[64]= 8370 Dur[65]= 8235 ' freq= 6.07164541590771 Dur[66]= 8102 ' freq= 6.17131572451246 Dur[67]= 7972 ' freq= 6.27195183140993 Dur[68]= 7843 ' freq= 6.37511156445238 Dur[69]= 7717 ' freq= 6.47920176234288 Dur[70]= 7593 ' freq= 6.58501251152377 Dur[71]= 7470 ' freq= 6.69344042838019 Dur[72]= 7350 ' freq= 6.80272108843537 Dur[73]= 7231 ' freq= 6.91467293597013 Dur[74]= 7115 ' freq= 7.02740688685875 Dur[75]= 7000 ' freq= 7.14285714285714 Dur[76]= 6888 ' freq= 7.25900116144018 Dur[77]= 6777 ' freq= 7.37789582411096 Dur[78]= 6667 ' freq= 7.49962501874906 Dur[79]= 6560 ' freq= 7.62195121951219 Dur[80]= 6454 ' freq= 7.74713356058258 Dur[81]= 6350 ' freq= 7.8740157480315 Dur[82]= 6248 ' freq= 8.00256081946223 Dur[83]= 6147 ' freq= 8.13404912965674 Dur[84]= 6048 ' freq= 8.26719576719577 Dur[85]= 5951 ' freq= 8.40194925222652 Dur[86]= 5855 ' freq= 8.5397096498719 Dur[87]= 5760 ' freq= 8.68055555555555 Dur[88]= 5668 ' freq= 8.82145377558222 Dur[89]= 5576 ' freq= 8.96700143472023 Dur[90]= 5486 ' freq= 9.11410864017499 Dur[91]= 5398 ' freq= 9.26268988514264 Dur[92]= 5311 ' freq= 9.41442289587648 Dur[93]= 5225 ' freq= 9.56937799043062 Dur[94]= 5141 ' freq= 9.72573429293912 Dur[95]= 5058 Dur[96]= 4977 Dur[97]= 4897 Dur[98]= 4818 Dur[99]= 4740 Dur[100]= 4664 Dur[101]= 4589 Dur[102]= 4515 Dur[103]= 4442 Dur[104]= 4370 Dur[105]= 4300 Dur[106]= 4231 Dur[107]= 4162 Dur[108]= 4095 Dur[109]= 4029 Dur[110]= 3964 Dur[111]= 3901 Dur[112]= 3838 Dur[113]= 3776 Dur[114]= 3715 Dur[115]= 3655 Dur[116]= 3596 Dur[117]= 3538 Dur[118]= 3481 Dur[119]= 3425 Dur[120]= 3370 Dur[121]= 3316 Dur[122]= 3262 Dur[123]= 3210 Dur[124]= 3158 Dur[125]= 3107 Dur[126]= 3057 Dur[127]= 3008 ' 04.12.2016: Bug code: Dur[127] geeft freq = 6.386 Hz, period = 156.6ms ' = 75ms to 220ms ' this is way too much, so we divide by 16: For i = 0 To 127 Dur[i] = Dur[i] >> 4 ' the range is now 5ms to 38ms Next i Set Dur5[0] ' used for light flashing and valve release time Dur5[1]= 41667 ' = 1 second , full period = 2 seconds, freq = 0.5Hz Dur5[2]= 39494 ' freq= 1.0550125757499 Dur5[3]= 38450 ' freq= 1.08365843086259 Dur5[4]= 37434 ' freq= 1.11307011451265 Dur5[5]= 36445 ' freq= 1.14327525495038 Dur5[6]= 35482 ' freq= 1.17430434210774 Dur5[7]= 34544 ' freq= 1.20619113787247 Dur5[8]= 33631 ' freq= 1.23893629885126 Dur5[9]= 32743 ' freq= 1.27253662360403 Dur5[10]= 31877 ' freq= 1.30710752789367 Dur5[11]= 31035 ' freq= 1.34257021642232 Dur5[12]= 30215 ' freq= 1.37900601246621 Dur5[13]= 29416 ' freq= 1.41646269603844 Dur5[14]= 28639 ' freq= 1.45489251254117 Dur5[15]= 27882 ' freq= 1.49439303732396 Dur5[16]= 27146 ' freq= 1.53490999287802 Dur5[17]= 26428 ' freq= 1.57661066545583 Dur5[18]= 25730 ' freq= 1.61938074880166 Dur5[19]= 25050 ' freq= 1.66333998669328 Dur5[20]= 24388 ' freq= 1.70849051446066 Dur5[21]= 23743 ' freq= 1.75490319953951 Dur5[22]= 23116 ' freq= 1.8025033166061 Dur5[23]= 22505 ' freq= 1.85144042064726 Dur5[24]= 21910 ' freq= 1.90171915411532 Dur5[25]= 21331 ' freq= 1.95333864641445 Dur5[26]= 20768 ' freq= 2.006291730868 Dur5[27]= 20219 ' freq= 2.06076792455941 Dur5[28]= 19685 ' freq= 2.11667090000847 Dur5[29]= 19164 ' freq= 2.17421554303207 Dur5[30]= 18658 ' freq= 2.23317969057062 Dur5[31]= 18165 ' freq= 2.29378842095605 Dur5[32]= 17685 ' freq= 2.35604561304307 Dur5[33]= 17218 ' freq= 2.41994811631239 Dur5[34]= 16763 ' freq= 2.48563304102289 Dur5[35]= 16320 ' freq= 2.5531045751634 Dur5[36]= 15888 ' freq= 2.62252433702585 Dur5[37]= 15469 ' freq= 2.69355916133342 Dur5[38]= 15060 ' freq= 2.76671093404161 Dur5[39]= 14662 ' freq= 2.84181330423316 Dur5[40]= 14274 ' freq= 2.91906029610948 Dur5[41]= 13897 ' freq= 2.99824902257082 Dur5[42]= 13530 ' freq= 3.07957625030796 Dur5[43]= 13172 ' freq= 3.16327563518575 Dur5[44]= 12824 ' freq= 3.24911624038262 Dur5[45]= 12485 ' freq= 3.33733813910025 Dur5[46]= 12155 ' freq= 3.42794460441519 Dur5[47]= 11834 ' freq= 3.52092839840009 Dur5[48]= 11522 ' freq= 3.61627032343922 Dur5[49]= 11217 ' freq= 3.71459986330272 Dur5[50]= 10921 ' freq= 3.81527943106553 Dur5[51]= 10632 ' freq= 3.91898670679709 Dur5[52]= 10351 ' freq= 4.02537597011561 Dur5[53]= 10078 ' freq= 4.13441820467024 Dur5[54]= 9811 ' freq= 4.24693371385859 Dur5[55]= 9552 ' freq= 4.36208821887214 Dur5[56]= 9300 ' freq= 4.48028673835125 Dur5[57]= 9054 ' freq= 4.60201752448273 Dur5[58]= 8815 ' freq= 4.72679145396105 Dur5[59]= 8582 ' freq= 4.85512312592247 Dur5[60]= 8355 ' freq= 4.9870337123479 Dur5[61]= 8134 ' freq= 5.12253094008688 Dur5[62]= 7919 ' freq= 5.26160710527423 Dur5[63]= 7710 ' freq= 5.40423692174665 Dur5[64]= 7506 ' freq= 5.5511146638245 Dur5[65]= 7308 ' freq= 5.70151432220398 Dur5[66]= 7115 ' freq= 5.85617240571562 Dur5[67]= 6927 ' freq= 6.01510995621 Dur5[68]= 6744 ' freq= 6.1783313562673 Dur5[69]= 6565 ' freq= 6.34678852500635 Dur5[70]= 6392 ' freq= 6.51856487275761 Dur5[71]= 6223 ' freq= 6.69559162247576 Dur5[72]= 6059 ' freq= 6.87682235792485 Dur5[73]= 5898 ' freq= 7.06454165253758 Dur5[74]= 5743 ' freq= 7.25520924023449 Dur5[75]= 5591 ' freq= 7.45245334764204 Dur5[76]= 5443 ' freq= 7.65509216730969 Dur5[77]= 5299 ' freq= 7.86311882745172 Dur5[78]= 5159 ' freq= 8.07650061381405 Dur5[79]= 5023 ' freq= 8.29517552591413 Dur5[80]= 4890 ' freq= 8.52079072937969 Dur5[81]= 4761 ' freq= 8.75166281593503 Dur5[82]= 4635 ' freq= 8.98957209636821 Dur5[83]= 4513 ' freq= 9.23258734027624 Dur5[84]= 4393 ' freq= 9.48478640261021 Dur5[85]= 4277 ' freq= 9.74203101862676 Dur5[86]= 4164 ' freq= 10.0064040986231 Dur5[87]= 4054 ' freq= 10.277914816642 Dur5[88]= 3947 ' freq= 10.5565408326999 Dur5[89]= 3843 ' freq= 10.842223956978 Dur5[90]= 3741 ' freq= 11.1378419317473 Dur5[91]= 3642 ' freq= 11.4406004027091 Dur5[92]= 3546 ' freq= 11.7503290092122 Dur5[93]= 3452 ' freq= 12.0702974121282 Dur5[94]= 3361 ' freq= 12.3971040364971 Dur5[95]= 3272 ' freq= 12.7343113284434 Dur5[96]= 3186 ' freq= 13.0780498012136 Dur5[97]= 3102 ' freq= 13.4321942832581 Dur5[98]= 3020 ' freq= 13.7969094922737 Dur5[99]= 2940 ' freq= 14.172335600907 Dur5[100]= 2862 ' freq= 14.5585837409737 Dur5[101]= 2787 ' freq= 14.9503647889008 Dur5[102]= 2713 ' freq= 15.3581521071385 Dur5[103]= 2641 ' freq= 15.7768522024486 Dur5[104]= 2571 ' freq= 16.2064047711656 Dur5[105]= 2504 ' freq= 16.640042598509 Dur5[106]= 2437 ' freq= 17.0975242784845 Dur5[107]= 2373 ' freq= 17.5586458772299 Dur5[108]= 2310 ' freq= 18.037518037518 Dur5[109]= 2249 ' freq= 18.5267526307989 Dur5[110]= 2190 ' freq= 19.0258751902588 Dur5[111]= 2132 ' freq= 19.5434646654159 Dur5[112]= 2076 ' freq= 20.0706486833654 Dur5[113]= 2021 ' freq= 20.616856341745 Dur5[114]= 1967 ' freq= 21.182850364345 Dur5[115]= 1915 ' freq= 21.7580504786771 Dur5[116]= 1865 ' freq= 22.3413762287757 Dur5[117]= 1815 ' freq= 22.9568411386593 Dur5[118]= 1767 ' freq= 23.5804565176382 Dur5[119]= 1721 ' freq= 24.2107301956227 Dur5[120]= 1675 ' freq= 24.8756218905473 Dur5[121]= 1631 ' freq= 25.5466993664418 Dur5[122]= 1588 ' freq= 26.2384550797649 Dur5[123]= 1546 ' freq= 26.9512721000431 Dur5[124]= 1505 ' freq= 27.6854928017719 Dur5[125]= 1465 ' freq= 28.4414106939704 Dur5[126]= 1427 ' freq= 29.1987853305302 Dur5[127]= 1389 ' = 36ms, full period = 72ms, freq.= 13.8 Hz Return '[EOF]