'********************************************** '* < 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 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 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 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 '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 cirkels IF cnt > 8 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 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 = 12! + (11 * (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 = 14! + ( 13! * (SIN(Task(%linus).patch/ 66!))) SELECT CASE Task(%linus + 2).freq CASE > 20 vmax = 1 CASE > 10 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 , 64 IF n2 > 107 THEN DO n2 = n2 - 12 LOOP UNTIL n2 < 108 END IF IF n2 THEN Play Toypi.channel, n2 , 64 ' 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 = 8 END IF Play Toypi.channel, n, 60 DECR n Task(%Linus+4).freq = Task(%Linus+4).freq * 0.8 IF n < 72 THEN stoptask %Linus + 4 END SUB