' *************************************************************************** ' * * ' *************************************************************************** ' 08.2000: start coding by Kristof Lauwers ' beating tasks done, work in midisimu ' implementation of detuning not done yet ... ' 03.2001: continued by Godfried-Willem Raes ' 21.03.2001: 82C54 board prototypes ready for testing ' 23.03.2001: test coding with hardware ' 24.03.2001: further testing... ' 27.03.2001: resolution of taskfrequency is limited to 1ms increments. ' 29.03.2001: Flipbyte procedure added to dll, to overcome hardware bug in timerboard prototype.(D0-D7 mirror error) ' 10.04.2001: TIG welding rototoms nearly finished. ' 15.04.2001: stepper circuits redesigned. Software mapping changed ' 16.04.2001: hardware fully debugged. ' 24.04.2001: first test with hardware mounted on instrument ' 26.04.2001: Rotomoton basically working... ' 30.04.2001: polishing ' 01.05.2001: procs. moved to DLL ' 03.05.2001: dll extended, testcode removed from this module. ' 04.05.2001: written for Rotomoton ' 11.05.2001: ready. ' 15.05.2001: all rotomoton code now in g_n*h.dll ' 16.05.2001: support for NiDAQ cards added. ' 09.07.2001: midi listen written by Kristof Lauwers ' roto_listen moved to dll. ' 02.06.2002: display testcode removed. ' 22.06.2002: listentask replaced to standard %ppListen. , %Rotstuk changed to 19,20,21 (in g_kons.bi) ' 24.07.2004: listen improved with mask. task declares done in dll now. Major rewrite! To be checked. ' 19.09.2006: This version now placed in archive as rotomo.inc. Start rebuilding to make it a ' midi robot. The test code for evaluation and experiment is now rotomoton.inc ' 21.09.2006: Start translation of Rotstuk. Not finished yet: motor implementation problem. ' 23.09.2006: Test pulseboard with PIC controller 18F252. Check mapping, hardware and dynamic range. ' 11.01.2007: test code added for new controllers. ' 31.08.2007: motor PICs programmed ' 01.08.2007: code upgraded and adapted to new implementation. Debug session. ' will not work as long as key aftertouch is not implemented on the beater pic. ' Rotomoton should now work as a midi controlled robot. ' 06.09.2007: Pic programming session. Sysex implemented. Pincode = roto ' 17.09.2007: Motor pics reprogrammed. New ctrls implemented. DECLARE FUNCTION Init_Rotomoton () AS LONG ' midi-pulse board PIC: [ fills the entire last column in the GMT cockpit] DECLARE SUB BasB0 () ' for testing individual beaters - task 48 DECLARE SUB BasB1 () DECLARE SUB BasB2 () DECLARE SUB TenB0 () DECLARE SUB TenB1 () DECLARE SUB TenB2 () DECLARE SUB MezB0 () DECLARE SUB MezB1 () DECLARE SUB AltB0 () DECLARE SUB AltB1 () DECLARE SUB SopB0 () DECLARE SUB SopB1 () DECLARE SUB N60 () ' extra outputs DECLARE SUB N61 () DECLARE SUB N62 () DECLARE SUB N63 () ' task 63 ' midi-hub board PIC: [ third column of the GMT cockpit] DECLARE SUB Roto_Light1 ' 32 note 114 DECLARE SUB Roto_Light2 ' 33 note 115 DECLARE SUB Roto_Light3 ' 34 note 116 DECLARE SUB Roto_Light4 ' 35 note 117 ' check tuning of each drum. Calibrates on end positions. [2007] DECLARE SUB Tune_Bas () ' 43 DECLARE SUB Tune_Ten () ' 44 DECLARE SUB Tune_Alt () ' 45 DECLARE SUB Tune_Mez () ' 46 DECLARE SUB Tune_Sop () ' 47 ' calibrates only the lowest position [2007] DECLARE SUB Roto_CaliBas () DECLARE SUB Roto_CaliTen () DECLARE SUB Roto_CaliAlt () DECLARE SUB Roto_CaliMez () DECLARE SUB Roto_CaliSop () ' calibrates only the highest position [2007] DECLARE SUB Roto_CaliBas_H () DECLARE SUB Roto_CaliTen_H () DECLARE SUB Roto_CaliAlt_H () DECLARE SUB Roto_CaliMez_H () DECLARE SUB Roto_CaliSop_H () ' compositions for %Rotstuk = 19 ' was 16 ' first piece for rotomoton by Godfried-Willem Raes ' nr 20,21 reserved was: nr.17,19 reserved! ' also uses 25-29 %g_rotstuk= 1 ' define to include rotstuk -gwr DECLARE SUB RotStuk () ' composition nr. 1 for Rotomoton by Godfried-Willem RAES, 05.2001 DECLARE SUB Rotstuk_UI () ' auxiliary task for Rotstuk. %Rotstuk+1 DECLARE SUB Rotstuk_Hold () ' id. %Rotstuk+2 DECLARE SUB Rotstuk_bas_beat () 'basRoto ' was task 11 tasknumbers set in Rotomoton.motortasks(1,2,3,4,5) DECLARE SUB Rotstuk_ten_beat () 'tenorRoto ' task 12 DECLARE SUB Rotstuk_alt_beat () 'altoRoto ' task 13 DECLARE SUB Rotstuk_mez_beat () 'mezzoroto ' task 14 DECLARE SUB Rotstuk_sop_beat () 'highroto ' task 15 '%swarm = %true 'SHOULD COME AFTER DECLARATION OF ROTOMOTON TYPE!! #IF %DEF(%swarm) #INCLUDE ".\rotomo~1\swarm.inc" ' will need complete revision. #ENDIF ' tasks 1,2,3,4,5 used for motor movement resided in the DLL and cannot be moved. (Roto_M1 etc...) FUNCTION Init_Rotomoton () AS LONG LOCAL note AS BYTE LOCAL retval AS LONG LOCAL m AS ASCIIZ * 30 Task(14).naam = "" ' delete shownote task Task(14).cptr = %False Task(15).naam = "" ' delete global task. Task(15).cptr = %False '#IF %DEF(%G_Rotstuk) Task(%Rotstuk).naam = "RotStuk" Task(%Rotstuk).freq = 100 Task(%Rotstuk).cptr = CODEPTR(RotStuk) Task(%Rotstuk+1).naam ="R-Pitch" Task(%Rotstuk+1).freq = 1 Task(%Rotstuk+1).cptr = CODEPTR(Rotstuk_UI) Task(%Rotstuk+2).naam = "R-Hold" Task(%Rotstuk+2).freq = 0.5 Task(%Rotstuk+2).cptr = CODEPTR(Rotstuk_Hold) 'for rotstuk ' drum 1 - motor 1 Task(25).naam = "RSBasBt" Task(25).freq = 5 Task(25).level = 64 Task(25).channel = Rotomoton.channel '8 'for midi task(25).patch = 117 task(25).duur = 63 'used for midi note. must be global so we can change it for simu of rotating toms 'or do we use pitchbend instead? Task(25).cptr = CODEPTR(Rotstuk_bas_beat) ' drum 2 - motor 2 Task(26).naam = "RSTenBt" Task(26).freq = 5 Task(26).level = 64 Task(26).channel = Rotomoton.channel '8 'for midi task(26).patch = 117 task(26).duur = 68 Task(26).cptr = CODEPTR(Rotstuk_ten_beat) ' drum 3 - motor 3 Task(27).naam = "RSAltBt" Task(27).freq = 5 Task(27).level = 64 Task(27).channel = Rotomoton.channel '8 'for midi task(27).patch = 117 task(27).duur = 73 Task(27).cptr = CODEPTR(Rotstuk_alt_beat) ' drum 4 - motor 4 Task(28).naam = "RSMezBt" Task(28).freq = 5 Task(28).level = 64 Task(28).channel = Rotomoton.channel '8 'for midi task(28).patch = 117 task(28).duur = 78 Task(28).cptr = CODEPTR(Rotstuk_mez_beat) ' drum 5 - motor 5 Task(29).naam = "RSSopBt" Task(29).freq = 5 Task(29).level = 64 Task(29).channel = Rotomoton.channel '8 'for midi task(29).patch = 117 task(29).duur = 83 Task(29).cptr = CODEPTR(Rotstuk_sop_beat) '#endif ' derde kolom in kokpit - test procedures midihub board - adapted rotomoton 2006/7 Task(32).naam = "Spot1" Task(32).cptr = CODEPTR(Roto_light1) Task(32).freq = 0.5 Task(33).naam = "Spot2" Task(33).cptr = CODEPTR(Roto_light2) Task(33).freq = 0.3333 Task(34).naam = "BluForw" Task(34).cptr = CODEPTR(Roto_light3) Task(34).freq = 1.2 Task(35).naam = "BluBack" Task(35).cptr = CODEPTR(Roto_light4) Task(35).freq = 1.5 ' slider tuning controllers for drum tuning and traject testing. [2007] Task(43).naam = "TuneBas" Task(43).cptr = CODEPTR(Tune_Bas) Task(43).freq = 20 Task(44).naam = "TuneTen" Task(44).cptr = CODEPTR(Tune_Ten) Task(44).freq = 20 Task(45).naam = "TuneAlt" Task(45).cptr = CODEPTR(Tune_Alt) Task(45).freq = 20 Task(46).naam = "TuneMez" Task(46).cptr = CODEPTR(Tune_Mez) Task(46).freq = 20 Task(47).naam = "TuneSop" Task(47).cptr = CODEPTR(Tune_Sop) Task(47).freq = 20 ' vierde kolom ' test procedures for individual beaters - adapted to Rotomoton 2006 Task(48).naam = "BasB0" Task(48).cptr = CODEPTR(BasB0) Task(48).freq = 100 Task(48).level = 20 Task(49).naam = "BasB1" Task(49).cptr = CODEPTR(BasB1) Task(49).freq = 100 Task(49).level = 64 Task(50).naam = "BasB2" Task(50).cptr = CODEPTR(BasB2) Task(50).freq = 100 Task(50).level = 64 Task(51).naam = "TenB0" Task(51).cptr = CODEPTR(TenB0) Task(51).freq = 100 Task(51).level = 64 Task(52).naam = "TenB1" Task(52).cptr = CODEPTR(TenB1) Task(52).freq = 100 Task(52).level = 64 Task(53).naam = "TenB2" Task(53).cptr = CODEPTR(TenB2) Task(53).freq = 100 Task(53).level = 64 Task(54).naam = "AltB0" Task(54).cptr = CODEPTR(AltB0) Task(54).freq = 100 Task(54).level = 64 Task(55).naam = "AltB1" Task(55).cptr = CODEPTR(AltB1) Task(55).freq = 100 Task(55).level = 64 Task(56).naam = "MezB0" Task(56).cptr = CODEPTR(MezB0) Task(56).freq = 100 Task(56).level = 64 Task(57).naam = "MezB1" Task(57).cptr = CODEPTR(MezB1) Task(57).freq = 100 Task(57).level = 64 Task(58).naam = "SopB0" Task(58).cptr = CODEPTR(SopB0) Task(58).freq = 100 Task(58).level = 64 Task(59).naam = "SopB1" Task(59).cptr = CODEPTR(SopB1) Task(59).freq = 100 Task(59).level = 64 Task(60).naam = "N60" Task(60).cptr = CODEPTR(N60) Task(60).freq = 100 Task(60).level = 64 Task(61).naam = "N61" Task(61).cptr = CODEPTR(N61) Task(61).freq = 100 Task(61).level = 64 Task(62).naam = "N62" Task(62).cptr = CODEPTR(N62) Task(62).freq = 100 Task(62).level = 64 Task(63).naam = "N63" Task(63).cptr = CODEPTR(N63) Task(63).freq = 100 Task(63).level = 64 'delete unnecessary buttons IF ISFALSE hMidiI(0) THEN ButnSW(0).tag0 = "" ButnSW(0).cptr = %False END IF IF ISFALSE hMidiO(0) THEN ButnOS(0).tag = "" ButnOS(0).cptr = %False END IF ButnSW(1).tag0 = "" ButnSW(1).tag1 = "" ButnSW(1).cptr = CODEPTR(Roto_Start_Button) ButnSW(2).tag0 = "" ButnSW(3).tag0 = "" ButnSW(4).tag0 = "" ButnSW(5).tag0 = "" ButnSW(6).tag0 = "" ButnSW(7).tag0 = "" ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" ButnSW(11).tag0 = "" ' one shot buttons 'ButnOS(2).tag = "" '"Log" 'ButnOS(2).cptr = 0 '"CODEPTR(Roto_Log) ButnOS(2).tag = "CalL1" ButnOS(2).cptr = CODEPTR(Roto_Calibas) ButnOS(3).tag = "CalL2" ButnOS(3).cptr = CODEPTR(Roto_CaliTen) ButnOS(4).tag = "CalL3" ButnOS(4).cptr = CODEPTR(Roto_CaliAlt) ButnOS(5).tag = "CalL4" ButnOS(5).cptr = CODEPTR(Roto_CaliMez) ButnOS(6).tag = "CalL5" ButnOS(6).cptr= CODEPTR(Roto_CaliSop) ButnOS(7).tag = "CalH1" ButnOS(7).cptr = CODEPTR(Roto_Calibas_H) ButnOS(8).tag = "CalH2" ButnOS(8).cptr = CODEPTR(Roto_CaliTen_H) ButnOS(9).tag = "CalH3" ButnOS(9).cptr = CODEPTR(Roto_CaliAlt_H) ButnOS(10).tag = "CalH4" ButnOS(10).cptr = CODEPTR(Roto_CaliMez_H) ButnOS(11).tag = "CalH5" ButnOS(11).cptr= CODEPTR(Roto_CaliSop_H) ' #ENDIF SetDlgItemText gh.Cockpit, %GMT_TITLE, "" #IF %DEF(%swarm) SwarmInit 'will not be compatible with other pieces! overwrites tasks ' to be adapted by krl. #ENDIF FUNCTION = %true END FUNCTION SUB Roto_Start_Button () STATIC tog AS BYTE IF ButnSW(1).Flag THEN SetDlgItemText gh.Cockpit, App.butnSWparam, "Stop" App.MTstart = %True IF ISFALSE tog THEN IF hMidiI(0) THEN ClearMiBuf 0 ' start with a blank midi input buffer BlockSysExReception hMidiI(0) 'SxThread END IF App.tstart = timeGetTime ' start the chronometerfunction Runtime %True MM_Rotomoton_On ' ctrl 66 and 65 - calibrates low and/or high ' Controller Rotomoton.channel, 111, %True ' calibrate not required. ' Controller Rotomoton.channel, 112, %True ' Controller Rotomoton.channel, 113, %True ' Controller Rotomoton.channel, 114, %True ' Controller Rotomoton.channel, 115, %True tog = %True END IF ELSE App.MTstart = %False SetDlgItemText gh.Cockpit, App.butnSWparam, "Cont" END IF END SUB '#IF %DEF(%G_Rotstuk) 'playing tasks: - translated 21.09.2006 gwr SUB Rotstuk_bas_beat() STATIC slnr AS LONG STATIC beater AS LONG IF ISFALSE task(25).tog THEN Task(25).tog = %true DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Velo " IF ISFALSE Task(25).hParam THEN MakeTaskParameterDialog 25,2,Slider(),0,UDctrl(),TaskParamLabels() END IF beater = 48 EXIT SUB END IF IF slnr = %False THEN slnr = TaskEX(25).SliderNumbers(0) MoveWindow Task(25).hparam, 190,0, 190, 92, %True END IF IF ISFALSE Slider(slnr).value THEN stoptask 25 'stoptask Rotomoton.beattask(1) 'NoteOff Rotomoton.channel, 48 EXIT SUB ELSE 'Task(Rotomoton.beattask(1)).freq = Slider(slnr).value / 4 'Task(Rotomoton.beattask(1)).level = Slider(slnr+1).value 'sic 11 as roto_bas_beat uses its own level mPlay Rotomoton.channel, beater, Slider(slnr+1).value KeyPress Rotomoton.channel, beater, Slider(slnr).value / 4 ' not implemented on pic's 2007 END IF INCR beater IF beater > 50 THEN beater = 48 'Roto_bas_beat 'IF ISFALSE Task(Rotomoton.beattask(1)).swit THEN starttask Rotomoton.beattask(1) END SUB SUB Rotstuk_ten_beat() STATIC slnr AS LONG STATIC beater AS LONG IF ISFALSE task(26).tog THEN Task(26).tog = %true DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Velo " IF ISFALSE Task(26).hParam THEN MakeTaskParameterDialog 26,2,Slider(),0,UDctrl(),TaskParamLabels() END IF beater = 51 EXIT SUB END IF IF slnr = %False THEN slnr = TaskEX(26).SliderNumbers(0) MoveWindow Task(26).hparam, 190,92, 190, 92, %True END IF IF ISFALSE Slider(slnr).value THEN stoptask 26 'stoptask Rotomoton.beattask(2) 'NoteOff Rotomoton.channel, 51 EXIT SUB ELSE 'Task(Rotomoton.beattask(2)).freq = Slider(slnr).value / 4 'Task(Rotomoton.beattask(2)).level = Slider(slnr+1).value 'sic 11 as roto_bas_beat uses its own level mPlay Rotomoton.channel, beater, Slider(slnr+1).value KeyPress Rotomoton.channel, beater, Slider(slnr).value / 4 END IF INCR beater IF beater > 53 THEN beater = 51 'IF ISFALSE Task(Rotomoton.beattask(2)).swit THEN starttask Rotomoton.beattask(2) END SUB SUB Rotstuk_alt_beat() STATIC slnr AS LONG STATIC beater AS LONG IF ISFALSE task(27).tog THEN Task(27).tog = %true DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Velo " IF ISFALSE Task(27).hParam THEN MakeTaskParameterDialog 27,2,Slider(),0,UDctrl(),TaskParamLabels() END IF beater = 54 EXIT SUB END IF IF slnr = %False THEN slnr = TaskEX(27).SliderNumbers(0) MoveWindow Task(27).hparam, 190,92+92, 190, 92, %True END IF IF ISFALSE Slider(slnr).value THEN stoptask 27 'stoptask Rotomoton.beattask(3) 'NoteOff Rotomoton.channel, 54 EXIT SUB ELSE 'Task(Rotomoton.beattask(3)).freq = Slider(slnr).value / 4 'Task(Rotomoton.beattask(3)).level = Slider(slnr+1).value mPlay Rotomoton.channel, beater, Slider(slnr+1).value KeyPress Rotomoton.channel, beater, Slider(slnr).value /4 END IF INCR beater IF beater > 55 THEN beater = 54 'IF ISFALSE Task(Rotomoton.beattask(3)).swit THEN starttask Rotomoton.beattask(3) END SUB SUB Rotstuk_mez_beat() STATIC slnr AS LONG STATIC beater AS LONG IF ISFALSE task(28).tog THEN Task(28).tog = %true DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Velo " IF ISFALSE Task(28).hParam THEN MakeTaskParameterDialog 28,2,Slider(),0,UDctrl(),TaskParamLabels() END IF beater = 56 EXIT SUB END IF IF slnr = %False THEN slnr = TaskEX(28).SliderNumbers(0) MoveWindow Task(28).hparam, 190,92+92+92, 190, 92, %True END IF IF ISFALSE Slider(slnr).value THEN stoptask 28 'stoptask Rotomoton.beattask(4) 'NoteOff Rotomoton.channel, 56 EXIT SUB ELSE 'Task(Rotomoton.beattask(4)).freq = Slider(slnr).value / 4 'Task(Rotomoton.beattask(4)).level = Slider(slnr+1).value 'sic 11 as roto_bas_beat uses its own level mPlay Rotomoton.channel, beater, Slider(slnr+1).value KeyPress Rotomoton.channel, beater, Slider(slnr).value / 4 END IF INCR beater IF beater > 57 THEN beater = 56 'IF ISFALSE Task(Rotomoton.beattask(4)).swit THEN starttask Rotomoton.beattask(4) END SUB SUB Rotstuk_sop_beat() STATIC slnr AS LONG STATIC beater AS LONG IF ISFALSE task(29).tog THEN Task(29).tog = %true DIM TaskParamLabels(0 TO 1) AS ASCIIZ * 8 TaskParamLabels(0) = "Speed" TaskParamLabels(1) = "Velo " IF ISFALSE Task(29).hParam THEN MakeTaskParameterDialog 29,2,Slider(),0,UDctrl(),TaskParamLabels() END IF beater = 58 EXIT SUB END IF IF slnr = %False THEN slnr = TaskEX(29).SliderNumbers(0) MoveWindow Task(29).hparam, 190,92+92+92+92, 190, 92, %True END IF IF ISFALSE Slider(slnr).value THEN NoteOff Rotomoton.channel, 58 stoptask 29 'stoptask Rotomoton.beattask(5) EXIT SUB ELSE 'Task(Rotomoton.beattask(5)).freq = Slider(slnr).value / 4 'Task(Rotomoton.beattask(5)).level = Slider(slnr+1).value mPlay Rotomoton.channel, beater, Slider(slnr+1).value KeyPress Rotomoton.channel, beater, Slider(slnr).value / 4 END IF INCR beater IF beater > 59 THEN beater = 58 'IF ISFALSE Task(Rotomoton.beattask(5)).swit THEN starttask Rotomoton.beattask(5) END SUB '#endif ' hardware test code - 16pulse board PIC1 SUB BasB0 IF ISFALSE Task(48).tog THEN Task(48).tog = %True Task(48).level = Slider(0).value ' cockpit sliders Task(48).freq = Slider(1).value / 8 ' note 48 = note 0 mPlay Rotomoton.channel, 48, Slider(0).value END SUB SUB BasB1 Task(49).level = Slider(0).value Task(49).freq = Slider(1).value / 8 ' note 49 = note 1 mPlay Rotomoton.channel, 49, Slider(0).value END SUB SUB BasB2 Task(50).level = Slider(0).value Task(50).freq = Slider(1).value / 8 ' note 50 = note 2 mPlay Rotomoton.channel, 50, Slider(0).value END SUB SUB TenB0 Task(51).level = Slider(0).value Task(51).freq = Slider(1).value / 8 ' note 51 = note 3 mPlay Rotomoton.channel, 51, Slider(0).value END SUB SUB TenB1 Task(52).level = Slider(0).value Task(52).freq = Slider(1).value / 8 ' note 52 = note 4 mPlay Rotomoton.channel, 52, Slider(0).value END SUB SUB TenB2 Task(53).level = Slider(0).value Task(53).freq = Slider(1).value / 8 ' note 53 = note 5 mPlay Rotomoton.channel, 53, Slider(0).value END SUB SUB AltB0 Task(54).level = Slider(0).value Task(54).freq = Slider(1).value / 8 ' note 54 = note 6 mPlay Rotomoton.channel, 54, Slider(0).value END SUB SUB AltB1 Task(55).level = Slider(0).value Task(55).freq = Slider(1).value / 8 ' note 55 = note 7 mPlay Rotomoton.channel, 55, Slider(0).value END SUB SUB MezB0 Task(56).level = Slider(0).value Task(56).freq = Slider(1).value / 8 ' note 56 mPlay Rotomoton.channel, 56, Slider(0).value END SUB SUB MezB1 () Task(57).level = Slider(0).value Task(57).freq = Slider(1).value / 8 ' note 57 mPlay Rotomoton.channel, 57, Slider(0).value END SUB SUB SopB0 () Task(58).level = Slider(0).value Task(58).freq = Slider(1).value / 8 ' note 58 mPlay Rotomoton.channel, 58, Slider(0).value END SUB SUB SopB1 () Task(59).level = Slider(0).value Task(59).freq = Slider(1).value / 8 ' note 59 mPlay Rotomoton.channel, 59, Slider(0).value END SUB SUB N60 Task(60).level = Slider(0).value Task(60).freq = Slider(1).value / 8 ' note 60 mPlay Rotomoton.channel, 60, Slider(0).value END SUB SUB N61 Task(61).level = Slider(0).value Task(61).freq = Slider(1).value / 8 ' note 61 mPlay Rotomoton.channel, 61, Slider(0).value END SUB SUB N62 () Task(62).level = Slider(0).value Task(62).freq = Slider(1).value / 8 ' note 62 mPlay Rotomoton.channel, 62, Slider(0).value END SUB SUB N63 Task(63).level = Slider(0).value Task(63).freq = Slider(1).value / 8 ' note 63 mPlay Rotomoton.channel, 63, Slider(0).value END SUB SUB Roto_Light1 () '32 - spotlights - now with pwm dimming STATIC onoff AS BYTE mPlay Rotomoton.channel, 114, onoff * 127 BIT TOGGLE onoff, 0 END SUB SUB Roto_Light2 () '33 STATIC onoff AS BYTE mPlay Rotomoton.channel, 115, onoff *127 BIT TOGGLE onoff,0 END SUB SUB Roto_Light3 () 'blue LEDspot - oriented outwards frontal STATIC onoff AS BYTE mPlay Rotomoton.channel, 116, onoff * 127 BIT TOGGLE onoff, 0 END SUB SUB Roto_Light4 () 'blue LED spot - oriented towards drums STATIC onoff AS BYTE mPlay Rotomoton.channel, 117, onoff *127 BIT TOGGLE onoff,0 END SUB #IF %DEF(%g_rotstuk) ' composition code... SUB RotStuk () ' parametric rubberbanding algorithm ' by Godfried-Willem Raes ' implements a convergence parameter: converge to max., converge to min, converge to avg. STATIC onoff AS BYTE ' for lights STATIC t AS SINGLE LOCAL i AS LONG STATIC slnr AS LONG LOCAL taskslidernr AS LONG LOCAL tp AS BYTE LOCAL fchanging AS BYTE LOCAL vchanging AS BYTE LOCAL fconverge AS BYTE LOCAL vconverge AS BYTE LOCAL lv AS LONG LOCAL lm AS LONG LOCAL av AS LONG ' following mapped on sliders in the cockpit! LOCAL f_cvg AS INTEGER ' -1 for converge to minimum, +1 for converge to maximum, 0 for converge to average LOCAL v_cvg AS INTEGER IF ISFALSE Task(%Rotstuk).tog THEN SetDlgItemText gh.Cockpit, %GMT_TITLE, "" SetDlgItemText gh.Cockpit, %GMT_AUTHOR, $gwr SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER0, "f-converge" SetDlgItemText gh.Cockpit, %GMT_TEXT_SLIDER1, "v-converge" DIM TaskParamLabels(0 TO 10) AS ASCIIZ * 8 TaskParamLabels(0) = "Bas" TaskParamLabels(1) = "Ten" TaskParamLabels(2) = "Alt" TaskParamlabels(3) = "Mez" TaskParamLabels(4) = "Sop" TaskParamLabels(5) = "Bv" TaskParamLabels(6) = "Tv" TaskParamLabels(7) = "Av" TaskParamlabels(8) = "Mv" TaskParamLabels(9) = "Sv" TaskParamLabels(10) ="Freq" onoff = %False IF ISFALSE Task(%Rotstuk).hParam THEN MakeTaskParameterdialog %Rotstuk,11,Slider(),0,UDctrl(),Taskparamlabels() END IF Task(%Rotstuk).tog = %True t = TIMER ' second resolution is more then good enough here. 'timeGetTime Task(%Rotstuk).freq = 1 IF ISFALSE Task(25).swit THEN starttask 25 ' beaters IF ISFALSE task(26).swit THEN starttask 26 IF ISFALSE Task(27).swit THEN starttask 27 IF ISFALSE task(28).swit THEN starttask 28 IF ISFALSE task(29).swit THEN starttask 29 EXIT SUB END IF IF ISFALSE slnr THEN slnr = TaskEX(%Rotstuk).SliderNumbers(0) Slider(slnr).value = 1 Slider(slnr+1).value = 1 Slider(slnr+2).value = 1 Slider(slnr+3).value = 1 Slider(slnr+4).value = 1 Slider(slnr+5).value = 1 Slider(slnr+6).value = 1 Slider(slnr+7).value = 1 Slider(slnr+8).value = 1 Slider(slnr+9).value = 1 Slider(slnr+10).value = 40 ' task frequency (divide by 20) SendMessage Slider(slnr).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+2).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+3).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+4).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+5).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+6).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+7).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+8).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+9).h, %TBM_SETPOS,%True, 1 SendMessage Slider(slnr+10).h, %TBM_SETPOS,%True, 40 FOR i = 0 TO 4 taskslidernr = TaskEX(25+i).Slidernumbers(0) Slider(Taskslidernr).value = 1 Slider(Taskslidernr+1).value = 1 SendMessage Slider(Taskslidernr).h, %TBM_SETPOS,%True, 1 SendMessage Slider(Taskslidernr+1).h, %TBM_SETPOS,%True, 1 NEXT i MoveWindow Task(%Rotstuk).hparam, 0,182, 190, 182+182, %True EXIT SUB END IF ' IF ISFALSE task(%Rotstuk+1).tog THEN ' Task(%Rotstuk+1).freq = 0.1 ' starttask %rotstuk + 1 ' EXIT SUB ' END IF Task(%Rotstuk).freq = Slider(slnr+10).value / 20 ' we access the sliders in other tasks as well! FOR i = 1 TO 5 taskslidernr = TaskEX(25+i-1).Slidernumbers(0) tp = Slider(taskslidernr).value IF Slider(slnr+ i-1).value <> tp THEN INCR fchanging IF Slider(slnr + i -1).value < tp THEN IF tp > 0 THEN DECR tp DECR Slider(taskslidernr).value SendMessage Slider(taskslidernr).h, %TBM_SETPOS,%True,tp END IF ELSE IF tp < 127 THEN INCR tp INCR Slider(taskslidernr).value SendMessage Slider(taskslidernr).h, %TBM_SETPOS,%True,tp END IF END IF ELSE ' freq waarden gelijk... END IF NEXT i FOR i = 5 TO 9 taskslidernr = TaskEX(25+i-5).Slidernumbers(1) tp = Slider(taskslidernr).value IF Slider(slnr+i).value <> tp THEN INCR vchanging IF Slider(slnr + i).value < tp THEN IF tp > 0 THEN DECR Slider(taskslidernr).value DECR tp SendMessage Slider(taskslidernr).h, %TBM_SETPOS,%True,tp IF ISFALSE Task(25+i-1).swit THEN starttask 25' ??25+i-1 END IF ELSE IF tp < 127 THEN INCR tp INCR Slider(taskslidernr).value SendMessage Slider(taskslidernr).h, %TBM_SETPOS,%True,tp END IF END IF ELSE ' velo waarde is gelijk geworden... END IF NEXT i IF ISFALSE fchanging THEN f_cvg = SGN(Slider(0).value - 64) fconverge = %False SELECT CASE f_cvg CASE %False ' calculate the average value: av = Slider(slnr).value + Slider(slnr+1).value + Slider(slnr+2).value + Slider(slnr+3).value + Slider(slnr+4).value av = av / 5 ' get the highest slider: lm = MAX(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) ' find the corresponding slider: i = %False DO IF Slider(slnr+i).value = lm THEN EXIT LOOP INCR i LOOP ' now set (descend) this slider to the average value: IF Slider(slnr+i).value <> av THEN Slider(slnr+i).value = av SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,av fconverge = %true END IF ' find the slider corresponding to the minimum value: lv = MIN(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) i= %False DO IF Slider(slnr+i).value = lv THEN EXIT LOOP INCR i LOOP ' now set (raise) this slider to the average value: IF Slider(slnr+i).value <> av THEN Slider(slnr+i).value = av SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,av fconverge = %True END IF CASE -1 ' minimum value: lv = MIN(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) ' get the highest slider: lm = MAX(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) ' find the corresponding slider: i = %False DO IF Slider(slnr+i).value = lm THEN EXIT LOOP INCR i LOOP ' now set (descend) this slider to the minimum value: IF Slider(slnr+i).value <> lv THEN Slider(slnr+i).value = lv SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,lv fconverge = %true END IF CASE +1 'maximum value: lm = MAX(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) ' get the lowest slider: lv = MIN(Slider(slnr).value,Slider(slnr+1).value,Slider(slnr+2).value,Slider(slnr+3).value,Slider(slnr+4).value) ' find the corresponding slider: i = %False DO IF Slider(slnr+i).value = lv THEN EXIT LOOP INCR i LOOP ' now set (descend) this slider to the minimum value: IF Slider(slnr+i).value <> lm THEN Slider(slnr+i).value = lm SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,lm fconverge = %true END IF END SELECT END IF IF ISFALSE vchanging THEN v_cvg = SGN(Slider(1).value - 64) vconverge = %false SELECT CASE v_cvg CASE %False ' calculate average value: av = Slider(slnr+5).value + Slider(slnr+6).value + Slider(slnr+7).value + Slider(slnr+8).value + Slider(slnr+9).value av = av / 5 ' get the highest slider: lm = MAX(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' find the corresponding slider: i = 5 DO IF Slider(slnr+i).value = lm THEN EXIT LOOP INCR i LOOP ' now set this slider to the average value: IF Slider(slnr+i).value <> av THEN Slider(slnr+i).value = av SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,av vconverge = %True END IF ' get the lowest amplitude lv = MIN(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' find the corresponding slider: i = 5 DO IF Slider(slnr+i).value = lv THEN EXIT LOOP INCR i LOOP ' now set this slider to the average value: IF Slider(slnr+i).value <> av THEN Slider(slnr+i).value = av SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,av vconverge = %True END IF CASE -1 ' minimum value: lv = MIN(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' get the highest slider: lm = MAX(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' find the corresponding slider: i = 5 DO IF Slider(slnr+i).value = lm THEN EXIT LOOP INCR i LOOP ' now set (descend) this slider to the minimum value: IF Slider(slnr+i).value <> lv THEN Slider(slnr+i).value = lv SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,lv fconverge = %true END IF CASE +1 ' get the highest slider: lm = MAX(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' minimum value: lv = MIN(Slider(slnr+5).value,Slider(slnr+6).value,Slider(slnr+7).value,Slider(slnr+8).value,Slider(slnr+9).value) ' find the corresponding slider: i = 5 DO IF Slider(slnr+i).value = lv THEN EXIT LOOP INCR i LOOP ' now set (descend) this slider to the minimum value: IF Slider(slnr+i).value <> lm THEN Slider(slnr+i).value = lm SendMessage Slider(slnr+i).h, %TBM_SETPOS,%True,lm fconverge = %true END IF END SELECT END IF IF ISFALSE (fchanging + vchanging) THEN IF onoff THEN 'Roto_Light 1, %False mPlay Rotomoton.channel, 114, %False onoff = %False END IF ELSE IF ISFALSE onoff THEN mPlay Rotomoton.channel, 114, 127 'Roto_Light 1, %True onoff = %True END IF END IF IF ISFALSE (fchanging+vchanging+fconverge+vconverge) THEN IF TIMER > t + 300 THEN ' only after 5 minutes ' we better let all velo sliders go to zero, and all frequency slider to max. lv = %False FOR i = slnr TO slnr + 9 av = Slider(i).value IF av > %False THEN DECR av INCR lv Slider(i).value = av SendMessage Slider(i).h,%TBM_SETPOS,%True,av END IF NEXT i IF ISFALSE INT(lv) THEN stoptask %Rotstuk stoptask %Rotstuk+2 stoptask %Rotstuk+1 END IF END IF END IF END SUB SUB Rotstuk_UI () ' the number of sliders for a single task being limited to 12, we place all ' extra command sliders in this separate task as well as the entire motor control. ' starting both tasks together gives a windows crash! (Thanks to mr.Gates...) LOCAL i AS LONG LOCAL lowval AS SINGLE LOCAL highval AS SINGLE LOCAL value AS SINGLE LOCAL slv AS SINGLE LOCAL motmoving AS BYTE STATIC slnr AS LONG STATIC cnt AS DWORD STATIC onoff AS BYTE ' for lights IF ISFALSE Task(%rotstuk+1).tog THEN onoff = %False Task(%Rotstuk+1).freq = 0.5 DIM TaskParamLabels(0 TO 3) AS LOCAL ASCIIZ * 8 TaskParamLabels(0) = "Mdens" TaskParamLabels(1) = "mMin" TaskParamLabels(2) = "mMax" TaskParamLabels(3) = "Speed" IF ISFALSE Task(%Rotstuk+1).hParam THEN MakeTaskParameterdialog %Rotstuk+1,4,Slider(),0,UDctrl(),Taskparamlabels() END IF ' Rotomoton.freq(1) = Rotomoton.maxfreq(1) ' Rotomoton.freq(2) = Rotomoton.maxfreq(2) ' Rotomoton.freq(3) = Rotomoton.maxfreq(3) ' Rotomoton.freq(4) = Rotomoton.maxfreq(4) ' Rotomoton.freq(5) = 10 + (Rotomoton.maxfreq(5) / 2) cnt = 1 Task(%rotstuk+1).tog = %True 'MSGBOX "First pass..." EXIT SUB END IF IF ISFALSE slnr THEN slnr = TaskEX(%Rotstuk+1).SliderNumbers(0) IF Slider(slnr).h THEN Slider(slnr).value = 125 ' motor event density SendMessage Slider(slnr).h, %TBM_SETPOS,%True,125 ELSE MSGBOX "Error" END IF IF Slider(slnr+1).h THEN Slider(slnr+1).value = 1 ' lowest limit for motor movements SendMessage Slider(slnr+1).h, %TBM_SETPOS,%True,1 ELSE MSGBOX "Error2" END IF IF slider(slnr+2).h THEN Slider(slnr+2).value = 120 ' highest limit for motor movements SendMessage Slider(slnr+2).h, %TBM_SETPOS,%True,120 ELSE MSGBOX "Error3" END IF IF slider(slnr+3).h THEN Slider(slnr+3).value = 40 ' task frequency (divide by 20) SendMessage Slider(slnr+3).h, %TBM_SETPOS,%True,40 ELSE MSGBOX "Error4" END IF Task(%rotstuk+1).freq = 1 'MSGBOX "Slidermsg's sent..." MoveWindow Task(%Rotstuk+1).hparam, 0,0, 190, 182, %True EXIT SUB END IF Task(%Rotstuk+1).freq = Slider(slnr+3).value / 20 IF Task(%Rotstuk+1).freq < 0.2 THEN Task(%Rotstuk+1).freq = 0.2 ' motors: motmoving = %False FOR i = 1 TO 5 IF Task(24 + i).swit THEN ' rotate only when the beater task is on IF Task(24 + i).level > 1 THEN ' only if velocity value is larger then 1 'IF ISFALSE Rotomoton.command(i) THEN slv = Slider(slnr).value ' event density slider IF ISFALSE cnt MOD ((128- slv) + (5-i)) THEN value = Slider(slnr+1).value 'lowval = Rotomoton.maxstep(i) * (value / 128!) ' ondergrens, minimum waarde 'value = (Rotomoton.maxstep(i) - lowval) ' resterend variatietrajekt ' het mobiel deel daarbovenop is: slv = Slider(slnr+2).value highval = (slv/128!) * value ' daarvan nemen we een random waarde: highval = highval * RND(1) 'Rotomoton.command(i) = INT(lowval + highval) OR %Roto_Position 'starttask Rotomoton.motortask(i) IF Rotomoton.ctrl(101+i) <> highval THEN Controller Rotomoton.channel, 101+i, highval Rotomoton.ctrl(101+i) = highval Motmoving = %True ELSE Motmoving = %False END IF END IF ' INCR cnt 'ELSE ' INCR MotMoving 'END IF END IF END IF NEXT i IF Motmoving THEN IF ISFALSE onoff THEN 'Roto_Light 2, %True mPlay Rotomoton.channel, 115, 127 onoff = %True END IF ELSE IF onoff THEN 'Roto_Light 2, %False mPlay Rotomoton.channel, 115, %False onoff = %False END IF END IF 'IF ISFALSE Task(%Rotstuk).swit THEN stoptask %rotstuk +1 END SUB SUB Rotstuk_Hold () ' pushing the beaters against the skin is no longer implemented!!! STATIC note AS BYTE STATIC slnr AS LONG STATIC holdtime() AS LONG LOCAL i AS LONG LOCAL tn AS LONG IF ISFALSE Task(%Rotstuk+2).tog THEN DIM holdtime(48 TO 59) AS STATIC LONG DIM TaskParamLabels(0 TO 1) AS LOCAL ASCIIZ * 8 TaskParamLabels(0) = "ONt" TaskParamLabels(1) = "Speed" IF ISFALSE Task(%Rotstuk+2).hParam THEN MakeTaskParameterdialog %Rotstuk+2,2,Slider(),0,UDctrl(),Taskparamlabels() END IF note = 48 Task(%Rotstuk+2).tog = %True Task(%Rotstuk+2).freq = 1 EXIT SUB END IF IF ISFALSE slnr THEN slnr = TaskEX(%Rotstuk+2).SliderNumbers(0) MoveWindow Task(%Rotstuk+2).hparam, 0,182*3, 190, 92, %True EXIT SUB END IF tn = TimegetTime FOR i = 48 TO 59 IF holdtime(i) THEN IF tn > holdtime(i) THEN 'Roto_Hold LOBYT(i),%False Noteoff Rotomoton.channel, LOBYT(i) holdtime(i) = %False ELSE ITERATE FOR END IF ELSE '... IF i = note THEN 'Roto_Hold note, %True mPlay Rotomoton.channel, note, 127 '??? holdtime(note) = tn + (Slider(slnr).value * 10) ' in ms. INCR note IF note > 59 THEN note = 48 END IF EXIT FOR END IF END IF NEXT i Task(%Rotstuk+2).freq = Slider(slnr+1).value / 4 IF Task(%Rotstuk+2).freq < 0.5 THEN FOR note = 48 TO 59 NoteOff Rotomoton.channel, note 'Roto_Hold note,%False holdtime(note) = %False NEXT i note = 48 Stoptask %Rotstuk + 2 END IF END SUB #ENDIF SUB Roto_Calibas () ' calibrates low position only [2007] Controller Rotomoton.channel, 81, 127 rotomoton.ctrl(81) = 127 rotomoton.ctrl(101) = %False SLEEP 500 END SUB SUB Roto_CaliTen () Controller Rotomoton.channel, 82, 127 rotomoton.ctrl(82) = 127 rotomoton.ctrl(102) = %False SLEEP 500 END SUB SUB Roto_CaliAlt () Controller Rotomoton.Channel, 83, 127 rotomoton.ctrl(83) = 127 rotomoton.ctrl(103) = %False SLEEP 500 END SUB SUB Roto_CaliMez () Controller Rotomoton.channel, 84, 127 rotomoton.ctrl(84) = 127 rotomoton.ctrl(104) = %False SLEEP 500 END SUB SUB Roto_CaliSop () Controller Rotomoton.channel, 85, 127 rotomoton.ctrl(85) = 127 rotomoton.ctrl(105) = %False SLEEP 500 END SUB SUB Roto_Calibas_H () ' calibrates high position only [2007] rotomoton.ctrl(91) = 127 Controller Rotomoton.channel, 91, 127 rotomoton.ctrl(101) = 127 SLEEP 500 END SUB SUB Roto_CaliTen_H () Controller Rotomoton.channel, 92, 127 rotomoton.ctrl(92) = 127 rotomoton.ctrl(102) = 127 SLEEP 500 END SUB SUB Roto_CaliAlt_H () Controller Rotomoton.Channel, 93, 127 rotomoton.ctrl(93) = 127 rotomoton.ctrl(103) = 127 SLEEP 500 END SUB SUB Roto_CaliMez_H () Controller Rotomoton.channel, 94, 127 rotomoton.ctrl(94) = 127 rotomoton.ctrl(104) = 127 SLEEP 500 END SUB SUB Roto_CaliSop_H () Controller Rotomoton.channel, 95, 127 rotomoton.ctrl(95) = 127 rotomoton.ctrl(105) = 127 SLEEP 500 END SUB SUB Tune_Bas () ' adapted to implementation 08.2007 STATIC slnr AS LONG STATIC oldval AS LONG IF ISFALSE task(43).tog THEN Task(43).tog = %true DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Pitch" IF ISFALSE Task(43).hParam THEN MakeTaskParameterDialog 43,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(43).SliderNumbers(0) 'MoveWindow Task(43).hparam, 190,0, 190, 92, %True END IF Slider(slnr).value = rotomoton.ctrl(101) ' send to slider... SendMessage Slider(slnr).h, %TBM_SETPOS,%True, rotomoton.ctrl(101) oldval = slider(slnr).value END IF IF slider(slnr).value <> oldval THEN SELECT CASE slider(slnr).value CASE 0 Controller Rotomoton.channel, 81, 127 ' recalibrate low position rotomoton.ctrl(101) = %False CASE >= 127 Controller Rotomoton.channel, 91, 127 ' recalibrate high position rotomoton.ctrl(101) = 127 CASE ELSE Controller Rotomoton.channel, 101, slider(slnr).value rotomoton.ctrl(101) = slider(slnr).value END SELECT oldval = slider(slnr).value END IF END SUB SUB tune_Ten () STATIC slnr AS LONG STATIC oldval AS LONG IF ISFALSE task(44).tog THEN Task(44).tog = %true DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Pitch" IF ISFALSE Task(44).hParam THEN MakeTaskParameterDialog 44,1,Slider(),0,UDctrl(),TaskParamLabels() END IF 'EXIT SUB IF ISFALSE slnr THEN slnr = TaskEX(44).SliderNumbers(0) END IF slider(slnr).value = rotomoton.ctrl(102) SendMessage Slider(slnr).h, %TBM_SETPOS,%True, rotomoton.ctrl(102) oldval = slider(slnr).value END IF IF slider(slnr).value <> oldval THEN SELECT CASE slider(slnr).value CASE 0 Controller Rotomoton.channel, 82, 127 rotomoton.ctrl(102) = 0 CASE >= 127 Controller Rotomoton.channel, 92, 127 rotomoton.ctrl(102) = 127 CASE ELSE Controller Rotomoton.channel, 102, slider(slnr).value rotomoton.ctrl(102) = slider(slnr).value END SELECT oldval = slider(slnr).value END IF END SUB SUB Tune_Alt () STATIC slnr AS LONG STATIC oldval AS LONG IF ISFALSE task(45).tog THEN Task(45).tog = %true DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Pitch" IF ISFALSE Task(45).hParam THEN MakeTaskParameterDialog 45,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(45).SliderNumbers(0) END IF slider(slnr).value = rotomoton.ctrl(103) SendMessage Slider(slnr).h, %TBM_SETPOS,%True, rotomoton.ctrl(103) oldval = slider(slnr).value END IF IF slider(slnr).value <> oldval THEN SELECT CASE slider(slnr).value CASE 0 Controller Rotomoton.channel, 83, 127 rotomoton.ctrl(103) = %False CASE >= 127 Controller Rotomoton.channel, 93, 127 rotomoton.ctrl(103) = 127 CASE ELSE Controller Rotomoton.channel, 103, slider(slnr).value rotomoton.ctrl(103) = slider(slnr).value END SELECT oldval = slider(slnr).value END IF END SUB SUB Tune_Mez () STATIC slnr AS LONG STATIC oldval AS LONG IF ISFALSE task(46).tog THEN Task(46).tog = %true DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Pitch" IF ISFALSE Task(46).hParam THEN MakeTaskParameterDialog 46,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(46).SliderNumbers(0) END IF slider(slnr).value = rotomoton.ctrl(104) SendMessage Slider(slnr).h, %TBM_SETPOS,%True, rotomoton.ctrl(104) oldval = slider(slnr).value END IF IF slider(slnr).value <> oldval THEN SELECT CASE slider(slnr).value CASE 0 Controller Rotomoton.channel, 84, 127 rotomoton.ctrl(104) = 0 CASE >= 127 Controller Rotomoton.channel, 94, 127 rotomoton.ctrl(104) = 127 CASE ELSE Controller Rotomoton.channel, 104, slider(slnr).value rotomoton.ctrl(104) = slider(slnr).value END SELECT oldval = slider(slnr).value END IF END SUB SUB tune_Sop () STATIC slnr AS LONG STATIC oldval AS LONG IF ISFALSE task(47).tog THEN Task(47).tog = %true DIM TaskParamLabels(0) AS ASCIIZ * 8 TaskParamLabels(0) = "Pitch" IF ISFALSE Task(47).hParam THEN MakeTaskParameterDialog 47,1,Slider(),0,UDctrl(),TaskParamLabels() END IF IF ISFALSE slnr THEN slnr = TaskEX(47).SliderNumbers(0) END IF slider(slnr).value = rotomoton.ctrl(105) SendMessage Slider(slnr).h, %TBM_SETPOS,%True, rotomoton.ctrl(105) oldval = slider(slnr).value END IF IF slider(slnr).value <> oldval THEN SELECT CASE slider(slnr).value CASE 0 Controller Rotomoton.channel, 85, 127 rotomoton.ctrl(105) = %False CASE >= 127 Controller Rotomoton.channel, 95, 127 rotomoton.ctrl(105) = 127 CASE ELSE Controller Rotomoton.channel, 105, slider(slnr).value rotomoton.ctrl(105) = slider(slnr).value END SELECT oldval = slider(slnr).value END IF END SUB '[eof] _