'********************************************** '* < TOYPI > * '* musical automat by dr.Godfried-Willem Raes * '* 2008 * '* User interface code * '********************************************** '07.08.2008: start coding '09.08.2008: First version firmware in PIC controllers '20.08.2008: Further work on Linus' dream. %Toypi_Scale_Test = 24 %Toypi_Dyna_Test = 25 %Toypi_Lites = 26 %Toypi_underlites = 27 %Linus = 48 ' demo composition for Toypi by gwr 48,49,50,51 DECLARE FUNCTION Init_Toypi () AS LONG DECLARE SUB Toypi_Scale_Test () DECLARE SUB Toypi_Dyna_Test () DECLARE SUB Toypi_Lites () ' yellow leds on keyboard panel DECLARE SUB Toypi_Lites_Off () DECLARE SUB Toypi_underlites () 'declare sub Toypi_underlites_Off () DECLARE SUB Linus () DECLARE SUB Linus_One () DECLARE SUB Linus_Two () DECLARE SUB Linus_Three () DECLARE SUB Linus_end () FUNCTION Init_Toypi () AS LONG LOCAL m AS ASCIIZ * 40 LOCAL i AS DWORD LOCAL j AS LONG LOCAL retval AS LONG CONTROL SET TEXT gh.Cockpit,0, " test code " IF ISFALSE hMidiI(0) THEN ButnSw(0).tag0 = "" ButnSw(0).cptr = %False END IF ButnSW(2).tag0 = "Pow On" ' switches solenoid voltage on/off - not yet implemented ButnSW(2).tag1 = "Pow Off" ButnSW(2).cptr = CODEPTR(Toypi_Power) ButnSW(3).tag0 = "" ButnSW(4).tag0 = "" ' harm ButnSW(5).tag0 = "" ' melo ButnSW(6).tag0 = "" ' psy ButnSW(7).tag0 = "" 'spec ButnSW(8).tag0 = "" ButnSW(9).tag0 = "" ButnSW(10).tag0 = "" ButnSW(11).tag0 = "" ButnOS(5).tag = "" ButnOS(6).tag = "" CONTROL SET TEXT gh.cockpit, %GMT_TITLE, " CONTROL SET TEXT gh.cockpit, %GMT_AUTHOR, $gwr Task(%Toypi_Scale_Test).naam = "Scale" Task(%Toypi_Scale_Test).cptr = CODEPTR(Toypi_Scale_Test) Task(%Toypi_Scale_Test).freq = 4 Task(%Toypi_Scale_Test).flags = %False Task(%Toypi_Dyna_Test).naam = "Dyna" Task(%Toypi_Dyna_Test).cptr = CODEPTR(Toypi_Dyna_Test) Task(%Toypi_Dyna_Test).freq = 4 Task(%Toypi_Dyna_Test).flags = %False Task(%Toypi_lites).naam = "Yellow" Task(%Toypi_lites).cptr = CODEPTR(Toypi_lites) Task(%Toypi_lites).freq = 4 Task(%Toypi_lites).flags = %False Taskex(%Toypi_lites).stopcptr = CODEPTR(Toypi_lites_off) Task(%Toypi_underlites).naam = "BlueWhit" Task(%Toypi_underlites).cptr = CODEPTR(Toypi_underlites) Task(%Toypi_underlites).freq = 4 Task(%Toypi_underlites).flags = %False Taskex(%Toypi_underlites).stopcptr = CODEPTR(Toypi_lites_off) ' procedures for "Linus' Dream" by Godfried-Willem Raes Task(%Linus).naam = "Linus" Task(%Linus).cptr = CODEPTR(Linus) Task(%Linus).freq = 2 Task(%Linus).flags = %False TaskEx(%Linus).stopcptr = CODEPTR(Linus_End) Task(%Linus+1).naam = "-V1" Task(%Linus+1).cptr = CODEPTR(Linus_One) Task(%Linus+1).freq = 10 Task(%Linus+1).flags = %False Task(%Linus+2).naam = "-V2" Task(%Linus+2).cptr = CODEPTR(Linus_Two) Task(%Linus+2).freq = 10 Task(%Linus+2).flags = %False Task(%Linus+3).naam = "-V3" Task(%Linus+3).cptr = CODEPTR(Linus_Three) Task(%Linus+3).freq = 2 Task(%Linus+3).flags = %False Task(%Linus+4).naam = "LinEnd" Task(%Linus+4).cptr = CODEPTR(Linus_End) Task(%Linus+4).freq = 2 Task(%Linus+4).flags = %False TaskEx(%Linus+4).stopcptr = CODEPTR(MM_Toypi_Off) ' end procedures for Linus' dream. FUNCTION = %true END FUNCTION SUB Toypi_Power () ' buttonswitch handler IF ISFALSE ButnSW(2).flag THEN Toypi.ctrl(66) = %False Controller Toypi.channel, 123, %False 'Controller Toypi.channel, 66, Toypi.ctrl(66) ELSE Toypi.ctrl(66) = %True ' Controller Toypi.channel, 66, Toypi.ctrl(66) END IF END SUB SUB Toypi_Scale_test () STATIC note AS INTEGER STATIC qt AS INTEGER STATIC init AS LONG LOCAL velo AS DWORD STATIC slnr() AS INTEGER IF ISFALSE init THEN 'Task(%Toypi_Scale_Test).tog THEN init = 1 note = toypi.lowtes ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 1) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed IF ISFALSE Task(%Toypi_Scale_Test).hParam THEN MakeTaskParameterDialog BYVAL %Toypi_Scale_Test,2, Slider(),0,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Toypi_Scale_Test).SliderNumbers(0) slnr(1) = TaskEX(%Toypi_Scale_Test).SliderNumbers(1) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value qt = %False Task(%Toypi_Scale_Test).tog = %True END IF velo = Slider(Slnr(0)).value IF velo THEN Play Toypi.channel, note, velo INCR note IF note > Toypi.hightes THEN note = Toypi.lowtes END IF Task(%Toypi_Scale_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Toypi_Dyna_Test () STATIC note AS INTEGER LOCAL velo AS DWORD STATIC slnr() AS INTEGER STATIC ud AS INTEGER STATIC init AS LONG IF ISFALSE init THEN init = 1 ' create sliders: DIM Slnr(0 TO 1) AS STATIC INTEGER DIM TaskParamLabels(0 TO 2) AS STATIC ASCIIZ*8 TaskParamLabels(0)="Velo" ' attack force for beaters TaskParamLabels(1)="Freq" ' speed TaskParamLabels(2)="Note" ' up down for the note IF Task(%Toypi_Dyna_Test).hParam = %Null THEN MakeTaskParameterDialog BYVAL %Toypi_Dyna_Test,2, Slider(),1,UdCtrl(), TaskParamLabels() END IF slnr(0) = TaskEX(%Toypi_Dyna_Test).SliderNumbers(0) slnr(1) = TaskEX(%Toypi_Dyna_Test).SliderNumbers(1) ud = TaskEX(%Toypi_Dyna_Test).UpDownNumbers(0) Slider(Slnr(0)).value = 1 Slider(Slnr(1)).value = 4 UdCtrl(ud).value = 72 UdCtrl(ud).minval = 72 UdCtrl(ud).maxval = 107 UdCtrl(ud).resetval = 72 UdCtrl(ud).stap = 1 UDctrl(ud).cptr = CODEPTR(Toypi_UD_Noot_CB) SendMessage Slider(Slnr(0)).h, %TBM_SETPOS,%True, Slider(Slnr(0)).value SendMessage Slider(Slnr(1)).h, %TBM_SETPOS,%True, Slider(Slnr(1)).value Task(%Toypi_Dyna_Test).tog = %True END IF note = UdCtrl(ud).value velo = Slider(Slnr(0)).value 'was / 2 ' range 256micro sec to 16ms IF velo THEN Play Toypi.channel, note, velo Task(%Toypi_Dyna_Test).freq = MAX(.5, Slider(Slnr(1)).value / 2!) END SUB SUB Toypi_UD_Noot_CB () ' for callback on parameter UpDown. LOCAL note AS SINGLE note = UDCtrl(TaskEX(%Toypi_Dyna_Test).UpdownNumbers(0)).value CONTROL SET TEXT Task(%Toypi_Dyna_Test).hparam, %GMT_TEXT0_ID + 16, "N=" & STR$(note) END SUB SUB Toypi_Lites () ' yellow led's on keyboard panel STATIC n AS DWORD IF ISFALSE Task(%Toypi_lites).tog THEN n = 59 Task(%Toypi_lites).tog = %True END IF NoteOff Toypi.channel, n ' not working with play and zero velo ? INCR n IF n > 67 THEN n = 60 Play Toypi.channel, n, 127 END SUB SUB Toypi_UnderLites () ' leds under keyboard panel STATIC n AS DWORD IF ISFALSE Task(%Toypi_underlites).tog THEN n = 47 Task(%Toypi_underlites).tog = %True END IF NoteOff Toypi.channel, n ' not working with play and zero velo ? INCR n IF n > 55 THEN n = 48 Play Toypi.channel, n, 127 END SUB SUB Toypi_Lites_Off () ' all lites ' this also works simply with ctrl 123. LOCAL n AS BYTE FOR n = 60 TO 67 Noteoff Toypi.channel, n NEXT n FOR n = 48 TO 55 Noteoff Toypi.channel, n NEXT n END SUB SUB Linus () STATIC tstart AS DWORD STATIC cnt AS DWORD STATIC n AS DWORD STATIC cycle AS DWORD STATIC velo1 AS SINGLE STATIC velo2 AS SINGLE STATIC lite1 AS BYTE STATIC lite2 AS BYTE STATIC oldlite1 AS BYTE STATIC oldlite2 AS BYTE STATIC cyc8 AS INTEGER STATIC cyc9 AS INTEGER STATIC cyc10 AS INTEGER STATIC cyc11 AS INTEGER LOCAL t AS INTEGER LOCAL i AS INTEGER IF ISFALSE task(%linus).tog THEN DIM n1(0 TO 8) AS STATIC INTEGER DIM n2(0 TO 8) AS STATIC INTEGER cnt = %False n = %False cycle = %False oldlite1 = %False oldlite2 = %False tstart = Timegettime Task(%linus).freq = 256 ' 64 ' bepaalt de duur van het stuk - must become slider. n1(0) = 72 : n2(0) = 80 n1(1) = 74 : n2(1) = 79 n1(2) = 79 : n2(2) = 87 n1(3) = 79 : n2(3) = 86 n1(4) = 81 : n2(4) = 88 n1(5) = 79 : n2(5) = 87 n1(6) = 80 : n2(6) = 83 n1(7) = 79 : n2(7) = 81 n1(8) = 81 : n2(8) = 89 velo1 = 1 '64 '1 velo2 = 1 '64 '1 cyc8 = 0 cyc9 = 0 cyc10 = 0 cyc11 = 0 ProgChange Toypi.channel, 0 ' default velo scaling MM_Toypi_On %MM_White Task(%linus).tog = %True END IF 'chordal structures with very fast repetition on notes SELECT CASE cnt CASE %False 'Play Toypi.channel, n1(cnt), velo1 + (ABS(SIN(n/314)) * 5) Task(%linus + 1).level = velo1 + (ABS(SIN(n/100)) * 20) Task(%linus + 1).pan = n1(cnt) IF ISFALSE Task(%linus+1).swit THEN starttask %linus + 1 CASE ELSE ' vanaf de eerste cirkel 'Play Toypi.channel, n1(cnt-1), velo1 + (ABS(SIN(n/500)) * 5) Task(%linus + 1).level = velo1 + (ABS(SIN(n/50)) * 20) Task(%linus + 1).pan = n1(cnt-1) IF n2(cnt) <> n1(cnt-1) THEN 'Play Toypi.channel, n2(cnt), velo2 + (ABS(SIN(n/ 400)) * 5) Task(%linus + 2).level = velo2 + (ABS(SIN(n/66)) * 20) Task(%linus + 2).pan = n2(cnt) IF ISFALSE Task(%linus + 2).swit THEN starttask %linus + 2 ELSE Task(%linus + 2).pan = %False IF Task(%linus + 2).swit THEN stoptask %linus +2 END IF END SELECT ' trage noten: IF Task(%linus +1).swit AND Task(%linus+2).swit THEN Task(%linus+3).freq = (Task(%linus + 1).freq + Task(%linus + 2).freq )/ 30 ' was: / 20 IF ISFALSE Task(%linus+3).swit THEN starttask %linus + 3 END IF SELECT CASE Task(%linus + 1).pan CASE 72 TO 76 lite1 = 60 CASE 77 TO 80 lite1 = 61 CASE 81 TO 85 lite1 = 62 CASE 86 TO 89 lite1 = 63 CASE 90 TO 94 lite1 = 64 CASE 95 TO 98 lite1 = 65 CASE 99 TO 103 lite1 = 66 CASE 104 TO 107 lite1 = 67 CASE ELSE lite1 = %False END SELECT SELECT CASE Task(%linus + 2).pan CASE 72 TO 76 lite2 = 60 CASE 77 TO 80 lite2 = 61 CASE 81 TO 85 lite2 = 62 CASE 86 TO 89 lite2 = 63 CASE 90 TO 94 lite2 = 64 CASE 95 TO 98 lite2 = 65 CASE 99 TO 103 lite2 = 66 CASE 104 TO 107 lite2 = 67 CASE ELSE lite2 = %False END SELECT IF lite1 <> oldlite1 THEN IF oldlite1 <> lite2 THEN NoteOff Toypi.channel, oldlite1 Play Toypi.channel, lite1, 127 oldlite1 = lite1 END IF IF lite2 <> oldlite2 THEN IF lite2 <> lite1 THEN IF oldlite2 <> lite1 THEN NoteOff Toypi.channel, oldlite2 Play Toypi.channel, lite2, 127 oldlite2 = lite2 END IF END IF INCR n ' fast counter (ticks) Task(%linus).patch = n MOD 628 ' for pass to playing tasks, the patch field is defined as word. cnt = n \ 628 ' aantal volledige cirkels cycle = cnt \ 8 SELECT CASE cycle CASE 8 IF ISFALSE cyc8 THEN 'incr cycle FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc8 = %True END IF CASE 9 IF ISFALSE cyc9 THEN ' INCR cycle FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc9 = %True END IF CASE 10 IF ISFALSE cyc10 THEN 'INCR cycle FOR i = 0 TO 8 n1(i) = n1(i) + 7 IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) n2(i) = n2(i) + 7 IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) NEXT i cyc10 = %True END IF CASE 11 t = %False FOR i = 0 TO 7 IF n2(i+1) < n1(i) + 12 THEN INCR n2(i+1) : t = %True IF n2(i+1) > n1(i) + 12 THEN DECR n2(i+1) : t = %True IF ISTRUE t THEN EXIT FOR NEXT i Task(%linus).freq = task(%linus).freq * 0.99 IF ISFALSE t THEN stoptask %Linus stoptask %linus + 1 stoptask %linus + 2 stoptask %linus + 3 starttask %linus + 4 ' ending 'Controller Toypi.channel, 123, %False END IF END SELECT ' IF cnt = 8 THEN ' if cycle <> oldcycle then ' 'cnt = 1 ' 'n = 627 ' FOR i = 0 TO 8 ' n1(i) = n1(i) + 7 ' IF n1(i) > 107 THEN n1(i) = 72 + (n1(i) MOD 12) ' n2(i) = n2(i) + 7 ' IF n2(i) > 107 THEN n2(i) = 72 + (n2(i) MOD 12) ' NEXT i ' INCR cycle ' oldcycle = cycle ' end if ' END IF ' IF cycle > 11 THEN ' t = %False ' FOR i = 0 TO 7 ' IF n2(i+1) < n1(i) + 12 THEN INCR n2(i+1) : t = %True ' IF n2(i+1) > n1(i) + 12 THEN DECR n2(i+1) : t = %True ' IF ISTRUE t THEN EXIT FOR ' NEXT i ' IF ISFALSE t THEN ' stoptask %Linus ' stoptask %linus + 1 ' stoptask %linus + 2 ' stoptask %linus + 3 ' starttask %linus + 4 ' ending ' 'Controller Toypi.channel, 123, %False ' END IF ' END IF END SUB SUB Linus_one () ' note repeat task for voice 1 LOCAL vmax AS INTEGER 'Task(%linus+1).freq = 33 + ((SIN(Task(%linus).patch/ 100!)) * 32!) Task(%linus+1).freq = 16! + (14 * (SIN(Task(%linus).patch/ 100!))) SELECT CASE Task(%linus + 1).freq CASE > 12 vmax =1 CASE > 8 vmax = 2 CASE > 6 vmax = 3 '4 CASE > 4 vmax = 6 '12 CASE > 2 vmax = 12 '24 CASE > 1 vmax = 27 '64 END SELECT Play Toypi.channel, Task(%linus+1).pan, MIN(Task(%linus+1).level, vmax) END SUB SUB Linus_Two () ' note repeat task for voice 2 LOCAL vmax AS INTEGER 'Task(%linus + 2).freq = 33 + ((SIN(Task(%linus).patch/ 66!)) * 32!) Task(%linus + 2).freq = 16! + ( 14! * (SIN(Task(%linus).patch/ 66!))) SELECT CASE Task(%linus + 2).freq CASE > 20 vmax = 1 CASE > 12 vmax = 2 CASE > 6 vmax = 3 '4 CASE > 4 vmax = 6 '12 CASE > 2 vmax = 12 '24 CASE > 1 vmax = 27 '64 END SELECT IF Task(%linus+2).pan THEN Play Toypi.channel, Task(%linus+2).pan, MIN(Task(%linus+2).level, vmax) END IF END SUB SUB Linus_Three () ' long notes fill in STATIC n1 AS SINGLE STATIC n2 AS SINGLE STATIC cnt AS SINGLE n1 = DifNoteF (Task(%linus + 1).pan, Task(%linus + 2).pan) ' in g_mus n2 = SumNoteF (Task(%linus + 1).pan, Task(%linus + 2).pan) IF n1 < 72 THEN DO n1 = n1 + 12 LOOP UNTIL n1 > 71 END IF IF n1 THEN Play Toypi.channel, n1 , 18 IF n2 > 107 THEN DO n2 = n2 - 12 LOOP UNTIL n2 < 108 END IF IF n2 THEN Play Toypi.channel, n2 , 18 ' alternating blue lights: INCR cnt IF ISFALSE cnt MOD 2 THEN Play Toypi.channel, 48, 127 NoteOff Toypi.channel, 55 ELSE NoteOff Toypi.channel, 48 Play Toypi.channel, 55, 127 END IF END SUB SUB Linus_End () ' ending for Linus' Dream STATIC n AS INTEGER IF ISFALSE Task(%Linus+4).tog THEN n= 107 Task(%Linus+4).tog = %TRue Task(%Linus + 4).freq = 64 END IF Play Toypi.channel, n, 60 DECR n Task(%Linus+4).freq = Task(%Linus+4).freq * 0.9 IF n < 72 THEN stoptask %Linus + 4 Controller Toypi.channel, 123, %False END IF END SUB