Giter VIP home page Giter VIP logo

inky's Introduction

Inky

CircleCI hex.pm

This is a port of Pimoroni's python Inky library written in Elixir. This library is intended to support both Inky pHAT and wHAT, but since we only have pHATs, the wHAT support may not be fully functional.

See the API reference for details on how to use the functionality provided.

Host Development

An inky host development library is underway for allowing host-side development, but until that is finished you can not see results without using a physical device.

Scenic Driver

A basic driver for scenic is in the works, check it out, to follow how it is progressing.

Getting started

Inky is available on Hex. Add inky to your mix.exs deps:

{:inky, "~> 1.0.1"},

Run mix deps.get to get the new dep.

Usage

A sample for Inky only, both host development and on-device is available as pappersverk/sample_inky.

A sample for using it with Scenic both for host development and on-device is available as pappersverk/sample_scenic_inky.

Brief example

In typical usage this would be inside a nerves project. If Inky is installed in your application you can do the following to test it and your display (note the config in init, adjust accordingly):

# Start your Inky process ...
{:ok, pid} = Inky.start_link(:phat, :red, %{name: InkySample})

painter = fn x, y, w, h, _pixels_so_far ->
  wh = w / 2
  hh = h / 2

  case {x >= wh, y >= hh} do
    {true, true} -> :red
    {false, true} -> if(rem(x, 2) == 0, do: :black, else: :white)
    {true, false} -> :black
    {false, false} -> :white
  end
end

Inky.set_pixels(InkySample, painter, border: :white)

# Flip a few pixels
Inky.set_pixels(pid, %{{0,0}: :black, {3,49}: :red, {23, 4}: white})

inky's People

Contributors

alexslade avatar brynjarm avatar jasonmj avatar kottkrig avatar lawik avatar mnishiguchi avatar nyaray avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

inky's Issues

Support the Inky Impression

This issue will be used for now to capture any and all notes about implementing support for the impression.

It is different hardware but I think we could extend the current API or make a 2.x series to support it where we extend the API in a breaking fashion if necessary.

The way we built the Phat and What support was by porting from Pimoroni. pimoroni/inky

Example for the 7color should be the Impression: https://github.com/pimoroni/inky/blob/master/examples/7color/stripes.py

That indicates using this:
https://github.com/pimoroni/inky/blob/master/library/inky/inky_uc8159.py

Make any notes on progress or dead ends available here :)

Ping @jasonmj @axelson who have also ordered this thing.

Add a convenient way to get display info by type

On the calling side it is usually useful to have access to whatever size the display is. In the Scenic driver I'm already expected to provide that information so it ends up a bit redundant. But it seems like if you pass :phat to the start_link if you could get {:ok, pid, display} it would help.

What do you think?

Consider making the busy waits into aspects of sync/async updates

In the original source, busy waiting is an option, likely depending on the single threaded nature of normal python programming, but the reasons don't really matter.

Since our library will be wrapped in a GenServer, we should probably make it an option to busy-wait on the display (maybe as an opts field in set/show calls?) when handling synchronous show requests, whether set or show.

Version 1.0.1 cannot compile on Elixir 1.10

Hello! I'm trying to use this library in an Elixir 1.10 project, and referencing version 1.0.1 from Hex yields the following error:

== Compilation error in file lib/display/display.ex ==
** (CompileError) lib/display/display.ex:17: type t/0 undefined (no such type in Inky.Display)
    (elixir 1.10.2) lib/kernel/typespec.ex:898: Kernel.Typespec.compile_error/2
    (elixir 1.10.2) lib/kernel/typespec.ex:937: Kernel.Typespec.fn_args/6
    (elixir 1.10.2) lib/kernel/typespec.ex:377: Kernel.Typespec.translate_spec/8
    (stdlib 3.9.2) lists.erl:1354: :lists.mapfoldl/3
    (elixir 1.10.2) lib/kernel/typespec.ex:229: Kernel.Typespec.translate_typespecs_for_module/2
    (elixir 1.10.2) src/elixir_erl_compiler.erl:12: anonymous fn/3 in :elixir_erl_compiler.spawn/2
could not compile dependency :inky, "mix compile" failed. You can recompile this dependency with "mix deps.compile inky", update it with "mix deps.update inky" or clean it with "mix deps.clean inky"

