mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-21 15:09:00 +00:00
working more or less
This commit is contained in:
+183
-13
@@ -1,59 +1,229 @@
|
|||||||
package apds9930
|
package apds9930
|
||||||
|
|
||||||
import "tinygo.org/x/drivers"
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"tinygo.org/x/drivers"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errInvalidParam = errors.New("apds9930: invalid param")
|
||||||
|
|
||||||
type Dev struct {
|
type Dev struct {
|
||||||
bus drivers.I2C
|
bus drivers.I2C
|
||||||
_txerr error
|
_txerr error
|
||||||
addr uint16
|
addr uint16
|
||||||
buf [8]byte
|
buf [3]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(bus drivers.I2C, addr uint8) Dev {
|
func New(bus drivers.I2C, addr uint8) Dev {
|
||||||
return Dev{bus: bus, addr: uint16(addr)}
|
return Dev{bus: bus, addr: uint16(addr)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dev) Init() error {
|
// Status contains info on:
|
||||||
|
//
|
||||||
|
// AVALID: Indicates that the ALS Ch0/Ch1 channels have completed an integration cycle.
|
||||||
|
// PSValid. Indicates that the PS has completed an integration cycle.
|
||||||
|
// AINTL ALS Interrupt. Indicates that the device is asserting an ALS interrupt
|
||||||
|
// PINT: Proximity Interrupt. Indicates that the device is asserting a proximity interrupt.
|
||||||
|
// PSAT: Proximity Saturation. Indicates that the proximity measurement is saturated
|
||||||
|
type Status uint8
|
||||||
|
|
||||||
|
func (s Status) ALSAvailable() bool { return s&(1<<0) != 0 } // AVALID
|
||||||
|
func (s Status) ProximityAvailable() bool { return s&(1<<1) != 0 } // PVALID
|
||||||
|
func (s Status) HasALSInterrupt() bool { return s&(1<<4) != 0 } // AINT
|
||||||
|
func (s Status) HasProxInterrupt() bool { return s&(1<<5) != 0 } // PINT
|
||||||
|
func (s Status) IsProximitySaturated() bool { return s&(1<<6) != 0 } // PSAT
|
||||||
|
|
||||||
|
type Enable uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
EnPower Enable = 1 << iota
|
||||||
|
EnALS
|
||||||
|
EnProx
|
||||||
|
EnWait
|
||||||
|
EnALSInt
|
||||||
|
EnProxInt
|
||||||
|
EnSleepAfterInt
|
||||||
|
)
|
||||||
|
|
||||||
|
// Luminic control gain.
|
||||||
|
type ALSGain uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
AGain1 ALSGain = iota
|
||||||
|
AGain8
|
||||||
|
AGain16
|
||||||
|
AGain120
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProxGain uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
PGain1 ProxGain = iota
|
||||||
|
PGain2
|
||||||
|
PGain4
|
||||||
|
PGain8
|
||||||
|
)
|
||||||
|
|
||||||
|
type Drive uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ Drive = iota
|
||||||
|
Drive12_5mA
|
||||||
|
Drive25mA
|
||||||
|
Drive50mA
|
||||||
|
Drive100mA
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
StartMode Enable
|
||||||
|
LEDDrive Drive
|
||||||
|
// ALSGain ALSGain
|
||||||
|
// ProximityGain ProxGain
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) Init(cfg Config) error {
|
||||||
|
if cfg.LEDDrive > Drive100mA {
|
||||||
|
return errInvalidParam
|
||||||
|
}
|
||||||
d.txNew()
|
d.txNew()
|
||||||
d.txWrite8(regENABLE, 0x00) // disable all features.
|
d.txWrite8(regENABLE, 0x00) // disable all features.
|
||||||
d.txWrite8(regATIME, 0xee) // set default integration time.
|
d.txWrite8(regATIME, 0xee) // set default integration time.
|
||||||
d.txWrite8(regPPULSE, 0x04)
|
d.txWrite8(regPPULSE, 0x04)
|
||||||
d.txWrite8(regWTIME, 0xee) // set default wait time.
|
d.txWrite8(regWTIME, 0xee) // set default wait time.
|
||||||
d.txWrite8(regPTIME, 0xff) // set default pulse count.
|
d.txWrite8(regPTIME, 0xff) // set default pulse count.
|
||||||
d.txWrite8(regCONTROL, 0x20)
|
if d.txErr() != nil {
|
||||||
|
return d.txErr()
|
||||||
|
}
|
||||||
|
if cfg.LEDDrive != 0 {
|
||||||
|
err := d.SetLEDDrive(cfg.LEDDrive)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) Status() (Status, error) {
|
||||||
|
d.txNew()
|
||||||
|
v := d.txRead8(regSTATUS)
|
||||||
|
return Status(v), d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable sets the ENABLE register used primarily to
|
||||||
|
// power the APDS-9930 device on/off, enable functions, and interrupts.
|
||||||
|
// Arguments must be ORed, i.e: d.Enable(EnPower|EnProx); to enable proximity.
|
||||||
|
func (d *Dev) Enable(en Enable) error {
|
||||||
|
en &= 0b01111111 // Seventh bit reserved.
|
||||||
|
d.txNew()
|
||||||
|
d.txWrite8(regENABLE, uint8(en))
|
||||||
return d.txErr()
|
return d.txErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Dev) enableLightSensor(withInterrupts bool) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) setAmbientLightGain() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Dev) EnableProximity() error {
|
func (d *Dev) EnableProximity() error {
|
||||||
|
return d.Enable(EnPower | EnALS | EnProx | EnWait)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) proxIntLowThresh() (uint16, error) {
|
||||||
d.txNew()
|
d.txNew()
|
||||||
d.txWrite8(regENABLE, 8|4|2|1)
|
return d.txRead16(regPILTL), d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) setProxIntLowThresh(loThresh uint16) error {
|
||||||
|
d.txNew()
|
||||||
|
d.txWrite16(regPILTL, loThresh)
|
||||||
return d.txErr()
|
return d.txErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dev) ProximityAvailable() bool {
|
func (d *Dev) proxIntHighThresh() (uint16, error) {
|
||||||
d.txNew()
|
d.txNew()
|
||||||
return d.txRead8(regSTATUS)&0x20 == 1
|
val := d.txRead16(regPIHTL)
|
||||||
|
return val, d.txErr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dev) ReadProximity() uint8 {
|
func (d *Dev) setProxIntHighThresh(hiThresh uint16) error {
|
||||||
d.txNew()
|
d.txNew()
|
||||||
h := d.txRead8(regPDATAH)
|
d.txWrite16(regPIHTL, hiThresh)
|
||||||
l := d.txRead8(regPDATAL)
|
return d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) LEDDrive() (Drive, error) {
|
||||||
|
d.txNew()
|
||||||
|
val := (d.txRead8(regCONTROL) >> 6) & 0b11
|
||||||
|
return 3 - Drive(val), d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetLEDDrive drive strength for proximity and ALS
|
||||||
|
//
|
||||||
|
// Value LED Current
|
||||||
|
// 3 100 mA
|
||||||
|
// 2 50 mA
|
||||||
|
// 1 25 mA
|
||||||
|
// 0 12.5 mA
|
||||||
|
func (d *Dev) SetLEDDrive(drive Drive) error {
|
||||||
|
if drive > 3 {
|
||||||
|
return errInvalidParam
|
||||||
|
}
|
||||||
|
drive = 3 - drive
|
||||||
|
current, err := d.LEDDrive()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Replace LED bits in Control register.
|
||||||
|
current &= 0b00111111
|
||||||
|
current |= drive << 6
|
||||||
|
d.txNew()
|
||||||
|
d.txWrite8(regCONTROL, uint8(current))
|
||||||
|
return d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) proxGain() (uint8, error) {
|
||||||
|
val := d.txRead8(regCONTROL)
|
||||||
|
return (val >> 2) & 0b11, d.txErr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadProximity returns a 10-bit value (0..1023), the higher the value the closer the object
|
||||||
|
func (d *Dev) ReadProximity() uint16 {
|
||||||
|
d.txNew()
|
||||||
|
v := d.txRead16(regPDATAL)
|
||||||
if d.txErr() != nil {
|
if d.txErr() != nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
return (h << 8) | l
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Dev) txRead8(reg uint8) uint8 {
|
func (d *Dev) txRead16(addr uint8) uint16 {
|
||||||
if d.txErr() != nil {
|
if d.txErr() != nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
d.buf[0] = reg | 0xa0
|
d.buf[0] = addr | protoAutoInc
|
||||||
|
d._txerr = d.bus.Tx(d.addr, d.buf[:1], d.buf[1:3])
|
||||||
|
return uint16(d.buf[1]) | uint16(d.buf[2])<<8
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Dev) txRead8(addr uint8) uint8 {
|
||||||
|
if d.txErr() != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
d.buf[0] = addr | protoAutoInc
|
||||||
d._txerr = d.bus.Tx(d.addr, d.buf[:1], d.buf[1:2])
|
d._txerr = d.bus.Tx(d.addr, d.buf[:1], d.buf[1:2])
|
||||||
return d.buf[1]
|
return d.buf[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Dev) txWrite16(addr uint8, val uint16) {
|
||||||
|
d.txWrite8(addr, uint8(val))
|
||||||
|
d.txWrite8(addr+1, uint8(val>>8))
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Dev) txWrite8(reg uint8, val uint8) {
|
func (d *Dev) txWrite8(reg uint8, val uint8) {
|
||||||
if d.txErr() != nil {
|
if d.txErr() != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package apds9930
|
package apds9930
|
||||||
|
|
||||||
|
const (
|
||||||
|
protoAutoInc = 0xA0
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
regENABLE = 0x00
|
regENABLE = 0x00
|
||||||
regATIME = 0x01
|
regATIME = 0x01
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
sensor := apds9930.New(bus, 0x39)
|
sensor := apds9930.New(bus, 0x39)
|
||||||
|
|
||||||
err = sensor.Init()
|
err = sensor.Init(apds9930.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
println("proximity enabled!")
|
println("proximity enabled!")
|
||||||
for {
|
for {
|
||||||
time.Sleep(50 * time.Millisecond)
|
stat, _ := sensor.Status()
|
||||||
|
if !stat.ProximityAvailable() {
|
||||||
|
time.Sleep(5 * time.Millisecond)
|
||||||
|
continue
|
||||||
|
}
|
||||||
prox := sensor.ReadProximity()
|
prox := sensor.ReadProximity()
|
||||||
println("proximity:", prox)
|
println("proximity:", prox)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user