Fledex.LedStrip (fledex v0.7.0)

View Source

This module defines a GenServer that manages the LED strip (be it a real one with the Fledex.Driver.Impl.Spi or a virtual one with e.g. the Fledex.Driver.Impl.Kino).

You would start an LedStrip for every led strip you have.

The Fledex.LedStrip will take several Fledex.Leds definitions and merge them together to be displayed on a single LED strip.

The role the LedStrip plays is similar to the one a window server plays on a normal computer, except that a window server would manage several screens, whereas here each LED strip would get its own.

Note

In general you shouldn't require to start an LedStrip directly, but you should use the Fledex DSL.

To see how to configure an led strip, look at start_link/3

Summary

Functions

This changes the config of the led strip. You probably don't need it.

Change the global config of the led strip.

Returns a specification to start this module under a supervisor.

Define a new namespace

Drop a previously defined namespace.

Checks whether the specified namespace already exists

Sets the leds in a specific strip and namespace.

Similar to set_leds/4 but allows to specify some options to rotate the leds.

This starts the server controlling a specfic led strip.

Types

drivers_config_t()

Functions

change_config(server, driver, strip_config)

@spec change_config(GenServer.server(), drivers_config_t(), keyword()) :: :ok

This changes the config of the led strip. You probably don't need it.

In some circumstances it might be necessary to change the config of the led_strip (including the drivers). Most of the time you don't need to call this If you do, you surely will know about it :)

change_global_config(server, global_config)

@spec change_global_config(
  GenServer.server(),
  keyword()
) :: {:ok, [keyword()]}

Change the global config of the led strip.

Change some aspect of the configuration for an led strip. The configuration will be updated and the old values will be returned.

Note:

Usually you want to change the full configuration of the led strip (i.e. including the drivers) and not just the gloal config, which you can do through change_config/3

child_spec(init_arg)

@spec child_spec({atom(), drivers_config_t(), keyword(), keyword()}) ::
  Supervisor.child_spec()

Returns a specification to start this module under a supervisor.

See Supervisor.

define_namespace(server, namespace)

@spec define_namespace(GenServer.server(), atom()) :: :ok | {:error, String.t()}

Define a new namespace

A namespace is a sequence of led definitions. Each namespace is independent from other namspaces. All namespaces will get mapped onto the physical leds when merging all namespaces together.

drop_namespace(server, namespace)

@spec drop_namespace(GenServer.server(), atom()) :: :ok

Drop a previously defined namespace.

exist_namespace(server, namespace)

@spec exist_namespace(GenServer.server(), atom()) :: boolean()

Checks whether the specified namespace already exists

set_leds(server, namespace, leds, count \\ nil)

@spec set_leds(
  {atom()} | GenServer.server(),
  atom(),
  [pos_integer()],
  non_neg_integer() | nil
) ::
  :ok | {:error, String.t()}

Sets the leds in a specific strip and namespace.

The count should correspond to the length of the leds list and will be calculated if not provided (but often this information is already available and therefore can be provided)

Note

Repeated calls of this function will result in previously set leds will be overwritten. We are passing a list of leds which means every led will be rewritten, except if we define a 'shorter" led sequence. In that case some leds might retain their previously set value.

set_leds_with_rotation(server, namespace, leds, count \\ nil, opts)

@spec set_leds_with_rotation(
  {atom()} | GenServer.server(),
  atom(),
  [pos_integer()],
  non_neg_integer() | nil,
  keyword()
) :: :ok | {:error, String.t()}

Similar to set_leds/4 but allows to specify some options to rotate the leds.

The recognized options are:

  • :offset: The amount to rotate
  • :rotate_left: whether we want to rotate to the left (or the right). The default is true

start_link(strip_name, driver \\ Null, global_config \\ [], opts \\ [])

@spec start_link(atom(), drivers_config_t(), keyword(), keyword()) ::
  GenServer.on_start()

This starts the server controlling a specfic led strip.

It is possible to install several drivers at the same time, so different hardware gets the same data at the same time (similar to mirroring a screen). If you want to send different data to different strips, you should start several instances of this server

Because we can have several drivers (even though that is rather the exception) the confirgation is split up into several parts (not all of them need to be present):

  • The name of the strip (mandatory)
  • The global configuration of the strip (optional, defaults will be used if not specified)
  • A driver module (that also provides a default set of configs)
  • A list of detailed configs that are overlayed over the defaults. This allows for example to reuse the Fledex.Driver.Impl.Spi defaults, but change for example to a different spi device by setting :dev to spidev0.1

Here some examples (with aliased module names) how you can start the server:

  • Without real driver: start_link({:name})
  • With real driver: start_link({:name, Spi})
  • With some global config overlay and real driver: start_link({:name, Spi, timer_only_dirty_update: true})
  • With real driver and some driver overlay: start_link({:name, {Spi, dev: "spidev0.1"}})
  • With several drivers: start_link({:name, [{Spi, []}, {Spi, dev: "spidev0.1"}]})
  • With several drivers and global config: start_link({:name, [{Spi, []}, {Spi, dev: "spidev0.1"}], timer_only_dirty_update: true})

The settings for for the driver are driver specific. The global config has the following properties:

  • :timer_update_timeout: This specifies the time interval between refreshes
  • :timer_only_dirty_update: This specifies if a refresh should always happen or only if some leds have changed
  • :merge_strategy: This specifies how a set of pixel definitions that overlap should be merged together. Two strategies are known :avg and :cap (default)
  • :group_leader: This allows to set a specific group leader which might be important in some cases.

The additional options that can be passed in a passed straight to GenServer