cc = { {{},{},{},{}}, {{},{},{},{}}, {{},{},{},{}}, {{},{},{},{}}, p = {0,0,0,0} } function init_cc() cc[1][1] = {cc=10, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[1][2] = {cc=11, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[1][3] = {cc=12, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[1][4] = {cc=13, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[2][1] = {cc=14, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[2][2] = {cc=15, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[2][3] = {cc=16, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[2][4] = {cc=17, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[3][1] = {cc=18, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[3][2] = {cc=19, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[3][3] = {cc=20, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[3][4] = {cc=21, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[4][1] = {cc=22, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[4][2] = {cc=23, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[4][3] = {cc=24, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} cc[4][4] = {cc=25, ch=1, a=true, slew=0, min=0, max=127, val=0, v=0, s=0} end init_cc() mode = 1 param = 1 dirty = true meta = { script = "erosion", version = "0.1", bank = 1, scene = 1, slot = { {},{},{},{},{},{},{},{} }, } function init() print("\\\\ erosion \\\\\\\\") temp = pset_read(1) if not temp or temp.script ~= "erosion" then print("writing default pset") pset_write(1,meta) pset_write(1+(meta.bank-1)*8+meta.scene,cc) else meta = temp print("read pset metadata") cc = pset_read(1+(meta.bank-1)*8+meta.scene) -- reset slew positions: for n=1,4 do for k=1,4 do slew.to(sl[n][k], cc.p[n], 0) end end delta_update_all() -- CAN REMOVE LATER: if not cc[1][1].ch then for x=1,4 do for y=1,4 do cc[x][y].ch = 1 end end end if not cc[1][1].a then for x=1,4 do for y=1,4 do cc[x][y].a = true end end end end -- start redraw rm = metro.new(redraw, 33, -1) set_mode(1) end RANGE = 1023 -- NORMAL -- function enter_normal() for i=1,4 do arc_res(i,1) end end function delta_slew(n,k,a) --print("delta_slew",n,k,a) local b = linlin(0,RANGE,cc[n][k].min,cc[n][k].max,a) cc[n][k].v = b local c = math.floor(b) if(c ~= cc[n][k].val) then --print("cc to "..c) cc[n][k].val = c midi_cc(cc[n][k].cc,c,cc[n][k].ch) end --point2(n,math.floor(b*8.0)) dirty = true end function delta_normal(n,d) local a = clamp(cc.p[n] + d*4,0,RANGE) if(cc.p[n] ~= a) then cc.p[n] = a --arc_led_all(n,0) for k=1,4 do if cc[n][k].a then if cc[n][k].slew > 0 then local sss = cc[n][k].slew * 32 --print("start slew "..sss) slew.to(sl[n][k], a, sss) else local b = linlin(0,RANGE,cc[n][k].min,cc[n][k].max,a) cc[n][k].v = b local c = math.floor(b) if(c ~= cc[n][k].val) then cc[n][k].val = c midi_cc(cc[n][k].cc,c,cc[n][k].ch) end --point2(n,math.floor(b*8.0)) end end end dirty = true --arc_refresh() --ps("%d %d %d %d %d %d",n,p[n],cc[n][1].val,cc[n][2].val,cc[n][3].val,cc[n][4].val) end end function delta_update_all() for n=1,4 do for k=1,4 do if cc[n][k].a then local b = linlin(0,RANGE,cc[n][k].min,cc[n][k].max,cc.p[n]) cc[n][k].v = b local c = math.floor(b) if(c ~= cc[n][k].val) then cc[n][k].val = c midi_cc(cc[n][k].cc,c,cc[n][k].ch) end end end end end function redraw_normal() for n=1,4 do arc_led_all(n,0) for k=1,4 do if cc[n][k].a then point2(n,math.floor(cc[n][k].v*8.0)) end end end end sl = {{},{},{},{}} for n=1,4 do for k=1,4 do do sl[n][k] = slew.new(function(a) delta_slew(n,k,a) end,0,cc.p[n],0) end end end s = {0,0} -- SCENE -- function enter_scene() arc_res(1,8) arc_res(2,8) saving = false scene_action = "load" end function delta_scene(n,d) if n==1 then s[1] = clamp(s[1] - d,1,28) meta.bank = (s[1] >> 2) + 1 elseif n==2 then s[2] = clamp(s[2] - d,1,28) meta.scene = (s[2] >> 2) + 1 elseif n==3 then if d>0 then scene_action = "erase" else scene_action = "load" end elseif n==4 then if d>0 then scene_action = "save" else scene_action = "load" end end dirty = true end function redraw_scene() arc_led_all(1,0) for n=1,8 do arc_led(1,42-n*2,n == meta.bank and 15 or 1) end arc_led_all(2,0) for n=1,8 do arc_led(2,51-n*4,n == meta.scene and 15 or 1) if meta.slot[meta.bank][n] then arc_led(2,52-n*4,1) arc_led(2,50-n*4,1) end end arc_led_all(3,scene_action=="erase" and 1 or 0) arc_led_all(4,scene_action=="save" and 1 or 0) end -- SELECT -- function enter_select() print("ENTER SELECT!") edit_n = 0 selected = false select_level = 2 seldelta = {0,0,0,0} dirty = true sm1 = metro.new(select_pulse, 150, -1) end function delta_select(n,d) if selected == false then seldelta[n] = seldelta[n] + d if math.abs(seldelta[n]) > 5 then selected = true select_level = 4 edit_n = n sm2 = metro.new(select_wait, 600, 1) end end end function redraw_select() if not selected then for n=1,4 do arc_led_all(n,select_level + math.abs(seldelta[n])) end else for n=1,4 do arc_led_all(n,edit_n == n and select_level or 0) end end end function select_pulse() if not selected then select_level = (select_level % 2) + 1 else select_level = select_level - 1 end dirty = true end function select_wait() print("wait") metro.stop(sm1) set_mode(4) print("TO EDIT MODE") for n=1,4 do if cc[edit_n][n].a then midi_cc(cc[edit_n][n].cc,cc[edit_n][n].min,cc[edit_n][n].ch) end end end -- EDIT -- TOTAL_PARAMS = 6 param_name = {"MIN","MAX","SLEW","CC NUM","CC CH","ACTIVE"} function enter_edit() param = 1 end function delta_edit(n,d) if param == 1 then local l = cc[edit_n][n].min local a = clamp(l + d,0,127) if l ~= a then cc[edit_n][n].min = a midi_cc(cc[edit_n][n].cc,a,cc[edit_n][n].ch) dirty = true end elseif param == 2 then local l = cc[edit_n][n].max local a = clamp(l + d,0,127) if l ~= a then cc[edit_n][n].max = a midi_cc(cc[edit_n][n].cc,a,cc[edit_n][n].ch) dirty = true end elseif param == 3 then local l = cc[edit_n][n].slew local a = clamp(l + d,0,127) if l ~= a then cc[edit_n][n].slew = a --print("slew = "..a) dirty = true end elseif param == 4 then local l = cc[edit_n][n].cc local a = clamp(l + d,0,127) if l ~= a then cc[edit_n][n].cc = a ps("cc %d,%d = %d",edit_n,n,a) dirty = true end elseif param == 5 then local l = cc[edit_n][n].ch local a = clamp(l - d,1,16) if l ~= a then cc[edit_n][n].ch = a ps("ch %d,%d = %d",edit_n,n,a) dirty = true end elseif param == 6 then cc[edit_n][n].a = d>0 dirty = true end end function redraw_edit() for n=1,4 do local act = cc[edit_n][n].a and 1 or 0 arc_led_all(n,0) arc_led(n,36,param == 1 and 10 or act) arc_led(n,30,param == 2 and 10 or act) arc_led(n,33,param == 3 and 10 or act) if param == 1 then point2(n,cc[edit_n][n].min * 8) elseif param == 2 then point2(n,cc[edit_n][n].max * 8) elseif param == 3 then point2(n,cc[edit_n][n].slew * 8) elseif param == 4 then local z = cc[edit_n][n].cc local a = math.floor(z / 100) local b = math.floor((z%100)/10) local c = math.floor(z%10) --ps("%d = %d %d %d",z,a,b,c) arc_led(n,63,a==1 and 10 or 1) for i=1,9 do arc_led(n,51+i,b==i and 10 or 1) arc_led(n,40+i,c==i and 10 or 1) end elseif param == 5 then for i=1,16 do arc_led(n,24-i,cc[edit_n][n].ch==i and 10 or 1) end elseif param == 6 then for i=1,32 do arc_led(n,(47+i)%64+1,cc[edit_n][n].a and 1 or 0) end end end end func_delta = {delta_normal, delta_scene, delta_select, delta_edit} func_redraw = {redraw_normal, redraw_scene, redraw_select, redraw_edit} func_enter = {enter_normal, enter_scene, enter_select, enter_edit} function set_mode(n) mode = n arc = func_delta[n] func_enter[n]() dirty = true end function redraw() if dirty then func_redraw[mode]() arc_refresh() dirty = false end end function arc_key(z) if z == 1 then km = metro.new(key_timer,500,1) elseif km then --print("keyshort") metro.stop(km) if mode==1 then set_mode(2) print("TO SCENE MODE") elseif mode==2 then set_mode(1) print("TO NORMAL MODE") elseif mode==3 then set_mode(1) print("TO NORMAL MODE") metro.stop(sm1) elseif mode==4 then print("EDIT MODE: TOGGLE PARAM") param = (param % TOTAL_PARAMS) + 1 ps("PARAM: %s", param_name[param]) if param==1 then for n=1,4 do if cc[edit_n][n].a then midi_cc(cc[edit_n][n].cc,cc[edit_n][n].min,cc[edit_n][n].ch) end end elseif param==2 then for n=1,4 do if cc[edit_n][n].a then midi_cc(cc[edit_n][n].cc,cc[edit_n][n].max,cc[edit_n][n].ch) end end end dirty = true end end end function key_timer() --print("keylong!") metro.stop(km) km = nil if mode==1 then set_mode(3) print("TO SELECT MODE") elseif mode==2 then if scene_action == "load" then if meta.slot[meta.bank][meta.scene] then set_mode(1) print("LOAD PSET") print("TO NORMAL MODE") slew.allfreeze() pset_write(1,meta) cc = pset_read(1+(meta.bank-1)*8+meta.scene) -- reset slew positions: for n=1,4 do for k=1,4 do slew.to(sl[n][k], cc.p[n], 0) end end -- CAN REMOVE LATER: if not cc[1][1].ch then for x=1,4 do for y=1,4 do cc[x][y].ch = 1 end end end if not cc[1][1].a then for x=1,4 do for y=1,4 do cc[x][y].a = true end end end else print("BLANK PSET HERE") init_cc() end elseif scene_action == "erase" then print("ERASED SLOT") meta.slot[meta.bank][meta.scene] = false scene_action = "load" pset_write(1,meta) elseif scene_action == "save" then print("SAVED PSET") meta.slot[meta.bank][meta.scene] = true scene_action = "load" pset_write(1+(meta.bank-1)*8+meta.scene,cc) pset_write(1,meta) end dirty = true elseif mode==3 then set_mode(1) metro.stop(sm1) print("TO NORMAL MODE") elseif mode==4 then set_mode(1) print("TO NORMAL MODE") print("UPDATE ALL POSITIONS") delta_update_all() end end -- draw point 1-1024 function pointr3(n,x) -- FIXME this is not efficient local xx = math.floor(linlin(0,127,1,768,127-x)) + 128 + 512 local c = xx >> 4 arc_led_rel(n,c%64+1,15) arc_led_rel(n,(c+1)%64+1,xx%16) arc_led_rel(n,(c+63)%64+1,15-(xx%16)) end function point2(n,x) local xx = math.floor(linlin(0,RANGE,1,768,x)) + 128 + 512 local c = xx >> 4 arc_led_rel(n,c%64+1,15-(xx%16)) arc_led_rel(n,(c+1)%64+1,(xx%16)) end init()