devices: Move interfaces and structs into physic

This made otherwise a weird import DAG.

Fixes #137
pull/1/head
Marc-Antoine Ruel 8 years ago
parent cd1516dfb2
commit fc241bc91d

@ -8,13 +8,13 @@ import (
"encoding/binary" "encoding/binary"
"time" "time"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
// sense180 reads the device's registers for bmp180. // sense180 reads the device's registers for bmp180.
// //
// It must be called with d.mu lock held. // It must be called with d.mu lock held.
func (d *Dev) sense180(env *devices.Environment) error { func (d *Dev) sense180(e *physic.Env) error {
// Request temperature conversion and read measurement. // Request temperature conversion and read measurement.
if err := d.writeCommands([]byte{0xF4, 0x20 | 0x0E}); err != nil { if err := d.writeCommands([]byte{0xF4, 0x20 | 0x0E}); err != nil {
return d.wrap(err) return d.wrap(err)
@ -38,8 +38,9 @@ func (d *Dev) sense180(env *devices.Environment) error {
} }
up := (int32(pressureBuf[0])<<16 + int32(pressureBuf[1])<<8 | int32(pressureBuf[2])) >> (8 - d.os) up := (int32(pressureBuf[0])<<16 + int32(pressureBuf[1])<<8 | int32(pressureBuf[2])) >> (8 - d.os)
pressure := d.cal180.compensatePressure(up, int32(rawTemp), uint(d.os)) pressure := d.cal180.compensatePressure(up, int32(rawTemp), uint(d.os))
env.Temperature = devices.Celsius(temp * 100) // Convert DeciCelsius to Kelvin.
env.Pressure = devices.KPascal(pressure) e.Temperature = physic.Temperature(temp)*100*physic.MilliCelsius + physic.ZeroCelsius
e.Pressure = physic.Pressure(pressure) * physic.Pascal
return nil return nil
} }

@ -9,7 +9,7 @@ import (
"time" "time"
"periph.io/x/periph/conn/i2c/i2ctest" "periph.io/x/periph/conn/i2c/i2ctest"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
var opts180 = &Opts{Temperature: O1x, Pressure: O1x} var opts180 = &Opts{Temperature: O1x, Pressure: O1x}
@ -74,13 +74,13 @@ func TestSense180_success(t *testing.T) {
values := []struct { values := []struct {
o Oversampling o Oversampling
c byte c byte
p devices.KPascal p physic.Pressure
}{ }{
{Oversampling(42), 0x34, 100567}, {Oversampling(42), 0x34, 100567 * physic.Pascal},
{O1x, 0x34, 100567}, {O1x, 0x34, 100567 * physic.Pascal},
{O2x, 0x74, 100567}, {O2x, 0x74, 100567 * physic.Pascal},
{O4x, 0xB4, 100568}, {O4x, 0xB4, 100568 * physic.Pascal},
{O8x, 0xF4, 100568}, {O8x, 0xF4, 100568 * physic.Pascal},
} }
for _, line := range values { for _, line := range values {
bus := i2ctest.Playback{ bus := i2ctest.Playback{
@ -110,18 +110,18 @@ func TestSense180_success(t *testing.T) {
if s := dev.String(); s != "BMP180{playback(119)}" { if s := dev.String(); s != "BMP180{playback(119)}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if err := dev.Sense(&env); err != nil { if err := dev.Sense(&e); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if env.Temperature != 25300 { if e.Temperature != 25300*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != line.p { if e.Pressure != line.p {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 0 { if e.Humidity != 0 {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if err := dev.Halt(); err != nil { if err := dev.Halt(); err != nil {
t.Fatal(err) t.Fatal(err)
@ -151,8 +151,8 @@ func TestSense180_fail_1(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("sensing should have failed") t.Fatal("sensing should have failed")
} }
if err := bus.Close(); err != nil { if err := bus.Close(); err != nil {
@ -181,8 +181,8 @@ func TestSense180_fail_2(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("sensing should have failed") t.Fatal("sensing should have failed")
} }
if err := bus.Close(); err != nil { if err := bus.Close(); err != nil {
@ -213,8 +213,8 @@ func TestSense180_fail_3(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("sensing should have failed") t.Fatal("sensing should have failed")
} }
if err := bus.Close(); err != nil { if err := bus.Close(); err != nil {
@ -247,8 +247,8 @@ func TestSense180_fail_4(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("sensing should have failed") t.Fatal("sensing should have failed")
} }
if err := bus.Close(); err != nil { if err := bus.Close(); err != nil {
@ -294,18 +294,18 @@ func TestSenseContinuous180_success(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := <-c e := <-c
if env.Temperature != 25300 { if e.Temperature != 25300*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 100567 { if e.Pressure != 100567*physic.Pascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 0 { if e.Humidity != 0 {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("Sense() should have failed") t.Fatal("Sense() should have failed")
} }
@ -314,7 +314,7 @@ func TestSenseContinuous180_success(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
env = <-c2 e = <-c2
if _, ok := <-c; ok { if _, ok := <-c; ok {
t.Fatal("c should be closed") t.Fatal("c should be closed")

@ -7,13 +7,13 @@ package bmxx80
import ( import (
"time" "time"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
// sense280 reads the device's registers for bme280/bmp280. // sense280 reads the device's registers for bme280/bmp280.
// //
// It must be called with d.mu lock held. // It must be called with d.mu lock held.
func (d *Dev) sense280(env *devices.Environment) error { func (d *Dev) sense280(e *physic.Env) error {
// All registers must be read in a single pass, as noted at page 21, section // All registers must be read in a single pass, as noted at page 21, section
// 4.1. // 4.1.
// Pressure: 0xF7~0xF9 // Pressure: 0xF7~0xF9
@ -32,18 +32,21 @@ func (d *Dev) sense280(env *devices.Environment) error {
tRaw := int32(buf[3])<<12 | int32(buf[4])<<4 | int32(buf[5])>>4 tRaw := int32(buf[3])<<12 | int32(buf[4])<<4 | int32(buf[5])>>4
t, tFine := d.cal280.compensateTempInt(tRaw) t, tFine := d.cal280.compensateTempInt(tRaw)
env.Temperature = devices.Celsius(t * 10) // Convert CentiCelsius to Kelvin.
e.Temperature = physic.Temperature(t)*10*physic.MilliCelsius + physic.ZeroCelsius
if d.opts.Pressure != Off { if d.opts.Pressure != Off {
p := d.cal280.compensatePressureInt64(pRaw, tFine) p := d.cal280.compensatePressureInt64(pRaw, tFine)
env.Pressure = devices.KPascal((int32(p) + 127) / 256) // It has 8 bits of fractional Pascal.
e.Pressure = physic.Pressure(p) * 15625 * physic.MicroPascal / 4
} }
if d.opts.Humidity != Off { if d.opts.Humidity != Off {
// This value is 16 bits as per doc. // This value is 16 bits as per doc.
hRaw := int32(buf[6])<<8 | int32(buf[7]) hRaw := int32(buf[6])<<8 | int32(buf[7])
h := d.cal280.compensateHumidityInt(hRaw, tFine) h := physic.RelativeHumidity(d.cal280.compensateHumidityInt(hRaw, tFine))
env.Humidity = devices.RelativeHumidity((int32(h)*100 + 511) / 1024) // Convert base 1024 to base 1000.
e.Humidity = h * physic.MicroRH * 1000 / 1024
} }
return nil return nil
} }

@ -17,7 +17,6 @@ import (
"periph.io/x/periph/conn/physic" "periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spitest" "periph.io/x/periph/conn/spi/spitest"
"periph.io/x/periph/devices"
) )
// Real data extracted from a device. // Real data extracted from a device.
@ -87,21 +86,21 @@ func TestSPISenseBME280_success(t *testing.T) {
if s := dev.String(); s != "BME280{playback}" { if s := dev.String(); s != "BME280{playback}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if err := dev.Sense(&env); err != nil { if err := dev.Sense(&e); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// TODO(maruel): The values do not make sense but I think I burned my SPI // TODO(maruel): The values do not make sense but I think I burned my SPI
// BME280 by misconnecting it in reverse for a few minutes. It still "work" // BME280 by misconnecting it in reverse for a few minutes. It still "work"
// but fail to read data. It could also be a bug in the driver. :( // but fail to read data. It could also be a bug in the driver. :(
if env.Temperature != 62680 { if e.Temperature != 62680*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 99576 { if e.Pressure != 99575933593750*physic.NanoPascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 995 { if e.Humidity != 9950*physic.MicroRH {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if err := s.Close(); err != nil { if err := s.Close(); err != nil {
t.Fatal(err) t.Fatal(err)
@ -288,7 +287,7 @@ func TestI2CSenseBME280_fail(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if dev.Sense(&devices.Environment{}) == nil { if dev.Sense(&physic.Env{}) == nil {
t.Fatal("sense fail read") t.Fatal("sense fail read")
} }
// The I/O didn't occur. // The I/O didn't occur.
@ -328,18 +327,18 @@ func TestI2CSenseBMP280_success(t *testing.T) {
if s := dev.String(); s != "BMP280{playback(118)}" { if s := dev.String(); s != "BMP280{playback(118)}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if err := dev.Sense(&env); err != nil { if err := dev.Sense(&e); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if env.Temperature != 23720 { if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 100943 { if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 0 { if e.Humidity != 0 {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if err := dev.Halt(); err != nil { if err := dev.Halt(); err != nil {
t.Fatal(err) t.Fatal(err)
@ -381,18 +380,18 @@ func TestI2CSenseBME280_success(t *testing.T) {
if s := dev.String(); s != "BME280{playback(118)}" { if s := dev.String(); s != "BME280{playback(118)}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if err := dev.Sense(&env); err != nil { if err := dev.Sense(&e); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if env.Temperature != 23720 { if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 100943 { if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 6531 { if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if err := dev.Halt(); err != nil { if err := dev.Halt(); err != nil {
t.Fatal(err) t.Fatal(err)
@ -430,8 +429,8 @@ func TestI2CSense280_idle_fail(t *testing.T) {
if s := dev.String(); s != "BME280{playback(118)}" { if s := dev.String(); s != "BME280{playback(118)}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("isIdle() should have failed") t.Fatal("isIdle() should have failed")
} }
} }
@ -466,8 +465,8 @@ func TestI2CSense280_command_fail(t *testing.T) {
if s := dev.String(); s != "BME280{playback(118)}" { if s := dev.String(); s != "BME280{playback(118)}" {
t.Fatal(s) t.Fatal(s)
} }
env := devices.Environment{} e := physic.Env{}
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("isIdle() should have failed") t.Fatal("isIdle() should have failed")
} }
} }
@ -511,20 +510,20 @@ func TestI2CSenseContinuous280_success(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
env := devices.Environment{} e := physic.Env{}
select { select {
case env = <-c: case e = <-c:
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
t.Fatal("failed") t.Fatal("failed")
} }
if env.Temperature != 23720 { if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 100943 { if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 6531 { if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
// This cancels the previous channel and resets the interval. // This cancels the previous channel and resets the interval.
@ -537,26 +536,26 @@ func TestI2CSenseContinuous280_success(t *testing.T) {
t.Fatal("c should be closed") t.Fatal("c should be closed")
} }
select { select {
case env = <-c2: case e = <-c2:
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
t.Fatal("failed") t.Fatal("failed")
} }
select { select {
case env = <-c2: case e = <-c2:
case <-time.After(2 * time.Second): case <-time.After(2 * time.Second):
t.Fatal("failed") t.Fatal("failed")
} }
if env.Temperature != 23720 { if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", env.Temperature) t.Fatalf("temp %d", e.Temperature)
} }
if env.Pressure != 100943 { if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", env.Pressure) t.Fatalf("pressure %d", e.Pressure)
} }
if env.Humidity != 6531 { if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", env.Humidity) t.Fatalf("humidity %d", e.Humidity)
} }
if dev.Sense(&env) == nil { if dev.Sense(&e) == nil {
t.Fatal("can't Sense() during SenseContinously") t.Fatal("can't Sense() during SenseContinously")
} }

@ -15,10 +15,10 @@ import (
"periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/i2c/i2creg" "periph.io/x/periph/conn/i2c/i2creg"
"periph.io/x/periph/conn/i2c/i2ctest" "periph.io/x/periph/conn/i2c/i2ctest"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spireg" "periph.io/x/periph/conn/spi/spireg"
"periph.io/x/periph/conn/spi/spitest" "periph.io/x/periph/conn/spi/spitest"
"periph.io/x/periph/devices"
"periph.io/x/periph/devices/bmxx80" "periph.io/x/periph/devices/bmxx80"
) )
@ -154,8 +154,8 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) {
} }
}() }()
i2cEnv := devices.Environment{} i2cEnv := physic.Env{}
spiEnv := devices.Environment{} spiEnv := physic.Env{}
if err2 := i2cDev.Sense(&i2cEnv); err2 != nil { if err2 := i2cDev.Sense(&i2cEnv); err2 != nil {
return err2 return err2
} }
@ -164,7 +164,7 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) {
return err2 return err2
} }
printEnv(spiDev, &spiEnv) printEnv(spiDev, &spiEnv)
delta := devices.Environment{ delta := physic.Env{
Temperature: i2cEnv.Temperature - spiEnv.Temperature, Temperature: i2cEnv.Temperature - spiEnv.Temperature,
Pressure: i2cEnv.Pressure - spiEnv.Pressure, Pressure: i2cEnv.Pressure - spiEnv.Pressure,
Humidity: i2cEnv.Humidity - spiEnv.Humidity, Humidity: i2cEnv.Humidity - spiEnv.Humidity,
@ -186,6 +186,6 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) {
return nil return nil
} }
func printEnv(dev interface{}, env *devices.Environment) { func printEnv(dev interface{}, e *physic.Env) {
fmt.Printf("%-18s: %8s %10s %9s\n", dev, env.Temperature, env.Pressure, env.Humidity) fmt.Printf("%-18s: %8s %10s %9s\n", dev, e.Temperature, e.Pressure, e.Humidity)
} }

@ -38,8 +38,8 @@ import (
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
"periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/mmr" "periph.io/x/periph/conn/mmr"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/devices"
) )
// Oversampling affects how much time is taken to measure each of temperature, // Oversampling affects how much time is taken to measure each of temperature,
@ -245,7 +245,7 @@ func (d *Dev) String() string {
// Sense requests a one time measurement as °C, kPa and % of relative humidity. // Sense requests a one time measurement as °C, kPa and % of relative humidity.
// //
// The very first measurements may be of poor quality. // The very first measurements may be of poor quality.
func (d *Dev) Sense(env *devices.Environment) error { func (d *Dev) Sense(e *physic.Env) error {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
if d.stop != nil { if d.stop != nil {
@ -266,9 +266,9 @@ func (d *Dev) Sense(env *devices.Environment) error {
return d.wrap(err) return d.wrap(err)
} }
} }
return d.sense280(env) return d.sense280(e)
} }
return d.sense180(env) return d.sense180(e)
} }
// SenseContinuous returns measurements as °C, kPa and % of relative humidity // SenseContinuous returns measurements as °C, kPa and % of relative humidity
@ -279,7 +279,7 @@ func (d *Dev) Sense(env *devices.Environment) error {
// //
// It's the responsibility of the caller to retrieve the values from the // It's the responsibility of the caller to retrieve the values from the
// channel as fast as possible, otherwise the interval may not be respected. // channel as fast as possible, otherwise the interval may not be respected.
func (d *Dev) SenseContinuous(interval time.Duration) (<-chan devices.Environment, error) { func (d *Dev) SenseContinuous(interval time.Duration) (<-chan physic.Env, error) {
d.mu.Lock() d.mu.Lock()
defer d.mu.Unlock() defer d.mu.Unlock()
if d.stop != nil { if d.stop != nil {
@ -302,7 +302,7 @@ func (d *Dev) SenseContinuous(interval time.Duration) (<-chan devices.Environmen
} }
} }
sensing := make(chan devices.Environment) sensing := make(chan physic.Env)
d.stop = make(chan struct{}) d.stop = make(chan struct{})
d.wg.Add(1) d.wg.Add(1)
go func() { go func() {
@ -433,14 +433,14 @@ func (d *Dev) makeDev(opts *Opts) error {
return nil return nil
} }
func (d *Dev) sensingContinuous(interval time.Duration, sensing chan<- devices.Environment, stop <-chan struct{}) { func (d *Dev) sensingContinuous(interval time.Duration, sensing chan<- physic.Env, stop <-chan struct{}) {
t := time.NewTicker(interval) t := time.NewTicker(interval)
defer t.Stop() defer t.Stop()
var err error var err error
for { for {
// Do one initial sensing right away. // Do one initial sensing right away.
var e devices.Environment e := physic.Env{}
d.mu.Lock() d.mu.Lock()
if d.is280 { if d.is280 {
err = d.sense280(&e) err = d.sense280(&e)
@ -514,5 +514,5 @@ var defaults = Opts{
var doSleep = time.Sleep var doSleep = time.Sleep
var _ conn.Resource = &Dev{} var _ conn.Resource = &Dev{}
var _ devices.Environmental = &Dev{} var _ physic.SenseEnv = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -9,7 +9,7 @@ import (
"log" "log"
"periph.io/x/periph/conn/i2c/i2creg" "periph.io/x/periph/conn/i2c/i2creg"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
"periph.io/x/periph/devices/bmxx80" "periph.io/x/periph/devices/bmxx80"
"periph.io/x/periph/host" "periph.io/x/periph/host"
) )
@ -30,7 +30,7 @@ func Example() {
if err != nil { if err != nil {
log.Fatalf("failed to initialize bme280: %v", err) log.Fatalf("failed to initialize bme280: %v", err)
} }
e := devices.Environment{} e := physic.Env{}
if err := d.Sense(&e); err != nil { if err := d.Sense(&e); err != nil {
log.Fatal(err) log.Fatal(err)
} }

@ -8,7 +8,6 @@ import (
"image" "image"
"image/color" "image/color"
"io" "io"
"time"
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
) )
@ -41,22 +40,3 @@ type Display interface {
// To be compatible with draw.Drawer, this function doesn't return an error. // To be compatible with draw.Drawer, this function doesn't return an error.
Draw(r image.Rectangle, src image.Image, sp image.Point) Draw(r image.Rectangle, src image.Image, sp image.Point)
} }
// Environment represents measurements from an environmental sensor.
//
// Deprecated: This interface will be removed in v3. Use physic.Env instead.
type Environment struct {
Temperature Celsius
Pressure KPascal
Humidity RelativeHumidity
}
// Environmental represents an environmental sensor.
//
// Deprecated: This interface will be removed in v3. Use physic.SenseEnv
// instead.
type Environmental interface {
conn.Resource
Sense(env *Environment) error
SenseContinuous(interval time.Duration) (<-chan Environment, error)
}

@ -28,7 +28,7 @@ import (
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
// ConvertAll performs a conversion on all DS18B20 devices on the bus. // ConvertAll performs a conversion on all DS18B20 devices on the bus.
@ -109,7 +109,7 @@ func (d *Dev) Halt() error {
} }
// Temperature performs a conversion and returns the temperature. // Temperature performs a conversion and returns the temperature.
func (d *Dev) Temperature() (devices.Celsius, error) { func (d *Dev) Temperature() (physic.Temperature, error) {
if err := d.onewire.TxPower([]byte{0x44}, nil); err != nil { if err := d.onewire.TxPower([]byte{0x44}, nil); err != nil {
return 0, err return 0, err
} }
@ -121,7 +121,7 @@ func (d *Dev) Temperature() (devices.Celsius, error) {
// device. // device.
// //
// It is useful in combination with ConvertAll. // It is useful in combination with ConvertAll.
func (d *Dev) LastTemp() (devices.Celsius, error) { func (d *Dev) LastTemp() (physic.Temperature, error) {
// Read the scratchpad memory. // Read the scratchpad memory.
spad, err := d.readScratchpad() spad, err := d.readScratchpad()
if err != nil { if err != nil {
@ -129,9 +129,10 @@ func (d *Dev) LastTemp() (devices.Celsius, error) {
} }
// spad[1] is MSB, spad[0] is LSB and has 4 fractional bits. Need to do sign // spad[1] is MSB, spad[0] is LSB and has 4 fractional bits. Need to do sign
// extension multiply by 1000 to get devices.Millis, divide by 16 due to 4 // extension multiply by 1000 to get Millis, divide by 16 due to 4 fractional
// fractional bits. Datasheet p.4. // bits. Datasheet p.4.
c := (devices.Celsius(int8(spad[1]))<<8 + devices.Celsius(spad[0])) * 1000 / 16 v := (int(int8(spad[1]))<<8 + int(spad[0])) * 1000 / 16
c := physic.Temperature(v)*physic.MilliKelvin + physic.ZeroCelsius
// The device powers up with a value of 85°C, so if we read that odds are // The device powers up with a value of 85°C, so if we read that odds are
// very high that either no conversion was performed or that the conversion // very high that either no conversion was performed or that the conversion

@ -11,7 +11,7 @@ import (
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
"periph.io/x/periph/conn/onewire/onewiretest" "periph.io/x/periph/conn/onewire/onewiretest"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
func TestNew_fail_resolution(t *testing.T) { func TestNew_fail_resolution(t *testing.T) {
@ -52,7 +52,7 @@ func TestTemperature(t *testing.T) {
}, },
} }
var addr onewire.Address = 0x740000070e41ac28 var addr onewire.Address = 0x740000070e41ac28
var temp devices.Celsius = 30000 // 30.000°C temp := 30*physic.Celsius + physic.ZeroCelsius
bus := onewiretest.Playback{Ops: ops} bus := onewiretest.Playback{Ops: ops}
dev, err := New(&bus, addr, 10) dev, err := New(&bus, addr, 10)
if err != nil { if err != nil {
@ -187,7 +187,7 @@ func TestRecordTemp(t *testing.T) {
t.Logf(" %#v,", op) t.Logf(" %#v,", op)
} }
t.Log("}") t.Log("}")
t.Logf("var temp devices.Celsius = %d // %s", temp, temp.String()) t.Logf("var temp physic.Temperature = %d // %s", temp, temp.String())
} }
// //

@ -31,7 +31,7 @@ import (
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
"periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/mmr" "periph.io/x/periph/conn/mmr"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
"periph.io/x/periph/devices/lepton/internal" "periph.io/x/periph/devices/lepton/internal"
) )
@ -132,7 +132,7 @@ type FFCMode struct {
ShutterTempLockoutState ShutterTempLockoutState // Default: ShutterTempLockoutStateInactive ShutterTempLockoutState ShutterTempLockoutState // Default: ShutterTempLockoutStateInactive
ElapsedTimeSinceLastFFC time.Duration // Uptime ElapsedTimeSinceLastFFC time.Duration // Uptime
DesiredFFCPeriod time.Duration // Default: 300s DesiredFFCPeriod time.Duration // Default: 300s
DesiredFFCTempDelta devices.Celsius // Default: 3K DesiredFFCTempDelta physic.Temperature // Default: 3K
ImminentDelay uint16 // Default: 52 ImminentDelay uint16 // Default: 52
VideoFreezeDuringFFC bool // Default: true VideoFreezeDuringFFC bool // Default: true
FFCDesired bool // Default: false FFCDesired bool // Default: false
@ -256,25 +256,25 @@ func (d *Dev) GetUptime() (time.Duration, error) {
if err := d.c.get(sysUptime, &v); err != nil { if err := d.c.get(sysUptime, &v); err != nil {
return 0, err return 0, err
} }
return v.ToD(), nil return v.Duration(), nil
} }
// GetTemp returns the temperature inside the camera. // GetTemp returns the temperature inside the camera.
func (d *Dev) GetTemp() (devices.Celsius, error) { func (d *Dev) GetTemp() (physic.Temperature, error) {
var v internal.CentiK var v internal.CentiK
if err := d.c.get(sysTemperature, &v); err != nil { if err := d.c.get(sysTemperature, &v); err != nil {
return 0, err return 0, err
} }
return v.ToC(), nil return v.Temperature(), nil
} }
// GetTempHousing returns the temperature of the camera housing. // GetTempHousing returns the temperature of the camera housing.
func (d *Dev) GetTempHousing() (devices.Celsius, error) { func (d *Dev) GetTempHousing() (physic.Temperature, error) {
var v internal.CentiK var v internal.CentiK
if err := d.c.get(sysHousingTemperature, &v); err != nil { if err := d.c.get(sysHousingTemperature, &v); err != nil {
return 0, err return 0, err
} }
return v.ToC(), nil return v.Temperature(), nil
} }
// GetFFCModeControl returns the internal state with regards to calibration. // GetFFCModeControl returns the internal state with regards to calibration.
@ -286,9 +286,9 @@ func (d *Dev) GetFFCModeControl() (*FFCMode, error) {
return &FFCMode{ return &FFCMode{
FFCShutterMode: FFCShutterMode(v.FFCShutterMode), FFCShutterMode: FFCShutterMode(v.FFCShutterMode),
ShutterTempLockoutState: ShutterTempLockoutState(v.ShutterTempLockoutState), ShutterTempLockoutState: ShutterTempLockoutState(v.ShutterTempLockoutState),
ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.ToD(), ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.Duration(),
DesiredFFCPeriod: v.DesiredFFCPeriod.ToD(), DesiredFFCPeriod: v.DesiredFFCPeriod.Duration(),
DesiredFFCTempDelta: devices.Celsius(v.DesiredFFCTempDelta * 10), DesiredFFCTempDelta: v.DesiredFFCTempDelta.Temperature(),
ImminentDelay: v.ImminentDelay, ImminentDelay: v.ImminentDelay,
VideoFreezeDuringFFC: v.VideoFreezeDuringFFC == internal.Enabled, VideoFreezeDuringFFC: v.VideoFreezeDuringFFC == internal.Enabled,
FFCDesired: v.FFCDesired == internal.Enabled, FFCDesired: v.FFCDesired == internal.Enabled,

@ -8,7 +8,7 @@ import (
"encoding/binary" "encoding/binary"
"time" "time"
"periph.io/x/periph/devices" "periph.io/x/periph/conn/physic"
) )
// Flag is used in FFCMode. // Flag is used in FFCMode.
@ -25,8 +25,8 @@ const (
// It is an implementation detail of the protocol. // It is an implementation detail of the protocol.
type DurationMS uint32 type DurationMS uint32
// ToD converts a millisecond based timing to time.Duration. // Duration converts a millisecond based timing to time.Duration.
func (d DurationMS) ToD() time.Duration { func (d DurationMS) Duration() time.Duration {
return time.Duration(d) * time.Millisecond return time.Duration(d) * time.Millisecond
} }
@ -35,10 +35,9 @@ func (d DurationMS) ToD() time.Duration {
// It is an implementation detail of the protocol. // It is an implementation detail of the protocol.
type CentiK uint16 type CentiK uint16
// ToC converts a Kelvin measurement to Celsius. // Temperature converts a Kelvin measurement to Temperature.
func (c CentiK) ToC() devices.Celsius { func (c CentiK) Temperature() physic.Temperature {
v := (int(c) - 27315) * 10 return physic.Temperature(c) * 10 * physic.MilliKelvin
return devices.Celsius(v)
} }
// Status returns the camera status as returned by the camera. // Status returns the camera status as returned by the camera.
@ -57,7 +56,7 @@ type FFCMode struct {
ElapsedTimeSinceLastFFC DurationMS // Uptime in ms. ElapsedTimeSinceLastFFC DurationMS // Uptime in ms.
DesiredFFCPeriod DurationMS // Default: 300000 DesiredFFCPeriod DurationMS // Default: 300000
ExplicitCommandToOpen Flag // Default: Disabled ExplicitCommandToOpen Flag // Default: Disabled
DesiredFFCTempDelta uint16 // Default: 300 DesiredFFCTempDelta CentiK // Default: 300
ImminentDelay uint16 // Default: 52 ImminentDelay uint16 // Default: 52
// These are documented at page 51 but not listed in the structure. // These are documented at page 51 but not listed in the structure.

@ -8,16 +8,18 @@ import (
"bytes" "bytes"
"testing" "testing"
"time" "time"
"periph.io/x/periph/conn/physic"
) )
func TestDuration(t *testing.T) { func TestDuration(t *testing.T) {
if d := DurationMS(100).ToD(); d != 100*time.Millisecond { if d := DurationMS(100).Duration(); d != 100*time.Millisecond {
t.Fatal(d) t.Fatal(d)
} }
} }
func TestCentiK(t *testing.T) { func TestCentiK(t *testing.T) {
if c := CentiK(100).ToC(); c != -272150 { if c := CentiK(100).Temperature(); c != physic.Kelvin {
t.Fatal(c) t.Fatal(c)
} }
} }

@ -29,27 +29,27 @@ import (
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/devices"
"periph.io/x/periph/devices/lepton/cci" "periph.io/x/periph/devices/lepton/cci"
"periph.io/x/periph/devices/lepton/internal" "periph.io/x/periph/devices/lepton/internal"
) )
// Metadata is constructed from telemetry data, which is sent with each frame. // Metadata is constructed from telemetry data, which is sent with each frame.
type Metadata struct { type Metadata struct {
SinceStartup time.Duration // SinceStartup time.Duration //
FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps). FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps).
AvgValue uint16 // Average value of the buffer. AvgValue uint16 // Average value of the buffer.
Temp devices.Celsius // Temperature inside the camera. Temp physic.Temperature // Temperature inside the camera.
TempHousing devices.Celsius // Camera housing temperature. TempHousing physic.Temperature // Camera housing temperature.
RawTemp uint16 // RawTemp uint16 //
RawTempHousing uint16 // RawTempHousing uint16 //
FFCSince time.Duration // Time since last internal calibration. FFCSince time.Duration // Time since last internal calibration.
FFCTemp devices.Celsius // Temperature at last internal calibration. FFCTemp physic.Temperature // Temperature at last internal calibration.
FFCTempHousing devices.Celsius // FFCTempHousing physic.Temperature //
FFCState cci.FFCState // Current calibration state. FFCState cci.FFCState // Current calibration state.
FFCDesired bool // Asserted at start-up, after period (default 3m) or after temperature change (default 3K). Indicates that a calibration should be triggered as soon as possible. FFCDesired bool // Asserted at start-up, after period (default 3m) or after temperature change (default 3K). Indicates that a calibration should be triggered as soon as possible.
Overtemp bool // true 10s before self-shutdown. Overtemp bool // true 10s before self-shutdown.
} }
// Frame is a FLIR Lepton frame, containing 14 bits resolution intensity stored // Frame is a FLIR Lepton frame, containing 14 bits resolution intensity stored
@ -334,16 +334,16 @@ func (m *Metadata) parseTelemetry(data []byte) error {
if err := binary.Read(bytes.NewBuffer(data), internal.Big16, &rowA); err != nil { if err := binary.Read(bytes.NewBuffer(data), internal.Big16, &rowA); err != nil {
return err return err
} }
m.SinceStartup = rowA.TimeCounter.ToD() m.SinceStartup = rowA.TimeCounter.Duration()
m.FrameCount = rowA.FrameCounter m.FrameCount = rowA.FrameCounter
m.AvgValue = rowA.FrameMean m.AvgValue = rowA.FrameMean
m.Temp = rowA.FPATemp.ToC() m.Temp = rowA.FPATemp.Temperature()
m.TempHousing = rowA.HousingTemp.ToC() m.TempHousing = rowA.HousingTemp.Temperature()
m.RawTemp = rowA.FPATempCounts m.RawTemp = rowA.FPATempCounts
m.RawTempHousing = rowA.HousingTempCounts m.RawTempHousing = rowA.HousingTempCounts
m.FFCSince = rowA.TimeCounterLastFFC.ToD() m.FFCSince = rowA.TimeCounterLastFFC.Duration()
m.FFCTemp = rowA.FPATempLastFFC.ToC() m.FFCTemp = rowA.FPATempLastFFC.Temperature()
m.FFCTempHousing = rowA.HousingTempLastFFC.ToC() m.FFCTempHousing = rowA.HousingTempLastFFC.Temperature()
if rowA.StatusBits&statusMaskNil != 0 { if rowA.StatusBits&statusMaskNil != 0 {
return fmt.Errorf("lepton: (Status: 0x%08X) & (Mask: 0x%08X) = (Extra: 0x%08X) in 0x%08X", rowA.StatusBits, statusMask, rowA.StatusBits&statusMaskNil, statusMaskNil) return fmt.Errorf("lepton: (Status: 0x%08X) & (Mask: 0x%08X) = (Extra: 0x%08X) in 0x%08X", rowA.StatusBits, statusMask, rowA.StatusBits&statusMaskNil, statusMaskNil)
} }

@ -18,9 +18,9 @@ import (
"periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/gpio/gpiotest" "periph.io/x/periph/conn/gpio/gpiotest"
"periph.io/x/periph/conn/i2c/i2ctest" "periph.io/x/periph/conn/i2c/i2ctest"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spitest" "periph.io/x/periph/conn/spi/spitest"
"periph.io/x/periph/devices"
"periph.io/x/periph/devices/lepton/internal" "periph.io/x/periph/devices/lepton/internal"
) )
@ -192,7 +192,7 @@ func TestNextFrame(t *testing.T) {
if err := d.NextFrame(&f); err != nil { if err := d.NextFrame(&f); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if f.Metadata.TempHousing != devices.Celsius(2000) { if f.Metadata.TempHousing != 2*physic.Celsius+physic.ZeroCelsius {
t.Fatal(f.Metadata.TempHousing) t.Fatal(f.Metadata.TempHousing)
} }
// Compare the frame with the reference image. It should match. // Compare the frame with the reference image. It should match.
@ -268,7 +268,7 @@ func TestReadImg(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if f.Metadata.TempHousing != devices.Celsius(2000) { if f.Metadata.TempHousing != 2*physic.Celsius+physic.ZeroCelsius {
t.Fatal(f.Metadata.TempHousing) t.Fatal(f.Metadata.TempHousing)
} }
if err := i.Close(); err != nil { if err := i.Close(); err != nil {

@ -1,113 +0,0 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package devices
import (
"strconv"
)
// Milli is a fixed point value with 0.001 precision.
//
// Deprecated: This interface will be removed in v3.
type Milli int32
// Float64 returns the value as float64 with 0.001 precision.
func (m Milli) Float64() float64 {
return float64(m) * .001
}
// String returns the value formatted as a string.
func (m Milli) String() string {
d := m % 1000
if d < 0 {
d = -d
}
return strconv.Itoa(int(m)/1000) + "." + prefixZeros(3, int(d))
}
// Celsius is a temperature at a precision of 0.001°C.
//
// Deprecated: This interface will be removed in v3. Use physic.Temperature
// instead.
type Celsius Milli
// Float64 returns the value as float64 with 0.001 precision.
func (c Celsius) Float64() float64 {
return Milli(c).Float64()
}
// String returns the temperature formatted as a string.
func (c Celsius) String() string {
return Milli(c).String() + "°C"
}
// ToF returns the temperature as Fahrenheit, a unit used in the United States.
func (c Celsius) ToF() Fahrenheit {
return Fahrenheit((c*9+2)/5 + 32000)
}
// Fahrenheit is an unsound unit used in the United States.
//
// Deprecated: This interface will be removed in v3. Use physic.Temperature
// instead.
type Fahrenheit Milli
// Float64 returns the value as float64 with 0.001 precision.
func (f Fahrenheit) Float64() float64 {
return Milli(f).Float64()
}
// String returns the temperature formatted as a string.
func (f Fahrenheit) String() string {
return Milli(f).String() + "°F"
}
// KPascal is pressure at precision of 1Pa.
//
// Deprecated: This interface will be removed in v3. Use physic.Pressure
// instead.
type KPascal Milli
// Float64 returns the value as float64 with 0.001 precision.
func (k KPascal) Float64() float64 {
return Milli(k).Float64()
}
// String returns the pressure formatted as a string.
func (k KPascal) String() string {
return Milli(k).String() + "KPa"
}
// RelativeHumidity is humidity level in %rH with 0.01%rH precision.
//
// Deprecated: This interface will be removed in v3. Use
// physic.RelativeHumidity instead.
type RelativeHumidity int32
// Float64 returns the value in %.
func (r RelativeHumidity) Float64() float64 {
return float64(r) * .01
}
// String returns the humidity formatted as a string.
func (r RelativeHumidity) String() string {
m := r % 100
if m < 0 {
m = -m
}
return strconv.Itoa(int(r)/100) + "." + prefixZeros(2, int(m)) + "%rH"
}
//
func prefixZeros(digits, v int) string {
// digits is expected to be around 2~3.
s := strconv.Itoa(v)
for len(s) < digits {
// O(n²) but since digits is expected to run 2~3 times at most, it doesn't matter.
s = "0" + s
}
return s
}

@ -1,80 +0,0 @@
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
package devices
import "testing"
func TestMilli(t *testing.T) {
o := Milli(10010)
if s := o.String(); s != "10.010" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f > 10.011 || f < 10.009 {
t.Fatalf("%f", f)
}
}
func TestMilli_neg(t *testing.T) {
o := Milli(-10010)
if s := o.String(); s != "-10.010" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f > -10.009 || f < -10.011 {
t.Fatalf("%f", f)
}
}
func TestCelsius(t *testing.T) {
o := Celsius(10010)
if s := o.String(); s != "10.010°C" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f > 10.011 || f < 10.009 {
t.Fatalf("%f", f)
}
if f := o.ToF(); f != 50018 {
t.Fatalf("%d", f)
}
}
func TestFahrenheit(t *testing.T) {
o := Fahrenheit(10010)
if s := o.String(); s != "10.010°F" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f > 10.011 || f < 10.009 {
t.Fatalf("%f", f)
}
}
func TestKPascal(t *testing.T) {
o := KPascal(10010)
if s := o.String(); s != "10.010KPa" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f > 10.011 || f < 10.009 {
t.Fatalf("%f", f)
}
}
func TestRelativeHumidity(t *testing.T) {
o := RelativeHumidity(5006)
if s := o.String(); s != "50.06%rH" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f >= 50.07 || f <= 50.05 {
t.Fatalf("%f", f)
}
}
func TestRelativeHumidity_neg(t *testing.T) {
o := RelativeHumidity(-5010)
if s := o.String(); s != "-50.10%rH" {
t.Fatalf("%#v", s)
}
if f := o.Float64(); f <= -50.11 || f >= -50.09 {
t.Fatalf("%f", f)
}
}
Loading…
Cancel
Save