'**************************************************************** '* Name : SynHub.BAS * '* Author : Godfried-Willem RAES * '* Notice : Copyleft (c) 2012 Logosoft Public Domain * '* Date : 17-01-2012 / 24.01.2012 /01.08.2012 /02.08.2012 * '* Version : 1.3 * '* Notes : Based On Spiro-hub code model * '**************************************************************** '17.01.2012: code start - Version 1.0 ' to do: add autorelease timer for the damper solenoid - CC34 '24.01.2012: Sustain controller (64) added and implemented ' CC34 added for damper release time control. ' release timer added. ' Version 1.1 ' bug: PWM out works on 8-bit mode. Bug killed. '01.08.2012: CC64 works fine ' CC33 only works with value 124 up to 127... ' CC34 not working at all ' Tested again version 1.2 now flashed. ' Aftertouch implemented. ' CC34 now works fine ' CC33 still works only with values 124 up to 127 ' if this problem persists, we may have to shorten the mechanical traject of the solenoid. '02.08.2012; Version 1.3 - controllers implemented differently ' CC33 = attack time ' CC34 = release time ' CC35 = attack force (PWM value) ' CC36 = damping force during release (PWM value) ' CC64 = sustain controller (switch) '03.08.2012: Code clean up. No structural changes, except powerdown and powerup. ' Motor voltage must raise to 48V for better torque ' Lookup required for velocity scaling in function of the active fret. Include "18F2525.inc" 'version for the Synchrochord board. (40MHz) 'Include "18F2520.inc" 'also possible. (40MHz) 'Include "18F25K20.inc" 'for test & debug on an Amicus board. (64MHz) ' Mapping defines for midi-events on pin outputs and inputs: ' lights: $define LEDLight1 PORTC.5 ' X11-2 - Not yet mounted $define LEDLight2 PORTC.4 ' X11-3 $define BlueArm1 PORTB.0 ' X12-2 - socketed lite On arm, 1W LED - 12V $define BlueArm2 PORTB.1 ' X12-3 - socketed lite On arm, 1W LED - 12V $define LEDLight5 PORTC.3 ' X15-2 $define LEDLight6 PORTC.0 ' X15-3 'red LED for debug: $define Debug_Led PORTB.5 ' for testing - red led - watchdog ' configure the input and output pins: Clear SSPCON1.5 'RC3 must be available for I/O TRISA = %01000111 'bits set to 0 are output, 1 = input TRISB = %11100000 TRISC = %11000000 'RC1 en RC2 zijn pwm outputs and must be set to output 'RC6 en RC7 zijn USART I/O and must be set to input 'constant definitions: 'initialisations for the midi input parser: Symbol Midichannel = 10 ' Synchrochord_Channel Symbol NoteOff_Status = 128 + Midichannel ' 2 bytes follow Symbol NoteOn_Status = 144 + Midichannel Symbol Keypres_Status = 160 + Midichannel ' 2 bytes follow Symbol Control_Status = 176 + Midichannel Symbol ProgChange_Status = 192 + Midichannel ' 1 byte message Symbol Aftertouch_Status = 208 + Midichannel ' 1 byte follows Symbol Pitchbend_Status = 224 + Midichannel ' lsb msb follow 'application specific constants Symbol NrTasks = 8 ' maximum 16 'Symbol PWMFreq2 = PWMminF * 2 ' PWMminF is processor dependent. 'Symbol PWMFreq3 = PWMminF * 3 ' declared in the processor include Symbol PWMFreq4 = PWMminF * 4 ' avoiding audible artifacts Symbol Lowtes = 39 ' lowest note on synchrochord Symbol Hightes = 87 ' highest note on synchrochord Symbol DefaultCC33 = 48 'Task_rsi[6] = CC33 << 6 ' <<4 was too short Symbol DefaultCC34 = 64 Symbol DefaultCC35 = 127 ' becomes 128 + DefaultCC35 = 255 Symbol DefaultCC36 = 70 ' becomes DefaultCC36 <<1 = 140 ' Setup the USART Declare Hserial_Baud = 31250 ' Set baud rate for the USART to MIDI specs. Declare Hserial_TXSTA = 0x24 ' instead of the normal 0x20 - ?? 0x24 Declare All_Digital = True ' no analog inputs ' Declare Hserial_Clear = On ' should clear on errors. Bytes get lost of course... ' Create variables Dim Cnt As Dword System Dim CntHw As Cnt.Word1 'used in the timer0 interrupt, to create a 32 bit timer Dim CntLw As TMR0L.Word 'this is the trick to read both TMR0L and TMR0H 'it makes Cntlw the low word of cnt 'We still have to copy the contents of Lw to Cnt Dim Tim3 As TMR3L.Word ' 16 bit counter for sampler ' Dim Sr as TMR0L.7 '512 S/s ' 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 veltim As Dword System ' 32 bit velo Dim newtim As Dword System Dim VelFlags As Word System ' bits 0 - 15 used as flags for active timers Dim VelFlags0 As VelFlags.Byte0 ' alias for bits 0-7 Dim VelFlags1 As VelFlags.Byte1 ' bits 8-15 - bit 8 and 9 used for attack and release timer Dim CC33 As Byte System ' damper attack time controller damping force controller Dim CC34 As Byte System ' damper release time Dim CC35 As Byte System ' damper attack force controller Dim CC36 As Byte System ' damper force controller during hold Dim CC64 As Byte System ' sustain controller Dim CC66 As Byte System ' global on/off switch Dim PowerOn As CC66.0 Dim st As Byte System Dim b1 As Byte System Dim b2 As Byte System Dim Lites As Byte System ' bits used as flags ' Dim tBit As Byte System ' for sampling rate bit '----------------------------------------------------------------------------------------- ' Load the USART Interrupt handler And buffer read subroutines into memory ' Include "ADC.inc" ' Load the ADC macros into the program Include "SynHub_Irq.inc" ' our own version for UART And Timer0/3 Interrupt 'Include "Timers.inc" ' required for velo support with timed pulses and periods. 'Include "DwordArrays.inc" ' support for dword arrays. 'framework for a multitasker: Dim Task_rsi[NrTasks] As Word 'task reschedule interval (period), if 0 the task is not active 'max. value limited to 65535. For longer periods, it will have to 'become dword!!! Dim Velmsb[NrTasks] As Word 'the application for velo-timers, is in fact just a one-shot task Dim VelLsb[NrTasks] As Word 'make sure we initialize those pins on start up: 'fault?: there should be no executable statements outside the main program. Low LEDLight1 'midi note 120 Low LEDLight2 'midi note 121 Low BlueArm1 'midi note 122 Low BlueArm2 'midi note 123 Low LEDLight5 'midi note 124 Low LEDLight6 'midi note 125 Low Debug_Led CC33 = DefaultCC33 Task_rsi[6] = CC33 << 6 ' <<4 was too short CC34 = DefaultCC34 '64 Task_rsi[7] = CC34 << 9 CC35 = 128 + DefaultCC35 ' 255 CC36 = DefaultCC36 << 1 ' 140 Clear CC64 ' sustain off HPWM 2, 0, PWMFreq4 'softshift 1 - amplitude control - plucker solenoid - X17-3 HPWM 1, 0, PWMFreq4 'solenoid 2 - damper control connected to RC2 - X17-2 Clear CC66 ' power off condition on startup '----------------------------------------------------------------------------------------- ' Main program starts here MAIN: High Debug_Led DelayMS 50 ' wait for stability Low Debug_Led Clear VelFlags0 Clear VelFlags1 Clear Lites Init_Usart_Interrupt ' Initiate the USART serial buffer interrupt ' this procedure is in the include file Clear_Serial_Buffer ' Clear the serial buffer and reset its pointers ' in the include as well ' Configure Timer0 for: ' Clear TMR0L and TMR0H registers ' Interrupt on Timer0 overflow ' 16-bit operation ' Internal clock source 40MHz ' 1:256 Prescaler : thus 40MHz / 256 = 156.250kHz ' Opentimer0 (Timer_INT_On & T0_16BIT & T0_SOURCE_INT & T0_PS_1_256) in macro file. Clear T1CON Clear IntConBits_T0IF ' clear interrupt flag Set INTCONBITS_T0IE ' enable interrupt on overflow T0CON = %10000111 ' bit 7 = enable/disable ' bit 6 = 1=8 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 ' open and start timer3 for sampling: Clear T3CON Clear PIR2BITS_TMR3IF ' clear IRQ flag Set PIE2BITS_TMR3IE ' irq on Clear Tim3 ' Clear TMR3L And TMR3H registers Set RCONbits_IPEN ' Enable priority interrupts Clear IPR2bits_TMR3IP ' Set Timer3 as a low priority interrupt source ' 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, lowest freq.=19Hz ' start the main program loop: LOOP: ' Create an infinite loop Bytein = HRSIn ' Read data from the serial buffer, with no timeout ' Start the midi parser. Midi_Parse: If Bytein > Control_Status Then ' here higher statusses are not implemented. If Bytein > 253 Then '254 = midiclock, 255= reset 'midiclock can interrupt all other msg's... '255 had to be intercepted since thats what we 'get when no new byte flows in (?) 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 '= 255 'reset value. Cannot be 0 !!! Set release '= 255 '0 is a valid midi note! Case NoteOn_Status statusbyte = Bytein Set noteAan '= 255 Set velo '= 255 Case Keypres_Status 'used for lights statusbyte = Bytein Set notePres '= 255 Set pres '= 255 Case Control_Status statusbyte = Bytein Set Ctrl '= 255 Set value '= 255 ' Case ProgChange_Status ' statusbyte = Bytein ' prog = 255 Case Aftertouch_Status ' used for modulation of exciter force statusbyte = Bytein aft = 255 ' Case Pitchbend_Status ' 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 Lowtes To Hightes ' release plucker: HPWM 2, 0, PWMFreq4 ' ok ' apply damper If CC64 = 0 Then If release = 0 Then ' this happens with normal sequencers HPWM 1, CC35, PWMFreq4 Else HPWM 1, 128 + release, PWMFreq4 ' steer damper attack force End If ' start the attack duration timer: Set VelFlags1.0 Clear VelFlags1.1 Cnt.Word0 = CntLw ' Task_rsi[6] = CC33 << 6 ' <<4 was too short - moved to controller procedure veltim = Cnt + Task_rsi[6] Velmsb[6] = veltim.Word1 VelLsb[6] = veltim.Word0 ' when this timer runs out, we ' ' start a release timer... Else Clear VelFlags1 HPWM 1, 0, PWMFreq4 EndIf Case 120 Clear Lites.0 Clear VelFlags0.0 'Low LEDLight1 = sets TRIS also Clear LEDLight1 ' = 0 ' one machine cycle only Case 121 Clear Lites.1 Clear VelFlags0.1 Clear LEDLight2 '= 0 Case 122 ' blue arm light Clear Lites.2 Clear VelFlags0.2 Clear BlueArm1 '= 0 Case 123 Clear Lites.3 ' blue armlight Clear VelFlags0.3 Clear BlueArm2 '= 0 Case 124 Clear Lites.4 Clear VelFlags0.4 Clear LEDLight5 '= 0 Case 125 Clear Lites.5 Clear VelFlags0.5 Clear LEDLight6 '= 0 End Select Set noteUit '= 255 'reset EndIf GoTo Check_Timers Case NoteOn_Status If noteAan = 255 Then noteAan = Bytein Else velo = Bytein If velo = 0 Then Select noteAan Case Lowtes To Hightes HPWM 2, 0, PWMFreq4 ' release plucker ok ' damp and start attack timer... If CC64 = 0 Then HPWM 1, CC35, PWMFreq4 Set VelFlags1.0 Clear VelFlags1.1 Cnt.Word0 = CntLw 'Task_rsi[6] = CC33 << 6 ' <<4 was too short - moved to controller procedure veltim = Cnt + Task_rsi[6] Velmsb[6] = veltim.Word1 VelLsb[6] = veltim.Word0 Else Clear VelFlags1 HPWM 1, 0, PWMFreq4 EndIf Case 120 Clear Lites.0 '= 0 Clear VelFlags0.0 Clear LEDLight1 '= 0 Case 121 Clear Lites.1 '= 0 Clear VelFlags0.1 Clear LEDLight2 '= 0 Case 122 Clear Lites.2 '= 0 Clear VelFlags0.2 Clear BlueArm1 '= 0 Case 123 Clear Lites.3 '= 0 Clear VelFlags0.3 Clear BlueArm2 '= 0 Case 124 Clear Lites.4 '= 0 Clear VelFlags0.4 Clear LEDLight5 '= 0 Case 125 Clear Lites.5 '= 0 Clear VelFlags0.5 Clear LEDLight6 '= 0 End Select Set noteAan '= 255 'reset !!! GoTo Check_Timers 'jump out EndIf Select noteAan Case Lowtes To Hightes HPWM 1, 0, PWMFreq4 ' release damper Clear VelFlags1 ' cancel damping timers ' clear damper release timer ' steer the excursion of the plucker motor using the ' softshift solenoid. HPWM 2, velo <<1, PWMFreq4 ' 8 bit mode Case > 119 'omleiding van de kode naar keypres: 'If noteAan > 119 Then If velo < 127 Then notePres = noteAan pres = velo GoSub KeyPres Else ' plain ON without flashing Select noteAan Case 120 Set Lites.0 Clear VelFlags0.0 Set LEDLight1 '= 1 Case 121 Set Lites.1 Clear VelFlags0.1 'so flashing is reset Set LEDLight2 '= 1 Case 122 Set Lites.2 Clear VelFlags0.2 Set BlueArm1 '= 1 Case 123 Set Lites.3 Clear VelFlags0.3 Set BlueArm2 '= 1 Case 124 Set Lites.4 Clear VelFlags0.4 Set LEDLight5 '= 1 Case 125 Set Lites.5 Clear VelFlags0.5 Set LEDLight6 '= 1 End Select EndIf End Select Set noteAan '= 255 'reset EndIf GoTo Check_Timers Case Keypres_Status 'used for lite flashing speed modulation 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 GoTo Check_Timers Case Aftertouch_Status 'added 01.08.2012 If aft = 255 Then 'single byte message aft = Bytein 'weak coding... GoSub Aftertouch EndIf End Select EndIf Check_Timers: ' here we check the Task counters and compare them with the 32 bit cnt value ' using the Velflags dword variable: If VelFlags0 > 0 Then 'if any bit is set here, there is a timer running If VelFlags0.0 = 1 Then veltim.Word1 = Velmsb[0] veltim.Word0 = VelLsb[0] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task0 'note 0 LEDLight1 EndIf If VelFlags0.1 = 1 Then veltim.Word1 = Velmsb[1] veltim.Word0 = VelLsb[1] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task1 'note 1 LEDLight2 EndIf If VelFlags0.2 = 1 Then veltim.Word1 = Velmsb[2] veltim.Word0 = VelLsb[2] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task2 'note 2 BlueArm1 EndIf If VelFlags0.3 = 1 Then veltim.Word1 = Velmsb[3] veltim.Word0 = VelLsb[3] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task3 'note 3 BlueArm2 EndIf If VelFlags0.4 = 1 Then veltim.Word1 = Velmsb[4] veltim.Word0 = VelLsb[4] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task4 'note 4 LEDLight5 EndIf If VelFlags0.5 = 1 Then veltim.Word1 = Velmsb[5] veltim.Word0 = VelLsb[5] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then GoSub Task5 'note 5 LEDLight6 EndIf 'Else ' If CntHw > 0xFF Then Clear CntHw EndIf If VelFlags1.0 = 1 Then ' this is the attack pulse timer veltim.Word1 = Velmsb[6] veltim.Word0 = VelLsb[6] Cnt.Word0 = CntLw If Cnt >= veltim Then HPWM 1, CC36, PWMFreq4 ' apply the holding force value 'Cnt.Word0 = CntLw 'Task_rsi[7] = CC34 << 9 ' program the timer for release - done in controller procedure veltim = Cnt + Task_rsi[7] ' set time-out Velmsb[7] = veltim.Word1 VelLsb[7] = veltim.Word0 Clear VelFlags1.0 Set VelFlags1.1 ' start duration timer for the hold and release time of the damper End If EndIf If VelFlags1.1 = 1 Then ' this is the damping release timer veltim.Word1 = Velmsb[7] veltim.Word0 = VelLsb[7] Cnt.Word0 = CntLw 'read counter If Cnt >= veltim Then ' 32 bit compare HPWM 1, 0 , PWMFreq4 ' release damper - release time set with CC34 Clear VelFlags1.1 EndIf EndIf GoTo LOOP ' end of the main loop KeyPres: 'the note to which the pressure should be applied is passed in NotePres, the value in Pres 'here we use it for flashing lights. Select notePres Case 120 If Lites.0 = 1 Then Set VelFlags0.0 Cnt.Word0 = CntLw 'read timer Task_rsi[0] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[0] 'add the period duration Velmsb[0] = veltim.Word1 VelLsb[0] = veltim.Word0 Else Clear VelFlags0.0 Clear LEDLight1 EndIf Case 121 If Lites.1 = 1 Then Set VelFlags0.1 Cnt.Word0 = CntLw 'read timer Task_rsi[1] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[1] 'add the period duration Velmsb[1] = veltim.Word1 VelLsb[1] = veltim.Word0 Else Clear VelFlags0.1 Clear LEDLight2 EndIf Case 122 If Lites.2 = 1 Then Set VelFlags0.2 Cnt.Word0 = CntLw 'read timer Task_rsi[2] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[2] 'add the period duration Velmsb[2] = veltim.Word1 VelLsb[2] = veltim.Word0 Else Clear VelFlags0.2 Clear BlueArm1 EndIf Case 123 If Lites.3 = 1 Then Set VelFlags0.3 Cnt.Word0 = CntLw 'read timer Task_rsi[3] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[3] 'add the period duration Velmsb[3] = veltim.Word1 VelLsb[3] = veltim.Word0 Else Clear VelFlags0.3 Clear BlueArm2 EndIf Case 124 If Lites.4 = 1 Then Set VelFlags0.4 Cnt.Word0 = CntLw 'read timer Task_rsi[4] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[4] 'add the period duration Velmsb[4] = veltim.Word1 VelLsb[4] = veltim.Word0 Else Clear VelFlags0.4 Clear LEDLight5 EndIf Case 125 If Lites.5 = 1 Then Set VelFlags0.5 Cnt.Word0 = CntLw 'read timer Task_rsi[5] = (~pres & 127) << 9 veltim = Cnt + Task_rsi[5] 'add the period duration Velmsb[5] = veltim.Word1 VelLsb[5] = veltim.Word0 Else Clear VelFlags0.5 Clear LEDLight6 EndIf End Select Set notePres '= 255 Return ProgChange: Set prog '= 255 'this is not realy required Return Pitchbend: 'only implemented on dsPIC based robots Set pblsb '= 255 Return Aftertouch: 'this is the channel aftertouch, affecting all notes - added 01.08.2012 ' volume modulation for exciter value = aft << 1 HPWM 2, value, PWMFreq4 Set aft '= 255 'not mandatory Return Controller: Select Ctrl Case 33 ' damping attack time CC33 = value Task_rsi[6] = CC33 << 6 ' <<4 was too short Case 34 ' damping hold/release time CC34 = value Task_rsi[7] = CC34 << 9 ' program the timer for release - must remain within word boundaries Case 35 ' attack force controll (for PWM during attack time) CC35 = 128 + value ' range 128 to 255 Case 36 ' hold force controll (for PWM during damper hold) CC36 = value << 1 ' range 0 to 254 Case 64 ' sustain controller ' if zero: no sustain and so the dampers will be active ' if non-zero: damping solenoid will be disabled. CC64 = value If CC64 > 0 Then Clear VelFlags1 HPWM 1, 0, PWMFreq4 EndIf Case 66 'on/off for the robot - resets controllers If value = 0 Then GoSub PowerDown Else GoSub PowerUp EndIf Case 123 GoSub AllNotesOff ' disregard value End Select Set Ctrl '= 255 'mandatory reset Return AllNotesOff: Clear VelFlags 'stop all running timers Clear LEDLight1 Clear LEDLight2 Clear BlueArm1 Clear BlueArm2 Clear LEDLight5 Clear LEDLight6 Low Debug_Led Clear Lites HPWM 2, 0, PWMFreq4 'softshift exciter HPWM 1, 0, PWMFreq4 'damper solenoid Clear CntHw 'reset counter Return PowerDown: Clear VelFlags 'stop all running timers Clear LEDLight1 Clear LEDLight2 Clear BlueArm1 Clear BlueArm2 Clear LEDLight5 Clear LEDLight6 Low Debug_Led Clear Lites HPWM 2, 0, PWMFreq4 'softshift 1 HPWM 1, 0, PWMFreq4 'softshift 2 Clear PowerOn ' = Clear CC66.0 Clear CntHw 'reset counter Return PowerUp: ' set all controllers to their default startup values GoSub AllNotesOff CC33 = DefaultCC33 Task_rsi[6] = CC33 << 6 ' <<4 was too short CC34 = DefaultCC34 Task_rsi[7] = CC34 << 9 CC35 = 128 + DefaultCC35 '255 CC36 = DefaultCC36 << 1 '140 Set PowerOn ' = set CC66.0 Return Task0: If Lites.0 = 0 Then Clear VelFlags0.0 'stop task, as lite is switched off Clear LEDLight1 '= 0 Else 'reload task0 - light 'Set VelFlags0.0 'can just stay set Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[0] 'add the period duration Velmsb[0] = veltim.Word1 VelLsb[0] = veltim.Word0 btg LEDLight1 ' toggle EndIf Return Task1: If Lites.1 = 0 Then Clear VelFlags0.1 'stop task, as lite is switched off Clear LEDLight2 ' = 0 ' geel Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[1] 'add the period duration in Task_rsi[1] Velmsb[1] = veltim.Word1 VelLsb[1] = veltim.Word0 btg LEDLight2 EndIf Return Task2: If Lites.2 = 0 Then Clear VelFlags0.2 'stop task, as lite is switched off Clear BlueArm1 ' rood Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[2] 'add the period duration Velmsb[2] = veltim.Word1 VelLsb[2] = veltim.Word0 btg BlueArm1 EndIf Return Task3: If Lites.3 = 0 Then Clear VelFlags0.3 'stop task, as lite is switched off Clear BlueArm2 'rood Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[3] 'add the period duration Velmsb[3] = veltim.Word1 VelLsb[3] = veltim.Word0 btg BlueArm2 EndIf Return Task4: If Lites.4 = 0 Then Clear VelFlags0.4 'stop task, as lite is switched off Clear LEDLight5 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[4] 'add the period duration Velmsb[4] = veltim.Word1 VelLsb[4] = veltim.Word0 btg LEDLight5 EndIf Return Task5: If Lites.5 = 0 Then Clear VelFlags0.5 'stop task, as lite is switched off Clear LEDLight6 Else Cnt.Word0 = CntLw veltim = Cnt + Task_rsi[5] 'add the period duration Velmsb[5] = veltim.Word1 VelLsb[5] = veltim.Word0 btg LEDLight6 EndIf Return '[EOF]