-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9cd6125
commit 535a66c
Showing
28 changed files
with
1,596 additions
and
440 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,6 @@ erl_crash.dump | |
*.ez | ||
_images | ||
/priv | ||
rel/nerves_system_libs | ||
rel/nerves_io_neopixel | ||
*.o | ||
.DS_Store | ||
.tool-versions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,3 @@ | ||
# This file is responsible for configuring your application | ||
# and its dependencies with the aid of the Mix.Config module. | ||
use Mix.Config | ||
|
||
# This configuration is loaded before any dependency and is restricted | ||
# to this project. If another project depends on this project, this | ||
# file won't be loaded nor affect the parent project. For this reason, | ||
# if you want to provide default values for your application for | ||
# 3rd-party users, it should be done in your "mix.exs" file. | ||
|
||
# You can configure for your application as: | ||
# | ||
# config :blinky, key: :value | ||
# | ||
# And access this configuration in your application as: | ||
# | ||
# Application.get_env(:blinky, :key) | ||
# | ||
# Or configure a 3rd-party app: | ||
# | ||
# config :logger, level: :info | ||
# | ||
|
||
# It is also possible to import configuration files, relative to this | ||
# directory. For example, you can emulate configuration per environment | ||
# by uncommenting the line below and defining dev.exs, test.exs and such. | ||
# Configuration from the imported file will override the ones defined | ||
# here (which is why it is important to import them last). | ||
# | ||
# import_config "#{Mix.env}.exs" | ||
|
||
config :logger, | ||
compile_time_purge_level: :info | ||
|
||
import_config "#{Mix.env}.exs" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
use Mix.Config | ||
|
||
config :logger, level: :debug | ||
|
||
config :nerves_neopixel, | ||
canvas: {8, 4}, | ||
channels: [:channel1] | ||
|
||
config :nerves_neopixel, :channel1, | ||
pin: 18, | ||
arrangement: [ | ||
%{ | ||
type: :matrix, | ||
origin: {0, 0}, | ||
count: {8, 4}, | ||
direction: {:right, :down}, | ||
progressive: true | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use Mix.Config | ||
|
||
config :logger, level: :warn | ||
|
||
config :nerves_neopixel, | ||
canvas: {1, 1}, | ||
channels: [:channel1] | ||
|
||
config :nerves_neopixel, :channel1, | ||
pin: 18, | ||
arrangement: [ | ||
%{ | ||
type: :strip, | ||
origin: {0, 0}, | ||
count: 1, | ||
direction: :right | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,45 @@ | ||
defmodule Nerves.Neopixel do | ||
@moduledoc false | ||
alias Nerves.Neopixel.HAL | ||
|
||
use GenServer | ||
require Logger | ||
|
||
def start_link(channel1, channel2 \\ [pin: 0, count: 0]) do | ||
GenServer.start_link(__MODULE__, [channel1, channel2], [name: __MODULE__]) | ||
end | ||
@moduledoc """ | ||
# `Nerves.Neopixel` | ||
""" | ||
|
||
def stop() do | ||
GenServer.stop(__MODULE__) | ||
def set_brightness(channel, brightness) do | ||
GenServer.cast(HAL, {:set_brightness, channel, brightness}) | ||
end | ||
|
||
# render() | ||
def render({_, _} = data) do | ||
render(0, data) | ||
def set_gamma(channel, gamma) do | ||
GenServer.cast(HAL, {:set_gamma, channel, gamma}) | ||
end | ||
|
||
def render(channel, {_, _} = data) do | ||
GenServer.call(__MODULE__, {:render, channel, data}) | ||
def set_pixel({x, y}, {r, g, b}) do | ||
GenServer.cast(HAL, {:set_pixel, {x, y}, {r, g, b, 0}}) | ||
end | ||
|
||
def init([ch1, ch2]) do | ||
ch1_pin = (ch1[:pin] || raise "Must pass pin for channel 1") | ||
|> to_string | ||
ch1_count = (ch1[:count] || raise "Must pass count for channel 1") | ||
|> to_string | ||
|
||
ch2_pin = (ch2[:pin] || 0) | ||
|> to_string | ||
ch2_count = (ch2[:count] || 0) | ||
|> to_string | ||
|
||
|
||
port = Port.open({:spawn_executable, rpi_ws281x_path()}, | ||
[{:args, [ch1_pin, ch1_count, ch2_pin, ch2_count]}, | ||
{:packet, 2}, | ||
:use_stdio, | ||
:exit_status, | ||
:binary]) | ||
{:ok, %{ | ||
port: port | ||
}} | ||
def set_pixel({x, y}, {r, g, b, w}) do | ||
GenServer.cast(HAL, {:set_pixel, {x, y}, {r, g, b, w}}) | ||
end | ||
|
||
def handle_call({:render, channel, {brightness, data}}, _from, s) do | ||
data = ws2811_brg(data) | ||
payload = | ||
{channel, {brightness, data}} | ||
|> :erlang.term_to_binary | ||
send s.port, {self(), {:command, payload}} | ||
{:reply, :ok, s} | ||
def fill({x, y}, width, height, {r, g, b}) do | ||
GenServer.cast(HAL, {:fill, {x, y}, width, height, {r, g, b, 0}}) | ||
end | ||
def fill({x, y}, width, height, {r, g, b, w}) do | ||
GenServer.cast(HAL, {:fill, {x, y}, width, height, {r, g, b, w}}) | ||
end | ||
|
||
def handle_info {_port, {:exit_status, exit_status}}, state do | ||
{:stop, "rpi_ws281x OS process died with status: #{exit_status}", state} | ||
def copy({xs, ys}, {xd, yd}, width, height) do | ||
GenServer.cast(HAL, {:copy, {xs, ys}, {xd, yd}, width, height}) | ||
end | ||
|
||
defp ws2811_brg(data) when is_list(data) do | ||
Enum.reduce(data, <<>>, fn({r, g, b}, acc) -> | ||
acc <> <<b :: size(8), r :: size(8), g :: size(8), 0x00 :: size(8)>> | ||
end) | ||
def copy_blit({xs, ys}, {xd, yd}, width, height) do | ||
GenServer.cast(HAL, {:copy_blit, {xs, ys}, {xd, yd}, width, height}) | ||
end | ||
|
||
defp rpi_ws281x_path do | ||
Path.join(:code.priv_dir(:nerves_neopixel), "rpi_ws281x") | ||
def blit({x, y}, width, height, data) do | ||
GenServer.cast(HAL, {:blit, {x, y}, width, height, data}) | ||
end | ||
|
||
def render, do: GenServer.cast(HAL, :render) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
defmodule Nerves.Neopixel.Application do | ||
use Application | ||
|
||
require Logger | ||
|
||
@moduledoc """ | ||
# `Nerves.Neopixel.Application` | ||
""" | ||
|
||
def start(_type, _args) do | ||
Logger.debug("Nerves.Neopixel.start") | ||
Nerves.Neopixel.Supervisor.start_link([]) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
defmodule Nerves.Neopixel.Canvas do | ||
alias Nerves.Neopixel.Canvas | ||
|
||
defstruct [ | ||
:width, | ||
:height, | ||
] | ||
|
||
def load_config({width, height}), do: %Canvas{width: width, height: height} | ||
def load_config(_), do: raise "You must specify :canvas dimensions as {width, height} for :nerves_neopixel" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,71 @@ | ||
defmodule Nerves.Neopixel.Channel do | ||
alias Nerves.Neopixel.{ | ||
Channel, | ||
Matrix, | ||
Strip | ||
} | ||
|
||
defstruct [ | ||
pin: 0, count: 0, brightness: 0, | ||
data: [], invert: false, type: :ws2811] | ||
pin: 0, | ||
brightness: 255, | ||
gamma: nil, | ||
invert: false, | ||
type: :gbr, | ||
arrangement: nil | ||
] | ||
|
||
@valid_types [ | ||
:rgb, :rbg, :grb, :gbr, :brg, :bgr, | ||
:rgbw, :rbgw, :grbw, :gbrw, :brgw, :bgrw | ||
] | ||
|
||
def load_config(channel_config) do | ||
if is_nil(pwm_channel(channel_config[:pin])), do: raise "Each channel must specify a PWM-capable I/O :pin" | ||
|
||
%Channel{ | ||
pin: channel_config[:pin], | ||
brightness: Keyword.get(channel_config, :brightness, 255), | ||
gamma: load_gamma(channel_config[:gamma]), | ||
invert: Keyword.get(channel_config, :invert, false), | ||
type: load_channel_type(channel_config[:type]), | ||
arrangement: load_arrangement(channel_config[:arrangement]) | ||
} | ||
end | ||
|
||
def total_count(%Channel{arrangement: arrangement}) do | ||
Enum.reduce(arrangement, 0, fn (%Strip{count: count}, acc) -> acc + count end) | ||
end | ||
|
||
def pwm_channel(%Channel{pin: pin}), do: pwm_channel(pin) | ||
def pwm_channel(pin) when is_number(pin) and pin in [12, 18, 40, 52], do: 1 | ||
def pwm_channel(pin) when is_number(pin) and pin in [13, 19, 41, 45, 53], do: 2 | ||
def pwm_channel(_), do: nil | ||
|
||
defp load_gamma(nil), do: nil | ||
defp load_gamma(gamma_table) when is_list(gamma_table) and length(gamma_table) == 256 do | ||
gamma_table | ||
end | ||
defp load_gamma(_), do: raise "The :gamma on a :channel must be set as a list of 256 8-bit integers" | ||
|
||
defp load_channel_type(nil), do: :gbr | ||
defp load_channel_type(type) when type in @valid_types, do: type | ||
defp load_channel_type(_), do: raise "Channel :type must be one of #{inspect @valid_types}" | ||
|
||
defp load_arrangement(sections) when is_list(sections) do | ||
sections | ||
|> Enum.map(&load_section/1) | ||
|> List.flatten() | ||
end | ||
defp load_arrangement(_), do: raise "You must configure the :arrangement of pixels in each channel as a list" | ||
|
||
defp load_section(%{type: :matrix} = matrix_config) do | ||
matrix_config | ||
|> Matrix.load_config() | ||
|> Matrix.to_strip_list() | ||
end | ||
defp load_section(%{type: :strip} = strip_config) do | ||
strip_config | ||
|> Strip.load_config() | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
defmodule Nerves.Neopixel.Config do | ||
alias Nerves.Neopixel.{ | ||
Canvas, | ||
Channel, | ||
Config | ||
} | ||
|
||
defstruct [ | ||
:canvas, | ||
:channels | ||
] | ||
|
||
def load(), do: load(Application.get_all_env(:nerves_neopixel)) | ||
def load(config) do | ||
canvas = | ||
config | ||
|> Keyword.get(:canvas) | ||
|> Canvas.load_config() | ||
|
||
channels = | ||
config | ||
|> Keyword.get(:channels) | ||
|> Enum.map(fn name -> Keyword.get(config, name) end) | ||
|> Enum.map(& Channel.load_config/1) | ||
|
||
%Config{ | ||
canvas: canvas, | ||
channels: validate_channels(channels), | ||
} | ||
end | ||
|
||
defp validate_channels(channels) when is_list(channels) do | ||
pwm_channels = Enum.map(channels, & Channel.pwm_channel/1) | ||
if (Enum.dedup(pwm_channels) != pwm_channels) do | ||
raise "Each channel must have a :pin from a different hardware PWM channel" | ||
end | ||
channels | ||
end | ||
defp validate_channels(_), do: raise "You must configure a list of :channels for :nerves_neopixel" | ||
end |
Oops, something went wrong.