Skip to content

Commit

Permalink
Rework GPIO function setting to be a bit nicer. Add functions for set…
Browse files Browse the repository at this point in the history
…ting pins as inputs, outputs, including compulsory specification of pull up/down/none mode for outputs.
  • Loading branch information
Jon-Bright committed Feb 21, 2021
1 parent e1935e5 commit 7f3d9b9
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
51 changes: 46 additions & 5 deletions rpi/gpio.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package rpi
import (
"fmt"
"log"
"time"
"unsafe"
)

Expand Down Expand Up @@ -35,17 +36,57 @@ type gpioT struct {
test uint32
}

func (rp *RPi) gpioFunctionSet(pin int, alt int) error {
type PullMode uint

const (
// See p101. These are GPPUD values
PullNone = 0
PullDown = 1
PullUp = 2
)

func (rp *RPi) gpioSetPinFunction(pin int, fnc uint32) error {
if pin > 53 { // p94
return fmt.Errorf("pin %d not supported")
}
reg := pin / 10
offset := uint((pin % 10) * 3)
rp.gpio.fsel[reg] &= ^(0x7 << offset)
rp.gpio.fsel[reg] |= fnc << offset
return nil
}

func (rp *RPi) gpioSetInput(pin int) error {
return rp.gpioSetPinFunction(pin, 0)
}

func (rp *RPi) gpioSetOutput(pin int, pm PullMode) error {
if pm > PullUp {
return fmt.Errorf("%d is an invalid pull mode", pm)
}
err := rp.gpioSetPinFunction(pin, 1)
if err != nil {
return fmt.Errorf("couldn't set pin as output: %v", err)
}

// See p101 for the description of this procedure.
rp.gpio.pud = uint32(pm)
time.Sleep(10 * time.Microsecond) // Datasheet says to sleep for 150 cycles after setting pud
reg := pin / 32
offset := uint(pin % 32)
rp.gpio.pudclk[reg] = 1 << offset
time.Sleep(10 * time.Microsecond) // Datasheet says to sleep for 150 cycles after setting pudclk
rp.gpio.pud = 0
rp.gpio.pudclk[reg] = 0
return nil
}

func (rp *RPi) gpioSetAltFunction(pin int, alt int) error {
funcs := []uint32{4, 5, 6, 7, 3, 2} // See p92 in datasheet - these are the alt functions only
if alt >= len(funcs) {
return fmt.Errorf("%d is an invalid alt function", alt)
}

rp.gpio.fsel[reg] &= ^(0x7 << offset)
rp.gpio.fsel[reg] |= (funcs[alt]) << offset
return nil
return rp.gpioSetPinFunction(pin, funcs[alt])
}

func (rp *RPi) InitGPIO() error {
Expand Down
2 changes: 1 addition & 1 deletion rpi/pwm.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (rp *RPi) InitPWM(freq uint, buf *DMABuf, bytes uint, pins []int) error {
if !ok {
return fmt.Errorf("invalid pin %d for PWM channel %d", pin, channel)
}
rp.gpioFunctionSet(pin, alt)
rp.gpioSetAltFunction(pin, alt)
}

if rp.pwmBuf == nil {
Expand Down

0 comments on commit 7f3d9b9

Please sign in to comment.