mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-19 22:23:58 +00:00
gps: improvements and bugfixes (#186)
* gps: buxfixes and refactoring of API to separate device from parser Signed-off-by: deadprogram <ron@hybridgroup.com> * gps: simplify time parser Signed-off-by: deadprogram <ron@hybridgroup.com> * gps: add support for RMC sentences Signed-off-by: deadprogram <ron@hybridgroup.com> * gps: small renaming to remove reduntant use of word GPS Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
+30
-20
@@ -3,13 +3,19 @@ package gps // import "tinygo.org/x/drivers/gps"
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"machine"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidNMEASentenceLength = errors.New("invalid NMEA sentence length")
|
||||
errInvalidNMEAChecksum = errors.New("invalid NMEA sentence checksum")
|
||||
)
|
||||
|
||||
// Device wraps a connection to a GPS device.
|
||||
type GPSDevice struct {
|
||||
type Device struct {
|
||||
buffer []byte
|
||||
bufIdx int
|
||||
sentence strings.Builder
|
||||
@@ -19,8 +25,8 @@ type GPSDevice struct {
|
||||
}
|
||||
|
||||
// NewUART creates a new UART GPS connection. The UART must already be configured.
|
||||
func NewUART(uart *machine.UART) GPSDevice {
|
||||
return GPSDevice{
|
||||
func NewUART(uart *machine.UART) Device {
|
||||
return Device{
|
||||
uart: uart,
|
||||
buffer: make([]byte, bufferSize),
|
||||
bufIdx: bufferSize,
|
||||
@@ -29,8 +35,8 @@ func NewUART(uart *machine.UART) GPSDevice {
|
||||
}
|
||||
|
||||
// NewI2C creates a new I2C GPS connection.
|
||||
func NewI2C(bus *machine.I2C) GPSDevice {
|
||||
return GPSDevice{
|
||||
func NewI2C(bus *machine.I2C) Device {
|
||||
return Device{
|
||||
bus: bus,
|
||||
address: I2C_ADDRESS,
|
||||
buffer: make([]byte, bufferSize),
|
||||
@@ -39,17 +45,17 @@ func NewI2C(bus *machine.I2C) GPSDevice {
|
||||
}
|
||||
}
|
||||
|
||||
// ReadNextSentence returns the next valid NMEA sentence from the GPS device.
|
||||
func (gps *GPSDevice) NextSentence() (sentence string) {
|
||||
// NextSentence returns the next valid NMEA sentence from the GPS device.
|
||||
func (gps *Device) NextSentence() (sentence string, err error) {
|
||||
sentence = gps.readNextSentence()
|
||||
for !validSentence(sentence) {
|
||||
sentence = gps.readNextSentence()
|
||||
if err = validSentence(sentence); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return sentence
|
||||
return sentence, nil
|
||||
}
|
||||
|
||||
// readNextSentence returns the next sentence from the GPS device.
|
||||
func (gps *GPSDevice) readNextSentence() (sentence string) {
|
||||
func (gps *Device) readNextSentence() (sentence string) {
|
||||
gps.sentence.Reset()
|
||||
var b byte = ' '
|
||||
|
||||
@@ -69,7 +75,7 @@ func (gps *GPSDevice) readNextSentence() (sentence string) {
|
||||
return sentence
|
||||
}
|
||||
|
||||
func (gps *GPSDevice) readNextByte() (b byte) {
|
||||
func (gps *Device) readNextByte() (b byte) {
|
||||
gps.bufIdx += 1
|
||||
if gps.bufIdx >= bufferSize {
|
||||
gps.fillBuffer()
|
||||
@@ -77,7 +83,7 @@ func (gps *GPSDevice) readNextByte() (b byte) {
|
||||
return gps.buffer[gps.bufIdx]
|
||||
}
|
||||
|
||||
func (gps *GPSDevice) fillBuffer() {
|
||||
func (gps *Device) fillBuffer() {
|
||||
if gps.uart != nil {
|
||||
gps.uartFillBuffer()
|
||||
} else {
|
||||
@@ -85,7 +91,7 @@ func (gps *GPSDevice) fillBuffer() {
|
||||
}
|
||||
}
|
||||
|
||||
func (gps *GPSDevice) uartFillBuffer() {
|
||||
func (gps *Device) uartFillBuffer() {
|
||||
for gps.uart.Buffered() < bufferSize {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
@@ -93,7 +99,7 @@ func (gps *GPSDevice) uartFillBuffer() {
|
||||
gps.bufIdx = 0
|
||||
}
|
||||
|
||||
func (gps *GPSDevice) i2cFillBuffer() {
|
||||
func (gps *Device) i2cFillBuffer() {
|
||||
for gps.available() < bufferSize {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
@@ -102,7 +108,7 @@ func (gps *GPSDevice) i2cFillBuffer() {
|
||||
}
|
||||
|
||||
// Available returns how many bytes of GPS data are currently available.
|
||||
func (gps *GPSDevice) available() (available int) {
|
||||
func (gps *Device) available() (available int) {
|
||||
var lengthBytes [2]byte
|
||||
gps.bus.Tx(gps.address, []byte{BYTES_AVAIL_REG}, lengthBytes[0:2])
|
||||
available = int(lengthBytes[0])*256 + int(lengthBytes[1])
|
||||
@@ -110,7 +116,7 @@ func (gps *GPSDevice) available() (available int) {
|
||||
}
|
||||
|
||||
// WriteBytes sends data/commands to the GPS device
|
||||
func (gps *GPSDevice) WriteBytes(bytes []byte) {
|
||||
func (gps *Device) WriteBytes(bytes []byte) {
|
||||
if gps.uart != nil {
|
||||
gps.uart.Write(bytes)
|
||||
} else {
|
||||
@@ -119,14 +125,18 @@ func (gps *GPSDevice) WriteBytes(bytes []byte) {
|
||||
}
|
||||
|
||||
// validSentence checks if a sentence has been received uncorrupted
|
||||
func validSentence(sentence string) bool {
|
||||
func validSentence(sentence string) error {
|
||||
if len(sentence) < 4 || sentence[0] != '$' || sentence[len(sentence)-3] != '*' {
|
||||
return false
|
||||
return errInvalidNMEASentenceLength
|
||||
}
|
||||
var cs byte = 0
|
||||
for i := 1; i < len(sentence)-3; i++ {
|
||||
cs ^= sentence[i]
|
||||
}
|
||||
checksum := hex.EncodeToString([]byte{cs})
|
||||
return (checksum[0] == sentence[len(sentence)-2]) && (checksum[1] == sentence[len(sentence)-1])
|
||||
if (checksum[0] != sentence[len(sentence)-2]) || (checksum[1] != sentence[len(sentence)-1]) {
|
||||
return errInvalidNMEAChecksum
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user