From 70fc8eaa1da8a7d27715dd9e048297f704abf70d Mon Sep 17 00:00:00 2001 From: Kent Gibson Date: Mon, 18 Mar 2024 10:18:12 +0800 Subject: [PATCH] extend examples --- CHANGELOG.md | 1 + README.md | 4 +- examples/find_line_by_name/.gitignore | 4 ++ examples/find_line_by_name/main.go | 30 +++++++++ examples/get_chip_info/.gitignore | 4 ++ examples/get_chip_info/main.go | 28 ++++++++ examples/get_line_info/.gitignore | 4 ++ examples/get_line_info/main.go | 33 +++++++++ examples/get_line_value/.gitignore | 4 ++ examples/get_line_value/main.go | 30 +++++++++ examples/get_multiple_line_values/.gitignore | 4 ++ examples/get_multiple_line_values/main.go | 39 +++++++++++ examples/readme/{readme.go => main.go} | 0 .../reconfigure_input_to_output/.gitignore | 4 ++ examples/reconfigure_input_to_output/main.go | 45 +++++++++++++ examples/select_watch_line_value/main.go | 14 ++-- examples/toggle_line_value/main.go | 17 ++--- .../toggle_multiple_line_values/.gitignore | 4 ++ examples/toggle_multiple_line_values/main.go | 63 +++++++++++++++++ examples/watch_line_info/.gitignore | 4 ++ examples/watch_line_info/main.go | 47 +++++++++++++ examples/watch_line_rising/.gitignore | 4 ++ examples/watch_line_rising/main.go | 67 +++++++++++++++++++ examples/watch_line_value/main.go | 12 ++-- 24 files changed, 443 insertions(+), 23 deletions(-) create mode 100644 examples/find_line_by_name/.gitignore create mode 100644 examples/find_line_by_name/main.go create mode 100644 examples/get_chip_info/.gitignore create mode 100644 examples/get_chip_info/main.go create mode 100644 examples/get_line_info/.gitignore create mode 100644 examples/get_line_info/main.go create mode 100644 examples/get_line_value/.gitignore create mode 100644 examples/get_line_value/main.go create mode 100644 examples/get_multiple_line_values/.gitignore create mode 100644 examples/get_multiple_line_values/main.go rename examples/readme/{readme.go => main.go} (100%) create mode 100644 examples/reconfigure_input_to_output/.gitignore create mode 100644 examples/reconfigure_input_to_output/main.go create mode 100644 examples/toggle_multiple_line_values/.gitignore create mode 100644 examples/toggle_multiple_line_values/main.go create mode 100644 examples/watch_line_info/.gitignore create mode 100644 examples/watch_line_info/main.go create mode 100644 examples/watch_line_rising/.gitignore create mode 100644 examples/watch_line_rising/main.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 53aa06c..e26d251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ SPDX-License-Identifier: MIT ## [Unreleased](https://github.com/warthog618/gpiod/compare/v0.9.0...HEAD) - add *FindLine* functions to *Chip* and global. +- rework and extend examples. ## v0.9.0 - 2024-03-16 diff --git a/README.md b/README.md index 42a11c1..9d2dd52 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ l.SetValue(1) // Set line active l.SetValue(0) // Set line inactive ``` -Also refer to the [blinker](example/blinker/blinker.go) example. +Also refer to the [toggle_line_value](examples/toggle_line_value/main.go) example. For collections of lines, all lines are set simultaneously using the [*SetValues*](https://pkg.go.dev/github.com/warthog618/go-gpiocdev#Lines.SetValues) @@ -214,7 +214,7 @@ Note that the *Close* waits for the event handler to return and so must not be called from the event handler context - it should be called from a separate goroutine. -Also see the [watcher](example/watcher/watcher.go) example. +Also see the [watch_line_value](examples/watch_line_value/main.go) example. ### Line Configuration diff --git a/examples/find_line_by_name/.gitignore b/examples/find_line_by_name/.gitignore new file mode 100644 index 0000000..842553c --- /dev/null +++ b/examples/find_line_by_name/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson . +# +# SPDX-License-Identifier: CC0-1.0 +find_line_by_name diff --git a/examples/find_line_by_name/main.go b/examples/find_line_by_name/main.go new file mode 100644 index 0000000..a584b66 --- /dev/null +++ b/examples/find_line_by_name/main.go @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2024 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that finds a line by name. +package main + +import ( + "fmt" + "os" + + "github.com/warthog618/go-gpiocdev" +) + +// Finds the chip and offset of a named line. +func main() { + name := "GPIO22" + if len(os.Args) > 1 { + name = os.Args[1] + } + chip, offset, err := gpiocdev.FindLine(name) + if err != nil { + fmt.Printf("Finding line %s returned error: %s\n", name, err) + os.Exit(1) + } + fmt.Printf("%s:%d %s\n", chip, offset, name) +} diff --git a/examples/get_chip_info/.gitignore b/examples/get_chip_info/.gitignore new file mode 100644 index 0000000..0d158c8 --- /dev/null +++ b/examples/get_chip_info/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson . +# +# SPDX-License-Identifier: CC0-1.0 +get_chip_info diff --git a/examples/get_chip_info/main.go b/examples/get_chip_info/main.go new file mode 100644 index 0000000..357edd3 --- /dev/null +++ b/examples/get_chip_info/main.go @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that read the info for gpiochip0. +package main + +import ( + "fmt" + "os" + + "github.com/warthog618/go-gpiocdev" +) + +// Reads the info for gpiochip0. +func main() { + c, err := gpiocdev.NewChip("gpiochip0") + if err != nil { + fmt.Printf("Opening chip returned error: %s\n", err) + os.Exit(1) + } + defer c.Close() + + fmt.Printf("%s (%s): %d lines\n", c.Name, c.Label, c.Lines()) +} diff --git a/examples/get_line_info/.gitignore b/examples/get_line_info/.gitignore new file mode 100644 index 0000000..39f38f0 --- /dev/null +++ b/examples/get_line_info/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson . +# +# SPDX-License-Identifier: CC0-1.0 +get_line_info diff --git a/examples/get_line_info/main.go b/examples/get_line_info/main.go new file mode 100644 index 0000000..bae329e --- /dev/null +++ b/examples/get_line_info/main.go @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that read the info for line 22 on gpiochip0. +package main + +import ( + "fmt" + "os" + + "github.com/warthog618/go-gpiocdev" +) + +// Reads the info for line 22 on gpiochip0. +func main() { + c, err := gpiocdev.NewChip("gpiochip0") + if err != nil { + fmt.Printf("Opening chip returned error: %s\n", err) + os.Exit(1) + } + defer c.Close() + + info, err := c.LineInfo(22) + if err != nil { + fmt.Printf("Reading line info returned error: %s\n", err) + os.Exit(1) + } + fmt.Printf("%v\n", info) +} diff --git a/examples/get_line_value/.gitignore b/examples/get_line_value/.gitignore new file mode 100644 index 0000000..7188114 --- /dev/null +++ b/examples/get_line_value/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson +# +# SPDX-License-Identifier: CC0-1.0 +get_line_value diff --git a/examples/get_line_value/main.go b/examples/get_line_value/main.go new file mode 100644 index 0000000..d174b2d --- /dev/null +++ b/examples/get_line_value/main.go @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that reads an input pin. +package main + +import ( + "fmt" + + "github.com/warthog618/go-gpiocdev" +) + +// This example reads line 22 on gpiochip0. +func main() { + offset := 22 + chip := "gpiochip0" + l, err := gpiocdev.RequestLine(chip, offset, gpiocdev.AsInput) + if err != nil { + panic(err) + } + defer l.Close() + + values := map[int]string{0: "inactive", 1: "active"} + v, err := l.Value() + fmt.Printf("%s:%d %s\n", chip, offset, values[v]) +} diff --git a/examples/get_multiple_line_values/.gitignore b/examples/get_multiple_line_values/.gitignore new file mode 100644 index 0000000..45d94b8 --- /dev/null +++ b/examples/get_multiple_line_values/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson +# +# SPDX-License-Identifier: CC0-1.0 +get_multiple_line_values diff --git a/examples/get_multiple_line_values/main.go b/examples/get_multiple_line_values/main.go new file mode 100644 index 0000000..732549b --- /dev/null +++ b/examples/get_multiple_line_values/main.go @@ -0,0 +1,39 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that reads multiple input pins. +package main + +import ( + "fmt" + "os" + + "github.com/warthog618/go-gpiocdev" +) + +// This example reads lines 21 and 22 on gpiochip0. +func main() { + offsets := []int{21, 22} + chip := "gpiochip0" + l, err := gpiocdev.RequestLines(chip, offsets, gpiocdev.AsInput) + if err != nil { + fmt.Printf("Requesting lines returned error: %s\n", err) + os.Exit(1) + } + defer l.Close() + + values := map[int]string{0: "inactive", 1: "active"} + vv := []int{0, 0} + err = l.Values(vv) + if err != nil { + fmt.Printf("Reading values returned error: %s\n", err) + os.Exit(1) + } + for i, o := range offsets { + fmt.Printf("%s:%d %s\n", chip, o, values[vv[i]]) + } +} diff --git a/examples/readme/readme.go b/examples/readme/main.go similarity index 100% rename from examples/readme/readme.go rename to examples/readme/main.go diff --git a/examples/reconfigure_input_to_output/.gitignore b/examples/reconfigure_input_to_output/.gitignore new file mode 100644 index 0000000..3e6290c --- /dev/null +++ b/examples/reconfigure_input_to_output/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson +# +# SPDX-License-Identifier: CC0-1.0 +reconfigure_input_to_output diff --git a/examples/reconfigure_input_to_output/main.go b/examples/reconfigure_input_to_output/main.go new file mode 100644 index 0000000..654c698 --- /dev/null +++ b/examples/reconfigure_input_to_output/main.go @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that requests a line as an input and subsequently switches it to an output. +// DO NOT run this on a platform where that line is externally driven. +package main + +import ( + "fmt" + "time" + + "github.com/warthog618/go-gpiocdev" +) + +// This example requests line 23 on gpiochip0 as an input then switches it to an output. +// DO NOT run this on a platform where that line is externally driven. +func main() { + offset := 23 + chip := "gpiochip0" + l, err := gpiocdev.RequestLine(chip, offset, gpiocdev.AsInput) + if err != nil { + panic(err) + } + // revert line to input on the way out. + defer func() { + l.Reconfigure(gpiocdev.AsInput) + fmt.Printf("Input pin: %s:%d\n", chip, offset) + l.Close() + }() + + values := map[int]string{0: "inactive", 1: "active"} + v, err := l.Value() + fmt.Printf("Read pin: %s:%d %s\n", chip, offset, values[v]) + + l.Reconfigure(gpiocdev.AsOutput(v)) + fmt.Printf("Set pin %s:%d %s\n", chip, offset, values[v]) + time.Sleep(500 * time.Millisecond) + v ^= 1 + l.SetValue(v) + fmt.Printf("Set pin %s:%d %s\n", chip, offset, values[v]) +} diff --git a/examples/select_watch_line_value/main.go b/examples/select_watch_line_value/main.go index 1ecb8f7..7002b84 100644 --- a/examples/select_watch_line_value/main.go +++ b/examples/select_watch_line_value/main.go @@ -18,7 +18,6 @@ import ( "time" "github.com/warthog618/go-gpiocdev" - "github.com/warthog618/go-gpiocdev/device/rpi" ) func printEvent(evt gpiocdev.LineEvent) { @@ -45,7 +44,7 @@ func printEvent(evt gpiocdev.LineEvent) { } } -// Watches GPIO 23 (Raspberry Pi J8-16) and reports when it changes state. +// Watches line 23 on gpiochip0 and reports when it changes state. func main() { echan := make(chan gpiocdev.LineEvent, 6) @@ -57,12 +56,13 @@ func main() { // if you want the handler to block, rather than dropping // events when the channel fills then <- ctx.Done() instead // to ensure that the handler can't be left blocked - fmt.Printf("event chan overflow - discarding event") + fmt.Println("event chan overflow - discarding event") } } - offset := rpi.J8p16 - l, err := gpiocdev.RequestLine("gpiochip0", offset, + offset := 23 + chip := "gpiochip0" + l, err := gpiocdev.RequestLine(chip, offset, gpiocdev.WithPullUp, gpiocdev.WithBothEdges, gpiocdev.WithEventHandler(eh)) @@ -74,7 +74,7 @@ func main() { os.Exit(1) } - fmt.Printf("Watching Pin %d...\n", offset) + fmt.Printf("Watching Pin %s:%d...\n", chip, offset) done := false for !done { select { @@ -82,7 +82,7 @@ func main() { case evt := <-echan: printEvent(evt) case <-ctx.Done(): - fmt.Println("exiting...") + fmt.Println("select_watch_line_value exiting...") l.Close() done = true } diff --git a/examples/toggle_line_value/main.go b/examples/toggle_line_value/main.go index 29b3533..c057ee9 100644 --- a/examples/toggle_line_value/main.go +++ b/examples/toggle_line_value/main.go @@ -16,26 +16,27 @@ import ( "time" "github.com/warthog618/go-gpiocdev" - "github.com/warthog618/go-gpiocdev/device/rpi" ) -// This example drives GPIO 22, which is pin J8-15 on a Raspberry Pi. +// This example drives line 22 on gpiochip0. // The pin is toggled high and low at 1Hz with a 50% duty cycle. -// Do not run this on a device which has this pin externally driven. +// DO NOT run this on a device which has this pin externally driven. func main() { - offset := rpi.J8p15 + offset := 22 + chip := "gpiochip0" v := 0 - l, err := gpiocdev.RequestLine("gpiochip0", offset, gpiocdev.AsOutput(v)) + l, err := gpiocdev.RequestLine(chip, offset, gpiocdev.AsOutput(v)) if err != nil { panic(err) } // revert line to input on the way out. defer func() { l.Reconfigure(gpiocdev.AsInput) + fmt.Printf("Input pin %s:%d\n", chip, offset) l.Close() }() values := map[int]string{0: "inactive", 1: "active"} - fmt.Printf("Set pin %d %s\n", offset, values[v]) + fmt.Printf("Set pin %s:%d %s\n", chip, offset, values[v]) // capture exit signals to ensure pin is reverted to input on exit. quit := make(chan os.Signal, 1) @@ -44,10 +45,10 @@ func main() { for { select { - case <-time.After(2 * time.Second): + case <-time.After(500 * time.Millisecond): v ^= 1 l.SetValue(v) - fmt.Printf("Set pin %d %s\n", offset, values[v]) + fmt.Printf("Set pin %s:%d %s\n", chip, offset, values[v]) case <-quit: return } diff --git a/examples/toggle_multiple_line_values/.gitignore b/examples/toggle_multiple_line_values/.gitignore new file mode 100644 index 0000000..1b8b77b --- /dev/null +++ b/examples/toggle_multiple_line_values/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson +# +# SPDX-License-Identifier: CC0-1.0 +toggle_multiple_line_values diff --git a/examples/toggle_multiple_line_values/main.go b/examples/toggle_multiple_line_values/main.go new file mode 100644 index 0000000..d64fbf2 --- /dev/null +++ b/examples/toggle_multiple_line_values/main.go @@ -0,0 +1,63 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that toggles multiple output pins. +package main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + "time" + + "github.com/warthog618/go-gpiocdev" +) + +// This example drives lines 21 and 22 on gpiochip0. +// The pins are toggled high and low opposite each other at 1Hz with a 50% duty cycle. +// DO NOT run this on a device which has either of those pins externally driven. +func main() { + offsets := []int{21, 22} + chip := "gpiochip0" + vv := []int{0, 1} + l, err := gpiocdev.RequestLines(chip, offsets, gpiocdev.AsOutput(vv...)) + if err != nil { + panic(err) + } + // revert lines to input on the way out. + defer func() { + l.Reconfigure(gpiocdev.AsInput) + fmt.Printf("Input pins %s:%v\n", chip, offsets) + l.Close() + }() + + values := map[int]string{0: "inactive", 1: "active"} + for i, o := range offsets { + fmt.Printf("Set pin %s:%d %s\n", chip, o, values[vv[i]]) + } + + // capture exit signals to ensure pin is reverted to input on exit. + quit := make(chan os.Signal, 1) + signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) + defer signal.Stop(quit) + + for { + select { + case <-time.After(500 * time.Millisecond): + for i := range vv { + vv[i] ^= 1 + } + l.SetValues(vv) + for i, o := range offsets { + fmt.Printf("Set pin %s:%d %s\n", chip, o, values[vv[i]]) + } + case <-quit: + return + } + } +} diff --git a/examples/watch_line_info/.gitignore b/examples/watch_line_info/.gitignore new file mode 100644 index 0000000..ab0707b --- /dev/null +++ b/examples/watch_line_info/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson . +# +# SPDX-License-Identifier: CC0-1.0 +watch_line_info diff --git a/examples/watch_line_info/main.go b/examples/watch_line_info/main.go new file mode 100644 index 0000000..d9603fb --- /dev/null +++ b/examples/watch_line_info/main.go @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that watches an input pin and reports edge events. +package main + +import ( + "fmt" + "os" + "time" + + "github.com/warthog618/go-gpiocdev" +) + +func eventHandler(evt gpiocdev.LineInfoChangeEvent) { + t := time.Now() + fmt.Printf("%s event: %#v\n", t.Format(time.RFC3339Nano), evt) +} + +// Watches lines 21-23 on gpiochip0 and and reports when they change state. +func main() { + offsets := []int{21, 22, 23} + chip := "gpiochip0" + c, err := gpiocdev.NewChip(chip) + if err != nil { + fmt.Printf("Opening chip returned error: %s\n", err) + os.Exit(1) + } + defer c.Close() + + for _, o := range offsets { + info, err := c.WatchLineInfo(o, eventHandler) + if err != nil { + fmt.Printf("Watching line %d returned error: %s\n", o, err) + os.Exit(1) + } + fmt.Printf("Watching Pin %s:%d: %#v\n", chip, o, info) + } + // In a real application the main thread would do something useful. + // But we'll just run for a minute then exit. + time.Sleep(time.Minute) + fmt.Println("watch_line_info exiting...") +} diff --git a/examples/watch_line_rising/.gitignore b/examples/watch_line_rising/.gitignore new file mode 100644 index 0000000..8963234 --- /dev/null +++ b/examples/watch_line_rising/.gitignore @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2019 Kent Gibson . +# +# SPDX-License-Identifier: CC0-1.0 +watch_line_rising diff --git a/examples/watch_line_rising/main.go b/examples/watch_line_rising/main.go new file mode 100644 index 0000000..c63f53f --- /dev/null +++ b/examples/watch_line_rising/main.go @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2020 Kent Gibson +// +// SPDX-License-Identifier: MIT + +//go:build linux +// +build linux + +// A simple example that watches an input pin and reports rising edge events. +package main + +import ( + "fmt" + "os" + "syscall" + "time" + + "github.com/warthog618/go-gpiocdev" +) + +func eventHandler(evt gpiocdev.LineEvent) { + t := time.Now() + edge := "rising" + if evt.Type == gpiocdev.LineEventFallingEdge { + // shouldn't see any of these, but check to confirm + edge = "falling" + } + if evt.Seqno != 0 { + // only uAPI v2 populates the sequence numbers + fmt.Printf("%s event: #%d(%d)%3d %-7s (%s)\n", + t.Format(time.RFC3339Nano), + evt.Seqno, + evt.LineSeqno, + evt.Offset, + edge, + evt.Timestamp) + } else { + fmt.Printf("%s event:%3d %-7s (%s)\n", + t.Format(time.RFC3339Nano), + evt.Offset, + edge, + evt.Timestamp) + } +} + +// Watches gpiochip0:23 reports when it rises. +func main() { + offset := 23 + chip := "gpiochip0" + l, err := gpiocdev.RequestLine(chip, offset, + gpiocdev.WithPullUp, + gpiocdev.WithRisingEdge, + gpiocdev.WithEventHandler(eventHandler)) + if err != nil { + fmt.Printf("RequestLine returned error: %s\n", err) + if err == syscall.Errno(22) { + fmt.Println("Note that the WithPullUp option requires Linux 5.5 or later - check your kernel version.") + } + os.Exit(1) + } + defer l.Close() + + // In a real application the main thread would do something useful. + // But we'll just run for a minute then exit. + fmt.Printf("Watching Pin %s:%d...\n", chip, offset) + time.Sleep(time.Minute) + fmt.Println("watch_line_rising exiting...") +} diff --git a/examples/watch_line_value/main.go b/examples/watch_line_value/main.go index 20441ee..1e04ed8 100644 --- a/examples/watch_line_value/main.go +++ b/examples/watch_line_value/main.go @@ -15,7 +15,6 @@ import ( "time" "github.com/warthog618/go-gpiocdev" - "github.com/warthog618/go-gpiocdev/device/rpi" ) func eventHandler(evt gpiocdev.LineEvent) { @@ -42,10 +41,11 @@ func eventHandler(evt gpiocdev.LineEvent) { } } -// Watches GPIO 23 (Raspberry Pi J8-16) and reports when it changes state. +// Watches gpiochip0:23 and reports when it changes state. func main() { - offset := rpi.J8p16 - l, err := gpiocdev.RequestLine("gpiochip0", offset, + offset := 23 + chip := "gpiochip0" + l, err := gpiocdev.RequestLine(chip, offset, gpiocdev.WithPullUp, gpiocdev.WithBothEdges, gpiocdev.WithEventHandler(eventHandler)) @@ -60,7 +60,7 @@ func main() { // In a real application the main thread would do something useful. // But we'll just run for a minute then exit. - fmt.Printf("Watching Pin %d...\n", offset) + fmt.Printf("Watching Pin %s:%d...\n", chip, offset) time.Sleep(time.Minute) - fmt.Println("exiting...") + fmt.Println("watch_line_value exiting...") }