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"
"path"
"strconv"
"time"
)
type digitalPin struct {
@ -19,11 +20,13 @@ type digitalPin struct {
val *os.File
activeLow *os.File
readBuf []byte
initialized bool
}
func newDigitalPin(n int) DigitalPin {
return &digitalPin{n: n}
return &digitalPin{n: n, readBuf: make([]byte, 1)}
}
func (p *digitalPin) N() int {
@ -107,21 +110,36 @@ func (p *digitalPin) SetDirection(dir Direction) error {
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) {
if err := p.init(); err != nil {
return 0, err
}
buf := make([]byte, 1)
if _, err := p.val.Read(buf); err != nil {
return 0, err
return p.read()
}
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)
var val int
if buf[0] == '1' {
val = 1
}
return val, nil
_, err := p.val.Write(bytes)
return err
}
func (p *digitalPin) Write(val int) error {
@ -129,12 +147,58 @@ func (p *digitalPin) Write(val int) error {
return err
}
str := "0"
if val == High {
str = "1"
return p.write(val)
}
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 {

View File

@ -2,6 +2,8 @@
package embd
import "time"
// The Direction type indicates the direction of a GPIO pin.
type Direction int
@ -32,6 +34,9 @@ type DigitalPin interface {
// Read reads the value from the pin.
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(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")
// Wait until ECHO goes high
for {
v, err := d.EchoPin.Read()
if err != nil {
return 0, err
}
if v == embd.High {
break
}
duration, err := d.EchoPin.TimePulse(embd.High)
if err != nil {
return 0, err
}
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
distance := float64(duration.Nanoseconds()) / 10000000 * (d.speedSound / 2)