Circuits.GPIO.Chip (circuits_cdev v0.1.0) View Source
Control GPIOs using the GPIO chip interface
With the character device driver for GPIOs there three concepts to learn.
First, the API is made up of chips and lines that are grouped together for that chip. A chip is more of a grouping identifier than anything physical property about the board.
Secondly, the API requires us to request lines from a GPIO chip. The reason for this is the kernel can provide control over who "owns" that line and prevent multiple programs from trying to control the same GPIO pin.
Lastly, you can listen for events on a line. These events report if the line is high or low.
Generally speaking the character device driver allows more fine grain control
and more reliability than the sysfs
API.
Link to this section Summary
Functions
Getting information about a line
Listen to line events on the line offset
Open a GPIO Chip
Read value from a line handle
Read values for a line handle
Request a line handle for a single GPIO offset
Request a line handle for multiple GPIO offsets
Set the value of the GPIO
Set values of the GPIOs
Link to this section Types
Specs
line_direction() :: :input | :output
The direction of the line
With the character device you drive a line with configured offsets. These
offsets all share a direction, either :output
or :input
, which is called
the line direction.
The :output
direction means you control the GPIOs by setting the value of
the GPIOs to 1 or 0. See Circuits.GPIO.Chip.set_value/2
for more
information.
The :input
direction means you can only read the current value of the GPIOs
on the line. See Circuits.GPIO.Chip.read_value/1
for more information.
Specs
offset() :: non_neg_integer()
The offset of the pin
An offset is the pin number provided. Normally these are labeled GPIO N
or
GPIO_N
where N
is the pin number. For example, if you wanted to use to
use GPIO 17
on a Raspberry PI the offset value would be 17
.
More resources:
Raspberry PI: https://pinout.xyz/ Beaglebone: https://beagleboard.org/Support/bone101
Specs
offset_value() :: 0 | 1
The value of the offset
This is either 0 for low or off, or 1 for high or on.
Specs
t() :: %Circuits.GPIO.Chip{ label: String.t(), name: String.t(), number_of_lines: non_neg_integer(), reference: reference() }
Link to this section Functions
Specs
get_line_info(t(), offset()) :: {:ok, Circuits.GPIO.Chip.LineInfo.t()} | {:error, atom()}
Getting information about a line
Specs
Listen to line events on the line offset
Circuits.GPIO.Chip.listen_event(mygpio_chip, 24)
# cause the offset to change value
flush
{:circuits_cdev, 24, timestamp, new_value}
The timestamp will be in nanoseconds so as you do time calculations and conversions be sure to take that into account.
The new_value
will be the value the offset value changed to either 1
or
0
.
Specs
Open a GPIO Chip
{:ok, chip} = Circuits.GPIO.Chip.open(gpiochip_device)
Specs
read_value(Circuits.GPIO.Chip.LineHandle.t()) :: {:ok, offset_value()} | {:error, atom()}
Read value from a line handle
This is useful when you have a line handle that contains only one GPIO offset.
If you want to read multiple GPIOs at once see
Circuits.GPIO.Chip.read_values/1
.
{:ok, line_handle} = Circuits.GPIO.Chip.request_line("gpiochip0", 17)
{:ok, 0} = Circuits.GPIO.Chip.read_value(line_handle)
Specs
read_values(Circuits.GPIO.Chip.LineHandle.t()) :: {:ok, [offset_value()]} | {:error, atom()}
Read values for a line handle
This is useful when you a line handle that contains multiple GPIO offsets.
{:ok, line_handle} = Circuits.GPIO.Chip.request_lines("gpiochip0", [17, 22, 23, 24])
{:ok, [0, 0, 0, 0]} = Circuits.GPIO.Chip.read_values(line_handle)
Note that the values in the list match the index order of how the offsets were requested.
Note that the order of the values returned return the order that the offsets were requested.
Specs
request_line(t() | String.t(), offset(), line_direction()) :: {:ok, Circuits.GPIO.Chip.LineHandle.t()}
Request a line handle for a single GPIO offset
{:ok, line_handle} = Circuits.GPIO.Chip.request_line(my_gpio_chip, 17, :output)
See Circuits.GPIO.Chip.request_lines/3
and Circuits.GPIO.LineHandle
for
more details about line handles.
Specs
request_lines(t() | String.t(), [offset()], line_direction()) :: {:ok, Circuits.GPIO.Chip.LineHandle.t()}
Request a line handle for multiple GPIO offsets
{:ok, line_handle} = Circuits.GPIO.Chip.request_lines(my_gpio_chip, [17, 24], :output)
For the GPIO character device driver you drive GPIOs by requesting for a line handle what contains one or more GPIO offsets. The line handle is mechanism by which you can read and set the values of the GPIO(s). The line handle is attached to the calling process and kernel will not allow others to control the GPIO(s) that are part of that the line handle. Moreover, one the process that requested the line handle goes away the kernel will be able to automatically free the system resources that were tied to that line handle.
Specs
set_value(Circuits.GPIO.Chip.LineHandle.t(), offset_value()) :: :ok | {:error, atom()}
Set the value of the GPIO
{:ok, line_handle} = Circuits.GPIO.Chip.request_lines(my_gpio_chip, 17)
{:ok, 0} = Circuits.GPIO.Chip.read_value(line_handle)
:ok = Circuits.GPIO.Chip.set_value(line_handle, 1)
{:ok, 1} = Circuits.GPIO.Chip.read_value(line_handle)
Specs
set_values(Circuits.GPIO.Chip.LineHandle.t(), [offset_value()]) :: :ok | {:error, atom()}
Set values of the GPIOs
{:ok, line_handle} = Circuits.GPIO.Chip.request_lines(my_gpio_chip, [17, 24, 22])
{:ok, [0, 0, 0]} = Circuits.GPIO.Chip.read_value(line_handle)
:ok = Circuits.GPIO.Chip.set_value(line_handle, [1, 0, 1])
{:ok, [1, 0, 1]} = Circuits.GPIO.Chip.read_value(line_handle)
Note that the order of the values that were sent matches the order by which the GPIO offsets where requested. In the example above offset 17 was set to 1, offset 24 was stayed at 0, offset 22 was set to 1.