I see this has been fixed on master thanks to #34, can I ask you to release 1.0.2 on Hex with this fix?
Thank you for the library, it's awesome otherwise!

Not working with wHAT display

The library (v1.0.0) is not working with my Inky wHAT red on Raspberry Pi Zero W

If I configure it to use pHAT it works on part of the screen, so it has something to do with wHAT part of the implementation.

Verified that the screen works fine with the Python library

Small example

{:ok, pid} = Inky.start_link(:what, :red, %{name: InkySample})

painter = fn x, y, w, h, _pixels_so_far ->:black end

Inky.set_pixels(InkySample, painter, border: :white)

Error

16:17:31.481 [error] GenServer InkySample terminating
** (MatchError) no match of right hand side value: {:error, :transfer_failed}
    (inky) lib/hal/rpiio.ex:101: Inky.RpiIO.spi_write/3
    (inky) lib/hal/rpihal.ex:243: Inky.RpiHAL.write_command/3
    (inky) lib/hal/rpihal.ex:93: Inky.RpiHAL.do_update/5
    (inky) lib/inky.ex:165: Inky.handle_call/3
    (stdlib) gen_server.erl:661: :gen_server.try_handle_call/4
    (stdlib) gen_server.erl:690: :gen_server.handle_msg/6
    (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.172.0>): {:set_pixels, #Function<11.128620087/5 in :erl_eval.expr/5>, [border: :white]}
State: %Inky.State{border: :black, display: %Inky.Display{accent: :red, height: 300, luts: <<72, 160, 16, 16, 19, 0, 0, 72, 160, 128, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 165, 0, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 12, 32, 12, 6, 16, 8, 4, 4, 6, ...>>, packed_dimensions: %{height: <<44, 1>>, width: "1"}, rotation: 0, type: :what, width: 400}, hal_mod: Inky.RpiHAL, hal_state: %Inky.RpiHAL.State{display: %Inky.Display{accent: :red, height: 300, luts: <<72, 160, 16, 16, 19, 0, 0, 72, 160, 128, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 165, 0, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 12, 32, 12, 6, 16, 8, ...>>, packed_dimensions: %{height: <<44, 1>>, width: "1"}, rotation: 0, type: :what, width: 400}, io_mod: Inky.RpiIO, io_state: %Inky.RpiIO.State{busy_pid: #Reference<0.269476080.1512177672.81328>, dc_pid: #Reference<0.269476080.1512177672.81326>, reset_pid: #Reference<0.269476080.1512177672.81327>, spi_pid: #Reference<0.269476080.1512177672.81331>}}, pixels: %{}, type: nil, wait_type: :nowait}
Client #PID<0.172.0> is alive

    (stdlib) gen.erl:169: :gen.do_call/4
    (elixir) lib/gen_server.ex:1007: GenServer.call/3
    (stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
    (elixir) src/elixir.erl:275: :elixir.eval_forms/4
    (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5
    (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3
    (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3
    (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1
** (EXIT from #PID<0.172.0>) shell process exited with reason: an exception was raised:
    ** (MatchError) no match of right hand side value: {:error, :transfer_failed}
        (inky) lib/hal/rpiio.ex:101: Inky.RpiIO.spi_write/3
        (inky) lib/hal/rpihal.ex:243: Inky.RpiHAL.write_command/3
        (inky) lib/hal/rpihal.ex:93: Inky.RpiHAL.do_update/5
        (inky) lib/inky.ex:165: Inky.handle_call/3
        (stdlib) gen_server.erl:661: :gen_server.try_handle_call/4
        (stdlib) gen_server.erl:690: :gen_server.handle_msg/6
        (stdlib) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Testing/Helping

Hi there, I've just purchased an Inky phat for my rpi0 and I'm trying to get your repo to work. I wanted to reach out to you and see how this project is coming along and if there's anything I can do to test/help out?

I've got the yellow version of the Inky phat. So far, I've added this repo as a dependency to a basic Nerves sandbox and I'm able to interact with with it over ssh in an iex session.

I ran the few commands I saw in the "Examples" comment under Inky.ex and all went well until I ran Inky.show(state).

iex(20)> Inky.show(state) "send_command/2" "spi_write/3 binary" ** (MatchError) no match of right hand side value: {:error, :timeout} (inky_zero_nerves) lib/inky/inky.ex:279: Inky.spi_write/3 (inky_zero_nerves) lib/inky/inky.ex:85: Inky.setup/2 (inky_zero_nerves) lib/inky/inky.ex:135: Inky.update/3

I haven't got time right now to dig in further and see if I can get this to work, but I would like to spend some time playing with it over the holidays. I figured it'd be good to drop you a line and say hi before I got to tinkering with it.

Anyhow, I'll see what I can do on my own over the next few days and check back later with a progress report. Until then, thanks for the work you've done here!

Clean up IO tests to use hex or constants in comparisons

Currently we have things like:

assert get_border_command() == [send_command: {60, 51}]

While the command being sent is provided in hex:

write_command(state, 0x3C, border_data)

0x3C is output as 60 and that's why things are this way right now. We should probably change it so that the connection remains clear.

Host dev library should handle border

I think this should be fairly straight-forward. If it isn't I might skip it.

Putting it in this repo/issues thing because I've yet to move all things to their right locations.

Experiment with higher SPI speeds

When looking at the Python library, I found this pimoroni/inky#30 which indicates that we might be able to make things go a bit faster.

This can be done independently of any other on-going work as one could, for example, make the SPI speed be a config-parameter that defaults to the current value if not set, thus making any change backwards compatible.

Allow setting an optional rotation

This would give the end-user the power to control the direction of the display instead of adapting their pixel-wrangling to whatever orientation we are currently defaulting to. And we can handle any transformation for the hardware internally. Such as the phat -90 and what 0.

GenServerify the main entrypoint, Inky (inky.ex)

Re-written (again ^^) thoughts after a longer chat with @lawik

In Inky, we'd expose a simple API:

  • start_link(opts \\ []), accepts name

  • stop(pid | name)

  • set_pixels(pid | name, pixels | painter, opts \\ []), updates genserver state either with specific pixels or by calling painter.(x,y) for all points in the screen, in an undefined order.

    To begin with, it only accepts an :update option with one of the following values

    • :state_only: do not push to display, just update pixel state
    • {:timeout, :once}: Use genserver timeouts to avoid multiple updates. When the timeout triggers, update the display if not busy. Otherwise just updates pixel state.
    • {:timeout, :await}: Use genserver timeouts to avoid multiple updates. When the timeout triggers, await device ready with a busy wait and then push to the display.
    • :once: Check if busy once, return timeout if failed, otherwise push to display. Update pixel state regardless. If there has been a timeout previously set, but that has yet to fire, it will be set again.
    • :await: Busy wait until you can push to display.
  • show(async \\ false), render pixels, blocking the client by default, the genserver always busy waits internally

Missing dependencies?

I did a clean clone, fetched and built deps and tried running mix to just compile everything and got a warning.

Generated inky_zero_nerves app
You have configured application :nerves_firmware_ssh in your configuration file,
but the application is not available.

This usually means one of:

  1. You have not added the application as a dependency in a mix.exs file.

  2. You are configuring an application that does not really exist.

Please ensure :nerves_firmware_ssh exists or remove the configuration.

You have configured application :nerves_init_gadget in your configuration file,
but the application is not available.

This usually means one of:

  1. You have not added the application as a dependency in a mix.exs file.

  2. You are configuring an application that does not really exist.

Please ensure :nerves_init_gadget exists or remove the configuration.

Use constants or something elegant for all the magic numbers

The Python Inky library is full of assorted pieces of hex and binary. And so are we. We probably wan't to collect these magic numbers as constants or some other more elegant solution that allows us to mostly update those values when the inky library updates to fix something.

display orientation upside down

The display orientation is upside down compared to how Pimoroni uses Inky. It is fine when we use Inky standalone, but a problem may arise when we want to use something like Adafruit CYBERDECK Bonnet for Raspberry Pi 400.

It would be nice if the orientation is consistent with Pimoroni's settings, but probably it will require some breaking changes, meaning users existing code for Inky will be upside down suddenly.

This library
Pin header at the bottom

Pimoroni (pimoroni/inky)
Pin header at the top

Adafruit CYBERDECK Bonnet for Raspberry Pi 400
Pin header at the top

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.