cleanup and a working chaser!!

11845b4 · gmorell · 2022-11-24 00:49

11 files +117 -50

Files changed

modified lib/lambent_ex/machine.ex
+38 −17
@@ -45,53 +45,76 @@ defmodule LambentEx.Machine do
45 45 specs =
46 46 1..cnt
47 47 |> Enum.map(fn id ->
48 − Parent.child_spec({opts[:step], opts[:step_opts] |> Map.put(:id, id) |> Map.put(:name, opts[:name])})
48 + Parent.child_spec(
49 + {opts[:step], opts[:step_opts] |> Map.put(:id, id) |> Map.put(:name, opts[:name])},
50 + id: id
51 + )
49 52 end)
50 53
51 − pids = specs |> Enum.map(fn x -> Parent.start_child(x) |> IO.inspect end) |> Enum.filter(fn {status, pid} -> status == :ok end)
52 − pids = []
54 + pids =
55 + specs
56 + |> Enum.map(fn x -> Parent.start_child(x) end)
57 + |> Enum.filter(fn {status, pid} -> status == :ok end)
58 + |> Enum.map(fn {:ok, v} -> v end)
53 59
54 60 {:ok,
55 61 %{
56 62 steps: pids,
57 63 name: opts[:name],
64 + # todo configurable
58 65 speed: 1000,
59 66 bright_tgt: 255,
60 67 bright_curr: 255,
61 68 bright_delay: 0,
62 69 bright_mvmul: 2,
63 − cnt: 0
70 + cnt: cnt
64 71 }}
65 − |> IO.inspect()
66 72 end
67 73
68 74 defp via_tuple(name), do: {:via, Registry, {@registry, name}}
69 75
70 76 # public
71 77
72 − def faster(_id) do
73 − via_tuple("machine-opts-id") |> GenServer.cast(:faster)
78 + def faster(id) do
79 + via_tuple("machine-#{id}") |> GenServer.cast(:faster)
74 80 end
75 81
76 − def slower(_id) do
77 − via_tuple("machine-opts-id") |> GenServer.cast(:slower)
82 + def slower(id) do
83 + via_tuple("machine-#{id}") |> GenServer.cast(:slower)
78 84 end
79 85
80 − def brighter(_id) do
81 − via_tuple("machine-opts-id") |> GenServer.cast(:brighter)
86 + def brighter(id) do
87 + via_tuple("machine-#{id}") |> GenServer.cast(:brighter)
82 88 end
83 89
84 − def dimmer(_id) do
85 − via_tuple("machine-opts-id") |> GenServer.cast(:dimmer)
90 + def dimmer(id) do
91 + via_tuple("machine-#{id}") |> GenServer.cast(:dimmer)
86 92 end
87 93
88 94 # impls
89 95
96 + defp bmath(i, state) do
97 + (i * state.bright_curr / 255.0) |> trunc
98 + end
99 +
90 100 @impl true
91 101 def handle_info(:step, state) do
92 102 Process.send_after(self(), :step, state.speed)
93 − # IO.puts(state.cnt)
94 − {:noreply, bright_step(state) |> Map.put(:cnt, state.cnt + 1)}
103 +
104 + state[:steps]
105 + |> Enum.map(&GenServer.cast(&1, :step))
106 +
107 + state[:steps]
108 + |> Enum.map(&GenServer.call(&1, :read))
109 + |> Enum.map(fn x -> x |> Enum.map(fn y -> bmath(y, state) end) end)
110 +
111 + # |> IO.inspect()
112 + {:noreply, bright_step(state)}
113 + end
114 +
115 + def handle_info({:EXIT, pid, err}, state) do
116 + IO.inspect(err)
117 + {:noreply, state}
95 118 end
96 119
97 120 defp do_slower(current_val) do
@@ -139,8 +162,6 @@ defmodule LambentEx.Machine do
139 162 end
140 163
141 164 defp do_bright_step(tgt, curr) do
142 − IO.inspect({"Bs", tgt, curr})
143 −
144 165 if curr < tgt do
145 166 curr + 1
146 167 else
added lib/lambent_ex/machine/behaviors.ex
+11 −0
@@ -0,0 +1,11 @@
1 +defmodule LambentEx.Machine.Steps do
2 + @doc """
3 + Steps the machine Forward
4 + """
5 + @callback step() :: {:ok, term} | {:error, String.t()}
6 +
7 + @doc """
8 + Read the machine state
9 + """
10 + @callback read() :: [float]
11 +end
modified lib/lambent_ex/machine/steps/chase.ex
+39 −8
@@ -1,28 +1,59 @@
1 +defmodule LambentEx.Machine.Steps.Chase.Cfg do
2 + # @enforce_keys [:h]
3 + defstruct [:h, s: 255, v: 0, spacing: 30, fadeby: 15, id: 0, status: 0, window: 0]
4 +end
5 +
1 6 defmodule LambentEx.Machine.Steps.Chase do
2 7 @moduledoc false
3 8 use GenServer
9 + # @behaviour LambentEx.Machine.Steps
4 10
5 11 @registry :lambent_steps
6 12 @cls :chase
7 13
14 + alias LambentEx.Machine.Steps.Chase.Cfg
15 + alias LambentEx.Utils.Color
16 +
17 + defp n(opts) do
18 + "#{@cls}-#{opts[:name]}-#{opts[:id]}"
19 + end
20 +
8 21 def start_link(opts) do
9 − GenServer.start_link(__MODULE__, opts, name: via_tuple("#{@cls}-#{opts[:name]}-#{opts[:id]}"))
10 −# GenServer.start_link(__MODULE__, opts, name: {:global, "#{@cls}-#{opts[:name]}-#{opts[:id]}"})
22 + GenServer.start_link(__MODULE__, opts, name: via_tuple(n(opts)))
11 23 end
12 24
13 25 def init(opts) do
14 − IO.inspect(opts)
15 − {:ok, opts}
26 + opts = opts |> Map.put(:status, opts.id)
27 + cfg = struct(%LambentEx.Machine.Steps.Chase.Cfg{}, opts)
28 + {:ok, %{cfg | window: 255 / (cfg.spacing - cfg.fadeby)}}
16 29 end
17 30
18 31 defp via_tuple(name) do
19 − IO.inspect(name)
20 32 {:via, Registry, {@registry, name}}
21 33 end
22 34
23 − # defp via_tuple(name), do: {:via, Registry, {@registry, name}}
35 + defp read(state) do
36 + Color.hsv2rgb([state.h, state.s, state.v])
37 + end
38 +
39 + defp step_v(state) do
40 + if state.fadeby < state.status and state.status < state.spacing do
41 + state.window * (state.status |> Integer.mod(state.fadeby))
42 + else
43 + 0
44 + end
45 + end
46 +
47 + def handle_cast(:step, state) do
48 + state =
49 + state
50 + |> Map.put(:status, (state.status + 1) |> Integer.mod(state.spacing))
51 + |> Map.put(:v, step_v(state))
52 +
53 + {:noreply, state}
54 + end
24 55
25 − def step(id) do
26 − IO.puts("steppy#{id}")
56 + def handle_call(:read, _from, state) do
57 + {:reply, read(state), state}
27 58 end
28 59 end
modified lib/lambent_ex/supervision/machine.ex
+4 −2
@@ -6,12 +6,14 @@ defmodule LambentEx.MachineSupervisor do
6 6 end
7 7
8 8 def start_child(step, opts, name, count \\ 300) do
9 − # If MyWorker is not using the new child specs, we need to pass a map:
10 − # spec = %{id: MyWorker, start: {MyWorker, :start_link, [foo, bar, baz]}}
11 9 spec = {LambentEx.Machine, step: step, step_opts: opts, count: count, name: name}
12 10 DynamicSupervisor.start_child(__MODULE__, spec)
13 11 end
14 12
13 + def abort_child(pid) do
14 + DynamicSupervisor.terminate_child(__MODULE__, pid)
15 + end
16 +
15 17 @impl true
16 18 def init(init_arg) do
17 19 DynamicSupervisor.init(
modified lib/lambent_ex/util/color.ex
+25 −23
@@ -1,10 +1,9 @@
1 1 defmodule LambentEx.Utils.Color do
2 −
3 − # floating point modulo 💍💍💍
2 + # floating point modulo 🌀💍💍💍
4 3 @spec _fmod(float, float) :: float
5 4 defp _fmod(mod, b) when mod >= b do
6 5 mod = mod - b
7 − _fmod(mod ,b)
6 + _fmod(mod, b)
8 7 end
9 8
10 9 defp _fmod(mod, _b) do
@@ -15,8 +14,7 @@ defmodule LambentEx.Utils.Color do
15 14 defp fmod(a, b) do
16 15 a = abs(a)
17 16 b = abs(b)
18 − mod = a
19 − _fmod(mod, b) |> abs
17 + _fmod(a, b) |> abs
20 18 end
21 19
22 20 @spec sys_255_to_1([number]) :: [float]
@@ -26,24 +24,28 @@ defmodule LambentEx.Utils.Color do
26 24
27 25 @spec _rgb_to_hsv([float]) :: [float]
28 26 defp _rgb_to_hsv([r, g, b]) do
29 − maxc = Enum.max([r,g,b])
30 − minc = Enum.min([r,g,b])
27 + maxc = Enum.max([r, g, b])
28 + minc = Enum.min([r, g, b])
31 29
32 30 v = maxc
31 +
33 32 if minc == maxc do
34 − [0.0, 0.0, v]
33 + [0.0, 0.0, v]
35 34 else
36 − mami = maxc-minc
37 − s = (mami) / maxc
38 − rc = (maxc-r) / mami
39 − gc = (maxc-g) / mami
40 − bc = (maxc-b) / maxc-minc
41 − h = cond do
42 − r == maxc -> bc-gc
43 − g == maxc -> 2.0 + rc - bc
44 − true -> 4.0 + gc - rc
45 − end
46 − h = (h/6.0) |> fmod(1.0)
35 + mami = maxc - minc
36 + s = mami / maxc
37 + rc = (maxc - r) / mami
38 + gc = (maxc - g) / mami
39 + bc = (maxc - b) / maxc - minc
40 +
41 + h =
42 + cond do
43 + r == maxc -> bc - gc
44 + g == maxc -> 2.0 + rc - bc
45 + true -> 4.0 + gc - rc
46 + end
47 +
48 + h = (h / 6.0) |> fmod(1.0)
47 49 [h, s, v]
48 50 end
49 51 end
@@ -69,16 +71,16 @@ defmodule LambentEx.Utils.Color do
69 71 end
70 72 end
71 73
72 − @spec rgb_to_hsv([float]) :: [float]
73 − def rgb_to_hsv(rgb) do
74 + @spec rgb2hsv([float]) :: [float]
75 + def rgb2hsv(rgb) do
74 76 rgb
75 77 |> sys_255_to_1
76 78 |> _rgb_to_hsv
77 79 |> sys_1_to_255
78 80 end
79 81
80 − @spec hsv_to_rgb([float]) :: [float]
81 − def hsv_to_rgb(hsv) do
82 + @spec hsv2rgb([float]) :: [float]
83 + def hsv2rgb(hsv) do
82 84 hsv
83 85 |> sys_255_to_1
84 86 |> _hsv_to_rgb

Parents: 9f986ce