'**************************************************************** '* Name : Vacca_Hub.BAS * '* Author : Godfried-Willem RAES * '* Notice : Copyleft (c) 2013 Logosoft Public Domain * '* Date : 29-10-2013 * '* Version : 1.0 * '* Notes : Based On Whisper-hub code model, General_Hub.bas * '**************************************************************** '26.08.2013: PIC: 18F2525 On MidiHub board ' framework: Midi monitoring only on HUB boards. ' This steers only the power relay and four lights. Include "18F2525.inc" 'version for the Vacca board. (40MHz) 'Include "18F2520.inc" 'also possible. (40MHz) 'Include "18F25K20.inc" 'for test & debug on an Amicus board. (64MHz) ' Mapping defines for midi-events on pin outputs and inputs: $define X11_2 PORTC.5 ' X11-2 - light LED strip, white note 24 $define X11_3 PORTC.4 ' X11-3 - light E10 12V/3W tungsten left note 25 $define X17_2 PORTC.1 ' X17-2 - pwm - note 29 $define X17_3 PORTC.2 ' X17-3 - pwm - note 30 $define X12_2 PORTB.0 ' X12-2 - light E10 12V/3W tungsten right note 26 $define X12_3 PORTB.1 ' X12-3 - light Frontal light note 27 $define X15_2 PORTC.3 ' X15-2 - nc ? backlight note 28 $define X15_3 PORTC.0 ' X15-3 - power relay (90V power for solenoids) $define BlueLed PORTA.3 'midi buffer overflow ? $define GreenLed PORTA.4 'for code monitoring and debug (valid Vacca notes received) $define YellowLed PORTA.5 'for code monitoring and debug (valid Vitello notes received) 'red LED for debug: $define Debug_Led PORTB.5 ' for testing - red led - watchdog ' configure the input and output pins: Clear SSPCON1.5 'RC3 must be available for I/O TRISA = %01000111 'bits set to 0 are output, 1 = input TRISB = %11100000 TRISC = %11000000 'RC1 en RC2 zijn pwm outputs and must be set to output 'RC6 en RC7 zijn USART I/O and must be set to input 'constant definitions: 'initialisations for the midi input parser: Symbol Midichannel = 4 ' Vacca_Channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel ' 2 bytes follow 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 'application specific constants Symbol NrTasks = 5 ' maximum 16 Symbol fPWM = PWMminF * 4 ' in avoidance of audible artifacts ' 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 All_Digital = True Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables Dim Cnt As Dword System Dim CntHw As Cnt.Word1 'used in the timer0 interrupt, to create a 32 bit timer Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H 'it makes Cntlw the low word of cnt 'We still have to copy the contents of Lw to Cnt ' Dim Tim3 As TMR3L.Word 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 VelFlags As Word System ' bits 0 - 15 used as flags for active timers Dim VelFlags0 As VelFlags.Byte0 ' alias for bits 0-7 ' Dim VelFlags1 As VelFlags.Byte1 ' bits 8-15 - not used in this code. Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim st As Byte System Dim b1 As Byte System Dim b2 As Byte System Dim Lites As Byte System ' bits used as flags Dim pw1 As Byte System ' X17_2 Dim pw2 As Byte System '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler And buffer read subroutines into memory 'Include "ADC.inc" ' Load the ADC macros into the program - used in the IRQ include. Include "Vacca_Irq.inc" ' our own version for UART And Timer0/3 Interrupt 'Include "Timers.inc" ' required for velo support with timed pulses and periods. 'framework for a multitasker: Dim Task_rsi[NrTasks] As Word 'task reschedule interval (period), if 0 the task is not active 'max. value limited to 65535. For longer periods, it will have to 'become dword!!! Dim Velmsb[NrTasks] As Word 'the application for velo-timers, is in fact just a one-shot task Dim VelLsb[NrTasks] As Word Dim Dur[128] As Word ' duration lookup 'DeclareDwordArray(TimeVals , NrTasks) 'alternative using the macro's. [not yet used] ' assigning values syntax: DwordArray Timvals,[i], value ' reading values syntax: value = DwordArray TimVals,[i] 'make sure we initialize the used pins on start up: 'fault?: there should be no executable statements outside the main program. Low X17_2 Low X17_3 Low X11_2 Low X11_3 Low X12_2 Low X12_3 Low X15_2 Low X15_3 Low Debug_Led Clear CC66 HPWM 2, 0, fPWM ' connected to RC1 HPWM 1, 0, fPWM ' connected to RC2 Low GreenLED Low YellowLed Low BlueLED GoSub Dur_Lookup '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High BlueLed DelayMS 200 ' wait for stability Low BlueLed Clear VelFlags0 Clear Lites 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 ' Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) in macro file. 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 bit, 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 ' open and start timer3 for sampling: Clear T3CON Clear PIR2BITS_TMR3IF ' clear IRQ flag Set PIE2BITS_TMR3IE ' irq on ' Clear Tim3 ' Clear TMR3L And TMR3H registers Set RCONbits_IPEN ' Enable priority interrupts Clear IPR2bits_TMR3IP ' Set Timer3 as a low priority interrupt source = not used for Vacca ' we can also set T3Con in one instruction as: T3CON = %10110000 ' 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 set to 0 for Vacca! ' maximum count = 52.42ms, 1 tick =0.8uS, lowest freq.=19Hz ' start the main program loop: LOOP: ' Create an infinite loop Bytein = HRSIn ' Read data from the serial buffer, with no timeout ' Start the midi parser. Midi_Parse: If Bytein > Control_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 (?) GoTo Check_Timers 'throw away... Else Clear statusbyte 'reset the status byte GoTo Check_Timers 'throw away End If 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 Set velo Case Keypres_Status statusbyte = Bytein Set notePres Set pres Case Control_Status statusbyte = Bytein Set Ctrl Set value Case ProgChange_Status statusbyte = Bytein Set prog Case Aftertouch_Status statusbyte = Bytein Set aft Case Pitchbend_Status 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 24 Clear Lites.0 Clear VelFlags0.0 Clear X11_2 Case 25 Clear Lites.1 Clear VelFlags0.1 Clear X11_3 Case 26 Clear Lites.2 Clear VelFlags0.2 Clear X12_2 Case 27 Clear Lites.3 Clear VelFlags0.3 Clear X12_3 Case 28 Clear Lites.4 Clear VelFlags0.4 Clear X15_2 Case 29 HPWM 2, 0, fPWM ' X17_2 Case 30 HPWM 1, 0, fPWM ' X17-3 End Select Set noteUit 'reset EndIf GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then Select noteAan Case 24 Clear Lites.0 Clear VelFlags0.0 Clear X11_2 Case 25 Clear Lites.1 Clear VelFlags0.1 Clear X11_3 Case 26 Clear Lites.2 Clear VelFlags0.2 Clear X12_2 Case 27 Clear Lites.3 Clear VelFlags0.3 Clear X12_3 Case 28 Clear Lites.4 Clear VelFlags0.4 Clear X15_2 Case 29 HPWM 2, 0, fPWM ' X17_2 Case 30 HPWM 1, 0, fPWM ' X17-3 End Select Set noteAan 'reset !!! GoTo Check_Timers 'jump out EndIf Select noteAan Case 24 Set X11_2 Set Lites.0 If velo < 127 Then Set VelFlags0.0 Cnt.Word0 = CntLw ' read timer Task_rsi[0] = Dur[velo] veltim = Cnt + Task_rsi[0] ' add period duration Velmsb[0] = veltim.Word1 VelLsb[0] = veltim.Word0 Else Clear VelFlags0.0 EndIf Case 25 Set X11_3 Set Lites.1 If velo < 127 Then Set VelFlags0.1 Cnt.Word0 = CntLw ' read timer Task_rsi[1] = Dur[velo] veltim = Cnt + Task_rsi[1] ' add period duration Velmsb[1] = veltim.Word1 VelLsb[1] = veltim.Word0 Else Clear VelFlags0.1 EndIf Case 26 Set X12_2 Set Lites.2 If velo < 127 Then Set VelFlags0.2 Cnt.Word0 = CntLw ' read timer Task_rsi[2] = Dur[velo] veltim = Cnt + Task_rsi[2] ' add period duration Velmsb[2] = veltim.Word1 VelLsb[2] = veltim.Word0 Else Clear VelFlags0.2 EndIf Case 27 Set X12_3 Set Lites.3 If velo < 127 Then Set VelFlags0.3 Cnt.Word0 = CntLw ' read timer Task_rsi[3] = Dur[velo] veltim = Cnt + Task_rsi[3] ' add period duration Velmsb[3] = veltim.Word1 VelLsb[3] = veltim.Word0 Else Clear VelFlags0.3 EndIf Case 28 Set X15_2 Set Lites.4 If velo < 127 Then Set VelFlags0.4 Cnt.Word0 = CntLw ' read timer Task_rsi[4] = Dur[velo] veltim = Cnt + Task_rsi[4] ' add period duration Velmsb[4] = veltim.Word1 VelLsb[4] = veltim.Word0 Else Clear VelFlags0.4 EndIf Case 29 'pw1 = velo >> 1 'pw1 = pw1 + velo + 64 pw1 = velo << 1 HPWM 2, pw1, fPWM ' X17_2 Case 30 'pw2 = velo >> 1 'pw2 = pw2 + velo + 64 pw2 = velo << 1 ' 128 + velo HPWM 1, pw2, fPWM ' X17-3 End Select Set noteAan 'reset EndIf GoTo Check_Timers Case Keypres_Status If notePres = 255 Then notePres = Bytein Else pres = Bytein GoSub KeyPres EndIf GoTo Check_Timers Case Control_Status If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein GoSub Controller EndIf GoTo Check_Timers Case ProgChange_Status If prog = 255 Then 'single byte message prog = Bytein 'weak coding... GoSub ProgChange EndIf Case Pitchbend_Status If pblsb = 255 Then pblsb = Bytein Else pbmsb = Bytein GoSub Pitchbend EndIf End Select EndIf Check_Timers: ' ' here we check the Task counters and compare them with the 32 bit cnt value ' ' using the Velflags dword variable: If VelFlags0 > 0 Then 'if any bit is set here, there is a timer running If VelFlags0.0 = 1 Then veltim.Word1 = Velmsb[0] veltim.Word0 = VelLsb[0] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task0 'note 24 X11_2 EndIf If VelFlags0.1 = 1 Then veltim.Word1 = Velmsb[1] veltim.Word0 = VelLsb[1] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task1 'note 25 X11_3 EndIf If VelFlags0.2 = 1 Then veltim.Word1 = Velmsb[2] veltim.Word0 = VelLsb[2] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task2 'note 26 X12_2 EndIf If VelFlags0.3 = 1 Then veltim.Word1 = Velmsb[3] veltim.Word0 = VelLsb[3] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task3 'note 27 X13_3 EndIf If VelFlags0.4 = 1 Then veltim.Word1 = Velmsb[4] veltim.Word0 = VelLsb[4] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task4 'note 28 X15_2 EndIf Else If CntHw > 0xFF Then Clear CntHw EndIf GoTo LOOP ' end of the main loop KeyPres: 'the note to which the pressure should be applied is passed in NotePres, the value in Pres 'here we use it for flashing lights, shaking the shaker and slow PWM the gambling machine... '20.08.2013: coding modified such that the repetition period is only refreshed after the previous ' timer flip over. ' Thus we can make smoother accel. and decel. ' Select notePres ' Case 82 ' If Lites.6 = 1 Then ' Set VelFlags0.6 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[6] = Dur[pres] ' (~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[6] 'add the period duration ' 'Velmsb[6] = veltim.Word1 ' 'VelLsb[6] = veltim.Word0 ' Else ' Clear VelFlags0.6 ' Clear Gamble ' EndIf ' Case 83 ' If Lites.4 = 1 Then ' Set VelFlags0.4 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[4] = Dur[pres] '(~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[4] 'add the period duration ' 'Velmsb[4] = veltim.Word1 ' 'VelLsb[4] = veltim.Word0 ' Else ' Clear VelFlags0.4 ' Clear X11_2 ' EndIf ' Case 86 ' If Lites.5 = 1 Then ' Set VelFlags0.5 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[5] = Dur[pres] '(~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[5] 'add the period duration ' 'Velmsb[5] = veltim.Word1 ' 'VelLsb[5] = veltim.Word0 ' Else ' Clear VelFlags0.5 ' Clear X11_3 ' EndIf ' Case 120 ' If Lites.0 = 1 Then ' Set VelFlags0.0 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[0] = Dur[pres] '(~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[0] 'add the period duration ' 'Velmsb[0] = veltim.Word1 ' 'VelLsb[0] = veltim.Word0 ' Else ' Clear VelFlags0.0 ' Clear X12_2 ' EndIf ' Case 121 ' If Lites.1 = 1 Then ' Set VelFlags0.1 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[1] = Dur[pres] '(~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[1] 'add the period duration ' 'Velmsb[1] = veltim.Word1 ' 'VelLsb[1] = veltim.Word0 ' Else ' Clear VelFlags0.1 ' Clear X12_3 ' EndIf ' Case 122 ' If Lites.2 = 1 Then ' Set VelFlags0.2 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[2] = Dur[pres] ' (~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[2] 'add the period duration ' 'Velmsb[2] = veltim.Word1 ' 'VelLsb[2] = veltim.Word0 ' Else ' Clear VelFlags0.2 ' Clear X15_2 ' EndIf ' Case 123 ' If Lites.3 = 1 Then ' Set VelFlags0.3 ' 'Cnt.Word0 = CntLw 'read timer ' Task_rsi[3] = Dur[pres] '(~pres & 127) << 9 ' 'veltim = Cnt + Task_rsi[3] 'add the period duration ' 'Velmsb[3] = veltim.Word1 ' 'VelLsb[3] = veltim.Word0 ' Else ' Clear VelFlags0.3 ' Clear X15_3 ' EndIf ' End Select Set notePres '= 255 Return ProgChange: ' Set prog '= 255 'this is not realy required Return Pitchbend: ' 'only implemented on dsPIC based robots ' Set pblsb '= 255 Return Aftertouch: ' 'this is the channel aftertouch, affecting all notes ' Set aft '= 255 'not mandatory Return Controller: Select Ctrl Case 66 'on/off for the robot If value = 0 Then Clear PowerOn 'CC66.0 Clear X15_3 ' relay off GoSub AllNotesOff Else Set PowerOn 'CC66.0 Set X15_3 ' relay ON EndIf Case 123 GoSub AllNotesOff End Select Set Ctrl '= 255 'mandatory reset Return AllNotesOff: Clear VelFlags0 HPWM 1, 0, fPWM ' connected to RC2 HPWM 2, 0, fPWM ' connected to RC1 Clear X11_2 Clear X11_3 Clear Lites Clear X12_2 Clear X12_3 Clear X15_2 Return Task0: If Lites.0 = 0 Then Clear VelFlags0.0 'stop task, as lite is switched off Clear X11_2 '= 0 Else 'reload task0 - light 'Set VelFlags0.0 'can just stay set Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[0] 'add the period duration Velmsb[0] = veltim.Word1 VelLsb[0] = veltim.Word0 btg X11_2 'Toggle EndIf Return Task1: If Lites.1 = 0 Then Clear VelFlags0.1 'stop task, as lite is switched off Clear X11_3 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[1] 'add the period duration in Task_rsi[1] Velmsb[1] = veltim.Word1 VelLsb[1] = veltim.Word0 btg X11_3 EndIf Return Task2: If Lites.2 = 0 Then Clear VelFlags0.2 'stop task, as lite is switched off Clear X12_2 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[2] 'add the period duration Velmsb[2] = veltim.Word1 VelLsb[2] = veltim.Word0 btg X12_2 EndIf Return Task3: If Lites.3 = 0 Then Clear VelFlags0.3 'stop task, as lite is switched off Clear X12_3 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[3] 'add the period duration Velmsb[3] = veltim.Word1 VelLsb[3] = veltim.Word0 btg X12_3 EndIf Return Task4: If Lites.4 = 0 Then Clear VelFlags0.4 'stop task, as lite is switched off Clear X15_2 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[4] 'add the period duration Velmsb[4] = veltim.Word1 VelLsb[4] = veltim.Word0 btg X15_2 EndIf Return Dur_Lookup: 'this lookup is for a good scaling of the velocity byte on event periodicity ' the values are calculated based on a timer resolution of 24 microseconds. ' The values must be containable in a word (16 bits!) ' This is the simple Power Basic program wherewith the lookup was calculated: 'FUNCTION PBMAIN ()AS LONG ' OPEN "Whisper_Dur_scales.inc" FOR OUTPUT AS #1 ' LOCAL unit, fastest, slowest, velo_traject AS DOUBLE ' LOCAL velo, i AS DWORD ' unit = 0.000024 ' in seconds (24 microseconds) ' fastest = 1 / 16 ' 16 Hz ' slowest = 1.5 ' 0.66 Hz ' velo_traject = slowest - fastest ' PRINT# 1, "Lookup for Whisper durations in periodic events" ' FOR i = 1 TO 127 ' velo = velo_traject / i ' PRINT i; velo, ' PRINT# 1 ,"Dur[";i;"] ="; velo ' NEXT i 'DO: LOOP UNTIL INKEY$ <> "" 'END FUNCTION Dur[ 1 ] = 59896 Dur[ 2 ] = 29948 Dur[ 3 ] = 19965 Dur[ 4 ] = 14974 Dur[ 5 ] = 11979 Dur[ 6 ] = 9983 Dur[ 7 ] = 8557 Dur[ 8 ] = 7487 Dur[ 9 ] = 6655 Dur[ 10 ] = 5990 Dur[ 11 ] = 5445 Dur[ 12 ] = 4991 Dur[ 13 ] = 4607 Dur[ 14 ] = 4278 Dur[ 15 ] = 3993 Dur[ 16 ] = 3743 Dur[ 17 ] = 3523 Dur[ 18 ] = 3328 Dur[ 19 ] = 3152 Dur[ 20 ] = 2995 Dur[ 21 ] = 2852 Dur[ 22 ] = 2723 Dur[ 23 ] = 2604 Dur[ 24 ] = 2496 Dur[ 25 ] = 2396 Dur[ 26 ] = 2304 Dur[ 27 ] = 2218 Dur[ 28 ] = 2139 Dur[ 29 ] = 2065 Dur[ 30 ] = 1997 Dur[ 31 ] = 1932 Dur[ 32 ] = 1872 Dur[ 33 ] = 1815 Dur[ 34 ] = 1762 Dur[ 35 ] = 1711 Dur[ 36 ] = 1664 Dur[ 37 ] = 1619 Dur[ 38 ] = 1576 Dur[ 39 ] = 1536 Dur[ 40 ] = 1497 Dur[ 41 ] = 1461 Dur[ 42 ] = 1426 Dur[ 43 ] = 1393 Dur[ 44 ] = 1361 Dur[ 45 ] = 1331 Dur[ 46 ] = 1302 Dur[ 47 ] = 1274 Dur[ 48 ] = 1248 Dur[ 49 ] = 1222 Dur[ 50 ] = 1198 Dur[ 51 ] = 1174 Dur[ 52 ] = 1152 Dur[ 53 ] = 1130 Dur[ 54 ] = 1109 Dur[ 55 ] = 1089 Dur[ 56 ] = 1070 Dur[ 57 ] = 1051 Dur[ 58 ] = 1033 Dur[ 59 ] = 1015 Dur[ 60 ] = 998 Dur[ 61 ] = 982 Dur[ 62 ] = 966 Dur[ 63 ] = 951 Dur[ 64 ] = 936 Dur[ 65 ] = 921 Dur[ 66 ] = 908 Dur[ 67 ] = 894 Dur[ 68 ] = 881 Dur[ 69 ] = 868 Dur[ 70 ] = 856 Dur[ 71 ] = 844 Dur[ 72 ] = 832 Dur[ 73 ] = 820 Dur[ 74 ] = 809 Dur[ 75 ] = 799 Dur[ 76 ] = 788 Dur[ 77 ] = 778 Dur[ 78 ] = 768 Dur[ 79 ] = 758 Dur[ 80 ] = 749 Dur[ 81 ] = 739 Dur[ 82 ] = 730 Dur[ 83 ] = 722 Dur[ 84 ] = 713 Dur[ 85 ] = 705 Dur[ 86 ] = 696 Dur[ 87 ] = 688 Dur[ 88 ] = 681 Dur[ 89 ] = 673 Dur[ 90 ] = 666 Dur[ 91 ] = 658 Dur[ 92 ] = 651 Dur[ 93 ] = 644 Dur[ 94 ] = 637 Dur[ 95 ] = 630 Dur[ 96 ] = 624 Dur[ 97 ] = 617 Dur[ 98 ] = 611 Dur[ 99 ] = 605 Dur[ 100 ] = 599 Dur[ 101 ] = 593 Dur[ 102 ] = 587 Dur[ 103 ] = 582 Dur[ 104 ] = 576 Dur[ 105 ] = 570 Dur[ 106 ] = 565 Dur[ 107 ] = 560 Dur[ 108 ] = 555 Dur[ 109 ] = 550 Dur[ 110 ] = 545 Dur[ 111 ] = 540 Dur[ 112 ] = 535 Dur[ 113 ] = 530 Dur[ 114 ] = 525 Dur[ 115 ] = 521 Dur[ 116 ] = 516 Dur[ 117 ] = 512 Dur[ 118 ] = 508 Dur[ 119 ] = 503 Dur[ 120 ] = 499 Dur[ 121 ] = 495 Dur[ 122 ] = 491 Dur[ 123 ] = 487 Dur[ 124 ] = 483 Dur[ 125 ] = 479 Dur[ 126 ] = 475 Dur[ 127 ] = 472 Return '[EOF]