' ******************************************************************** ' * PIC firmware for * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/pianet/picworks * ' * source code development directory: * ' * Pianet_PH.bas * ' ******************************************************************** ' This board can be operated on high pulse/velo voltages, limited only by ' the specs of the mosfets used. ' 08.08.2014: code adapted to new 12 output pulse hold board. - for Zi ' --------------------------------------------------------------------- ' 01.08.2018: Start recoding for Version 1.0 ' --------------------------------------------------------------------- ' 07.04.2021: Start coding for the low windchest on the robot. ' use tmr0 for timers, not loopcount. ' 08.04.2021: Repeats implemented, same way as on the 14-note boards now. ' 09.04.2021: Program change implemented for registration ' bit 0 in the patch could switch these pipes on or off. ' 13.04.2021: Register implemented. This board uses only bit0 = pedal. ' 03.05.2021: checked for consistency with the firmware on the other boards. ' note repetitions added and tested. ' 04.05.2021: Measurement of velo pulses: ' velo 1 = 7.5 ms ' velo 127 = 38 ms ' 1 unit = 25us ' Note that note36 and 47 use a Banggood solenoid, ' all other notes are served with Laukhuff pallet valves. ' If we want note repetitions up to 16 notes / s possible, ' the velocity pulse durations have to be kept below 31 ms. ' Lookup for note repetitions recalculated and made logarithmic ' Now the range is 2Hz to 14Hz (measured) (2Hz to 16Hz calculated) ' lookup calculated in PBCC. '----------------------------------------------------------------------------- '03.12.2021: Start adapting code to requirements for ' This robot uses 5 boards! (60 notes) ' mappings added and conditional compiles implemented for 5 boards ' The pedal code and prog. change code added for can be removed here. '05.12.2021: Further work. '08.12.2021: Code tested on board 1. Works o.k. at first sight, with a single solenoid ' connected. ' We use the player piano test code here. ' controller 30 voor global repetition rate. ' All five board programmed with version 1.0 ' Velo range is now 8ms to 38ms '16.12.2021: Boards 2-5 work,board 1 fails... '17.12.2021: Board 1 reprogrammed on the robot. The failure was not the code nor the programming ' but a bad solderjoint on the board. '18.12.2021: Now we set the hold and the velo at the same time on reception of a note-on. ' In the timer, we now only have to clear the velo-bit. ' The hardware diodes protect against power supply shorts now. ' Doing things this way, should reduce glitches. ' Individual lookup for every note implemented. ' to do: fill in data for the tables and add metacompiler statements ' to enable different sets of lookups for each board. ' All five PIC's programmed and tested o.k. Lookups to be done. ' Video of the working robot posted on Facebook. ' Thoroughly checked on the oscilloscope. Disfunctional velo/hold signals now must be ' due to hardware. Loopspeed is between 95 and 128 kHz. '19.12.2021: Hold voltage raised to 10V ' Velocity range changed to 3.8 ms to 10 ms, a reasonable compromise. ' Different lookups for each board implemented. ' This be version 1.2 - source code renamed to Pianet_PH.bas '20.12.2021: For research and alignment reasons, it would be a good idea to implement velo=1 as ' hold voltage only. Velo=0 cannot be used as it means note-off. ' ---------------------------------------------------------------------------------------------- '26.01.2022: New board designed with soft release on the hold signal. ' with hardware RC = 47nF+1.5nF(gate capacitance) and 1M, we get an RC time of 50ms. ' To be tested on the scope and with a solenoid connected. '07.02.2022: Testboard programmed. 50ms appears to be way too slow: note repeats faster than 8 notes/second ' become problematic. Let's try 22nF + 1.5nF and 1M, yielding 23.5ms ' 10nF+1.5nF gives 11.5ms '08.02.2022: We should use the formula t = -(ln(1- p) * RC) ' ---------------------------------------------------------------------------------------------- '30.01.2024: We can speed things up a bit, by filtering-out the noteOn with velo=0 cases. Include "18F4620.inc" ' (40MHz) ' defines for conditional compilation $define board1 '$define board2 '$define board3 '$define board4 '$define board5 ' Mapping defines for midi-events on pin outputs and inputs: ' This is very specific for the High Voltage Pulse/Hold board ' mapping: $define Note00_Hold PORTA.0 $define Note00_Velo PORTA.1 $define Note01_Hold PORTA.2 $define Note01_Velo PORTA.3 $define Note02_Hold PORTA.4 $define Note02_Velo PORTA.5 $define Note03_Hold PORTE.0 $define Note03_Velo PORTE.1 $define Note04_Hold PORTE.2 $define Note04_Velo PORTC.0 $define Note05_Hold PORTC.1 ' PWM - hpwm2 $define Note05_Velo PORTC.2 ' pwm - hpwm1 $define Note06_Hold PORTC.3 $define Note06_Velo PORTD.0 $define Note07_Hold PORTD.1 $define Note07_Velo PORTD.7 $define Note08_Hold PORTD.6 $define Note08_Velo PORTD.5 $define Note09_Hold PORTD.4 $define Note09_Velo PORTC.5 $define Note10_Hold PORTC.4 $define Note10_Velo PORTD.3 $define Note11_Hold PORTD.2 $define Note11_Velo PORTB.0 'red LED for debug: $define Debug_Led PORTB.3 ' for testing - red led - watchdog - used in IRQ $define Green_Led PORTB.1 ' PH12 board - CC66 $define Loopspeed PORTB.4 ' free: PORTB.2, B.5, B.6, B.7 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: ' with conditional compile statements for the 5 boards: $ifdef board1 Symbol Note0 = 29 Symbol Note1 = 30 Symbol Note2 = 31 Symbol Note3 = 32 Symbol Note4 = 33 Symbol Note5 = 34 Symbol Note6 = 35 Symbol Note7 = 36 Symbol Note8 = 37 Symbol Note9 = 38 Symbol Note10 = 39 Symbol Note11 = 40 $endif $ifdef board2 Symbol Note0 = 41 Symbol Note1 = 42 Symbol Note2 = 43 Symbol Note3 = 44 Symbol Note4 = 45 Symbol Note5 = 46 Symbol Note6 = 47 Symbol Note7 = 48 Symbol Note8 = 49 Symbol Note9 = 50 Symbol Note10 = 51 Symbol Note11 = 52 $endif $ifdef board3 Symbol Note0 = 53 Symbol Note1 = 54 Symbol Note2 = 55 Symbol Note3 = 56 Symbol Note4 = 57 Symbol Note5 = 58 Symbol Note6 = 59 Symbol Note7 = 60 Symbol Note8 = 61 Symbol Note9 = 62 Symbol Note10 = 63 Symbol Note11 = 64 $endif $ifdef board4 Symbol Note0 = 65 Symbol Note1 = 66 Symbol Note2 = 67 Symbol Note3 = 68 Symbol Note4 = 69 Symbol Note5 = 70 Symbol Note6 = 71 Symbol Note7 = 72 Symbol Note8 = 73 Symbol Note9 = 74 Symbol Note10 = 75 Symbol Note11 = 76 $endif $ifdef board5 Symbol Note0 = 77 Symbol Note1 = 78 Symbol Note2 = 79 Symbol Note3 = 80 Symbol Note4 = 81 Symbol Note5 = 82 Symbol Note6 = 83 Symbol Note7 = 84 Symbol Note8 = 85 Symbol Note9 = 86 Symbol Note10 = 87 Symbol Note11 = 88 $endif 'initialisations for the midi input parser: Symbol Midichannel = 0 ' Pianet_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 '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 CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim time As Cnt ' 32-bit alias for Cnt Dim maxtim As time.31 ' overflow bit, will cause timer reset after 1h45 Dim TimVals[12] As Dword ' lijst met timer waarden - de kleinste is eerst aan de beurt Dim Nxt As Dword System ' waarde voor de eerstvolgende timer Dim idx As Byte System ' index voor de eerstvolgende timer Dim Velflags As Word System ' so we can have only 16 tasks Dim Holdflags As Word System ' added 24.01.2016 Dim Waitflags As Word System Dim notes As Word System ' for note repetition mechanism Dim flags As Byte System Dim resort_flag As flags.0 Dim velo0 As Word System Dim velo1 As Word System Dim velo2 As Word System Dim velo3 As Word System Dim velo4 As Word System Dim velo5 As Word System Dim velo6 As Word System Dim velo7 As Word System Dim velo8 As Word System Dim velo9 As Word System Dim velo10 As Word System Dim velo11 As Word System Dim Rate0 As Word ' set with key pressure Dim Rate1 As Word Dim Rate2 As Word Dim Rate3 As Word Dim Rate4 As Word Dim Rate5 As Word Dim Rate6 As Word Dim Rate7 As Word Dim Rate8 As Word Dim Rate9 As Word Dim Rate10 As Word Dim Rate11 As Word Dim Pres0 As Byte 'indexes for durations lookup Dim Pres1 As Byte Dim Pres2 As Byte Dim Pres3 As Byte Dim Pres4 As Byte Dim Pres5 As Byte Dim Pres6 As Byte Dim Pres7 As Byte Dim Pres8 As Byte Dim Pres9 As Byte Dim Pres10 As Byte Dim Pres11 As Byte '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Dim Ringbuffer[256] As Byte ' Array for holding received characters Include "Pianet_PH_Irq.inc" ' for UART,Timer0, Timer3 Interrupt Dim Vel0[128] As Word Dim Vel1[128] As Word Dim Vel2[128] As Word Dim Vel3[128] As Word Dim Vel4[128] As Word Dim Vel5[128] As Word Dim Vel6[128] As Word Dim Vel7[128] As Word Dim Vel8[128] As Word Dim Vel9[128] As Word Dim Vel10[128] As Word Dim Vel11[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 Low Note11_Hold Low Note11_Velo Low Note10_Hold Low Note10_Velo Low Note09_Hold Low Note09_Velo Low Note08_Hold Low Note08_Velo Low Note07_Hold Low Note07_Velo Low Note06_Hold Low Note06_Velo Low Note05_Hold Low Note05_Velo Low Note04_Hold Low Note04_Velo Low Note03_Hold Low Note03_Velo Low Note02_Hold Low Note02_Velo Low Note01_Hold Low Note01_Velo Low Note00_Hold Low Note00_Velo Clear CC66 Low Green_Led Set idx Set TimVals ' no timers running on startup Clear Rate0 Clear Rate1 Clear Rate2 Clear Rate3 Clear Rate4 Clear Rate5 Clear Rate6 Clear Rate7 Clear Rate8 Clear Rate9 Clear Rate10 Clear Rate11 Clear Pres0 Clear Pres1 Clear Pres2 Clear Pres3 Clear Pres4 Clear Pres5 Clear Pres6 Clear Pres7 Clear Pres8 Clear Pres9 Clear Pres10 Clear Pres11 Clear notes Clear Velflags Clear Waitflags Clear Holdflags 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 Clear PIE2BITS_TMR3IE ' irq OFF for pianet ' 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 = %10110000 ' for pianet, we disable this timer ' 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 $ifdef board1 GoSub Vels_Lookup $endif $ifdef board2 GoSub Vels_Lookup $endif $ifdef board3 GoSub Vels_Lookup $endif $ifdef board4 GoSub Vels_Lookup $endif $ifdef board5 GoSub Vels_Lookup $endif HRSOut Midichannel, 66, 89 ' dummy ' start the main program loop: Do ' Create an infinite loop Cnt.Word0 = CntLw ' read timer 0 Bytein = GetMidiIn () ' 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. 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 Set velo 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 ' not implemented here ' statusbyte = Bytein ' Set aft ' Case Pitchbend_Status ' not on this board. ' statusbyte = Bytein ' Set pblsb ' Set pbmsb EndSelect 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... Set resort_flag Select noteUit Case Note0 Clear Note00_Hold Clear Note00_Velo Set TimVals[0] Clear Velflags.0 ' cancel running velo timer Clear notes.0 ' cancel note repetitions Clear Holdflags.0 Clear Waitflags.0 Case Note1 Clear Note01_Hold Clear Note01_Velo Set TimVals[1] Clear Velflags.1 ' cancel running velo timer Clear notes.1 ' cancel note repetitions Clear Holdflags.1 Clear Waitflags.1 Case Note2 Clear Note02_Hold Clear Note02_Velo Set TimVals[2] Clear Velflags.2 ' cancel running velo timer Clear notes.2 ' cancel note repetitions Clear Holdflags.2 Clear Waitflags.2 Case Note3 Clear Note03_Hold Clear Note03_Velo Set TimVals[3] Clear Velflags.3 ' cancel running velo timer Clear notes.3 ' cancel note repetitions Clear Holdflags.3 Clear Waitflags.3 Case Note4 Clear Note04_Hold Clear Note04_Velo Set TimVals[4] Clear Velflags.4 ' cancel running velo timer Clear notes.4 ' cancel note repetitions Clear Holdflags.4 Clear Waitflags.4 Case Note5 Clear Note05_Hold Clear Note05_Velo Set TimVals[5] Clear Velflags.5 ' cancel running velo timer Clear notes.5 ' cancel note repetitions Clear Holdflags.5 Clear Waitflags.5 Case Note6 Clear Note06_Hold Clear Note06_Velo Set TimVals[6] Clear Velflags.6 ' cancel running velo timer Clear notes.6 ' cancel note repetitions Clear Holdflags.6 Clear Waitflags.6 Case Note7 Clear Note07_Hold Clear Note07_Velo Set TimVals[7] Clear Velflags.7 ' cancel running velo timer Clear notes.7 ' cancel note repetitions Clear Holdflags.7 Clear Waitflags.7 Case Note8 Clear Note08_Hold Clear Note08_Velo Set TimVals[8] Clear Velflags.8 ' cancel running velo timer Clear notes.8 ' cancel note repetitions Clear Holdflags.8 Clear Waitflags.8 Case Note9 Clear Note09_Velo Clear Note09_Hold Set TimVals[9] Clear Velflags.9 ' cancel running velo timer Clear notes.9 ' cancel note repetitions Clear Holdflags.9 Clear Waitflags.9 Case Note10 Clear Note10_Hold Clear Note10_Velo Set TimVals[10] Clear Velflags.10 ' cancel running velo timer Clear notes.10 ' cancel note repetitions Clear Holdflags.10 Clear Waitflags.10 Case Note11 Clear Note11_Hold Clear Note11_Velo Set TimVals[11] Clear Velflags.11 ' cancel running velo timer Clear notes.11 ' cancel note repetitions Clear Holdflags.11 Clear Waitflags.11 Case Else 'Set noteUit Clear resort_flag 'GoTo Check_Timers EndSelect Set noteUit 'GoSub SortTimers EndIf 'GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein ' If velo = 0 Then ' we filter this out in the hub parser! ' Select noteAan ' Case Note0 ' Clear Note00_Hold ' Clear Note00_Velo ' Set TimVals[0] ' Clear Velflags.0 ' cancel running velo timer ' Clear notes.0 ' cancel note repetitions ' Clear Holdflags.0 ' Clear Waitflags.0 ' Case Note1 ' Clear Note01_Hold ' Clear Note01_Velo ' Set TimVals[1] ' Clear Velflags.1 ' cancel running velo timer ' Clear notes.1 ' cancel note repetitions ' Clear Holdflags.1 ' Clear Waitflags.1 ' Case Note2 ' Clear Note02_Hold ' Clear Note02_Velo ' Set TimVals[2] ' Clear Velflags.2 ' cancel running velo timer ' Clear notes.2 ' cancel note repetitions ' Clear Holdflags.2 ' Clear Waitflags.2 ' Case Note3 ' Clear Note03_Hold ' Clear Note03_Velo ' Set TimVals[3] ' Clear Velflags.3 ' cancel running velo timer ' Clear notes.3 ' cancel note repetitions ' Clear Holdflags.3 ' Clear Waitflags.3 ' Case Note4 ' Clear Note04_Hold ' Clear Note04_Velo ' Set TimVals[4] ' Clear Velflags.4 ' cancel running velo timer ' Clear notes.4 ' cancel note repetitions ' Clear Holdflags.4 ' Clear Waitflags.4 ' Case Note5 ' Clear Note05_Hold ' Clear Note05_Velo ' Set TimVals[5] ' Clear Velflags.5 ' cancel running velo timer ' Clear notes.5 ' cancel note repetitions ' Clear Holdflags.5 ' Clear Waitflags.5 ' Case Note6 ' Clear Note06_Hold ' Clear Note06_Velo ' Set TimVals[6] ' Clear Velflags.6 ' cancel running velo timer ' Clear notes.6 ' cancel note repetitions ' Clear Holdflags.6 ' Clear Waitflags.6 ' Case Note7 ' Clear Note07_Hold ' Clear Note07_Velo ' Set TimVals[7] ' Clear Velflags.7 ' cancel running velo timer ' Clear notes.7 ' cancel note repetitions ' Clear Holdflags.7 ' Clear Waitflags.7 ' Case Note8 ' Clear Note08_Hold ' Clear Note08_Velo ' Set TimVals[8] ' Clear Velflags.8 ' cancel running velo timer ' Clear notes.8 ' cancel note repetitions ' Clear Holdflags.8 ' Clear Waitflags.8 ' Case Note9 ' Clear Note09_Velo ' Clear Note09_Hold ' Set TimVals[9] ' Clear Velflags.9 ' cancel running velo timer ' Clear notes.9 ' cancel note repetitions ' Clear Holdflags.9 ' Clear Waitflags.9 ' Case Note10 ' Clear Note10_Hold ' Clear Note10_Velo ' Set TimVals[10] ' Clear Velflags.10 ' cancel running velo timer ' Clear notes.10 ' cancel note repetitions ' Clear Holdflags.10 ' Clear Waitflags.10 ' Case Note11 ' Clear Note11_Hold ' Clear Note11_Velo ' Set TimVals[11] ' Clear Velflags.11 ' cancel running velo timer ' Clear notes.11 ' cancel note repetitions ' Clear Holdflags.11 ' Clear Waitflags.11 ' Case Else ' Set noteAan ' GoTo Check_Timers ' EndSelect ' Set noteAan ' GoSub SortTimers ' GoTo Check_Timers ' Else ' case velo >0 ' If PowerOn = 1 Then Set resort_flag Select noteAan Case Note0 ' in principle it could be that Hold is still on. ' this is not a problem for the hardware however. Set Velflags.0 velo0 = Vel0[velo] ' read velo lookup TimVals[0] = time + velo0 ' set the timer value Set Note00_Hold ' 17.12.2021 - avoiding glitches Set Note00_Velo ' set the velo bit high If Pres0 > 0 Then ' if note repeats are programmed... Set notes.0 ' set the repeat flag Rate0 = Dur[Pres0] '- velo0 ' dur's must be > velo Else Clear notes.0 ' clear the note repeat flag EndIf Case Note1 Set Velflags.1 velo1 = Vel1[velo] ' read velo lookup TimVals[1] = time + velo1 ' set the timer value Set Note01_Hold Set Note01_Velo ' set the velo bit high If Pres1 > 0 Then ' if note repeats are programmed... Set notes.1 ' set the repeat flag Rate1 = Dur[Pres1] ' dur's must be > velo Else Clear notes.1 ' clear the note repeat flag EndIf Case Note2 Set Velflags.2 Set Note02_Hold Set Note02_Velo velo2 = Vel2[velo] TimVals[2] = time + velo2 If Pres2 > 0 Then ' if note repeats are programmed... Set notes.2 ' set the repeat flag Rate2 = Dur[Pres2] ' dur's must be > velo Else Clear notes.2 ' clear the note repeat flag EndIf Case Note3 Set Velflags.3 Set Note03_Hold Set Note03_Velo velo3 = Vel3[velo] TimVals[3] = time + velo3 If Pres3 > 0 Then ' if note repeats are programmed... Set notes.3 ' set the repeat flag Rate3 = Dur[Pres3] ' dur's must be > velo Else Clear notes.3 ' clear the note repeat flag EndIf Case Note4 Set Velflags.4 Set Note04_Hold Set Note04_Velo velo4 = Vel4[velo] TimVals[4] = time + velo4 If Pres4 > 0 Then ' if note repeats are programmed... Set notes.4 ' set the repeat flag Rate4 = Dur[Pres4] ' dur's must be > velo Else Clear notes.4 ' clear the note repeat flag EndIf Case Note5 Set Velflags.5 Set Note05_Hold Set Note05_Velo velo5 = Vel5[velo] TimVals[5] = time + velo5 If Pres5 > 0 Then ' if note repeats are programmed... Set notes.5 ' set the repeat flag Rate5 = Dur[Pres5] ' dur's must be > velo Else Clear notes.5 ' clear the note repeat flag EndIf Case Note6 Set Velflags.6 Set Note06_Velo Set Note06_Hold velo6 = Vel6[velo] TimVals[6] = time + velo6 If Pres6 > 0 Then ' if note repeats are programmed... Set notes.6 ' set the repeat flag Rate6 = Dur[Pres6] ' dur's must be > velo Else Clear notes.6 ' clear the note repeat flag EndIf Case Note7 Set Velflags.7 Set Note07_Hold Set Note07_Velo velo7 = Vel7[velo] TimVals[7] = time + velo7 If Pres7 > 0 Then ' if note repeats are programmed... Set notes.7 ' set the repeat flag Rate7 = Dur[Pres7] ' dur's must be > velo Else Clear notes.7 ' clear the note repeat flag EndIf Case Note8 Set Velflags.8 Set Note08_Hold Set Note08_Velo velo8 = Vel8[velo] TimVals[8] = time + velo8 If Pres8 > 0 Then ' if note repeats are programmed... Set notes.8 ' set the repeat flag Rate8 = Dur[Pres8] ' dur's must be > velo Else Clear notes.8 ' clear the note repeat flag EndIf Case Note9 Set Velflags.9 Set Note09_Hold Set Note09_Velo velo9 = Vel9[velo] TimVals[9] = time + velo9 If Pres9 > 0 Then ' if note repeats are programmed... Set notes.9 ' set the repeat flag Rate9 = Dur[Pres9] ' dur's must be > velo Else Clear notes.9 ' clear the note repeat flag EndIf Case Note10 Set Velflags.10 Set Note10_Hold Set Note10_Velo velo10 = Vel10[velo] TimVals[10] = time + velo10 If Pres10 > 0 Then ' if note repeats are programmed... Set notes.10 ' set the repeat flag Rate10 = Dur[Pres10] ' dur's must be > velo Else Clear notes.10 ' clear the note repeat flag EndIf Case Note11 Set Velflags.11 Set Note11_Hold Set Note11_Velo velo11 = Vel11[velo] TimVals[11] = time + velo11 If Pres11 > 0 Then ' if note repeats are programmed... Set notes.11 ' set the repeat flag Rate11 = Dur[Pres11] ' dur's must be > velo Else Clear notes.11 ' clear the note repeat flag EndIf Case Else Clear resort_flag ' Set noteAan ' GoTo Check_Timers EndSelect ' Else ' Set noteAan ' GoTo Check_Timers ' if power is OFF ' EndIf ' endif for power-on condition Set noteAan 'reset !!! 'GoSub SortTimers ' EndIf ' if velo > 0 endif EndIf ' if noteAan endif 'GoTo Check_Timers Case Keypres_Status 'here we use it for rolls and note repetitions If notePres = 255 Then notePres = Bytein Else pres = Bytein If notePres >= Note0 And notePres <= Note11 Then KeyPres () 'set resort_flag 'done in the proc when needed. EndIf Set notePres EndIf Case Control_Status 'this is where the action takes place for controllers If Ctrl = 255 Then Ctrl = Bytein Else value = Bytein Controller () EndIf ' Case ProgChange_Status ' not used here ' If prog = 255 Then 'single byte message ' prog = Bytein ' GoSub ProgChange ' EndIf ' Case Aftertouch_Status ' for changing vibrato frequency during notes ' If aft = 255 Then ' aft = Bytein ' GoSub Aftertouch ' EndIf '' GoTo Check_Timers End Select EndIf If resort_flag =1 Then idx = SortTimers () ' so we resort only if an incoming midi command changed something EndIf Check_Timers: ' 03.05.2021: note repetitions done and tested now. If idx < 12 Then ' we moeten alleen checken wanneer er een timer loopt If time >= Nxt Then ' nagaan of de eerstvolgende timer afgelopen is... ' in dit geval is de eerste timer afgelopen en moeten we de juiste aktie ondernemen: Set Nxt.31 ' timer reset, is immers afgelopen ' aan de hand van idx weten we welke timer dit is Select idx Case 0 If notes.0 = 0 Then ' er zijn geen noot repetities Set TimVals[0] ' cancel timer Clear Velflags.0 Clear Note00_Velo 'Set Note00_Hold ' 17.12.2021 remmed - should not be required Else ' in dit geval moet de noot worden herhaald: If Waitflags.0 = 1 Then ' wachttijd afgelopen. we moeten een nieuwe velo programmeren: Set Velflags.0 TimVals[0] = time + velo0 Set Note00_Velo Set Note00_Hold ' 17.12.2021 Clear Waitflags.0 ElseIf Holdflags.0 = 1 Then ' holdtijd afgelopen. we moeten een wachttijd programmeren: Clear Note00_Hold TimVals[0] = time + Dur[Pres0] ' waittime Clear Holdflags.0 Set Waitflags.0 ElseIf Velflags.0 = 1 Then ' velotijd afgelopen, we moeten een hold-tijd programmeren: Clear Note00_Velo TimVals[0] = time + Rate0 ' rate0 = Dur(Pres0) - velo 'Set Note00_Hold ' remmed 17.12.2021 - should not be required Set Holdflags.0 Clear Velflags.0 EndIf EndIf Case 1 If notes.1 = 0 Then Clear Note01_Velo 'Set Note01_Hold Set TimVals[1] Clear Velflags.1 Else If Waitflags.1 = 1 Then Set Velflags.1 TimVals[1] = time + velo1 Set Note01_Velo Set Note01_Hold 'new Clear Waitflags.1 ElseIf Holdflags.1 = 1 Then Clear Note01_Hold TimVals[1] = time + Dur[Pres1] Clear Holdflags.1 Set Waitflags.1 ElseIf Velflags.1 = 1 Then Clear Note01_Velo TimVals[1] = time + Rate1 'Set Note01_Hold Set Holdflags.1 Clear Velflags.1 EndIf EndIf Case 2 If notes.2 = 0 Then Clear Note02_Velo 'Set Note02_Hold Set TimVals[2] Clear Velflags.2 Else If Waitflags.2 = 1 Then Set Velflags.2 TimVals[2] = time + velo2 Set Note02_Velo Set Note02_Hold ' new Clear Waitflags.2 ElseIf Holdflags.2 = 1 Then Clear Note02_Hold TimVals[2] = time + Dur[Pres2] Clear Holdflags.2 Set Waitflags.2 ElseIf Velflags.2 = 1 Then Clear Note02_Velo TimVals[2] = time + Rate2 'Set Note02_Hold Set Holdflags.2 Clear Velflags.2 EndIf EndIf Case 3 If notes.3 = 0 Then Clear Note03_Velo 'Set Note03_Hold Set TimVals[3] Clear Velflags.3 Else If Waitflags.3 = 1 Then Set Velflags.3 TimVals[3] = time + velo3 Set Note03_Velo Set Note03_Hold ' new Clear Waitflags.3 ElseIf Holdflags.3 = 1 Then Clear Note03_Hold TimVals[3] = time + Dur[Pres3] Clear Holdflags.3 Set Waitflags.3 ElseIf Velflags.3 = 1 Then Clear Note03_Velo TimVals[3] = time + Rate3 'Set Note03_Hold Set Holdflags.3 Clear Velflags.3 EndIf EndIf Case 4 If notes.4 = 0 Then Clear Note04_Velo 'Set Note04_Hold Set TimVals[4] Clear Velflags.4 Else If Waitflags.4 = 1 Then Set Velflags.4 TimVals[4] = time + velo4 Set Note04_Velo Set Note04_Hold ' new Clear Waitflags.4 ElseIf Holdflags.4 = 1 Then Clear Note04_Hold TimVals[4] = time + Dur[Pres4] Clear Holdflags.4 Set Waitflags.4 ElseIf Velflags.4 = 1 Then Clear Note04_Velo TimVals[4] = time + Rate4 'Set Note04_Hold Set Holdflags.4 Clear Velflags.4 EndIf EndIf Case 5 If notes.5 = 0 Then Clear Note05_Velo 'Set Note05_Hold Set TimVals[5] Clear Velflags.5 Else If Waitflags.5 = 1 Then Set Velflags.5 TimVals[5] = time + velo5 Set Note05_Velo Set Note05_Hold Clear Waitflags.5 ElseIf Holdflags.5 = 1 Then Clear Note05_Hold TimVals[5] = time + Dur[Pres5] Clear Holdflags.5 Set Waitflags.5 ElseIf Velflags.5 = 1 Then Clear Note05_Velo TimVals[5] = time + Rate5 'Set Note05_Hold Set Holdflags.5 Clear Velflags.5 EndIf EndIf Case 6 If notes.6 = 0 Then Clear Note06_Velo 'Set Note06_Hold Set TimVals[6] Clear Velflags.6 Else If Waitflags.6 = 1 Then Set Velflags.6 TimVals[6] = time + velo6 Set Note06_Velo Set Note06_Hold Clear Waitflags.6 ElseIf Holdflags.6 = 1 Then Clear Note06_Hold TimVals[6] = time + Dur[Pres6] Clear Holdflags.6 Set Waitflags.6 ElseIf Velflags.6 = 1 Then Clear Note06_Velo TimVals[6] = time + Rate6 'Set Note06_Hold Set Holdflags.6 Clear Velflags.6 EndIf EndIf Case 7 If notes.7 = 0 Then Clear Note07_Velo 'Set Note07_Hold Set TimVals[7] Clear Velflags.7 Else If Waitflags.7 = 1 Then Set Velflags.7 TimVals[7] = time + velo7 Set Note07_Velo Set Note07_Hold Clear Waitflags.7 ElseIf Holdflags.7 = 1 Then Clear Note07_Hold TimVals[7] = time + Dur[Pres7] Clear Holdflags.7 Set Waitflags.7 ElseIf Velflags.7 = 1 Then Clear Note07_Velo TimVals[7] = time + Rate7 'Set Note07_Hold Set Holdflags.7 Clear Velflags.7 EndIf EndIf Case 8 If notes.8 = 0 Then Clear Note08_Velo 'Set Note08_Hold Set TimVals[8] Clear Velflags.8 Else If Waitflags.8 = 1 Then Set Velflags.8 TimVals[8] = time + velo8 Set Note08_Velo Set Note08_Hold Clear Waitflags.8 ElseIf Holdflags.8 = 1 Then Clear Note08_Hold TimVals[8] = time + Dur[Pres8] Clear Holdflags.8 Set Waitflags.8 ElseIf Velflags.8 = 1 Then Clear Note08_Velo TimVals[8] = time + Rate8 'Set Note08_Hold Set Holdflags.8 Clear Velflags.8 EndIf EndIf Case 9 If notes.9 = 0 Then Clear Note09_Velo 'Set Note09_Hold Set TimVals[9] Clear Velflags.9 Else If Waitflags.9 = 1 Then Set Velflags.9 TimVals[9] = time + velo9 Set Note09_Velo Set Note09_Hold Clear Waitflags.9 ElseIf Holdflags.9 = 1 Then Clear Note09_Hold TimVals[9] = time + Dur[Pres9] Clear Holdflags.9 Set Waitflags.9 ElseIf Velflags.9 = 1 Then Clear Note09_Velo TimVals[9] = time + Rate9 'Set Note09_Hold Set Holdflags.9 Clear Velflags.9 EndIf EndIf Case 10 If notes.10 = 0 Then Clear Note10_Velo 'Set Note10_Hold Set TimVals[10] Clear Velflags.10 Else If Waitflags.10 = 1 Then Set Velflags.10 TimVals[10] = time + velo10 Set Note10_Velo Set Note10_Hold Clear Waitflags.10 ElseIf Holdflags.10 = 1 Then Clear Note10_Hold TimVals[10] = time + Dur[Pres10] Clear Holdflags.10 Set Waitflags.10 ElseIf Velflags.10 = 1 Then Clear Note10_Velo TimVals[10] = time + Rate10 'Set Note10_Hold Set Holdflags.10 Clear Velflags.10 EndIf EndIf Case 11 If notes.11 = 0 Then Clear Note11_Velo 'Set Note11_Hold Set TimVals[11] Clear Velflags.11 Else If Waitflags.11 = 1 Then Set Velflags.11 TimVals[11] = time + velo11 Set Note11_Velo Set Note11_Hold Clear Waitflags.11 ElseIf Holdflags.11 = 1 Then Clear Note11_Hold TimVals[11] = time + Dur[Pres11] Clear Holdflags.11 Set Waitflags.11 ElseIf Velflags.11 = 1 Then Clear Note11_Velo TimVals[11] = time + Rate11 'et Note11_Hold Set Holdflags.11 Clear Velflags.11 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 Set TimVals EndIf Else ' idx > 11 , no timers running, so to avoid overflows, we can reset the loop timer If maxtim = 1 Then Clear time ' 16.06.2015 EndIf Btg PORTB.4 ' full load loop-speed: 10 microseconds or 93.8kHz (Tektronix measurement, 04.05.2021) ' goes up to 128kHz without timers running.(checked 08.12.2021) Loop ' end of the main loop Proc SortTimers(), Byte 'look up the next smallest timer value in the Timvals array ' zoek de de volgende kleinste timer waarde: Set Result ' makes it 255 Set Nxt.31 ' nxt is set on entry. - for speed, we just set the highest bit For i = 0 To 11 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 12 dword comparisons Result = i EndIf Next i EndProc Proc KeyPres () ' used for auto-repeat in and ' adapted to 12 notes 07.04.2021 ' improved 30.01.2024 Select notePres Case Note0 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 ' we have to cancel running timers here: Clear Velflags.0 Clear Holdflags.0 Clear Waitflags.0 Set TimVals[0] Clear Note00_Hold Clear Note00_Velo Set resort_flag EndIf Case Note1 Pres1 = pres If Pres1 > 0 Then Rate1 = Dur[Pres1] Else Clear Rate1 Clear notes.1 ' we have to cancel running timers here: Clear Velflags.1 Clear Holdflags.1 Clear Waitflags.1 Set TimVals[1] Clear Note01_Hold 'Hol1 Clear Note01_Velo 'Vel1 Set resort_flag EndIf Case Note2 Pres2 = pres If Pres2 > 0 Then Rate2 = Dur[Pres2] Else Clear Rate2 Clear notes.2 Clear Velflags.2 Clear Holdflags.2 Clear Waitflags.2 Set TimVals[2] Clear Note02_Hold 'Hol2 Clear Note02_Velo 'Vel2 Set resort_flag EndIf Case Note3 Pres3 = pres If Pres3 > 0 Then Rate3 = Dur[Pres3] Else Clear Rate3 Clear notes.3 Clear Velflags.3 Clear Holdflags.3 Clear Waitflags.3 Set TimVals[3] Clear Note03_Hold 'Hol3 Clear Note03_Velo 'Vel3 Set resort_flag EndIf Case Note4 Pres4 = pres If Pres4 > 0 Then Rate4 = Dur[Pres4] Else Clear Rate4 Clear notes.4 Clear Velflags.4 Clear Holdflags.4 Clear Waitflags.4 Set TimVals[4] Clear Note04_Hold 'Hol4 Clear Note04_Velo 'Vel4 Set resort_flag EndIf Case Note5 Pres5 = pres If Pres5 > 0 Then Rate5 = Dur[Pres5] Else Clear Rate5 Clear notes.5 Clear Velflags.5 Clear Holdflags.5 Clear Waitflags.5 Set TimVals[5] Clear Note05_Hold 'Hol5 Clear Note05_Velo 'Vel5 Set resort_flag EndIf Case Note6 Pres6 = pres If Pres6 > 0 Then Rate6 = Dur[Pres6] Else Clear Rate6 Clear notes.6 Clear Velflags.6 Clear Holdflags.6 Clear Waitflags.6 Set TimVals[6] Clear Note06_Hold 'Hol6 Clear Note06_Velo 'Vel6 Set resort_flag EndIf Case Note7 Pres7 = pres If Pres7 > 0 Then Rate7 = Dur[Pres7] Else Clear Rate7 Clear notes.7 Clear Velflags.7 Clear Holdflags.7 Clear Waitflags.7 Set TimVals[7] Clear Note07_Hold 'Hol7 Clear Note07_Velo 'Vel7 Set resort_flag EndIf Case Note8 Pres8 = pres If Pres8 > 0 Then Rate8 = Dur[Pres8] Else Clear Rate8 Clear notes.8 Clear Velflags.8 Clear Holdflags.8 Clear Waitflags.8 Set TimVals[8] Clear Note08_Hold 'Hol8 Clear Note08_Velo 'Vel8 Set resort_flag 'GoSub SortTimers EndIf Case Note9 Pres9 = pres If Pres9 > 0 Then Rate9 = Dur[Pres9] Else Clear Rate9 Clear notes.9 Clear Velflags.9 Clear Holdflags.9 Clear Waitflags.9 Set TimVals[9] Clear Note09_Hold 'Hol9 Clear Note09_Velo 'Vel9 Set resort_flag 'GoSub SortTimers EndIf Case Note10 Pres10 = pres If Pres10 > 0 Then Rate10 = Dur[Pres10] Else Clear Rate10 Clear notes.10 Clear Velflags.10 Clear Holdflags.10 Clear Waitflags.10 Set TimVals[10] Clear Note10_Hold 'Hol10 Clear Note10_Velo 'Vel10 Set resort_flag EndIf Case Note11 Pres11 = pres If Pres11 > 0 Then Rate11 = Dur[Pres11] Else Clear Rate11 Clear notes.11 Clear Velflags.11 Clear Holdflags.11 Clear Waitflags.11 Set TimVals[11] Clear Note11_Hold 'Hol11 Clear Note11_Velo 'Vel11 Set resort_flag EndIf EndSelect ' we do not need to resort here if pres changed ' as timers are only reprogrammed after reception of a note-on ' however on note-pressure zero we perform a full noteoff. EndProc 'ProgChange: ' ' used for registration on , not used on ' Set prog 'this is not realy required 'Return 'Pitchbend: ' 'only implemented on dsPIC based robots, irrelevant here ' Set pblsb 'Return 'Aftertouch: '' not used in , , ... '' 'this is the channel aftertouch, affecting any playing note '' 'used for fingered vibrato in '' '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 Proc Controller () Select Ctrl Case 30 ' can be used for global repeat frequency of the notes ' controller to set all repeat frequencies to one and the same value at once If value = 0 Then Clear notes Clear Rate0 Clear Pres0 Clear Rate1 Clear Pres1 Clear Rate2 Clear Pres2 Clear Rate3 Clear Pres3 Clear Rate4 Clear Pres4 Clear Rate5 Clear Pres5 Clear Rate6 Clear Pres6 Clear Rate7 Clear Pres7 Clear Rate8 Clear Pres8 Clear Rate9 Clear Pres9 Clear Rate10 Clear Pres10 Clear Rate11 Clear Pres11 ' should'nt we also cancel all running timers and ' perform an all-notes off: Clear Velflags Clear Holdflags Clear Waitflags Set TimVals Clear Note11_Hold Clear Note10_Hold Clear Note09_Hold Clear Note08_Hold Clear Note07_Hold Clear Note06_Hold Clear Note05_Hold Clear Note04_Hold Clear Note03_Hold Clear Note02_Hold Clear Note01_Hold Clear Note00_Hold Clear Note11_Velo Clear Note10_Velo Clear Note09_Velo Clear Note08_Velo Clear Note07_Velo Clear Note06_Velo Clear Note05_Velo Clear Note04_Velo Clear Note03_Velo Clear Note02_Velo Clear Note01_Velo Clear Note00_Velo Else Pres0 = value Rate0 = Dur[value] Pres1 = value Rate1 = Dur[value] Pres2 = value Rate2 = Dur[value] Pres3 = value Rate3 = Dur[value] Pres4 = value Rate4 = Dur[value] Pres5 = value Rate5 = Dur[value] Pres6 = value Rate6 = Dur[value] Pres7 = value Rate7 = Dur[value] Pres8 = value Rate8 = Dur[value] Pres9 = value Rate9 = Dur[value] Pres10 = value Rate10 = Dur[value] Pres11 = value Rate11 = Dur[value] EndIf GoSub SortTimers Case 66 'on/off for the robot If value = 0 Then Clear PowerOn 'CC66.0 =0 PowerDown () Else Set PowerOn 'CC66.0 =1 Set Green_Led EndIf Case 123 Set TimVals Clear Note11_Hold Clear Note10_Hold Clear Note09_Hold Clear Note08_Hold Clear Note07_Hold Clear Note06_Hold Clear Note05_Hold Clear Note04_Hold Clear Note03_Hold Clear Note02_Hold Clear Note01_Hold Clear Note00_Hold Clear Note11_Velo Clear Note10_Velo Clear Note09_Velo Clear Note08_Velo Clear Note07_Velo Clear Note06_Velo Clear Note05_Velo Clear Note04_Velo Clear Note03_Velo Clear Note02_Velo Clear Note01_Velo Clear Note00_Velo If PowerOn = 1 Then Set Green_Led End Select Set Ctrl 'mandatory reset EndProc Proc PowerDown () Set TimVals ' Clear CntHw ' reset timer Clear Note11_Hold Clear Note10_Hold Clear Note09_Hold Clear Note08_Hold Clear Note07_Hold Clear Note06_Hold Clear Note05_Hold Clear Note04_Hold Clear Note03_Hold Clear Note02_Hold Clear Note01_Hold Clear Note00_Hold Clear Note11_Velo Clear Note10_Velo Clear Note09_Velo Clear Note08_Velo Clear Note07_Velo Clear Note06_Velo Clear Note05_Velo Clear Note04_Velo Clear Note03_Velo Clear Note02_Velo Clear Note01_Velo Clear Note00_Velo Clear Green_Led Clear notes Clear Rate0 Clear Pres0 Clear Rate1 Clear Pres1 Clear Rate2 Clear Pres2 Clear Rate3 Clear Pres3 Clear Rate4 Clear Pres4 Clear Rate5 Clear Pres5 Clear Rate6 Clear Pres6 Clear Rate7 Clear Pres7 Clear Rate8 Clear Pres8 Clear Rate9 Clear Pres9 Clear Rate10 Clear Pres10 Clear Rate11 Clear Pres11 EndProc Dur_Lookup: ' lookup for repeat frequencies Set Dur[0] ' durations for note repetition on Chi ' the dur values are for a half period ! ' the frequencies are for the full period. ' 04.05.2021: recalculated for : ' slowest should be 2Hz, thus: Dur[1] = 20000 / 2 ' fastest should be 16Hz, Dur[127] = 2500 / 2 ' units are 25 us. ' calculated with log scale in PBCC 04.05.2021: Dur[1]= 10000 ' freq= 2.00000005052425 Dur[2]= 9678 ' freq= 2.06654272631148 Dur[3]= 9520 ' freq= 2.10073005674518 Dur[4]= 9366 ' freq= 2.1353833552469 Dur[5]= 9214 ' freq= 2.17060999622775 Dur[6]= 9064 ' freq= 2.20640967568454 Dur[7]= 8917 ' freq= 2.24290686388275 Dur[8]= 8772 ' freq= 2.27985186722628 Dur[9]= 8630 ' freq= 2.31749716167352 Dur[10]= 8489 ' freq= 2.35585140529389 Dur[11]= 8352 ' freq= 2.39463607581926 Dur[12]= 8216 ' freq= 2.43427464766827 Dur[13]= 8082 ' freq= 2.47448196786174 Dur[14]= 7951 ' freq= 2.51524875875527 Dur[15]= 7822 ' freq= 2.55672745353052 Dur[16]= 7695 ' freq= 2.59892151325353 Dur[17]= 7570 ' freq= 2.64183349914041 Dur[18]= 7447 ' freq= 2.68546498895502 Dur[19]= 7326 ' freq= 2.72981648880673 Dur[20]= 7207 ' freq= 2.7748873403042 Dur[21]= 7090 ' freq= 2.82067562305091 Dur[22]= 6975 ' freq= 2.867383584981 Dur[23]= 6862 ' freq= 2.91460223043464 Dur[24]= 6750 ' freq= 2.96274357532664 Dur[25]= 6641 ' freq= 3.01159471544082 Dur[26]= 6533 ' freq= 3.06138076002488 Dur[27]= 6427 ' freq= 3.11187186949471 Dur[28]= 6322 ' freq= 3.16330573432068 Dur[29]= 6220 ' freq= 3.21543416482998 Dur[30]= 6119 ' freq= 3.26850800870118 Dur[31]= 6019 ' freq= 3.32253517821123 Dur[32]= 5921 ' freq= 3.3775226725057 Dur[33]= 5825 ' freq= 3.433181787871 Dur[34]= 5731 ' freq= 3.48979244551431 Dur[35]= 5638 ' freq= 3.54735730848572 Dur[36]= 5546 ' freq= 3.60587767154828 Dur[37]= 5456 ' freq= 3.66535334101393 Dur[38]= 5367 ' freq= 3.72612957712948 Dur[39]= 5280 ' freq= 3.78752021688145 Dur[40]= 5194 ' freq= 3.85022629805419 Dur[41]= 5110 ' freq= 3.91351149696556 Dur[42]= 5027 ' freq= 3.978120438636 Dur[43]= 4945 ' freq= 4.04408057936356 Dur[44]= 4865 ' freq= 4.11057455662162 Dur[45]= 4786 ' freq= 4.17841857416536 Dur[46]= 4708 ' freq= 4.24763735908304 Dur[47]= 4632 ' freq= 4.31778940095909 Dur[48]= 4557 ' freq= 4.38885242599133 Dur[49]= 4483 ' freq= 4.46129835048907 Dur[50]= 4410 ' freq= 4.53514750685771 Dur[51]= 4338 ' freq= 4.60988832666648 Dur[52]= 4268 ' freq= 4.68603573224988 Dur[53]= 4198 ' freq= 4.7636061701185 Dur[54]= 4130 ' freq= 4.84202893239136 Dur[55]= 4063 ' freq= 4.92186551131845 Dur[56]= 3997 ' freq= 5.00312708073609 Dur[57]= 3932 ' freq= 5.08582339612015 Dur[58]= 3868 ' freq= 5.16996264837599 Dur[59]= 3806 ' freq= 5.25486087893918 Dur[60]= 3744 ' freq= 5.34188047682759 Dur[61]= 3683 ' freq= 5.42961870645921 Dur[62]= 3623 ' freq= 5.51952546025735 Dur[63]= 3564 ' freq= 5.61088525887011 Dur[64]= 3506 ' freq= 5.70369328539641 Dur[65]= 3450 ' freq= 5.79710159572247 Dur[66]= 3393 ' freq= 5.89362030506631 Dur[67]= 3338 ' freq= 5.99071454402951 Dur[68]= 3284 ' freq= 6.08920703463008 Dur[69]= 3231 ' freq= 6.19003420156066 Dur[70]= 3178 ' freq= 6.29227638988281 Dur[71]= 3127 ' freq= 6.39590678133755 Dur[72]= 3076 ' freq= 6.50195074942864 Dur[73]= 3026 ' freq= 6.6093854941317 Dur[74]= 2977 ' freq= 6.71817282675261 Dur[75]= 2928 ' freq= 6.82943503679102 Dur[76]= 2881 ' freq= 6.94203419133721 Dur[77]= 2834 ' freq= 7.05591832959693 Dur[78]= 2788 ' freq= 7.17231504581047 Dur[79]= 2743 ' freq= 7.2912870963334 Dur[80]= 2698 ' freq= 7.41152510848342 Dur[81]= 2654 ' freq= 7.53437577895743 Dur[82]= 2611 ' freq= 7.65843404374594 Dur[83]= 2569 ' freq= 7.78513059760316 Dur[84]= 2527 ' freq= 7.91295766775173 Dur[85]= 2486 ' freq= 8.04343474974563 Dur[86]= 2446 ' freq= 8.17661508799776 Dur[87]= 2406 ' freq= 8.3108250593154 Dur[88]= 2367 ' freq= 8.44951436638889 Dur[89]= 2329 ' freq= 8.58737677339738 Dur[90]= 2291 ' freq= 8.72981252956897 Dur[91]= 2253 ' freq= 8.8750834281085 Dur[92]= 2217 ' freq= 9.02120004747068 Dur[93]= 2181 ' freq= 9.1701056878691 Dur[94]= 2145 ' freq= 9.32183663726055 Dur[95]= 2111 ' freq= 9.47418309106703 Dur[96]= 2076 ' freq= 9.63159186382977 Dur[97]= 2043 ' freq= 9.78952545533162 Dur[98]= 2009 ' freq= 9.95272480977482 Dur[99]= 1977 ' freq= 10.1163381412456 Dur[100]= 1945 ' freq= 10.2827766093792 Dur[101]= 1913 ' freq= 10.452051479092 Dur[102]= 1882 ' freq= 10.6241702551089 Dur[103]= 1851 ' freq= 10.8020526628369 Dur[104]= 1821 ' freq= 10.9799618475117 Dur[105]= 1792 ' freq= 11.1607145676576 Dur[106]= 1763 ' freq= 11.3442997760876 Dur[107]= 1734 ' freq= 11.5307007813448 Dur[108]= 1706 ' freq= 11.7233297217131 Dur[109]= 1678 ' freq= 11.9154009563554 Dur[110]= 1651 ' freq= 12.113870687609 Dur[111]= 1624 ' freq= 12.3114807665389 Dur[112]= 1598 ' freq= 12.5156448718664 Dur[113]= 1572 ' freq= 12.7226466318336 Dur[114]= 1546 ' freq= 12.9324283900695 Dur[115]= 1521 ' freq= 13.1449231056474 Dur[116]= 1496 ' freq= 13.364517544432 Dur[117]= 1472 ' freq= 13.5823432972784 Dur[118]= 1448 ' freq= 13.8073873008233 Dur[119]= 1425 ' freq= 14.0350880738544 Dur[120]= 1402 ' freq= 14.2653355957507 Dur[121]= 1379 ' freq= 14.503263600611 Dur[122]= 1356 ' freq= 14.7438263953133 Dur[123]= 1334 ' freq= 14.9868868529356 Dur[124]= 1313 ' freq= 15.2322928448153 Dur[125]= 1291 ' freq= 15.4858695356117 Dur[126]= 1270 ' freq= 15.7418343213243 Dur[127]= 1250 ' freq= 16.000000404194 Return Vels_Lookup: 'Vel0[1]= 1160 ' measured 03.05.2021 as 30ms 'Vel0[127]= 6000 ' measured 03.05.2021 as 150ms ' ' a unit seems to be 25us now. ' as 6000 gives 150ms pulses, 1 unit is 150ms/6000 = 25us ' if we want to allow note repetitions up to 16 notes/sec ' the velo pulses should be shorter than 31 ms. ' for pianet: ' opgemeten bereik: 4.28ms tot 8.9ms [171 tot 357 units] $ifdef board1 For i = 0 To 127 Vel0[i] = 150 + i + i ' Vel0[1] = 152 = 3.8ms ' Vel0[127] = 404 = 10ms Vel1[i] = Vel0[i] Vel2[i] = Vel0[i] Vel3[i] = Vel0[i] Vel4[i] = Vel0[i] Vel5[i] = Vel0[i] Vel6[i] = Vel0[i] Vel7[i] = Vel0[i] Vel8[i] = Vel0[i] Vel9[i] = Vel0[i] Vel10[i] = Vel0[i] Vel11[i] = Vel0[i] Next i $endif $ifdef board2 For i = 0 To 127 Vel0[i] = 144 + i + i ' Vel0[1] = 146 = 3.65ms ' Vel0[127] = 398 = 9.95ms Vel1[i] = Vel0[i] Vel2[i] = Vel0[i] Vel3[i] = Vel0[i] Vel4[i] = Vel0[i] Vel5[i] = Vel0[i] Vel6[i] = Vel0[i] Vel7[i] = Vel0[i] Vel8[i] = Vel0[i] Vel9[i] = Vel0[i] Vel10[i] = Vel0[i] Vel11[i] = Vel0[i] Next i $endif $ifdef board3 For i = 0 To 127 Vel0[i] = 140 + i + i ' Vel0[1] = 142 = 3.55ms ' Vel0[127] = 394 = 9.85ms Vel1[i] = Vel0[i] Vel2[i] = Vel0[i] Vel3[i] = Vel0[i] Vel4[i] = Vel0[i] Vel5[i] = Vel0[i] Vel6[i] = Vel0[i] Vel7[i] = Vel0[i] Vel8[i] = Vel0[i] Vel9[i] = Vel0[i] Vel10[i] = Vel0[i] Vel11[i] = Vel0[i] Next i $endif $ifdef board4 For i = 0 To 127 Vel0[i] = 135 + i + i ' Vel0[1] = 137 = 3.42ms ' Vel0[127] = 389 = 9.725ms Vel1[i] = Vel0[i] Vel2[i] = Vel0[i] Vel3[i] = Vel0[i] Vel4[i] = Vel0[i] Vel5[i] = Vel0[i] Vel6[i] = Vel0[i] Vel7[i] = Vel0[i] Vel8[i] = Vel0[i] Vel9[i] = Vel0[i] Vel10[i] = Vel0[i] Vel11[i] = Vel0[i] Next i $endif $ifdef board5 For i = 0 To 127 Vel0[i] = 128 + i + i ' Vel0[1] = 130 = 3.25ms ' Vel0[127] = 382 = 9.55ms Vel1[i] = Vel0[i] Vel2[i] = Vel0[i] Vel3[i] = Vel0[i] Vel4[i] = Vel0[i] Vel5[i] = Vel0[i] Vel6[i] = Vel0[i] Vel7[i] = Vel0[i] Vel8[i] = Vel0[i] Vel9[i] = Vel0[i] Vel10[i] = Vel0[i] Vel11[i] = Vel0[i] Next i $endif Return '[EOF]