' ******************************************************************** ' * PIC firmware for * ' * beater solenoids * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/tubo/picworks * ' * source code development directory: * ' * Tubo_beat4865.bas * ' ******************************************************************** ' 24.09.2019: Starting from the code for the damper board and using the ' plain vanilla irq coding. ' This code is for the 18-output PCB, made for tubo. ' 25.09.2019: Version 1.0 ready. ' to do: block note on if timer still active. ' need notes flags to do this fast. ' 26.09.2019: Dur[] lookup changed. ' note-on blocking implemented. ' Firmware loaded in board. ' we could also implement a duty cycle protection by ' implementing wait-timers after time-out of the on-pulses. ' 29.09.2019: first testing with all hardware connected. ' Velo pulstimes need to be taken a lot shorter! ' divided by 8, the range becomes 3.75ms to 18.75ms ' With this scaling, the anchors start to move at velo=30 ' The traject for striking is sufficient from 64 on ' The end-positions are reached with value 79 ' 127 gives a quite strong hit. ' It's clear we have to calculate a new lookup table... ' 01.12.2019: New lookup tables prepared. ' such that velo = 32 gives p (76dBA) for all notes on tubo ' and velo = 64 fives f (90dBA) for all notes on tubo. ' We can add more refinement by creating 3 lookups, one for each group of 6 notes/tube diameters. ' Implemented, but for now, the three lookups are identical. ' 02.12.2019: 3 different lookups implemented and based on dbA measurements. ' velo 32 = 76dBA ' velo 64 = 90dBA ' velo 96 = 102dBA Include "18F4620.inc" ' (40MHz) ' Mapping defines for midi-events on pin outputs and inputs: ' This is very specific for the 26 output board 2017 ' mapping: $define Beat48 PORTA.0 $define Beat49 PORTA.1 $define Beat50 PORTA.2 $define Beat51 PORTA.3 $define Beat52 PORTA.4 $define Beat53 PORTA.5 $define Beat54 PORTE.0 ' - pin8 $define Beat55 PORTE.1 $define Beat56 PORTE.2 $define Beat57 PORTC.0 $define Beat58 PORTC.1 $define Beat59 PORTC.2 $define Beat60 PORTC.3 $define Beat61 PORTD.0 $define Beat62 PORTD.1 $define Beat63 PORTD.7 $define Beat64 PORTD.6 $define Beat65 PORTD.5 $define Sol19 PORTD.4 ' nc $define Sol20 PORTC.5 $define Sol21 PORTC.4 $define Sol22 PORTD.3 $define Sol23 PORTD.2 $define Sol24 PORTB.0 $define Sol25 PORTB.1 $define Sol26 PORTB.2 $define Loopspeed PORTB.4 ' for loopspeed measurement 'red LED for debug: $define Debug_Led PORTB.3 ' for testing - red led - watchdog - activated in IRQ code. 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 = 48 ' tubo Symbol Hightes = 65 ' for this board! 'initialisations for the midi input parser: Symbol Midichannel = 4 ' Tubo_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 = 18 ' 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... ' switched on 22.09.2019 ' 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 'make an alias, to avoid having to copy a dword in the main loop. Dim Cnt3 As Dword System Dim Cnt3Hw As Cnt3.Word1 Dim Tim3 As TMR3L.Word ' same trick for timer3 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 Nxt As Dword System Dim idx 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 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 ' 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 CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim MidiIn As Byte System Dim IndexIn As Byte System ' Pointer to the next empty location in the buffer Dim IndexOut As Byte System ' Pointer to the location of the oldest character in the buffer Dim Ringbuffer[256] As Byte ' Array for holding received midi messages Dim TimVals[NrTasks] As Dword Dim Resort As Byte System Dim Resort_flag As Resort.0 ' flag to signal the requirement to resort timers Dim notes As Dword ' flags only: notes.0 to notes.17 Dim Dur0[128] As Word ' for valve pulsing notes 48-53 Dim Dur1[128] As Word ' for valve pulsing notes 54- 59 Dim Dur2[128] As Word ' for valve pulsing notes 60 - 65 Dim stap As Float ' for lookup calculation Dim tmp As Float '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Include "Tubo_Damp_Irq_000.inc" ' this is the newest plain-basic version. 'Clear ' clear all RAM '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High Debug_Led DelayMS 10 ' wait for stability Low Debug_Led Low Beat48 Low Beat49 Low Beat50 Low Beat51 Low Beat52 Low Beat53 Low Beat54 Low Beat55 Low Beat56 Low Beat57 Low Beat58 Low Beat59 Low Beat60 Low Beat61 Low Beat62 Low Beat63 Low Beat64 Low Beat65 Low Sol19 Low Sol20 Low Sol21 Low Sol22 Low Sol23 Low Sol24 Low Sol25 Low Sol26 GoSub Dur_Lookup Set idx Set TimVals Clear CC66 GoSub Init_Usart_Interrupt ' Initiate the USART serial buffer interrupt ' this procedure is in the include file GoSub 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 ' 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 PIE1bits_RCIE ' disable/enable interrupt for USART receive Clear notes HRSOut Ctrl, 25,64 ' crucial for the code to work.... ' start the main program loop: Hoofdlus: ' Create an infinite loop Do 'looptimer version: ' Inc t ' byte ' If t.1 = tg Then ' Btg tg ' Inc time ' dword ' EndIf 'timer0 version: Cnt.Word0 = CntLw ' read timer 0 'time = Cnt ' make copy (dword!) - better declare time as an alias for Cnt GetMidiIn () ' we cannot create functions returning values in Proton... Bytein = MidiIn ' this function is defined in _irq.inc ' 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. 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 48 ' clear timer Clear Beat48 Set TimVals[0] Clear notes.0 Set Resort_flag Case 49 Clear Beat49 Set TimVals[1] Clear notes.1 Set Resort_flag Case 50 Clear Beat50 Set TimVals[2] Clear notes.2 Set Resort_flag Case 51 Clear Beat51 Set TimVals[3] Clear notes.3 Set Resort_flag Case 52 Clear Beat52 Set TimVals[4] Clear notes.4 Set Resort_flag Case 53 Clear Beat53 Set TimVals[5] Clear notes.5 Set Resort_flag Case 54 Clear Beat54 Set TimVals[6] Clear notes.6 Set Resort_flag Case 55 Clear Beat55 Set TimVals[7] Clear notes.7 Set Resort_flag Case 56 Clear Beat56 Set TimVals[8] Clear notes.8 Set Resort_flag Case 57 Clear Beat57 Set TimVals[9] Clear notes.9 Set Resort_flag Case 58 Clear Beat58 Set TimVals[10] Clear notes.10 Set Resort_flag Case 59 Clear Beat59 Set TimVals[11] Clear notes.11 Set Resort_flag Case 60 Clear Beat60 Set TimVals[12] Clear notes.12 Set Resort_flag Case 61 Clear Beat61 Set TimVals[13] Clear notes.13 Set Resort_flag Case 62 Clear Beat62 Set TimVals[14] Clear notes.14 Set Resort_flag Case 63 Clear Beat63 Set TimVals[15] Clear notes.15 Set Resort_flag Case 64 Clear Beat64 Set TimVals[16] Clear notes.16 Set Resort_flag Case 65 Clear Beat65 Set TimVals[17] Clear notes.17 Set Resort_flag 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 48 ' clear timer Clear Beat48 Set TimVals[0] Clear notes.0 Set Resort_flag Case 49 Clear Beat49 Set TimVals[1] Clear notes.1 Set Resort_flag Case 50 Clear Beat50 Set TimVals[2] Clear notes.2 Set Resort_flag Case 51 Clear Beat51 Set TimVals[3] Clear notes.3 Set Resort_flag Case 52 Clear Beat52 Set TimVals[4] Clear notes.4 Set Resort_flag Case 53 Clear Beat53 Set TimVals[5] Clear notes.5 Set Resort_flag Case 54 Clear Beat54 Set TimVals[6] Clear notes.6 Set Resort_flag Case 55 Clear Beat55 Set TimVals[7] Clear notes.7 Set Resort_flag Case 56 Clear Beat56 Set TimVals[8] Clear notes.8 Set Resort_flag Case 57 Clear Beat57 Set TimVals[9] Clear notes.9 Set Resort_flag Case 58 Clear Beat58 Set TimVals[10] Clear notes.10 Set Resort_flag Case 59 Clear Beat59 Set TimVals[11] Clear notes.11 Set Resort_flag Case 60 Clear Beat60 Set TimVals[12] Clear notes.12 Set Resort_flag Case 61 Clear Beat61 Set TimVals[13] Clear notes.13 Set Resort_flag Case 62 Clear Beat62 Set TimVals[14] Clear notes.14 Set Resort_flag Case 63 Clear Beat63 Set TimVals[15] Clear notes.15 Set Resort_flag Case 64 Clear Beat64 Set TimVals[16] Clear notes.16 Set Resort_flag Case 65 Clear Beat65 Set TimVals[17] Clear notes.17 Set Resort_flag End Select Else Select noteAan Case 48 ' if a beater is still active, we refuse to strike it again. If notes.0 = 0 Then ' burn out protection... Set Beat48 TimVals[0] = time + Dur0[velo] Set Resort_flag Set notes.0 EndIf Case 49 If notes.1 = 0 Then Set Beat49 TimVals[1] = time + Dur0[velo] Set Resort_flag Set notes.1 EndIf Case 50 If notes.2 = 0 Then Set Beat50 TimVals[2] = time + Dur0[velo] Set Resort_flag Set notes.2 EndIf Case 51 If notes.3 = 0 Then Set Beat51 TimVals[3] = time + Dur0[velo] Set Resort_flag Set notes.3 EndIf Case 52 If notes.4 = 0 Then Set Beat52 TimVals[4] = time + Dur0[velo] Set Resort_flag Set notes.4 EndIf Case 53 If notes.5 = 0 Then Set Beat53 TimVals[5] = time + Dur0[velo] Set Resort_flag Set notes.5 EndIf Case 54 If notes.6 = 0 Then Set Beat54 TimVals[6] = time + Dur1[velo] Set Resort_flag Set notes.6 EndIf Case 55 If notes.7 =0 Then Set Beat55 TimVals[7] = time + Dur1[velo] Set Resort_flag Set notes.7 EndIf Case 56 If notes.8 = 0 Then Set Beat56 TimVals[8] = time + Dur1[velo] Set Resort_flag Set notes.8 EndIf Case 57 If notes.9 = 0 Then Set Beat57 TimVals[9] = time + Dur1[velo] Set Resort_flag Set notes.9 EndIf Case 58 If notes.10 = 0 Then Set Beat58 TimVals[10]= time + Dur1[velo] Set Resort_flag Set notes.10 EndIf Case 59 If notes.11 = 0 Then Set Beat59 TimVals[11]= time + Dur1[velo] Set Resort_flag Set notes.11 EndIf Case 60 If notes.12 = 0 Then Set Beat60 TimVals[12]= time + Dur2[velo] Set Resort_flag Set notes.12 EndIf Case 61 If notes.13 = 0 Then Set Beat61 TimVals[13] = time + Dur2[velo] Set Resort_flag Set notes.13 EndIf Case 62 If notes.14 = 0 Then Set Beat62 TimVals[14] = time + Dur2[velo] Set Resort_flag Set notes.14 EndIf Case 63 If notes.15 = 0 Then Set Beat63 TimVals[15] = time + Dur2[velo] Set Resort_flag Set notes.15 EndIf Case 64 If notes.16 = 0 Then Set Beat64 TimVals[16]= time + Dur2[velo] Set Resort_flag Set notes.16 EndIf Case 65 If notes.17 = 0 Then Set Beat65 TimVals[17] = time + Dur2[velo] Set Resort_flag Set notes.17 EndIf End Select Set noteAan 'reset !!! EndIf EndIf Case Keypres_Status 'could be used for lite flashing 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 EndIf Case ProgChange_Status ' could be used to select alternative fingering lookups If prog = 255 Then 'single byte message prog = Bytein GoSub ProgChange ' should not happen when a note is playing! 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 ' clear notes.idx dit slikt de compiler niet... Select idx Case 0 Clear Beat48 Set TimVals[0] Clear notes.0 Case 1 Clear Beat49 Set TimVals[1] Clear notes.1 Case 2 Clear Beat50 Set TimVals[2] Clear notes.2 Case 3 Clear Beat51 Set TimVals[3] Clear notes.3 Case 4 Clear Beat52 Set TimVals[4] Clear notes.4 Case 5 Clear Beat53 Set TimVals[5] Clear notes.5 Case 6 Clear Beat54 Set TimVals[6] Clear notes.6 Case 7 Clear Beat55 Set TimVals[7] Clear notes.7 Case 8 Clear Beat56 Set TimVals[8] Clear notes.8 Case 9 Clear Beat57 Set TimVals[9] Clear notes.9 Case 10 Clear Beat58 Set TimVals[10] Clear notes.10 Case 11 Clear Beat59 Set TimVals[11] Clear notes.11 Case 12 Clear Beat60 Set TimVals[12] Clear notes.12 Case 13 Clear Beat61 Set TimVals[13] Clear notes.13 Case 14 Clear Beat62 Set TimVals[14] Clear notes.14 Case 15 Clear Beat63 Set TimVals[15] Clear notes.15 Case 16 Clear Beat64 Set TimVals[16] Clear notes.16 Case 17 Clear Beat65 Set TimVals[17] Clear notes.17 Case Else ' in dit geval is idx geset GoTo Jumpout ' no need to resort 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 ' also clears time, as it's an alias. Set TimVals Clear notes EndIf EndIf Jumpout: ' here we can insert a bit toggle command to measure the loop speed Btg Loopspeed ' with no midi coming in, the square wave frequency measured here is 111kHz ' thus the idle loop time is 10 microseconds ' with fast midi in, the loop time becomes 102kHz ' Measurements taken with Tektronix TDS2024C oscilloscope. (200MHz, 2GS/s) ' end of the main loop 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 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 ' ' EndSelect Set prog 'this is not realy required Return Pitchbend: 'only implemented on dsPIC based robots, irrelevant here Set pblsb '= 255 Return Aftertouch: 'this is the channel aftertouch, affecting any playing note Set aft ' reset Return Controller: Select Ctrl 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 ' we could also implement a more refined power-on ' by using a specific robot ID here. Case 123 ' clear all output ports used: Set TimVals Low Beat48 Low Beat49 Low Beat50 Low Beat51 Low Beat52 Low Beat53 Low Beat54 Low Beat55 Low Beat56 Low Beat57 Low Beat58 Low Beat59 Low Beat60 Low Beat61 Low Beat62 Low Beat63 Low Beat64 Low Beat65 Clear notes Set Resort_flag End Select Set Ctrl 'mandatory reset Return PowerDown: 'stop all running timers Set TimVals Low Beat48 Low Beat49 Low Beat50 Low Beat51 Low Beat52 Low Beat53 Low Beat54 Low Beat55 Low Beat56 Low Beat57 Low Beat58 Low Beat59 Low Beat60 Low Beat61 Low Beat62 Low Beat63 Low Beat64 Low Beat65 Clear notes Return Dur_Lookup: ' Noten 48 tot 53, buizen 60mm ' 01.12.2019: [ opgemeten met noot 53] ' 02.12.2019: opnieuw opgemeten ' distributie met drie vaste meetpunten. Dur0[1] = 280 ' minimum waarde Dur0[32] = 481 ' nieuwe waarde voor 76dBA (bereikt met oude velo = 28) Dur0[64] = 646 ' nieuwe waarde voor 90dBA (bereikt met oude velo = 51) Dur0[96] = 976 ' nieuwe waarde voor 102dBA Dur0[127] = 1057 ' maximum waarde ' en nu lineair interpolleren: stap = (Dur0[32] - Dur0[1]) / 32.0 For i = 2 To 31 ' ppp tot p tmp = (stap * i) + Dur0[1] Dur0[i] = tmp Next i stap = (Dur0[64] - Dur0[32]) / 32.0 For i = 33 To 63 ' p tot f tmp = (stap * (i- 32)) + Dur0[32] Dur0[i] = tmp Next i stap = (Dur0[96] - Dur0[64]) / 32.0 For i = 65 To 95 ' f tot ff tmp = (stap * (i- 64)) + Dur0[64] Dur0[i] = tmp Next i stap = (Dur0[127] - Dur0[96]) / 32.0 For i = 97 To 126 ' ff tot fff tmp = (stap * (i- 96)) + Dur0[96] Dur0[i] = tmp Next i ' lookup voor 54-59: ' 02.12.2019 : opgemeten ' distributie met drie vaste meetpunten. Dur1[1] = 280 ' minimum waarde Dur1[32] = 481 ' nieuwe waarde voor 76dBA Dur1[64] = 646 ' nieuwe waarde voor 90dBA Dur1[96] = 914 ' voor 102dBA Dur1[127] = 1040 ' maximum waarde ' en nu lineair interpolleren: stap = (Dur1[32] - Dur1[1]) / 32.0 For i = 2 To 31 ' ppp tot p tmp = (stap * i) + Dur1[1] Dur1[i] = tmp Next i stap = (Dur1[64] - Dur1[32]) / 32.0 For i = 33 To 63 ' p tot f tmp = (stap * (i- 32)) + Dur1[32] Dur1[i] = tmp Next i stap = (Dur1[96] - Dur1[64]) / 32.0 For i = 65 To 95 ' f tot ff tmp = (stap * (i- 64)) + Dur1[64] Dur1[i] = tmp Next i stap = (Dur1[127] - Dur1[96]) / 32.0 For i = 97 To 126 ' f tot fff tmp = (stap * (i- 96)) + Dur1[96] Dur1[i] = tmp Next i ' lookup voor 60-65: (aluminium buizen 50mm diameter) ' distributie met drie vaste meetpunten. (02.12.2019) ' as we changed the beaters, this has to be measured again now! Dur2[1] = 280 ' minimum waarde Dur2[32] = 481 ' nieuwe waarde voor 76dBA Dur2[64] = 646 ' nieuwe waarde voor 90dBA Dur2[96] = 772 ' nieuwe waarde voor 102dBA Dur2[127] = 980 ' maximum waarde ' en nu lineair interpolleren: stap = (Dur2[32] - Dur2[1]) / 32.0 For i = 2 To 31 ' ppp tot p tmp = (stap * i) + Dur2[1] Dur2[i] = tmp Next i stap = (Dur2[64] - Dur2[32]) / 32.0 For i = 33 To 63 ' p tot f tmp = (stap * (i- 32)) + Dur2[32] Dur2[i] = tmp Next i stap = (Dur2[96] - Dur2[64]) / 32.0 For i = 65 To 95 ' f tot ff tmp = (stap * (i- 64)) + Dur2[64] Dur2[i] = tmp Next i stap = (Dur2[127] - Dur2[96]) / 32.0 For i = 97 To 126 ' ff tot fff tmp = (stap * (i- 96)) + Dur2[96] Dur2[i] = tmp Next i Return '[EOF]