mirror of
https://github.com/hybridgroup/gobot.git
synced 2025-05-09 19:29:27 +08:00
WIP firmata refactor
This commit is contained in:
parent
167aa1091b
commit
d8be3d11d2
@ -6,142 +6,130 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/hybridgroup/gobot"
|
||||
)
|
||||
|
||||
const (
|
||||
Open byte = 1
|
||||
Close byte = 0
|
||||
Input byte = 0x00
|
||||
Output byte = 0x01
|
||||
Analog byte = 0x02
|
||||
PWM byte = 0x03
|
||||
Servo byte = 0x04
|
||||
Low byte = 0
|
||||
High byte = 1
|
||||
ReportVersion byte = 0xF9
|
||||
SystemReset byte = 0xFF
|
||||
DigitalMessage byte = 0x90
|
||||
DigitalMessageRangeStart byte = 0x90
|
||||
DigitalMessageRangeEnd byte = 0x9F
|
||||
AnalogMessage byte = 0xE0
|
||||
AnalogMessageRangeStart byte = 0xE0
|
||||
AnalogMessageRangeEnd byte = 0xEF
|
||||
ReportAnalog byte = 0xC0
|
||||
ReportDigital byte = 0xD0
|
||||
PinMode byte = 0xF4
|
||||
StartSysex byte = 0xF0
|
||||
EndSysex byte = 0xF7
|
||||
CapabilityQuery byte = 0x6B
|
||||
CapabilityResponse byte = 0x6C
|
||||
PinStateQuery byte = 0x6D
|
||||
PinStateResponse byte = 0x6E
|
||||
AnalogMappingQuery byte = 0x69
|
||||
AnalogMappingResponse byte = 0x6A
|
||||
StringData byte = 0x71
|
||||
I2CRequest byte = 0x76
|
||||
I2CReply byte = 0x77
|
||||
I2CConfig byte = 0x78
|
||||
FirmwareQuery byte = 0x79
|
||||
I2CModeWrite byte = 0x00
|
||||
I2CModeRead byte = 0x01
|
||||
I2CmodeContinuousRead byte = 0x02
|
||||
I2CModeStopReading byte = 0x03
|
||||
open byte = 1
|
||||
close byte = 0
|
||||
input byte = 0x00
|
||||
output byte = 0x01
|
||||
analog byte = 0x02
|
||||
pwm byte = 0x03
|
||||
servo byte = 0x04
|
||||
low byte = 0
|
||||
high byte = 1
|
||||
reportVersion byte = 0xF9
|
||||
systemReset byte = 0xFF
|
||||
digitalMessage byte = 0x90
|
||||
digitalMessageRangeStart byte = 0x90
|
||||
digitalMessageRangeEnd byte = 0x9F
|
||||
analogMessage byte = 0xE0
|
||||
analogMessageRangeStart byte = 0xE0
|
||||
analogMessageRangeEnd byte = 0xEF
|
||||
reportAnalog byte = 0xC0
|
||||
reportDigital byte = 0xD0
|
||||
pinMode byte = 0xF4
|
||||
startSysex byte = 0xF0
|
||||
endSysex byte = 0xF7
|
||||
capabilityQuery byte = 0x6B
|
||||
capabilityResponse byte = 0x6C
|
||||
pinStateQuery byte = 0x6D
|
||||
pinStateResponse byte = 0x6E
|
||||
analogMappingQuery byte = 0x69
|
||||
analogMappingResponse byte = 0x6A
|
||||
stringData byte = 0x71
|
||||
i2CRequest byte = 0x76
|
||||
i2CReply byte = 0x77
|
||||
i2CConfig byte = 0x78
|
||||
firmwareQuery byte = 0x79
|
||||
i2CModeWrite byte = 0x00
|
||||
i2CModeRead byte = 0x01
|
||||
i2CmodeContinuousRead byte = 0x02
|
||||
i2CModeStopReading byte = 0x03
|
||||
)
|
||||
|
||||
type board struct {
|
||||
Serial io.ReadWriteCloser
|
||||
Pins []pin
|
||||
AnalogPins []byte
|
||||
FirmwareName string
|
||||
MajorVersion byte
|
||||
MinorVersion byte
|
||||
Events []event
|
||||
Connected bool
|
||||
serial io.ReadWriteCloser
|
||||
pins []pin
|
||||
analogPins []byte
|
||||
firmwareName string
|
||||
majorVersion byte
|
||||
minorVersion byte
|
||||
connected bool
|
||||
events map[string]*gobot.Event
|
||||
}
|
||||
|
||||
type pin struct {
|
||||
SupportedModes []byte
|
||||
Mode byte
|
||||
Value int
|
||||
AnalogChannel byte
|
||||
}
|
||||
|
||||
type event struct {
|
||||
Name string
|
||||
Data []byte
|
||||
I2cReply map[string][]byte
|
||||
supportedModes []byte
|
||||
mode byte
|
||||
value int
|
||||
analogChannel byte
|
||||
}
|
||||
|
||||
func newBoard(sp io.ReadWriteCloser) *board {
|
||||
board := new(board)
|
||||
board.MajorVersion = 0
|
||||
board.MinorVersion = 0
|
||||
board.Serial = sp
|
||||
board.FirmwareName = ""
|
||||
board.Pins = []pin{}
|
||||
board.AnalogPins = []byte{}
|
||||
board.Connected = false
|
||||
board.Events = []event{}
|
||||
board := &board{
|
||||
majorVersion: 0,
|
||||
minorVersion: 0,
|
||||
serial: sp,
|
||||
firmwareName: "",
|
||||
pins: []pin{},
|
||||
analogPins: []byte{},
|
||||
connected: false,
|
||||
events: make(map[string]*gobot.Event),
|
||||
}
|
||||
|
||||
for _, s := range []string{
|
||||
"firmware_query",
|
||||
"capability_query",
|
||||
"analog_mapping_query",
|
||||
"report_version",
|
||||
"i2c_reply",
|
||||
"analog_mapping_query",
|
||||
"string_data",
|
||||
"firmware_query",
|
||||
} {
|
||||
board.events[s] = gobot.NewEvent()
|
||||
}
|
||||
|
||||
return board
|
||||
}
|
||||
|
||||
func (b *board) connect() {
|
||||
if b.Connected == false {
|
||||
if b.connected == false {
|
||||
b.initBoard()
|
||||
b.Connected = true
|
||||
|
||||
go func() {
|
||||
for {
|
||||
b.queryReportVersion()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
b.readAndProcess()
|
||||
for {
|
||||
b.queryReportVersion()
|
||||
<-time.After(1 * time.Second)
|
||||
b.readAndProcess()
|
||||
if b.connected == true {
|
||||
break
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *board) initBoard() {
|
||||
for {
|
||||
b.queryFirmware()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
b.readAndProcess()
|
||||
if len(b.findEvents("firmware_query")) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
for {
|
||||
gobot.On(b.events["firmware_query"], func(data interface{}) {
|
||||
b.events["firmware_query"] = gobot.NewEvent()
|
||||
b.queryCapabilities()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
b.readAndProcess()
|
||||
if len(b.findEvents("capability_query")) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
for {
|
||||
b.queryAnalogMapping()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
b.readAndProcess()
|
||||
if len(b.findEvents("analog_mapping_query")) > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
b.togglePinReporting(0, High, ReportDigital)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
b.togglePinReporting(1, High, ReportDigital)
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
}
|
||||
})
|
||||
|
||||
func (b *board) findEvents(name string) []event {
|
||||
ret := []event{}
|
||||
for key, val := range b.Events {
|
||||
if val.Name == name {
|
||||
ret = append(ret, val)
|
||||
if len(b.Events) > key+1 {
|
||||
b.Events = append(b.Events[:key], b.Events[key+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
gobot.On(b.events["capability_query"], func(data interface{}) {
|
||||
b.events["capability_query"] = gobot.NewEvent()
|
||||
b.queryAnalogMapping()
|
||||
})
|
||||
|
||||
gobot.On(b.events["analog_mapping_query"], func(data interface{}) {
|
||||
b.events["analog_mapping_query"] = gobot.NewEvent()
|
||||
b.togglePinReporting(0, high, reportDigital)
|
||||
<-time.After(50 * time.Millisecond)
|
||||
b.togglePinReporting(1, high, reportDigital)
|
||||
<-time.After(50 * time.Millisecond)
|
||||
b.connected = true
|
||||
})
|
||||
}
|
||||
|
||||
func (b *board) readAndProcess() {
|
||||
@ -149,59 +137,59 @@ func (b *board) readAndProcess() {
|
||||
}
|
||||
|
||||
func (b *board) reset() {
|
||||
b.write([]byte{SystemReset})
|
||||
b.write([]byte{systemReset})
|
||||
}
|
||||
|
||||
func (b *board) setPinMode(pin byte, mode byte) {
|
||||
b.Pins[pin].Mode = mode
|
||||
b.write([]byte{PinMode, pin, mode})
|
||||
b.pins[pin].mode = mode
|
||||
b.write([]byte{pinMode, pin, mode})
|
||||
}
|
||||
|
||||
func (b *board) digitalWrite(pin byte, value byte) {
|
||||
port := byte(math.Floor(float64(pin) / 8))
|
||||
portValue := byte(0)
|
||||
|
||||
b.Pins[pin].Value = int(value)
|
||||
b.pins[pin].value = int(value)
|
||||
|
||||
for i := byte(0); i < 8; i++ {
|
||||
if b.Pins[8*port+i].Value != 0 {
|
||||
if b.pins[8*port+i].value != 0 {
|
||||
portValue = portValue | (1 << i)
|
||||
}
|
||||
}
|
||||
b.write([]byte{DigitalMessage | port, portValue & 0x7F, (portValue >> 7) & 0x7F})
|
||||
b.write([]byte{digitalMessage | port, portValue & 0x7F, (portValue >> 7) & 0x7F})
|
||||
}
|
||||
|
||||
func (b *board) analogWrite(pin byte, value byte) {
|
||||
b.Pins[pin].Value = int(value)
|
||||
b.write([]byte{AnalogMessage | pin, value & 0x7F, (value >> 7) & 0x7F})
|
||||
b.pins[pin].value = int(value)
|
||||
b.write([]byte{analogMessage | pin, value & 0x7F, (value >> 7) & 0x7F})
|
||||
}
|
||||
|
||||
func (b *board) version() string {
|
||||
return fmt.Sprintf("%v.%v", b.MajorVersion, b.MinorVersion)
|
||||
return fmt.Sprintf("%v.%v", b.majorVersion, b.minorVersion)
|
||||
}
|
||||
|
||||
func (b *board) reportVersion() {
|
||||
b.write([]byte{ReportVersion})
|
||||
b.write([]byte{reportVersion})
|
||||
}
|
||||
|
||||
func (b *board) queryFirmware() {
|
||||
b.write([]byte{StartSysex, FirmwareQuery, EndSysex})
|
||||
b.write([]byte{startSysex, firmwareQuery, endSysex})
|
||||
}
|
||||
|
||||
func (b *board) queryPinState(pin byte) {
|
||||
b.write([]byte{StartSysex, PinStateQuery, pin, EndSysex})
|
||||
b.write([]byte{startSysex, pinStateQuery, pin, endSysex})
|
||||
}
|
||||
|
||||
func (b *board) queryReportVersion() {
|
||||
b.write([]byte{ReportVersion})
|
||||
b.write([]byte{reportVersion})
|
||||
}
|
||||
|
||||
func (b *board) queryCapabilities() {
|
||||
b.write([]byte{StartSysex, CapabilityQuery, EndSysex})
|
||||
b.write([]byte{startSysex, capabilityQuery, endSysex})
|
||||
}
|
||||
|
||||
func (b *board) queryAnalogMapping() {
|
||||
b.write([]byte{StartSysex, AnalogMappingQuery, EndSysex})
|
||||
b.write([]byte{startSysex, analogMappingQuery, endSysex})
|
||||
}
|
||||
|
||||
func (b *board) togglePinReporting(pin byte, state byte, mode byte) {
|
||||
@ -209,37 +197,37 @@ func (b *board) togglePinReporting(pin byte, state byte, mode byte) {
|
||||
}
|
||||
|
||||
func (b *board) i2cReadRequest(slaveAddress byte, numBytes uint) {
|
||||
b.write([]byte{StartSysex, I2CRequest, slaveAddress, (I2CModeRead << 3),
|
||||
byte(numBytes & 0x7F), byte(((numBytes >> 7) & 0x7F)), EndSysex})
|
||||
b.write([]byte{startSysex, i2CRequest, slaveAddress, (i2CModeRead << 3),
|
||||
byte(numBytes & 0x7F), byte(((numBytes >> 7) & 0x7F)), endSysex})
|
||||
}
|
||||
|
||||
func (b *board) i2cWriteRequest(slaveAddress byte, data []byte) {
|
||||
ret := []byte{StartSysex, I2CRequest, slaveAddress, (I2CModeWrite << 3)}
|
||||
ret := []byte{startSysex, i2CRequest, slaveAddress, (i2CModeWrite << 3)}
|
||||
for _, val := range data {
|
||||
ret = append(ret, byte(val&0x7F))
|
||||
ret = append(ret, byte((val>>7)&0x7F))
|
||||
}
|
||||
ret = append(ret, EndSysex)
|
||||
ret = append(ret, endSysex)
|
||||
b.write(ret)
|
||||
}
|
||||
|
||||
func (b *board) i2cConfig(data []byte) {
|
||||
ret := []byte{StartSysex, I2CConfig}
|
||||
ret := []byte{startSysex, i2CConfig}
|
||||
for _, val := range data {
|
||||
ret = append(ret, byte(val&0xFF))
|
||||
ret = append(ret, byte((val>>8)&0xFF))
|
||||
}
|
||||
ret = append(ret, EndSysex)
|
||||
ret = append(ret, endSysex)
|
||||
b.write(ret)
|
||||
}
|
||||
|
||||
func (b *board) write(commands []byte) {
|
||||
b.Serial.Write(commands[:])
|
||||
b.serial.Write(commands[:])
|
||||
}
|
||||
|
||||
func (b *board) read() []byte {
|
||||
buf := make([]byte, 1024)
|
||||
b.Serial.Read(buf)
|
||||
b.serial.Read(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
@ -251,27 +239,27 @@ func (b *board) process(data []byte) {
|
||||
break
|
||||
}
|
||||
switch {
|
||||
case ReportVersion == messageType:
|
||||
b.MajorVersion, _ = buf.ReadByte()
|
||||
b.MinorVersion, _ = buf.ReadByte()
|
||||
b.Events = append(b.Events, event{Name: "report_version"})
|
||||
case AnalogMessageRangeStart <= messageType && AnalogMessageRangeEnd >= messageType:
|
||||
case reportVersion == messageType:
|
||||
b.majorVersion, _ = buf.ReadByte()
|
||||
b.minorVersion, _ = buf.ReadByte()
|
||||
gobot.Publish(b.events["report_version"], b.version())
|
||||
case analogMessageRangeStart <= messageType && analogMessageRangeEnd >= messageType:
|
||||
leastSignificantByte, _ := buf.ReadByte()
|
||||
mostSignificantByte, _ := buf.ReadByte()
|
||||
|
||||
value := uint(leastSignificantByte) | uint(mostSignificantByte)<<7
|
||||
pin := (messageType & 0x0F)
|
||||
|
||||
b.Pins[b.AnalogPins[pin]].Value = int(value)
|
||||
b.Events = append(b.Events,
|
||||
event{Name: fmt.Sprintf("analog_read_%v", pin),
|
||||
Data: []byte{
|
||||
byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value & 0xff),
|
||||
},
|
||||
b.pins[b.analogPins[pin]].value = int(value)
|
||||
gobot.Publish(b.events[fmt.Sprintf("analog_read_%v", pin)],
|
||||
[]byte{
|
||||
byte(value >> 24),
|
||||
byte(value >> 16),
|
||||
byte(value >> 8),
|
||||
byte(value & 0xff),
|
||||
},
|
||||
)
|
||||
|
||||
case DigitalMessageRangeStart <= messageType && DigitalMessageRangeEnd >= messageType:
|
||||
case digitalMessageRangeStart <= messageType && digitalMessageRangeEnd >= messageType:
|
||||
port := messageType & 0x0F
|
||||
firstBitmask, _ := buf.ReadByte()
|
||||
secondBitmask, _ := buf.ReadByte()
|
||||
@ -279,18 +267,14 @@ func (b *board) process(data []byte) {
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
pinNumber := (8*byte(port) + byte(i))
|
||||
pin := b.Pins[pinNumber]
|
||||
if byte(pin.Mode) == Input {
|
||||
pin.Value = int((portValue >> (byte(i) & 0x07)) & 0x01)
|
||||
b.Events = append(b.Events,
|
||||
event{Name: fmt.Sprintf("digital_read_%v", pinNumber),
|
||||
Data: []byte{byte(pin.Value & 0xff)},
|
||||
},
|
||||
)
|
||||
pin := b.pins[pinNumber]
|
||||
if byte(pin.mode) == input {
|
||||
pin.value = int((portValue >> (byte(i) & 0x07)) & 0x01)
|
||||
gobot.Publish(fmt.Sprintf("digital_read_%v", pinNumber),
|
||||
[]byte{byte(pin.value & 0xff)})
|
||||
}
|
||||
}
|
||||
|
||||
case StartSysex == messageType:
|
||||
case startSysex == messageType:
|
||||
currentBuffer := []byte{messageType}
|
||||
for {
|
||||
b, err := buf.ReadByte()
|
||||
@ -298,25 +282,26 @@ func (b *board) process(data []byte) {
|
||||
break
|
||||
}
|
||||
currentBuffer = append(currentBuffer, b)
|
||||
if currentBuffer[len(currentBuffer)-1] == EndSysex {
|
||||
if currentBuffer[len(currentBuffer)-1] == endSysex {
|
||||
break
|
||||
}
|
||||
}
|
||||
command := currentBuffer[1]
|
||||
switch command {
|
||||
case CapabilityResponse:
|
||||
case capabilityResponse:
|
||||
supportedModes := 0
|
||||
n := 0
|
||||
|
||||
for _, val := range currentBuffer[2:(len(currentBuffer) - 5)] {
|
||||
if val == 127 {
|
||||
modes := []byte{}
|
||||
for _, mode := range []byte{Input, Output, Analog, PWM, Servo} {
|
||||
for _, mode := range []byte{input, output, analog, pwm, servo} {
|
||||
if (supportedModes & (1 << mode)) != 0 {
|
||||
modes = append(modes, mode)
|
||||
}
|
||||
}
|
||||
b.Pins = append(b.Pins, pin{modes, Output, 0, 0})
|
||||
b.pins = append(b.pins, pin{modes, output, 0, 0})
|
||||
b.Events[fmt.Sprintf("digital_read_%v", len(b.pins)-1)] = gobot.NewEvent()
|
||||
supportedModes = 0
|
||||
n = 0
|
||||
continue
|
||||
@ -327,42 +312,38 @@ func (b *board) process(data []byte) {
|
||||
}
|
||||
n ^= 1
|
||||
}
|
||||
b.Events = append(b.Events, event{Name: "capability_query"})
|
||||
|
||||
case AnalogMappingResponse:
|
||||
gobot.Publish(b.events["capability_query"], nil)
|
||||
case analogMappingResponse:
|
||||
pinIndex := byte(0)
|
||||
|
||||
for _, val := range currentBuffer[2 : len(b.Pins)-1] {
|
||||
for _, val := range currentBuffer[2 : len(b.pins)-1] {
|
||||
|
||||
b.Pins[pinIndex].AnalogChannel = val
|
||||
b.pins[pinIndex].analogChannel = val
|
||||
|
||||
if val != 127 {
|
||||
b.AnalogPins = append(b.AnalogPins, pinIndex)
|
||||
b.analogPins = append(b.analogPins, pinIndex)
|
||||
}
|
||||
|
||||
b.events[fmt.Sprintf("analog_read_%v", pinIndex)] = gobot.NewEvent()
|
||||
pinIndex++
|
||||
}
|
||||
|
||||
b.Events = append(b.Events, event{Name: "analog_mapping_query"})
|
||||
|
||||
case PinStateResponse:
|
||||
pin := b.Pins[currentBuffer[2]]
|
||||
pin.Mode = currentBuffer[3]
|
||||
pin.Value = int(currentBuffer[4])
|
||||
gobot.Publish(b.events["analog_mapping_query"], nil)
|
||||
case pinStateResponse:
|
||||
pin := b.pins[currentBuffer[2]]
|
||||
pin.mode = currentBuffer[3]
|
||||
pin.value = int(currentBuffer[4])
|
||||
|
||||
if len(currentBuffer) > 6 {
|
||||
pin.Value = int(uint(pin.Value) | uint(currentBuffer[5])<<7)
|
||||
pin.value = int(uint(pin.value) | uint(currentBuffer[5])<<7)
|
||||
}
|
||||
if len(currentBuffer) > 7 {
|
||||
pin.Value = int(uint(pin.Value) | uint(currentBuffer[6])<<14)
|
||||
pin.value = int(uint(pin.value) | uint(currentBuffer[6])<<14)
|
||||
}
|
||||
|
||||
b.Events = append(b.Events,
|
||||
event{Name: fmt.Sprintf("pin_%v_state", currentBuffer[2]),
|
||||
Data: []byte{byte(pin.Value & 0xff)},
|
||||
},
|
||||
gobot.Publish(b.events[fmt.Sprintf("pin_%v_state", currentBuffer[2])],
|
||||
[]byte{byte(pin.value & 0xff)},
|
||||
)
|
||||
case I2CReply:
|
||||
case i2CReply:
|
||||
i2cReply := map[string][]byte{
|
||||
"slave_address": []byte{byte(currentBuffer[2]) | byte(currentBuffer[3])<<7},
|
||||
"register": []byte{byte(currentBuffer[4]) | byte(currentBuffer[5])<<7},
|
||||
@ -379,21 +360,20 @@ func (b *board) process(data []byte) {
|
||||
byte(currentBuffer[i])|byte(currentBuffer[i+1])<<7,
|
||||
)
|
||||
}
|
||||
b.Events = append(b.Events, event{Name: "i2c_reply", I2cReply: i2cReply})
|
||||
|
||||
case FirmwareQuery:
|
||||
gobo.Publish(b.events["i2c_reply"], i2cReply)
|
||||
case firmwareQuery:
|
||||
name := []byte{}
|
||||
for _, val := range currentBuffer[4:(len(currentBuffer) - 1)] {
|
||||
if val != 0 {
|
||||
name = append(name, val)
|
||||
}
|
||||
}
|
||||
b.FirmwareName = string(name[:])
|
||||
b.Events = append(b.Events, event{Name: "firmware_query"})
|
||||
case StringData:
|
||||
b.firmwareName = string(name[:])
|
||||
gobot.Publish(b.events["firmware_query"], b.firmwareName)
|
||||
case stringData:
|
||||
str := currentBuffer[2 : len(currentBuffer)-1]
|
||||
fmt.Println(string(str[:len(str)]))
|
||||
b.Events = append(b.Events, event{Name: "string_data", Data: str})
|
||||
gobot.Publish(b.events["string_data"], str)
|
||||
default:
|
||||
fmt.Println("bad byte", fmt.Sprintf("0x%x", command))
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
|
||||
type FirmataAdaptor struct {
|
||||
gobot.Adaptor
|
||||
Board *board
|
||||
board *board
|
||||
i2cAddress byte
|
||||
connect func(*FirmataAdaptor)
|
||||
}
|
||||
@ -27,20 +27,20 @@ func NewFirmataAdaptor(name, port string) *FirmataAdaptor {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
f.Board = newBoard(sp)
|
||||
f.board = newBoard(sp)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) Connect() bool {
|
||||
f.connect(f)
|
||||
f.Board.connect()
|
||||
f.board.connect()
|
||||
f.SetConnected(true)
|
||||
return true
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) Disconnect() bool {
|
||||
err := f.Board.Serial.Close()
|
||||
err := f.board.serial.Close()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
@ -52,50 +52,54 @@ func (f *FirmataAdaptor) InitServo() {}
|
||||
func (f *FirmataAdaptor) ServoWrite(pin string, angle byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
f.Board.setPinMode(byte(p), Servo)
|
||||
f.Board.analogWrite(byte(p), angle)
|
||||
f.board.setPinMode(byte(p), servo)
|
||||
f.board.analogWrite(byte(p), angle)
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) PwmWrite(pin string, level byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
f.Board.setPinMode(byte(p), PWM)
|
||||
f.Board.analogWrite(byte(p), level)
|
||||
f.board.setPinMode(byte(p), pwm)
|
||||
f.board.analogWrite(byte(p), level)
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) DigitalWrite(pin string, level byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
f.Board.setPinMode(byte(p), Output)
|
||||
f.Board.digitalWrite(byte(p), level)
|
||||
f.board.setPinMode(byte(p), output)
|
||||
f.board.digitalWrite(byte(p), level)
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) DigitalRead(pin string) int {
|
||||
ret := make(chan int)
|
||||
p, _ := strconv.Atoi(pin)
|
||||
f.Board.setPinMode(byte(p), Input)
|
||||
f.Board.togglePinReporting(byte(p), High, ReportDigital)
|
||||
events := f.Board.findEvents(fmt.Sprintf("digital_read_%v", pin))
|
||||
if len(events) > 0 {
|
||||
return int(events[len(events)-1].Data[0])
|
||||
}
|
||||
return -1
|
||||
f.board.setPinMode(byte(p), input)
|
||||
f.board.togglePinReporting(byte(p), high, reportDigital)
|
||||
f.board.readAndProcess()
|
||||
|
||||
gobot.On(f.board.events[fmt.Sprintf("digital_read_%v", pin)], func(data interface{}) {
|
||||
ret <- int(data.([]byte)[0])
|
||||
})
|
||||
|
||||
return <-ret
|
||||
}
|
||||
|
||||
// NOTE pins are numbered A0-A5, which translate to digital pins 14-19
|
||||
func (f *FirmataAdaptor) AnalogRead(pin string) int {
|
||||
ret := make(chan int)
|
||||
|
||||
p, _ := strconv.Atoi(pin)
|
||||
p = f.digitalPin(p)
|
||||
f.Board.setPinMode(byte(p), Analog)
|
||||
f.Board.togglePinReporting(byte(p), High, ReportAnalog)
|
||||
events := f.Board.findEvents(fmt.Sprintf("analog_read_%v", pin))
|
||||
if len(events) > 0 {
|
||||
event := events[len(events)-1]
|
||||
return int(uint(event.Data[0])<<24 |
|
||||
uint(event.Data[1])<<16 |
|
||||
uint(event.Data[2])<<8 |
|
||||
uint(event.Data[3]))
|
||||
}
|
||||
return -1
|
||||
f.board.setPinMode(byte(p), analog)
|
||||
f.board.togglePinReporting(byte(p), high, reportAnalog)
|
||||
f.board.readAndProcess()
|
||||
|
||||
gobot.On(f.board.events[fmt.Sprintf("analog_read_%v", pin)], func(data interface{}) {
|
||||
b := data.([]byte)
|
||||
ret <- int(uint(b[0])<<24 | uint(b[1])<<16 | uint(b[2])<<8 | uint(b[3]))
|
||||
})
|
||||
|
||||
return <-ret
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) AnalogWrite(pin string, level byte) {
|
||||
@ -108,19 +112,22 @@ func (f *FirmataAdaptor) digitalPin(pin int) int {
|
||||
|
||||
func (f *FirmataAdaptor) I2cStart(address byte) {
|
||||
f.i2cAddress = address
|
||||
f.Board.i2cConfig([]byte{0})
|
||||
f.board.i2cConfig([]byte{0})
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) I2cRead(size uint) []byte {
|
||||
f.Board.i2cReadRequest(f.i2cAddress, size)
|
||||
ret := make(chan []byte)
|
||||
f.board.i2cReadRequest(f.i2cAddress, size)
|
||||
|
||||
events := f.Board.findEvents("i2c_reply")
|
||||
if len(events) > 0 {
|
||||
return events[len(events)-1].I2cReply["data"]
|
||||
}
|
||||
return make([]byte, 0)
|
||||
f.board.readAndProcess()
|
||||
|
||||
gobot.On(f.board.events["i2c_reply"], func(data interface{}) {
|
||||
ret <- data.(i2CReply)["data"]
|
||||
})
|
||||
|
||||
return <-ret
|
||||
}
|
||||
|
||||
func (f *FirmataAdaptor) I2cWrite(data []byte) {
|
||||
f.Board.i2cWriteRequest(f.i2cAddress, data)
|
||||
f.board.i2cWriteRequest(f.i2cAddress, data)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user