mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-17 13:23:26 +00:00
first implementation of 1-wire protocol (#505)
onewire: initial implementation for protocol and ds18b20 device
This commit is contained in:
@@ -249,6 +249,8 @@ endif
|
|||||||
@md5sum ./build/test.uf2
|
@md5sum ./build/test.uf2
|
||||||
tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
|
tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go
|
||||||
@md5sum ./build/test.uf2
|
@md5sum ./build/test.uf2
|
||||||
|
tinygo build -size short -o ./build/test.hex -target=arduino-nano33 ./examples/ds18b20/main.go
|
||||||
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
|
tinygo build -size short -o ./build/test.hex -target=nucleo-wl55jc ./examples/lora/lorawan/atcmd/
|
||||||
@md5sum ./build/test.hex
|
@md5sum ./build/test.hex
|
||||||
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go
|
tinygo build -size short -o ./build/test.uf2 -target=pico ./examples/as560x/main.go
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
## Currently supported devices
|
## Currently supported devices
|
||||||
|
|
||||||
The following 90 devices are supported.
|
The following 92 devices are supported.
|
||||||
|
|
||||||
| Device Name | Interface Type |
|
| Device Name | Interface Type |
|
||||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|
|
||||||
@@ -76,6 +76,7 @@ The following 90 devices are supported.
|
|||||||
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
|
| [Buzzer](https://en.wikipedia.org/wiki/Buzzer#Piezoelectric) | GPIO |
|
||||||
| [DHTXX thermometer and humidity sensor](https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf) | GPIO |
|
| [DHTXX thermometer and humidity sensor](https://cdn-shop.adafruit.com/datasheets/Digital+humidity+and+temperature+sensor+AM2302.pdf) | GPIO |
|
||||||
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
|
| [DS1307 real time clock](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
|
||||||
|
| [DS18B20 digital thermometer](https://datasheets.maximintegrated.com/en/ds/DS1307.pdf) | I2C |
|
||||||
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
| [DS3231 real time clock](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) | I2C |
|
||||||
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
|
| [ESP32 as WiFi Coprocessor with Arduino nina-fw](https://github.com/arduino/nina-fw) | SPI |
|
||||||
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
|
| [ESP8266/ESP32 AT Command set for WiFi/TCP/UDP](https://github.com/espressif/esp32-at) | UART |
|
||||||
@@ -110,6 +111,7 @@ The following 90 devices are supported.
|
|||||||
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
|
| [Microphone - PDM](https://cdn-learn.adafruit.com/assets/assets/000/049/977/original/MP34DT01-M.pdf) | I2S/PDM |
|
||||||
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
|
| [MMA8653 accelerometer](https://www.nxp.com/docs/en/data-sheet/MMA8653FC.pdf) | I2C |
|
||||||
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
|
| [MPU6050 accelerometer/gyroscope](https://store.invensense.com/datasheets/invensense/MPU-6050_DataSheet_V3%204.pdf) | I2C |
|
||||||
|
| [One Wire bus system](https://en.wikipedia.org/wiki/1-Wire) | 1-wire |
|
||||||
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
|
| [P1AM-100 Base Controller](https://facts-engineering.github.io/modules/P1AM-100/P1AM-100.html) | SPI |
|
||||||
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
|
| [PCD8544 display](http://eia.udg.edu/~forest/PCD8544_1.pdf) | SPI |
|
||||||
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
|
| [PCF8563 real time clock](https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf) | I2C |
|
||||||
@@ -121,7 +123,7 @@ The following 90 devices are supported.
|
|||||||
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
|
| [Servo](https://learn.sparkfun.com/tutorials/hobby-servo-tutorial/all) | PWM |
|
||||||
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
|
| [Shift register (PISO)](https://en.wikipedia.org/wiki/Shift_register#Parallel-in_serial-out_\(PISO\)) | GPIO |
|
||||||
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
|
| [Shift registers (SIPO)](https://en.wikipedia.org/wiki/Shift_register#Serial-in_parallel-out_(SIPO)) | GPIO |
|
||||||
| [SH1106 OLED display](https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf) | I2C / SPI |
|
| [SH1106 OLED display](https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf) | I2C / SPI |
|
||||||
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
|
| [SHT3x Digital Humidity Sensor](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHT3x_Datasheet_digital.pdf) | I2C |
|
||||||
| [SHTC3 Digital Humidity Sensor (RH/T)](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHTC3_Datasheet.pdf) | I2C |
|
| [SHTC3 Digital Humidity Sensor (RH/T)](https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/2_Humidity_Sensors/Datasheets/Sensirion_Humidity_Sensors_SHTC3_Datasheet.pdf) | I2C |
|
||||||
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
|
| [SPI NOR Flash Memory](https://en.wikipedia.org/wiki/Flash_memory#NOR_flash) | SPI/QSPI |
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
// Package ds18b20 provides a driver for the DS18B20 digital thermometer
|
||||||
|
//
|
||||||
|
// Datasheet:
|
||||||
|
// https://www.analog.com/media/en/technical-documentation/data-sheets/DS18B20.pdf
|
||||||
|
package ds18b20 // import "tinygo.org/x/drivers/ds18b20"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device ROM commands
|
||||||
|
const (
|
||||||
|
CONVERT_TEMPERATURE uint8 = 0x44
|
||||||
|
READ_SCRATCHPAD uint8 = 0xBE
|
||||||
|
WRITE_SCRATCHPAD uint8 = 0x4E
|
||||||
|
)
|
||||||
|
|
||||||
|
type OneWireDevice interface {
|
||||||
|
Write(uint8)
|
||||||
|
Read() uint8
|
||||||
|
Select([]uint8) error
|
||||||
|
Сrc8([]uint8, int) uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device wraps a connection to an 1-Wire devices.
|
||||||
|
type Device struct {
|
||||||
|
owd OneWireDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
// Errors list
|
||||||
|
var (
|
||||||
|
errReadTemperature = errors.New("Error: DS18B20. Read temperature error: CRC mismatch.")
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(owd OneWireDevice) Device {
|
||||||
|
return Device{
|
||||||
|
owd: owd,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure. Initializes the device, left for compatibility reasons.
|
||||||
|
func (d Device) Configure() {}
|
||||||
|
|
||||||
|
// ThermometerResolution sets thermometer resolution from 9 to 12 bits
|
||||||
|
func (d Device) ThermometerResolution(romid []uint8, resolution uint8) {
|
||||||
|
if 9 <= resolution && resolution <= 12 {
|
||||||
|
d.owd.Select(romid)
|
||||||
|
d.owd.Write(WRITE_SCRATCHPAD) // send three data bytes to scratchpad (TH, TL, and config)
|
||||||
|
d.owd.Write(0xFF) // to TH
|
||||||
|
d.owd.Write(0x00) // to TL
|
||||||
|
d.owd.Write(((resolution - 9) << 5) | 0x1F) // to resolution config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestTemperature sends request to device
|
||||||
|
func (d Device) RequestTemperature(romid []uint8) {
|
||||||
|
d.owd.Select(romid)
|
||||||
|
d.owd.Write(CONVERT_TEMPERATURE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadTemperatureRaw returns the raw temperature.
|
||||||
|
// ScratchPad memory map:
|
||||||
|
// byte 0: Temperature LSB
|
||||||
|
// byte 1: Temperature MSB
|
||||||
|
func (d Device) ReadTemperatureRaw(romid []uint8) ([]uint8, error) {
|
||||||
|
spb := make([]uint8, 9) // ScratchPad buffer
|
||||||
|
d.owd.Select(romid)
|
||||||
|
d.owd.Write(READ_SCRATCHPAD)
|
||||||
|
for i := 0; i < 9; i++ {
|
||||||
|
spb[i] = d.owd.Read()
|
||||||
|
}
|
||||||
|
if d.owd.Сrc8(spb, 8) != spb[8] {
|
||||||
|
return nil, errReadTemperature
|
||||||
|
}
|
||||||
|
return spb[:2:2], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadTemperature returns the temperature in celsius milli degrees (°C/1000)
|
||||||
|
func (d Device) ReadTemperature(romid []uint8) (int32, error) {
|
||||||
|
raw, err := d.ReadTemperatureRaw(romid)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
t := int32(uint16(raw[0]) | uint16(raw[1])<<8)
|
||||||
|
if t&0x8000 == 0x8000 {
|
||||||
|
t -= 0x10000
|
||||||
|
}
|
||||||
|
return (t * 625 / 10), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/onewire"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers/ds18b20"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Define pin for DS18B20
|
||||||
|
pin := machine.D2
|
||||||
|
|
||||||
|
ow := onewire.New(pin)
|
||||||
|
romIDs, err := ow.Search(onewire.SEARCH_ROM)
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
sensor := ds18b20.New(ow)
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
println()
|
||||||
|
println("Device:", machine.Device)
|
||||||
|
|
||||||
|
println()
|
||||||
|
println("Request Temperature.")
|
||||||
|
for _, romid := range romIDs {
|
||||||
|
println("Sensor RomID: ", hex.EncodeToString(romid))
|
||||||
|
sensor.RequestTemperature(romid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait 750ms or more for DS18B20 convert T
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
|
||||||
|
println()
|
||||||
|
println("Read Temperature")
|
||||||
|
for _, romid := range romIDs {
|
||||||
|
raw, err := sensor.ReadTemperatureRaw(romid)
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
println("Sensor RomID: ", hex.EncodeToString(romid))
|
||||||
|
println("Temperature Raw value: ", hex.EncodeToString(raw))
|
||||||
|
|
||||||
|
t, err := sensor.ReadTemperature(romid)
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
println("Temperature in celsius milli degrees (°C/1000): ", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"time"
|
||||||
|
"tinygo.org/x/drivers/onewire"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
pin := machine.D2
|
||||||
|
|
||||||
|
ow := onewire.New(pin)
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
|
println()
|
||||||
|
println("Device:", machine.Device)
|
||||||
|
|
||||||
|
romIDs, err := ow.Search(onewire.SEARCH)
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
for _, romid := range romIDs {
|
||||||
|
println(hex.EncodeToString(romid))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(romIDs) == 1 {
|
||||||
|
// only 1 device on bus
|
||||||
|
r, err := ow.ReadAddress()
|
||||||
|
if err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
println(hex.EncodeToString(r))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
// Package wire implements the Dallas Semiconductor Corp.'s 1-wire bus system.
|
||||||
|
//
|
||||||
|
// Wikipedia: https://en.wikipedia.org/wiki/1-Wire
|
||||||
|
package onewire // import "tinygo.org/x/drivers/onewire"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"machine"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OneWire ROM commands
|
||||||
|
const (
|
||||||
|
READ_ROM uint8 = 0x33
|
||||||
|
MATCH_ROM uint8 = 0x55
|
||||||
|
SKIP_ROM uint8 = 0xCC
|
||||||
|
SEARCH_ROM uint8 = 0xF0
|
||||||
|
)
|
||||||
|
|
||||||
|
// Device wraps a connection to an 1-Wire devices.
|
||||||
|
type Device struct {
|
||||||
|
p machine.Pin
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config wraps a configuration to an 1-Wire devices.
|
||||||
|
type Config struct{}
|
||||||
|
|
||||||
|
// Errors list
|
||||||
|
var (
|
||||||
|
errNoPresence = errors.New("Error: OneWire. No devices on the bus.")
|
||||||
|
errReadAddress = errors.New("Error: OneWire. Read address error: CRC mismatch.")
|
||||||
|
)
|
||||||
|
|
||||||
|
// New creates a new GPIO 1-Wire connection.
|
||||||
|
// The pin must be pulled up to the VCC via a resistor greater than 500 ohms (default 4.7k).
|
||||||
|
func New(p machine.Pin) Device {
|
||||||
|
return Device{
|
||||||
|
p: p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure initializes the protocol.
|
||||||
|
func (d *Device) Configure(config Config) {}
|
||||||
|
|
||||||
|
// Reset pull DQ line low, then up.
|
||||||
|
func (d Device) Reset() error {
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
time.Sleep(480 * time.Microsecond)
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
time.Sleep(70 * time.Microsecond)
|
||||||
|
precence := d.p.Get()
|
||||||
|
time.Sleep(410 * time.Microsecond)
|
||||||
|
if precence {
|
||||||
|
return errNoPresence
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteBit transmits a bit to 1-Wire bus.
|
||||||
|
func (d Device) WriteBit(data uint8) {
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
if data&1 == 1 { // Send '1'
|
||||||
|
time.Sleep(5 * time.Microsecond)
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
time.Sleep(60 * time.Microsecond)
|
||||||
|
} else { // Send '0'
|
||||||
|
time.Sleep(60 * time.Microsecond)
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
time.Sleep(5 * time.Microsecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write transmits a byte as bit array to 1-Wire bus. (LSB first)
|
||||||
|
func (d Device) Write(data uint8) {
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
d.WriteBit(data)
|
||||||
|
data >>= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBit receives a bit from 1-Wire bus.
|
||||||
|
func (d Device) ReadBit() (data uint8) {
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
time.Sleep(3 * time.Microsecond)
|
||||||
|
d.p.Configure(machine.PinConfig{Mode: machine.PinInput})
|
||||||
|
time.Sleep(8 * time.Microsecond)
|
||||||
|
if d.p.Get() {
|
||||||
|
data = 1
|
||||||
|
}
|
||||||
|
time.Sleep(60 * time.Microsecond)
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read receives a byte from 1-Wire bus. (LSB first)
|
||||||
|
func (d Device) Read() (data uint8) {
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
data >>= 1
|
||||||
|
data |= d.ReadBit() << 7
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadAddress receives a 64-bit unique ROM ID from Device. (LSB first)
|
||||||
|
// Note: use this if there is only one slave device on the bus.
|
||||||
|
func (d Device) ReadAddress() ([]uint8, error) {
|
||||||
|
var romid = make([]uint8, 8)
|
||||||
|
if err := d.Reset(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
d.Write(READ_ROM)
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
romid[i] = d.Read()
|
||||||
|
}
|
||||||
|
if d.Сrc8(romid, 7) != romid[7] {
|
||||||
|
return nil, errReadAddress
|
||||||
|
}
|
||||||
|
return romid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select selects the address of the device for communication
|
||||||
|
func (d Device) Select(romid []uint8) error {
|
||||||
|
if err := d.Reset(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(romid) == 0 {
|
||||||
|
d.Write(SKIP_ROM)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
d.Write(MATCH_ROM)
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
d.Write(romid[i])
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search searches for all devices on the bus.
|
||||||
|
// Note: max 32 slave devices per bus
|
||||||
|
func (d Device) Search(cmd uint8) ([][]uint8, error) {
|
||||||
|
var (
|
||||||
|
bit, bit_c uint8 = 0, 0
|
||||||
|
bitOffset uint8 = 0
|
||||||
|
lastZero uint8 = 0
|
||||||
|
lastFork uint8 = 0
|
||||||
|
lastAddress = make([]uint8, 8)
|
||||||
|
romIDs = make([][]uint8, 32) //
|
||||||
|
romIndex uint8 = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := range romIDs {
|
||||||
|
romIDs[i] = make([]uint8, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
for ok := true; ok; ok = (lastFork != 0) {
|
||||||
|
if err := d.Reset(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// send search command to bus
|
||||||
|
d.Write(cmd)
|
||||||
|
|
||||||
|
lastZero = 0
|
||||||
|
|
||||||
|
for bitOffset = 0; bitOffset < 64; bitOffset++ {
|
||||||
|
bit = d.ReadBit() // read first address bit
|
||||||
|
bit_c = d.ReadBit() // read second (complementary) address bit
|
||||||
|
|
||||||
|
if bit == 1 && bit_c == 1 { // no device
|
||||||
|
return nil, errNoPresence
|
||||||
|
}
|
||||||
|
|
||||||
|
if bit == 0 && bit_c == 0 { // collision
|
||||||
|
if bitOffset == lastFork {
|
||||||
|
bit = 1
|
||||||
|
}
|
||||||
|
if bitOffset < lastFork {
|
||||||
|
bit = (lastAddress[bitOffset>>3] >> (bitOffset & 0x07)) & 1
|
||||||
|
}
|
||||||
|
if bit == 0 {
|
||||||
|
lastZero = bitOffset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if bit == 0 {
|
||||||
|
lastAddress[bitOffset>>3] &= ^(1 << (bitOffset & 0x07))
|
||||||
|
} else {
|
||||||
|
lastAddress[bitOffset>>3] |= (1 << (bitOffset & 0x07))
|
||||||
|
}
|
||||||
|
d.WriteBit(bit)
|
||||||
|
}
|
||||||
|
lastFork = lastZero
|
||||||
|
copy(romIDs[romIndex], lastAddress)
|
||||||
|
romIndex++
|
||||||
|
}
|
||||||
|
return romIDs[:romIndex:romIndex], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crc8 compute a Dallas Semiconductor 8 bit CRC.
|
||||||
|
func (d Device) Сrc8(buffer []uint8, size int) (crc uint8) {
|
||||||
|
// Dow-CRC using polynomial X^8 + X^5 + X^4 + X^0
|
||||||
|
// Tiny 2x16 entry CRC table created by Arjen Lentz
|
||||||
|
// See http://lentz.com.au/blog/calculating-crc-with-a-tiny-32-entry-lookup-table
|
||||||
|
crc8_table := [...]uint8{
|
||||||
|
0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
|
||||||
|
0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
|
||||||
|
0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
|
||||||
|
0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74,
|
||||||
|
}
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
crc = buffer[i] ^ crc // just re-using crc as intermediate
|
||||||
|
crc = crc8_table[crc&0x0f] ^ crc8_table[16+((crc>>4)&0x0f)]
|
||||||
|
}
|
||||||
|
return crc
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user