gpio: provide an api to allow performance timing of pulses

the us020 driver is the first consumer of this functionality
This commit is contained in:
Karan Misra 2014-04-05 04:06:40 +05:30
parent af23a999ba
commit 5b852d9f42
3 changed files with 87 additions and 43 deletions

View File

@ -10,6 +10,7 @@ import (
"os" "os"
"path" "path"
"strconv" "strconv"
"time"
) )
type digitalPin struct { type digitalPin struct {
@ -19,11 +20,13 @@ type digitalPin struct {
val *os.File val *os.File
activeLow *os.File activeLow *os.File
readBuf []byte
initialized bool initialized bool
} }
func newDigitalPin(n int) DigitalPin { func newDigitalPin(n int) DigitalPin {
return &digitalPin{n: n} return &digitalPin{n: n, readBuf: make([]byte, 1)}
} }
func (p *digitalPin) N() int { func (p *digitalPin) N() int {
@ -107,21 +110,36 @@ func (p *digitalPin) SetDirection(dir Direction) error {
return err return err
} }
func (p *digitalPin) read() (int, error) {
if _, err := p.val.ReadAt(p.readBuf, 0); err != nil {
return 0, err
}
if p.readBuf[0] == 49 {
return 1, nil
}
return 0, nil
}
func (p *digitalPin) Read() (int, error) { func (p *digitalPin) Read() (int, error) {
if err := p.init(); err != nil { if err := p.init(); err != nil {
return 0, err return 0, err
} }
buf := make([]byte, 1) return p.read()
if _, err := p.val.Read(buf); err != nil { }
return 0, err
var (
lowBytes = []byte{48}
highBytes = []byte{49}
)
func (p *digitalPin) write(val int) error {
bytes := lowBytes
if val == High {
bytes = highBytes
} }
p.val.Seek(0, 0) _, err := p.val.Write(bytes)
var val int return err
if buf[0] == '1' {
val = 1
}
return val, nil
} }
func (p *digitalPin) Write(val int) error { func (p *digitalPin) Write(val int) error {
@ -129,12 +147,58 @@ func (p *digitalPin) Write(val int) error {
return err return err
} }
str := "0" return p.write(val)
if val == High { }
str = "1"
func (p *digitalPin) TimePulse(state int) (time.Duration, error) {
if err := p.init(); err != nil {
return 0, err
} }
_, err := p.val.WriteString(str)
return err aroundState := Low
if state == Low {
aroundState = High
}
// Wait for any previous pulse to end
for {
v, err := p.read()
if err != nil {
return 0, err
}
if v == aroundState {
break
}
}
// Wait until ECHO goes high
for {
v, err := p.read()
if err != nil {
return 0, err
}
if v == state {
break
}
}
startTime := time.Now() // Record time when ECHO goes high
// Wait until ECHO goes low
for {
v, err := p.read()
if err != nil {
return 0, err
}
if v == aroundState {
break
}
}
return time.Since(startTime), nil // Calculate time lapsed for ECHO to transition from high to low
} }
func (p *digitalPin) ActiveLow(b bool) error { func (p *digitalPin) ActiveLow(b bool) error {

View File

@ -2,6 +2,8 @@
package embd package embd
import "time"
// The Direction type indicates the direction of a GPIO pin. // The Direction type indicates the direction of a GPIO pin.
type Direction int type Direction int
@ -32,6 +34,9 @@ type DigitalPin interface {
// Read reads the value from the pin. // Read reads the value from the pin.
Read() (int, error) Read() (int, error)
// TimePulse measures the duration of a pulse on the pin.
TimePulse(state int) (time.Duration, error)
// SetDirection sets the direction of the pin (in/out). // SetDirection sets the direction of the pin (in/out).
SetDirection(dir Direction) error SetDirection(dir Direction) error

View File

@ -91,36 +91,11 @@ func (d *US020) Distance() (float64, error) {
glog.V(2).Infof("us020: waiting for echo to go high") glog.V(2).Infof("us020: waiting for echo to go high")
// Wait until ECHO goes high duration, err := d.EchoPin.TimePulse(embd.High)
for { if err != nil {
v, err := d.EchoPin.Read() return 0, err
if err != nil {
return 0, err
}
if v == embd.High {
break
}
} }
startTime := time.Now() // Record time when ECHO goes high
glog.V(2).Infof("us020: waiting for echo to go low")
// Wait until ECHO goes low
for {
v, err := d.EchoPin.Read()
if err != nil {
return 0, err
}
if v == embd.Low {
break
}
}
duration := time.Since(startTime) // Calculate time lapsed for ECHO to transition from high to low
// Calculate the distance based on the time computed // Calculate the distance based on the time computed
distance := float64(duration.Nanoseconds()) / 10000000 * (d.speedSound / 2) distance := float64(duration.Nanoseconds()) / 10000000 * (d.speedSound / 2)