' ******************************************************************** ' * PIC firmware for Bourdonola * ' * coded by dr.Godfried-Willem Raes * ' * http://www.logosfoundation.org/instrum_gwr/bourdonola/picworks * ' * source code development directory: * ' * Bourdonola.bas * ' * Version 1.1 * ' * Proton Compiler version 3.5.8.1 * ' ******************************************************************** ' hardware: bus driver board 2004 ' 08/09/2016: Recoded to replace an old failing 18F252 chip programmed by Johannes Taelman. ' strange bebaviour: it works with the programmer connected, but ' refuses to work when we remove it... Solved! Ground connection missing... ' The strobe pulses may be too short in this coding. (now 200ns) ' In the 2005 version we had 5 us strobes. ' DelayUS StrobeTime added, to make 2 us strobes. ' Checked on Tektronix O.K. ' 09.09.2016: Still not working. Rechecking the old PIC: it does start up, ' but the PWM is dead. ' enlarging the strobes to 5 us, as on the old PIC does not solve the problem. ' 22.09.2016: replaced CNY27 with 4N27. Now it works again. ' fixes to be done: ' scale PWM for motor ' lights interfere with notes! ' to get the original wind pressure scaling back, we badly need 10-bit resolution! ' Macro's for 10bit pwm included. Looks like working fine on the test-board. ' Strobes now back at 2us. ' 23.09.2016: Test on Bourdonola: Still gives interference with the lights. ' default windpressure must now be 87 for 50Hz on motorcontroller ' Interference bug solved: data0, data1, data2, data3 variables introduced. ' Strobe pulse duration now 1us. Works fine. The shortest we may make is ' 28ns, according to the latch datasheet. Maybe we can even drop the ' delayUS calls in the code... Include "18F2525.inc" 'version for the Bourdonola board. (40MHz) 'Include "18F2520.inc" 'also possible. (40MHz) Clear ' Mapping defines for midi-events on pin outputs and inputs: $define Latch0 PORTC.3 ' notes 32-39 - data0 $define Latch1 PORTA.0 ' notes 40-47 - data1 $define Latch2 PORTA.1 ' notes 48-55 - data2 $define Latch3 PORTA.2 ' notes 56-63 - data3 $define databus PORTB ' 8-bit databus $define motor PORTA.5 ' motor on/off - ctrl 66 $define debug_led PORTC.0 ' watchdog Declare All_Digital = True ' makes all analog pins, digital for I/O Clear SSPCON1.5 ' make sure RC3 is free for use. ' configure the input and output pins: TRISA = %11000000 'bits set to 0 are output, 1 = input - bits 6 and 7 are the clock! TRISB = %00000000 'bits 6 and 7 are for the ICP TRISC = %11000000 'RC6 en RC7 zijn USART I/O and must be set to input ' constants Symbol fPwm = 21000 ' PWMminF Symbol StrobeTime = 0 '1 ' 1us strobe Symbol True = 1 Symbol False = 0 'initialisations for the midi input parser: Symbol Midichannel = 2 ' Bourdonola channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel Symbol Control_Status = 176 + Midichannel Symbol ProgChange_Status = 192 + Midichannel ' 1 byte message Symbol Aftertouch_Status = 208 + Midichannel ' 1 byte follows Symbol Pitchbend_Status = 224 + Midichannel ' lsb msb follow ' Setup the USART Declare Hserial_Baud = 31250 ' Set baud rate for the USART to MIDI specs. Declare Hserial_TXSTA = 0x24 ' instead of the normal 0x20 - ?? 0x24 ' Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables: ' Dim Cnt As Dword System '32 bit counter ' Dim CntHw As Cnt.Word1 ' Word System 'used in the timer0 interrupt, where it is incremented Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H 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 ' 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 Velflags As Byte System ' so we can have only 8 tasks Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 ' handled on the hub board. Dim notes As Byte System ' used for flashing lites Dim CC30 As Byte System ' repeat freq. controller Dim pres0 As Byte System Dim pres1 As Byte System Dim pres2 As Byte System Dim pres3 As Byte System Dim time As Dword System ' 32-bit, incremented in loopcounter Dim maxtim As time.31 ' overflow bit, will cause timer reset after 1h45 Dim t As Byte System ' loopcounter, running at 4 times time-clock Dim tog As Byte System Dim tg As tog.0 ' divide by 4 bit Dim TimVals[8] 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 wind As Byte System Dim wind_pwm As Word System Dim Data0 As Byte System Dim Data1 As Byte System Dim Data2 As Byte System Dim Data3 As Byte System '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler and buffer read subroutines into memory Dim Ringbuffer[256] As Byte ' Array for holding received characters Include "Bourdonola_Irq.inc" ' for UART,Timer0, Timer3 Interrupt Include "HPWM10.inc" ' macro's for 10-bit PWM OpenAnalog2 ' 10-bit pwm init OpenAnalog1 ' velocity lookup table 'Dim Vels[128] As Word ' for Laukhuff solenoid Dim Dur[128] As Word ' duration lookup for repetitions 'Dim Dur5[128] As Word ' duration lookup for lite flashing repetitions ' Main program starts here: MAIN: Output PORTB High debug_led DelayMS 10 ' wait for stability Low debug_led High motor ' inverted Logic Clear databus High Latch0 High Latch1 High Latch2 High Latch3 Low databus ' =PORTB ' strobe low: Low Latch0 DelayUS StrobeTime High Latch0 Low Latch1 DelayUS StrobeTime High Latch1 Low Latch2 DelayUS StrobeTime High Latch2 Low Latch3 DelayUS StrobeTime High Latch3 wind = 87 ' default startup value wind_pwm = 1023 - wind ' HPWM 1,255 - (wind + wind),fPwm ' inverted PWM WriteAnalog1 wind_pwm '=940 Clear Velflags Set TimVals ' no timers running on startup Clear CC66 ' power off Clear Data0 Clear Data1 Clear Data2 Clear Data3 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 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 ' Dont sync external clock input ' doing it this way seems to work: 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 ' 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 GoSub Dur_Lookup 'GoSub Vels_Lookup ' start the main program loop: LOOP: ' Create an infinite loop Inc t ' byte If t.1 = tg Then Btg tg Inc time ' dword EndIf Bytein = HRSIn ' Read data from the serial buffer, with no timeout ' Start the midi parser. Midi_Parse: If Bytein > Pitchbend_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in. Else Clear statusbyte 'reset the status byte End If GoTo Check_Timers 'throw away... EndIf If StBit =1 Then 'should be faster than If Bytein > 127 Then 'status byte received, bit 7 is set Clear statusbyte 'if on another channel, the statusbyte needs a reset Select Bytein 'eqv to Select case ByteIn Case NoteOff_Status statusbyte = Bytein Set noteUit 'reset value. Cannot be 0 !!! Set release '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Case Keypres_Status statusbyte = Bytein notePres = 255 pres = 255 Case Control_Status ' controllers and switches statusbyte = Bytein Set Ctrl Set value Case ProgChange_Status ' could be used for different lookup tables statusbyte = Bytein prog = 255 Case Aftertouch_Status ' not used on this board statusbyte = Bytein Set aft Case Pitchbend_Status ' used for saw bending positioning statusbyte = Bytein pblsb = 255 pbmsb = 255 End Select Else 'midi byte is 7 bits Select statusbyte Case 0 'not a message for this channel GoTo Check_Timers 'disregard Case NoteOff_Status If noteUit = 255 Then noteUit = Bytein Else release = Bytein 'message complete, so we can do the action... Select noteUit Case 32 Clear Data0.7 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.0 Set TimVals[0] Case 33 Clear Data0.6 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.1 Set TimVals[1] Case 34 Clear Data0.5 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.2 Set TimVals[2] Case 35 Clear Data0.4 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.3 Set TimVals[3] Case 36 Clear Data0.3 ' this is the lowest note on bourdonola databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 37 Clear Data0.2 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 38 Clear Data0.1 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 39 Clear Data0.0 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 40 Clear Data1.7 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 41 Clear Data1.6 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 42 Clear Data1.5 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 43 Clear Data1.4 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 44 Clear Data1.3 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 45 Clear Data1.2 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 46 Clear Data1.1 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 47 Clear Data1.0 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 48 Clear Data2.7 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 49 Clear Data2.6 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 50 Clear Data2.5 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 51 Clear Data2.4 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 52 Clear Data2.3 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 53 Clear Data2.2 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 54 Clear Data2.1 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 55 Clear Data2.0 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 56 Clear Data3.7 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 57 Clear Data3.6 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 58 Clear Data3.5 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 59 Clear Data3.4 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 60 Clear Data3.3 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 61 Clear Data3.2 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 62 ' this is the highest note on bourdonola Clear Data3.1 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 ' Case 63 ' Clear databus.0 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case Else GoTo Check_Timers End Select Set noteUit '= 255 'reset GoTo resort EndIf GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then ' note off via velo=0 Select noteAan Case 32 Clear Data0.7 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.0 Set TimVals[0] Case 33 Clear Data0.6 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.1 Set TimVals[1] Case 34 Clear Data0.5 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.2 Set TimVals[2] Case 35 Clear Data0.4 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Clear notes.3 Set TimVals[3] Case 36 Clear Data0.3 ' this is the lowest note on bourdonola databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 37 Clear Data0.2 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 38 Clear Data0.1 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 39 Clear Data0.0 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 40 Clear Data1.7 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 41 Clear Data1.6 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 42 Clear Data1.5 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 43 Clear Data1.4 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 44 Clear Data1.3 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 45 Clear Data1.2 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 46 Clear Data1.1 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 47 Clear Data1.0 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 48 Clear Data2.7 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 49 Clear Data2.6 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 50 Clear Data2.5 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 51 Clear Data2.4 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 52 Clear Data2.3 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 53 Clear Data2.2 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 54 Clear Data2.1 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 55 Clear Data2.0 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 56 Clear Data3.7 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 57 Clear Data3.6 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 58 Clear Data3.5 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 59 Clear Data3.4 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 60 Clear Data3.3 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 61 Clear Data3.2 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 62 ' this is the highest note on bourdonola Clear Data3.1 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 ' Case 63 ' Clear databus.0 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case Else GoTo Check_Timers End Select GoTo resort Else If PowerOn = 1 Then ' dont do lights if power is off Select noteAan Case 32 Set Data0.7 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 If velo < 127 Then Set notes.0 pres0 = velo TimVals[0] = time + Dur[pres0] Else Clear notes.0 EndIf Case 33 Set Data0.6 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 If velo < 127 Then Set notes.1 pres1 = velo TimVals[1] = time + Dur[pres1] Else Clear notes.1 EndIf Case 34 Set Data0.5 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 If velo < 127 Then Set notes.2 pres2 = velo TimVals[2] = time + Dur[pres2] Else Clear notes.2 EndIf Case 35 Set Data0.4 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 If velo < 127 Then Set notes.3 pres3 = velo TimVals[3] = time + Dur[pres3] Else Clear notes.3 EndIf Case 36 Set Data0.3 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 37 Set Data0.2 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 38 Set Data0.1 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 39 Set Data0.0 databus = Data0 : Low Latch0 : DelayUS StrobeTime : High Latch0 Case 40 Set Data1.7 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 41 Set Data1.6 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 42 Set Data1.5 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 43 Set Data1.4 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 44 Set Data1.3 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 45 Set Data1.2 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 46 Set Data1.1 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 47 Set Data1.0 databus = Data1 : Low Latch1 : DelayUS StrobeTime : High Latch1 Case 48 Set Data2.7 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 49 Set Data2.6 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 50 Set Data2.5 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 51 Set Data2.4 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 52 Set Data2.3 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 53 Set Data2.2 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 54 Set Data2.1 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 55 Set Data2.0 databus = Data2 : Low Latch2 : DelayUS StrobeTime : High Latch2 Case 56 Set Data3.7 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 57 Set Data3.6 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 58 Set Data3.5 databus = Data3: Low Latch3 : DelayUS StrobeTime : High Latch3 Case 59 Set Data3.4 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 60 Set Data3.3 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 61 Set Data3.2 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case 62 Set Data3.1 databus = Data3 : Low Latch3 : DelayUS StrobeTime : High Latch3 'Case 63 ' Set databus.0 : Low Latch3 : DelayUS StrobeTime : High Latch3 Case Else Set noteAan GoTo Check_Timers End Select EndIf Set noteAan '= 255 GoTo resort EndIf EndIf GoTo Check_Timers Case Keypres_Status If notePres = 255 Then notePres = Bytein Else pres = Bytein GoSub KeyPres GoTo resort ' changing repetition rates requires timers! 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 GoTo Check_Timers Case ProgChange_Status ' not used If prog = 255 Then 'single byte message prog = Bytein GoSub ProgChange EndIf GoTo Check_Timers Case Aftertouch_Status If aft = 255 Then aft = Bytein GoSub Aftertouch EndIf GoTo Check_Timers Case Pitchbend_Status ' not used on this board If pblsb = 255 Then pblsb = Bytein Else pbmsb = Bytein GoSub Pitchbend EndIf GoTo Check_Timers End Select EndIf resort: GoSub SortTimers ' so we resort only if an incoming midi command changed something Check_Timers: If idx < 4 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 ' just toggle on/off If notes.0 = 0 Then ' no repeats required Clear Data0.7 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 Set TimVals[0] Else ' repeat flag is set Toggle Data0.7 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 TimVals[0] = time + Dur[pres0] EndIf Case 1 If notes.1 = 0 Then ' no repeats required Clear Data0.6 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 Set TimVals[1] Else ' repeat flag is set Toggle Data0.6 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 TimVals[1] = time + Dur[pres1] EndIf Case 2 If notes.2 = 0 Then ' no repeats required Clear Data0.5 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 Set TimVals[2] Else ' repeat flag is set Toggle Data0.5 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 TimVals[2] = time + Dur[pres2] EndIf Case 3 If notes.3 = 0 Then ' no repeats required Clear Data0.4 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 Set TimVals[3] Else ' repeat flag is set Toggle Data0.4 databus = Data0 Low Latch0 DelayUS StrobeTime High Latch0 TimVals[3] = time + Dur[pres3] EndIf 'Case Else ' ' in dit geval is idx geset ' GoTo jumpout End Select GoSub SortTimers ' find a new nxt and idx EndIf ' beveiliging tegen overflow crashes... If maxtim = 1 Then Clear time Clear notes Set TimVals EndIf Else ' idx > 5, 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.0 ' average loop-speed: 10 microseconds or 84kHz (Tektronix measurement, 27.05.2016) ' with glitches ca. 50 microseconds in length. ' to be measured again! GoTo LOOP SortTimers: 'look up the next smallest timer value in the Timvals array ' zoek de de volgende kleinste timer waarde: Set idx ' makes it 255 Set Nxt.31 ' nxt is set on entry. - for speed, we just set the highest bit For i = 0 To 3 If TimVals[i] < Nxt Then Nxt = TimVals[i] ' 8 dword comparisons idx = i EndIf Next i Return KeyPres: Select notePres ' note pressure will be overridden with each new note-on command Case 32 ' should program the repetition rate - notes.0 flag pres0 = pres Case 33 pres1 = pres Case 34 pres2 = pres Case 35 pres3 = pres EndSelect ' we do not need to resort here Set notePres '= 255 Return ProgChange: ' not implemented here. Set prog '= 255 'this is not realy required Return Pitchbend: Set pblsb Return Aftertouch: 'this is the channel aftertouch, affecting any playing note 'not implemented here. Set aft ' reset Return Controller: Select Ctrl Case 1 ' motor speed 'requires inverted PWM! 'HPWM 1, 255 - (value + value) , fPwm 'wind = value ' for compatibility with existing code: 'i = value >> 3 ' divide by 4 - we loose a lot on resolution this way of course.... 'HPWM 1, 255 - i, fPwm ' try using the 10 bit coding with the macro's wind = value wind_pwm = 1023 - value WriteAnalog1 wind_pwm Case 66 'on/off for the robot ' this should also go to the note boards! If value = 0 Then Clear PowerOn 'CC66.0 =0 GoSub PowerDown Else Set PowerOn 'CC66.0 =1 Clear motor ' inverted, this switches motor on EndIf Case 123 ' all notes off - no controller resets Clear databus Low Latch0 DelayUS StrobeTime : High Latch0 ' Clear databus Low Latch1 DelayUS StrobeTime : High Latch1 ' Clear databus Low Latch2 DelayUS StrobeTime : High Latch2 'Clear databus Low Latch3 DelayUS StrobeTime : High Latch3 Set TimVals[0] Set TimVals[1] Set TimVals[2] Set TimVals[3] Clear notes Clear Data0 Clear Data1 Clear Data2 Clear Data3 End Select Set Ctrl 'mandatory reset Return PowerDown: Set motor ' motor OFF Clear Data0 Clear Data1 Clear Data2 Clear Data3 Clear databus Low Latch0 DelayUS StrobeTime : High Latch0 'Clear databus Low Latch1 DelayUS StrobeTime : High Latch1 'Clear databus Low Latch2 DelayUS StrobeTime : High Latch2 'Clear databus Low Latch3 DelayUS StrobeTime : High Latch3 Clear CC66 wind = 87 ' reset controller wind_pwm = 1023 - wind WriteAnalog1 wind_pwm Set TimVals[0] Set TimVals[1] Set TimVals[2] Set TimVals[3] Clear notes Clear pres0 Clear pres1 Clear pres2 Clear pres3 Return Dur_Lookup: 'lookup for repeat frequencies Set Dur[0] Dur[1]= 23674 ' freq= 2.11202162710146 Dur[2]= 22917 ' freq= 2.18178644674259 Dur[3]= 22548 ' freq= 2.21749157353202 Dur[4]= 22185 ' freq= 2.25377507324769 Dur[5]= 21827 ' freq= 2.29074082558299 Dur[6]= 21475 ' freq= 2.32828870779977 Dur[7]= 21129 ' freq= 2.36641582658905 Dur[8]= 20789 ' freq= 2.40511809129828 Dur[9]= 20454 ' freq= 2.44450963136795 Dur[10]= 20124 ' freq= 2.48459550785132 Dur[11]= 19800 ' freq= 2.52525252525252 Dur[12]= 19481 ' freq= 2.56660335711719 Dur[13]= 19167 ' freq= 2.60865028434288 Dur[14]= 18858 ' freq= 2.65139463357726 Dur[15]= 18554 ' freq= 2.69483669289641 Dur[16]= 18255 ' freq= 2.73897562311695 Dur[17]= 17961 ' freq= 2.7838093647347 Dur[18]= 17672 ' freq= 2.82933454051607 Dur[19]= 17387 ' freq= 2.87571173865532 Dur[20]= 17107 ' freq= 2.92278014847723 Dur[21]= 16831 ' freq= 2.97070881112233 Dur[22]= 16560 ' freq= 3.01932367149758 Dur[23]= 16293 ' freq= 3.06880255324372 Dur[24]= 16030 ' freq= 3.11915159076731 Dur[25]= 15772 ' freq= 3.17017499365965 Dur[26]= 15518 ' freq= 3.22206469905916 Dur[27]= 15268 ' freq= 3.27482315954938 Dur[28]= 15022 ' freq= 3.32845160431367 Dur[29]= 14780 ' freq= 3.382949932341 Dur[30]= 14542 ' freq= 3.43831660019254 Dur[31]= 14307 ' freq= 3.4947927587894 Dur[32]= 14077 ' freq= 3.55189315905378 Dur[33]= 13850 ' freq= 3.6101083032491 Dur[34]= 13627 ' freq= 3.66918617450649 Dur[35]= 13407 ' freq= 3.72939509211606 Dur[36]= 13191 ' freq= 3.79046319460238 Dur[37]= 12978 ' freq= 3.85267375558638 Dur[38]= 12769 ' freq= 3.91573341686898 Dur[39]= 12564 ' freq= 3.97962432346386 Dur[40]= 12361 ' freq= 4.04498017959712 Dur[41]= 12162 ' freq= 4.1111659266568 Dur[42]= 11966 ' freq= 4.17850576633796 Dur[43]= 11773 ' freq= 4.24700586086809 Dur[44]= 11583 ' freq= 4.31667098333765 Dur[45]= 11397 ' freq= 4.38711941739054 Dur[46]= 11213 ' freq= 4.45910996165165 Dur[47]= 11032 ' freq= 4.53226976069616 Dur[48]= 10855 ' freq= 4.60617227084293 Dur[49]= 10680 ' freq= 4.6816479400749 Dur[50]= 10508 ' freq= 4.75827940616673 Dur[51]= 10338 ' freq= 4.83652544012381 Dur[52]= 10172 ' freq= 4.91545418796697 Dur[53]= 10008 ' freq= 4.99600319744204 Dur[54]= 9846 ' freq= 5.07820434694292 Dur[55]= 9688 ' freq= 5.16102394715111 Dur[56]= 9532 ' freq= 5.24548887956357 Dur[57]= 9378 ' freq= 5.33162721262529 Dur[58]= 9227 ' freq= 5.4188793757451 Dur[59]= 9078 ' freq= 5.50782110597048 Dur[60]= 8932 ' freq= 5.59785042543663 Dur[61]= 8788 ' freq= 5.68957669549385 Dur[62]= 8646 ' freq= 5.78302105019662 Dur[63]= 8507 ' freq= 5.87751263665217 Dur[64]= 8370 ' freq= 5.973715651135 Dur[65]= 8235 ' freq= 6.07164541590771 Dur[66]= 8102 ' freq= 6.17131572451246 Dur[67]= 7972 ' freq= 6.27195183140993 Dur[68]= 7843 ' freq= 6.37511156445238 Dur[69]= 7717 ' freq= 6.47920176234288 Dur[70]= 7593 ' freq= 6.58501251152377 Dur[71]= 7470 ' freq= 6.69344042838019 Dur[72]= 7350 ' freq= 6.80272108843537 Dur[73]= 7231 ' freq= 6.91467293597013 Dur[74]= 7115 ' freq= 7.02740688685875 Dur[75]= 7000 ' freq= 7.14285714285714 Dur[76]= 6888 ' freq= 7.25900116144018 Dur[77]= 6777 ' freq= 7.37789582411096 Dur[78]= 6667 ' freq= 7.49962501874906 Dur[79]= 6560 ' freq= 7.62195121951219 Dur[80]= 6454 ' freq= 7.74713356058258 Dur[81]= 6350 ' freq= 7.8740157480315 Dur[82]= 6248 ' freq= 8.00256081946223 Dur[83]= 6147 ' freq= 8.13404912965674 Dur[84]= 6048 ' freq= 8.26719576719577 Dur[85]= 5951 ' freq= 8.40194925222652 Dur[86]= 5855 ' freq= 8.5397096498719 Dur[87]= 5760 ' freq= 8.68055555555555 Dur[88]= 5668 ' freq= 8.82145377558222 Dur[89]= 5576 ' freq= 8.96700143472023 Dur[90]= 5486 ' freq= 9.11410864017499 Dur[91]= 5398 ' freq= 9.26268988514264 Dur[92]= 5311 ' freq= 9.41442289587648 Dur[93]= 5225 ' freq= 9.56937799043062 Dur[94]= 5141 ' freq= 9.72573429293912 Dur[95]= 5058 ' freq= 9.88533017002768 Dur[96]= 4977 ' freq= 10.0462125778581 Dur[97]= 4897 ' freq= 10.2103328568511 Dur[98]= 4818 ' freq= 10.3777501037775 Dur[99]= 4740 ' freq= 10.548523206751 Dur[100]= 4664 ' freq= 10.7204116638079 Dur[101]= 4589 ' freq= 10.8956199607758 Dur[102]= 4515 ' freq= 11.0741971207087 Dur[103]= 4442 ' freq= 11.2561909049977 Dur[104]= 4370 ' freq= 11.441647597254 Dur[105]= 4300 ' freq= 11.6279069767442 Dur[106]= 4231 ' freq= 11.8175372252422 Dur[107]= 4162 ' freq= 12.013455069678 Dur[108]= 4095 ' freq= 12.2100122100122 Dur[109]= 4029 ' freq= 12.4100273020601 Dur[110]= 3964 ' freq= 12.6135216952573 Dur[111]= 3901 ' freq= 12.8172263522174 Dur[112]= 3838 ' freq= 13.0276185513288 Dur[113]= 3776 ' freq= 13.2415254237288 Dur[114]= 3715 ' freq= 13.4589502018842 Dur[115]= 3655 ' freq= 13.6798905608755 Dur[116]= 3596 ' freq= 13.9043381535039 Dur[117]= 3538 ' freq= 14.1322781232335 Dur[118]= 3481 ' freq= 14.3636885952312 Dur[119]= 3425 ' freq= 14.5985401459854 Dur[120]= 3370 ' freq= 14.8367952522255 Dur[121]= 3316 ' freq= 15.0784077201448 Dur[122]= 3262 ' freq= 15.3280196198651 Dur[123]= 3210 ' freq= 15.5763239875389 Dur[124]= 3158 ' freq= 15.8328055731476 Dur[125]= 3107 ' freq= 16.0926939169617 Dur[126]= 3057 ' freq= 16.3559044815178 Dur[127]= 3008 ' freq= 16.6223404255319 Return '[EOF]