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"
"time"
"periph.io/x/periph/devices"
"periph.io/x/periph/conn/physic"
)
// sense180 reads the device's registers for bmp180.
//
// 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.
if err := d.writeCommands([]byte{0xF4, 0x20 | 0x0E}); err != nil {
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)
pressure := d.cal180.compensatePressure(up, int32(rawTemp), uint(d.os))
env.Temperature = devices.Celsius(temp * 100)
env.Pressure = devices.KPascal(pressure)
// Convert DeciCelsius to Kelvin.
e.Temperature = physic.Temperature(temp)*100*physic.MilliCelsius + physic.ZeroCelsius
e.Pressure = physic.Pressure(pressure) * physic.Pascal
return nil
}

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

@ -7,13 +7,13 @@ package bmxx80
import (
"time"
"periph.io/x/periph/devices"
"periph.io/x/periph/conn/physic"
)
// sense280 reads the device's registers for bme280/bmp280.
//
// 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
// 4.1.
// 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
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 {
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 {
// This value is 16 bits as per doc.
hRaw := int32(buf[6])<<8 | int32(buf[7])
h := d.cal280.compensateHumidityInt(hRaw, tFine)
env.Humidity = devices.RelativeHumidity((int32(h)*100 + 511) / 1024)
h := physic.RelativeHumidity(d.cal280.compensateHumidityInt(hRaw, tFine))
// Convert base 1024 to base 1000.
e.Humidity = h * physic.MicroRH * 1000 / 1024
}
return nil
}

