-
Notifications
You must be signed in to change notification settings - Fork 12
Start work on on Inky Impression #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
7d80cce
Start work on on Inky Impression
lawik 8ee2dda
More work on setup and update for Inky Impression
lawik 6e11741
Add all of the Impression code but not working, added cs0 but that wo…
lawik c56c9be
Kinda working!
axelson e415e0e
Kind of like a flag
axelson fc37b1f
Cleaning
axelson cc82eda
Clean up cs pin calls
axelson 99d2cd5
clean
axelson 7a636df
Merge pull request #42 from axelson/jax/inky-impression
lawik 753d5a8
Fix log typo
3f46d9a
Adds comments to byte commands defined for Impression in hal
3142798
Fix typo in comment
ae2e48f
Update mix deps for development on jasonmj
07f75e6
Update display definition for impression
63cdb4f
Add handling for impression in packed_width and packed_height
13793cd
Fix usage of state in log function
853021b
Add set_dimensions to do_update for impression
46a3b40
Replace buffer generation with PixelUtil.pixels_to_bits
9dfa181
Add a color_map for the impression
5bfb57f
Add notes about WIP toward impression support
4689834
Reverting dev changes to mix.exs
3bcf4f1
Cleaning up unused code
590c25f
Adding bit_size option to PixelUtil.pixels_to_bits
d5bca11
Merge pull request #46 from jasonmj/impression
lawik 9abc79f
Cleans up code for PR
80bdee8
Adds painter test
f86d1b8
Support circuits_gpio 1.0
axelson b30be19
Merge pull request #47 from axelson/impression
a68e31a
Add support for buttons on Inky Impression
40cda84
Support sending button messages to a process by registered atom name
6a6cd42
Merge pull request #48 from jasonmj/impression
lawik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,138 @@ | ||
| defmodule Inky.Buttons do | ||
| @moduledoc """ | ||
| The Inky Impression has 4 buttons that are monitored independently from the display | ||
| and can be started in supervison. | ||
|
|
||
| Supply the `:handler` option as an atom, a pid, or `{module, function, args}` tuple | ||
| specifying where to send events to. If no handler is supplied, events are simply logged | ||
|
|
||
| ```elixir | ||
| Inky.Buttons.start_link(handler: self()) | ||
| ``` | ||
|
|
||
| You can also query the current value of a button at any time | ||
|
|
||
| ```elixir | ||
| Inky.Buttons.get_value(:a) | ||
| ``` | ||
| """ | ||
|
|
||
| use GenServer | ||
|
|
||
| alias Circuits.GPIO | ||
|
|
||
| require Logger | ||
|
|
||
| @typedoc """ | ||
| Button name for Inky Impression button | ||
|
|
||
| These are labelled A, B, X, and Y on the board. | ||
| """ | ||
| @type name() :: :a | :b | :x | :y | ||
|
|
||
| defmodule Event do | ||
| defstruct [:action, :name, :value, :timestamp] | ||
|
|
||
| @type t :: %Event{ | ||
| action: :pressed | :released, | ||
| name: Buttons.name(), | ||
| value: 1 | 0, | ||
| timestamp: non_neg_integer() | ||
| } | ||
| end | ||
|
|
||
| @pin_a 5 | ||
| @pin_b 6 | ||
| @pin_x 16 | ||
| @pin_y 24 | ||
|
|
||
| @doc """ | ||
| Start a GenServer to watch the buttons on the Inky Impression | ||
|
|
||
| Options: | ||
|
|
||
| * `:handler` - pass an atom, a pid, or an MFA to receive button events | ||
| """ | ||
| @spec start_link(keyword) :: GenServer.on_start() | ||
| def start_link(opts \\ []) do | ||
| GenServer.start_link(__MODULE__, opts, name: __MODULE__) | ||
| end | ||
|
|
||
| @doc """ | ||
| Return the current state of the button | ||
|
|
||
| `0` - released | ||
| `1` - pressed | ||
| """ | ||
| @spec get_value(name()) :: 0 | 1 | ||
| def get_value(button) do | ||
| GenServer.call(__MODULE__, {:get_value, button}) | ||
| end | ||
|
|
||
| @impl GenServer | ||
| def init(opts) do | ||
| {:ok, %{button_to_ref: %{}, pin_to_button: %{}, handler: opts[:handler]}, {:continue, :init}} | ||
| end | ||
|
|
||
| @impl GenServer | ||
| def handle_continue(:init, state) do | ||
| {:ok, a} = GPIO.open(@pin_a, :input, pull_mode: :pullup) | ||
| {:ok, b} = GPIO.open(@pin_b, :input, pull_mode: :pullup) | ||
| {:ok, x} = GPIO.open(@pin_x, :input, pull_mode: :pullup) | ||
| {:ok, y} = GPIO.open(@pin_y, :input, pull_mode: :pullup) | ||
| :ok = GPIO.set_interrupts(a, :both) | ||
| :ok = GPIO.set_interrupts(b, :both) | ||
| :ok = GPIO.set_interrupts(x, :both) | ||
| :ok = GPIO.set_interrupts(y, :both) | ||
|
|
||
| button_to_ref = %{a: a, b: b, x: x, y: y} | ||
|
|
||
| pin_to_button = %{ | ||
| @pin_a => :a, | ||
| @pin_b => :b, | ||
| @pin_x => :x, | ||
| @pin_y => :y | ||
| } | ||
|
|
||
| {:noreply, %{state | button_to_ref: button_to_ref, pin_to_button: pin_to_button}} | ||
| end | ||
|
|
||
| @impl GenServer | ||
| def handle_call({:get_value, name}, _from, state) do | ||
| inverted_value = GPIO.read(state.button_to_ref[name]) | ||
| value = 1 - inverted_value | ||
|
|
||
| {:reply, value, state} | ||
| end | ||
|
|
||
| @impl GenServer | ||
| def handle_info({:circuits_gpio, pin, timestamp, inverted_value}, state) do | ||
| value = 1 - inverted_value | ||
| action = if value != 0, do: :pressed, else: :released | ||
|
|
||
| event = %Event{ | ||
| action: action, | ||
| name: state.pin_to_button[pin], | ||
| value: value, | ||
| timestamp: timestamp | ||
| } | ||
|
|
||
| _ = send_event(state.handler, event) | ||
|
|
||
| {:noreply, state} | ||
| end | ||
|
|
||
| def handle_info(_other, state), do: {:noreply, state} | ||
|
|
||
| defp send_event(handler, event) when is_atom(handler), do: send(handler, event) | ||
|
|
||
| defp send_event(handler, event) when is_pid(handler), do: send(handler, event) | ||
|
|
||
| defp send_event({m, f, a}, event) when is_atom(m) and is_atom(f) and is_list(a) do | ||
| apply(m, f, [event | a]) | ||
| end | ||
|
|
||
| defp send_event(_, event) do | ||
| Logger.info("[Inky] unhandled button event - #{inspect(event)}") | ||
| end | ||
| end |
This file contains hidden or 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 hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are required for one display but not the other, we should consider refactoring things so that we don't force re-usability where it is not required/meaningful (maybe that's exactly what you did here? :D). "False generalisation" only makes things unclear since you don't knew when/if something is required/missing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reverted this change too, since these keys can peacefully coexist in the struct the defines the impression display. We're not using packed dimensions because it's redundant/unnecessary, but if someone wants to use them in the future, it'll be possible.
As for luts, it's not used at all for the impression. Not sure we need to define a separate struct+key enforcement just for that though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is good food for thought, though... if the devices are diverting, perhaps our configurations should, too.
One way of dealing with it would be to have a protocol common for all types, for the things that are common to all displays and then have the specific drivers check if it is a value of the correct underlying type at runtime during init. But that might be a bit more than what you signed up for at this point and a bit of over-engineering before we have several displays where the fit is off... thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds like it might be a worthwhile refactor to open a separate issue for.