diff --git a/README.md b/README.md index 74f89a2..7b7e8ce 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ go-rpio ======= -Native GPIO-Gophers for your Pi! +Native GPIO-Gophers for your Pi! -go-rpio is a Go library for accessing [GPIO](http://elinux.org/Rpi_Low-level_peripherals)-pins +go-rpio is a Go library for accessing [GPIO](http://elinux.org/Rpi_Low-level_peripherals)-pins on the [Raspberry Pi](https://en.wikipedia.org/wiki/Raspberry_Pi). It requires no external c libraries such as @@ -22,7 +22,7 @@ err := rpio.Open() ``` Initialize a pin, run basic operations. -Pin refers to the bcm2835 pin, not the physical pin on the raspberry pi header. Pin 10 here is exposed on the pin header as physical pin 19. +Pin refers to the bcm2835 pin, not the physical pin on the raspberry pi header. Pin 10 here is exposed on the pin header as physical pin 19. ```go pin := rpio.Pin(10) @@ -39,6 +39,16 @@ pin.Mode(rpio.Output) // Alternative syntax pin.Write(rpio.High) // Alternative syntax ``` +Pull up/down/off can be set using: + +```go +pin.PullUp() +pin.PullDown() +pin.PullOff() + +pin.Pull(rpio.PullUp) +``` + Unmap memory when done ```go @@ -53,11 +63,10 @@ Currently, it supports basic functionality such as: - Pin Direction (Input / Output) - Write (High / Low) - Read (High / Low) +- Pull (Up / Down / Off) Would be nice to add in the future: - PWM -- PullUp -- PullDown - I2C - SPI - etc... diff --git a/examples/pullup/pullup.go b/examples/pullup/pullup.go new file mode 100644 index 0000000..e992004 --- /dev/null +++ b/examples/pullup/pullup.go @@ -0,0 +1,32 @@ +package main + +import ( + "fmt" + "github.com/stianeikeland/go-rpio" + "os" +) + +var ( + // Use mcu pin 22, corresponds to GPIO3 on the pi + pin = rpio.Pin(22) +) + +func main() { + // Open and map memory to access gpio, check for errors + if err := rpio.Open(); err != nil { + fmt.Println(err) + os.Exit(1) + } + + // Unmap gpio memory when done + defer rpio.Close() + + // Pull up and read value + pin.PullUp() + fmt.Printf("PullUp: %d\n", pin.Read()) + + // Pull down and read value + pin.PullDown() + fmt.Printf("PullDown: %d\n", pin.Read()) + +} diff --git a/rpio.go b/rpio.go index e47f2e8..4efe204 100644 --- a/rpio.go +++ b/rpio.go @@ -7,6 +7,7 @@ Supports simple operations such as: - Pin mode/direction (input/output) - Pin write (high/low) - Pin read (high/low) +- Pull up/down/off Example of use: @@ -59,12 +60,14 @@ import ( "reflect" "sync" "syscall" + "time" "unsafe" ) type Direction uint8 type Pin uint8 type State uint8 +type Pull uint8 // Memory offsets for gpio, see the spec for more details const ( @@ -87,6 +90,13 @@ const ( High ) +// Pull Up / Down / Off +const ( + PullOff Pull = iota + PullDown + PullUp +) + // Arrays for 8 / 32 bit access to memory and a semaphore for write locking var ( memlock sync.Mutex @@ -134,6 +144,26 @@ func (pin Pin) Read() State { return ReadPin(pin) } +// Set a given pull up/down mode +func (pin Pin) Pull(pull Pull) { + PullMode(pin, pull) +} + +// Pull up pin +func (pin Pin) PullUp() { + PullMode(pin, PullUp) +} + +// Pull down pin +func (pin Pin) PullDown() { + PullMode(pin, PullDown) +} + +// Disable pullup/down on pin +func (pin Pin) PullOff() { + PullMode(pin, PullOff) +} + // WritePin sets the direction of a given pin (Input or Output) func PinMode(pin Pin, direction Direction) { @@ -197,6 +227,36 @@ func TogglePin(pin Pin) { } } +func PullMode(pin Pin, pull Pull) { + // Pull up/down/off register has offset 38 / 39, pull is 37 + pullClkReg := uint8(pin)/32 + 38 + pullReg := 37 + shift := (uint8(pin) % 32) + + memlock.Lock() + + switch pull { + case PullDown, PullUp: + mem[pullReg] = mem[pullReg]&^3 | uint32(pull) + case PullOff: + mem[pullReg] = mem[pullReg] &^ 3 + } + + // Wait for value to clock in, this is ugly, sorry :( + time.Sleep(time.Microsecond) + + mem[pullClkReg] = 1 << shift + + // Wait for value to clock in + time.Sleep(time.Microsecond) + + mem[pullReg] = mem[pullReg] &^ 3 + mem[pullClkReg] = 0 + + memlock.Unlock() + +} + // Open and memory map GPIO memory range from /dev/mem . // Some reflection magic is used to convert it to a unsafe []uint32 pointer func Open() (err error) {