@ -17,7 +17,6 @@ import (
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi"
"periph.io/x/periph/conn/spi/spitest"
"periph.io/x/periph/devices"
)
// Real data extracted from a device.
@ -87,21 +86,21 @@ func TestSPISenseBME280_success(t *testing.T) {
if s := dev.String(); s != "BME280{playback}" {
t.Fatal(s)
}
env := devices.Environment{}
if err := dev.Sense(&env); err != nil {
e := physic.Env{}
if err := dev.Sense(&e); err != nil {
t.Fatal(err)
}
// 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"
// but fail to read data. It could also be a bug in the driver. :(
if env.Temperature != 62680 {
t.Fatalf("temp %d", env.Temperature)
if e.Temperature != 62680*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", e.Temperature)
}
if env.Pressure != 99576 {
t.Fatalf("pressure %d", env.Pressure)
if e.Pressure != 99575933593750*physic.NanoPascal {
t.Fatalf("pressure %d", e.Pressure)
}
if env.Humidity != 995 {
t.Fatalf("humidity %d", env.Humidity)
if e.Humidity != 9950*physic.MicroRH {
t.Fatalf("humidity %d", e.Humidity)
}
if err := s.Close(); err != nil {
t.Fatal(err)
@ -288,7 +287,7 @@ func TestI2CSenseBME280_fail(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if dev.Sense(&devices.Environment{}) == nil {
if dev.Sense(&physic.Env{}) == nil {
t.Fatal("sense fail read")
}
// The I/O didn't occur.
@ -328,18 +327,18 @@ func TestI2CSenseBMP280_success(t *testing.T) {
if s := dev.String(); s != "BMP280{playback(118)}" {
t.Fatal(s)
}
env := devices.Environment{}
if err := dev.Sense(&env); err != nil {
e := physic.Env{}
if err := dev.Sense(&e); err != nil {
t.Fatal(err)
}
if env.Temperature != 23720 {
t.Fatalf("temp %d", env.Temperature)
if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", e.Temperature)
}
if env.Pressure != 100943 {
t.Fatalf("pressure %d", env.Pressure)
if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", e.Pressure)
}
if env.Humidity != 0 {
t.Fatalf("humidity %d", env.Humidity)
if e.Humidity != 0 {
t.Fatalf("humidity %d", e.Humidity)
}
if err := dev.Halt(); err != nil {
t.Fatal(err)
@ -381,18 +380,18 @@ func TestI2CSenseBME280_success(t *testing.T) {
if s := dev.String(); s != "BME280{playback(118)}" {
t.Fatal(s)
}
env := devices.Environment{}
if err := dev.Sense(&env); err != nil {
e := physic.Env{}
if err := dev.Sense(&e); err != nil {
t.Fatal(err)
}
if env.Temperature != 23720 {
t.Fatalf("temp %d", env.Temperature)
if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", e.Temperature)
}
if env.Pressure != 100943 {
t.Fatalf("pressure %d", env.Pressure)
if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", e.Pressure)
}
if env.Humidity != 6531 {
t.Fatalf("humidity %d", env.Humidity)
if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", e.Humidity)
}
if err := dev.Halt(); err != nil {
t.Fatal(err)
@ -430,8 +429,8 @@ func TestI2CSense280_idle_fail(t *testing.T) {
if s := dev.String(); s != "BME280{playback(118)}" {
t.Fatal(s)
}
env := devices.Environment{}
if dev.Sense(&env) == nil {
e := physic.Env{}
if dev.Sense(&e) == nil {
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)}" {
t.Fatal(s)
}
env := devices.Environment{}
if dev.Sense(&env) == nil {
e := physic.Env{}
if dev.Sense(&e) == nil {
t.Fatal("isIdle() should have failed")
}
}
@ -511,20 +510,20 @@ func TestI2CSenseContinuous280_success(t *testing.T) {
if err != nil {
t.Fatal(err)
}
env := devices.Environment{}
e := physic.Env{}
select {
case env = <-c:
case e = <-c:
case <-time.After(2 * time.Second):
t.Fatal("failed")
}
if env.Temperature != 23720 {
t.Fatalf("temp %d", env.Temperature)
if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", e.Temperature)
}
if env.Pressure != 100943 {
t.Fatalf("pressure %d", env.Pressure)
if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", e.Pressure)
}
if env.Humidity != 6531 {
t.Fatalf("humidity %d", env.Humidity)
if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", e.Humidity)
}
// 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")
}
select {
case env = <-c2:
case e = <-c2:
case <-time.After(2 * time.Second):
t.Fatal("failed")
}
select {
case env = <-c2:
case e = <-c2:
case <-time.After(2 * time.Second):
t.Fatal("failed")
}
if env.Temperature != 23720 {
t.Fatalf("temp %d", env.Temperature)
if e.Temperature != 23720*physic.MilliCelsius+physic.ZeroCelsius {
t.Fatalf("temp %d", e.Temperature)
}
if env.Pressure != 100943 {
t.Fatalf("pressure %d", env.Pressure)
if e.Pressure != 100942695312500*physic.NanoPascal {
t.Fatalf("pressure %d", e.Pressure)
}
if env.Humidity != 6531 {
t.Fatalf("humidity %d", env.Humidity)
if e.Humidity != 65305*physic.MicroRH {
t.Fatalf("humidity %d", e.Humidity)
}
if dev.Sense(&env) == nil {
if dev.Sense(&e) == nil {
t.Fatal("can't Sense() during SenseContinously")
}

@ -15,10 +15,10 @@ import (
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/i2c/i2creg"
"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/spireg"
"periph.io/x/periph/conn/spi/spitest"
"periph.io/x/periph/devices"
"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{}
spiEnv := devices.Environment{}
i2cEnv := physic.Env{}
spiEnv := physic.Env{}
if err2 := i2cDev.Sense(&i2cEnv); err2 != nil {
return err2
}
@ -164,7 +164,7 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) {
return err2
}
printEnv(spiDev, &spiEnv)
delta := devices.Environment{
delta := physic.Env{
Temperature: i2cEnv.Temperature - spiEnv.Temperature,
Pressure: i2cEnv.Pressure - spiEnv.Pressure,
Humidity: i2cEnv.Humidity - spiEnv.Humidity,
@ -186,6 +186,6 @@ func run(i2cBus i2c.Bus, i2cAddr uint16, spiPort spi.PortCloser) (err error) {
return nil
}
func printEnv(dev interface{}, env *devices.Environment) {
fmt.Printf("%-18s: %8s %10s %9s\n", dev, env.Temperature, env.Pressure, env.Humidity)
func printEnv(dev interface{}, e *physic.Env) {
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/i2c"
"periph.io/x/periph/conn/mmr"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi"
"periph.io/x/periph/devices"
)
// 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.
//
// 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()
defer d.mu.Unlock()
if d.stop != nil {
@ -266,9 +266,9 @@ func (d *Dev) Sense(env *devices.Environment) error {
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
@ -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
// 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()
defer d.mu.Unlock()
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.wg.Add(1)
go func() {
@ -433,14 +433,14 @@ func (d *Dev) makeDev(opts *Opts) error {
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)
defer t.Stop()
var err error
for {
// Do one initial sensing right away.
var e devices.Environment
e := physic.Env{}
d.mu.Lock()
if d.is280 {
err = d.sense280(&e)
@ -514,5 +514,5 @@ var defaults = Opts{
var doSleep = time.Sleep
var _ conn.Resource = &Dev{}
var _ devices.Environmental = &Dev{}
var _ physic.SenseEnv = &Dev{}
var _ fmt.Stringer = &Dev{}

@ -9,7 +9,7 @@ import (
"log"
"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/host"
)
@ -30,7 +30,7 @@ func Example() {
if err != nil {
log.Fatalf("failed to initialize bme280: %v", err)
}
e := devices.Environment{}
e := physic.Env{}
if err := d.Sense(&e); err != nil {
log.Fatal(err)
}

@ -8,7 +8,6 @@ import (
"image"
"image/color"
"io"
"time"
"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.
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/onewire"
"periph.io/x/periph/devices"
"periph.io/x/periph/conn/physic"
)
// 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.
func (d *Dev) Temperature() (devices.Celsius, error) {
func (d *Dev) Temperature() (physic.Temperature, error) {
if err := d.onewire.TxPower([]byte{0x44}, nil); err != nil {
return 0, err
}
@ -121,7 +121,7 @@ func (d *Dev) Temperature() (devices.Celsius, error) {
// device.
//
// 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.
spad, err := d.readScratchpad()
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
// extension multiply by 1000 to get devices.Millis, divide by 16 due to 4
// fractional bits. Datasheet p.4.
c := (devices.Celsius(int8(spad[1]))<<8 + devices.Celsius(spad[0])) * 1000 / 16
// extension multiply by 1000 to get Millis, divide by 16 due to 4 fractional
// bits. Datasheet p.4.
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
// 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/onewiretest"
"periph.io/x/periph/devices"
"periph.io/x/periph/conn/physic"
)
func TestNew_fail_resolution(t *testing.T) {
@ -52,7 +52,7 @@ func TestTemperature(t *testing.T) {
},
}
var addr onewire.Address = 0x740000070e41ac28
var temp devices.Celsius = 30000 // 30.000°C
temp := 30*physic.Celsius + physic.ZeroCelsius
bus := onewiretest.Playback{Ops: ops}
dev, err := New(&bus, addr, 10)
if err != nil {
@ -187,7 +187,7 @@ func TestRecordTemp(t *testing.T) {
t.Logf(" %#v,", op)
}
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/i2c"
"periph.io/x/periph/conn/mmr"
"periph.io/x/periph/devices"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/devices/lepton/internal"
)
@ -132,7 +132,7 @@ type FFCMode struct {
ShutterTempLockoutState ShutterTempLockoutState // Default: ShutterTempLockoutStateInactive
ElapsedTimeSinceLastFFC time.Duration // Uptime
DesiredFFCPeriod time.Duration // Default: 300s
DesiredFFCTempDelta devices.Celsius // Default: 3K
DesiredFFCTempDelta physic.Temperature // Default: 3K
ImminentDelay uint16 // Default: 52
VideoFreezeDuringFFC bool // Default: true
FFCDesired bool // Default: false
@ -256,25 +256,25 @@ func (d *Dev) GetUptime() (time.Duration, error) {
if err := d.c.get(sysUptime, &v); err != nil {
return 0, err
}
return v.ToD(), nil
return v.Duration(), nil
}
// 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
if err := d.c.get(sysTemperature, &v); err != nil {
return 0, err
}
return v.ToC(), nil
return v.Temperature(), nil
}
// 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
if err := d.c.get(sysHousingTemperature, &v); err != nil {
return 0, err
}
return v.ToC(), nil
return v.Temperature(), nil
}
// GetFFCModeControl returns the internal state with regards to calibration.
@ -286,9 +286,9 @@ func (d *Dev) GetFFCModeControl() (*FFCMode, error) {
return &FFCMode{
FFCShutterMode: FFCShutterMode(v.FFCShutterMode),
ShutterTempLockoutState: ShutterTempLockoutState(v.ShutterTempLockoutState),
ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.ToD(),
DesiredFFCPeriod: v.DesiredFFCPeriod.ToD(),
DesiredFFCTempDelta: devices.Celsius(v.DesiredFFCTempDelta * 10),
ElapsedTimeSinceLastFFC: v.ElapsedTimeSinceLastFFC.Duration(),
DesiredFFCPeriod: v.DesiredFFCPeriod.Duration(),
DesiredFFCTempDelta: v.DesiredFFCTempDelta.Temperature(),
ImminentDelay: v.ImminentDelay,
VideoFreezeDuringFFC: v.VideoFreezeDuringFFC == internal.Enabled,
FFCDesired: v.FFCDesired == internal.Enabled,

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

@ -8,16 +8,18 @@ import (
"bytes"
"testing"
"time"
"periph.io/x/periph/conn/physic"
)
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)
}
}
func TestCentiK(t *testing.T) {
if c := CentiK(100).ToC(); c != -272150 {
if c := CentiK(100).Temperature(); c != physic.Kelvin {
t.Fatal(c)
}
}

@ -29,27 +29,27 @@ import (
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/physic"
"periph.io/x/periph/conn/spi"
"periph.io/x/periph/devices"
"periph.io/x/periph/devices/lepton/cci"
"periph.io/x/periph/devices/lepton/internal"
)
// Metadata is constructed from telemetry data, which is sent with each frame.
type Metadata struct {
SinceStartup time.Duration //
FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps).
AvgValue uint16 // Average value of the buffer.
Temp devices.Celsius // Temperature inside the camera.
TempHousing devices.Celsius // Camera housing temperature.
RawTemp uint16 //
RawTempHousing uint16 //
FFCSince time.Duration // Time since last internal calibration.
FFCTemp devices.Celsius // Temperature at last internal calibration.
FFCTempHousing devices.Celsius //
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.
Overtemp bool // true 10s before self-shutdown.
SinceStartup time.Duration //
FrameCount uint32 // Number of frames since the start of the camera, in 27fps (not 9fps).
AvgValue uint16 // Average value of the buffer.
Temp physic.Temperature // Temperature inside the camera.
TempHousing physic.Temperature // Camera housing temperature.
RawTemp uint16 //
RawTempHousing uint16 //
FFCSince time.Duration // Time since last internal calibration.
FFCTemp physic.Temperature // Temperature at last internal calibration.
FFCTempHousing physic.Temperature //
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.
Overtemp bool // true 10s before self-shutdown.
}
// 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 {
return err
}
m.SinceStartup = rowA.TimeCounter.ToD()
m.SinceStartup = rowA.TimeCounter.Duration()
m.FrameCount = rowA.FrameCounter
m.AvgValue = rowA.FrameMean
m.Temp = rowA.FPATemp.ToC()
m.TempHousing = rowA.HousingTemp.ToC()
m.Temp = rowA.FPATemp.Temperature()
m.TempHousing = rowA.HousingTemp.Temperature()
m.RawTemp = rowA.FPATempCounts
m.RawTempHousing = rowA.HousingTempCounts
m.FFCSince = rowA.TimeCounterLastFFC.ToD()
m.FFCTemp = rowA.FPATempLastFFC.ToC()
m.FFCTempHousing = rowA.HousingTempLastFFC.ToC()
m.FFCSince = rowA.TimeCounterLastFFC.Duration()
m.FFCTemp = rowA.FPATempLastFFC.Temperature()
m.FFCTempHousing = rowA.HousingTempLastFFC.Temperature()
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)
}

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