Adding APDS9960 driver initial imp. Not complete.

master
Guy Carver 2018-01-25 15:43:55 -05:00
rodzic 86d4ce9f7b
commit c81bab7396
1 zmienionych plików z 478 dodań i 0 usunięć

478
lib/APDS9960.py 100644
Wyświetl plik

@ -0,0 +1,478 @@
# MicroPython APDS9960 motion detection device driver.
import pyb
class APDS9960(object) :
_ADDRESS = 0x39
_RAM = const(0x00)
_ENABLE = const(0x80)
_ATIME = const(0x81)
_WTIME = const(0x83)
_AILTL = const(0x84)
_AILTH = const(0x85)
_AIHTL = const(0x86)
_AIHTH = const(0x87)
_PILT = const(0x89)
_PIHT = const(0x8B)
_PERS = const(0x8C)
_CONFIG1 = const(0x8D)
_PPULSE = const(0x8E)
_CONTROL = const(0x8F)
_CONFIG2 = const(0x90)
_ID = const(0x92)
_STATUS = const(0x93)
_CDATAL = const(0x94)
_CDATAH = const(0x95)
_RDATAL = const(0x96)
_RDATAH = const(0x97)
_GDATAL = const(0x98)
_GDATAH = const(0x99)
_BDATAL = const(0x9A)
_BDATAH = const(0x9B)
_PDATA = const(0x9C)
_POFFSET_UR = const(0x9D)
_POFFSET_DL = const(0x9E)
_CONFIG3 = const(0x9F)
_GPENTH = const(0xA0)
_GEXTH = const(0xA1)
_GCONF1 = const(0xA2)
_GCONF2 = const(0xA3)
_GOFFSET_U = const(0xA4)
_GOFFSET_D = const(0xA5)
_GOFFSET_L = const(0xA7)
_GOFFSET_R = const(0xA9)
_GPULSE = const(0xA6)
_GCONF3 = const(0xAA)
_GCONF4 = const(0xAB)
_GFLVL = const(0xAE)
_GSTATUS = const(0xAF)
_IFORCE = const(0xE4)
_PICLEAR = const(0xE5)
_CICLEAR = const(0xE6)
_AICLEAR = const(0xE7)
_GFIFO_U = const(0xFC)
_GFIFO_D = const(0xFD)
_GFIFO_L = const(0xFE)
_GFIFO_R = const(0xFF)
#A Gain
_AGAIN_1X = const(0x00) #No gain
_AGAIN_4X = const(0x01) #2x gain
_AGAIN_16X = const(0x02) #16x gain
_AGAIN_64X = const(0x03) #64x gain
#P Gain
_PGAIN_1X = const(0x00) #1x gain
_PGAIN_2X = const(0x04) #2x gain
_PGAIN_4X = const(0x08) #4x gain
_PGAIN_8X = const(0x0C) #8x gain
#Pulse Length
_PPULSELEN_4US = 0x00 #4uS
_PPULSELEN_8US = 0x40 #8uS
_PPULSELEN_16US = 0x80 #16uS
_PPULSELEN_32US = 0xC0 #32uS
#LED Drive
_LEDDRIVE_100MA = const(0x00) #100mA
_LEDDRIVE_50MA = const(0x40) #50mA
_LEDDRIVE_25MA = const(0x80) #25mA
_LEDDRIVE_12MA = const(0xC0) #12.5mA
#LED Boost
_LEDBOOST_100PCNT = const(0x00) #100%
_LEDBOOST_150PCNT = const(0x10) #150%
_LEDBOOST_200PCNT = const(0x20) #200%
_LEDBOOST_300PCNT = const(0x30) #300%
#Dimensions
_DIMENSIONS_ALL = const(0x00)
_DIMENSIONS_UP_DOWM = const(0x01)
_DIMENSIONS_LEFT_RIGHT = const(0x02)
#FIFO
_GFIFO_1 = const(0x00)
_GFIFO_4 = const(0x01)
_GFIFO_8 = const(0x02)
_GFIFO_16 = const(0x03)
#G Gain
_GGAIN_1 = const(0x00),
_GGAIN_2 = const(0x01),
_GGAIN_4 = const(0x02),
_GGAIN_8 = const(0x03),
#G Pulse
_GPULSE_4US = const(0x00)
_GPULSE_8US = const(0x01)
_GPULSE_16US = const(0x02)
_GPULSE_32US = const(0x03)
def __init__( self, aLoc ) :
"""aLoc I2C pin location is either 1, 'X', 2 or'Y'."""
self.i2c = pyb.I2C(aLoc, pyb.I2C.MASTER)
#Gesture Config 1.
self._gexpers = 0
self._gexmsk = 0
self._gfifoth = 0
#Gesture Config 2
self._gwtime = 0
self._gldrive = 0
self._ggain = 0
#Gesture Config 3
self._gdims = 0
#Gesture Config 4.
self._gmode = 0
self._gien = 0
#GPulse
self._gpulse = APDS9960._GPULSE_32US
self._gplen = 9 #10 pulses.
#PPulse
self._ppulse = 0
self._pplen = 0
#Enable
self._pon = 0
self._aen = 0
self._pen = 0
self._wen = 0
self._aien = 0
self._pien = 0
self._gen = 0
#Control
self._again = 0
self._pgain = 0
self._ldrive = 0
#Pers
self._apers = 0
self._ppers = 0
#Status
self._status = 0
#GStatus
self._gstatus = 0
sleep_us(50)
self.begin()
def read( self, aLoc ) :
"""Read 8 byte value and return in bytearray"""
return self.i2c.mem_read(1, self._ADDRESS, aLoc)
def write( self, aVal, aLoc ) :
"""Write 8 bit value to given address. aVal may be an int buffer."""
self.i2c.mem_write(aVal, self._ADDRESS, aLoc)
def reset( self ):
"""Reset the controller and set default frequency."""
self.write(0, _MODE1)
self.setfreq(_DEFAULTFREQ)
def writec3( self ) :
v = (self._pcmp << 5) | (self._sai << 4) | (self._pmask_u << 3) | (self._mask_d << 2) | (self._pmask_l << 1) | self._pmask_r
self.write(APDS9960._CONFIG3, v)
def writegc2( self ) :
v = (self._ggain << 5) | (self._gldrive << 3) | self._gwtime
self.write(APDS9960._GCONF2, v)
def writegc1( self ) :
v = (self._gfifoth << 7) | (self._gexmsk << 5) | self._gexpers
self.write(APDS9960._GCONF1, v)
def writegc4( self ) :
v = (self._gien << 1) | self._gmode
self.write(APDS9960._GCONF4, v)
def writegpulse( self ) :
v = (self._plen << 6) | self._gpulse
self.write(APDS9960._GPULSE, v)
def writepers( self ) :
v = (self._ppers << 4) | self._apers
self.write(APDS9960._PERS, v)
def writecontrol( self ) :
v = (self._ldrive << 6) | (self._pgain << 2) | self._again
self.write(APSD9960._CONTROL, v)
def writeenable( self ) :
v = (self._gen << 6) | (self._pien << 5) | (self._aien << 4) | (self._wen << 3) | (self._pen << 2) | (self._aen << 1) | self._pon
self.write(APDS9960._ENABLE)
def resetCounts( self ) :
self._gestCnt = 0
#todo - put these in an array.
self._ucount = 0
self._dcount = 0
self._lcount = 0
self._rcount = 0
@property
def status( self ) :
self._status = this.read(APDS9960._STATUS)[0]
return self._status
@property
def gstatus( self ) :
self._gstatus = this.read(APDS9960._GSTATUS)[0]
return self._gstatus
@property
def gpulse( self ) :
return (self._gplen << 6) | self._gpulse
@property
def proximityenable( self ) :
return self._pen
@proximityenable.setter
def proximityenable( self, aValue ) :
self._pen = aValue & 0x01
self.writeenable()
@property
def proximityintenable( self ) :
return self._pien
@proximityint.setter
def proximityintenable( self, aValue ) :
self._pien = aValue & 0x01
self.writeenable()
self.clearInterrupt()
def proximityintthreshold( self, aValue, aPersistance ) :
self.write(APDS9960._PILT, aValue & 0xFF)
self.write(APDS9960._PIHT, aValue >> 8)
self._ppers = min(aPersistance, 7)
self.writepers()
@property
def proximityint( self ) :
return self.status & 0x20
@property
def proximity( self ) :
return self.read(APDS9960._PDATA)[0]
@property
def gesturevalid( self ) :
return self.gstatus & 0x01
@property
def gesturedims( self ) :
return self._gdims
@gesturedims.setter
def gesturedims( self, aValue ) :
self._gdims = aValue & 0x03
self.write(APDS9960._GCONF3, self._gdims)
@property
def gesturefifothreshold( self ) :
return self._gfifoth
@gesturefifothreshold.setter
def gesturefifothreshold( self, aValue ) :
self._gfifoth = aValue & 0x03
self.writegc1()
@property
def gesturegain( self ) :
return self._ggain
@gesturegain.setter
def gesturegain( self, aValue ) :
self._ggain = aValue & 0x03
self.writegc2()
def gestureproximitythreshold( self, aValue ) :
self.write(APDS9960._GPENTH, aValue)
def gestureoffset( self, aUp, aDown, aLeft, aRight ) :
self.write(APDS9960._GOFFSET_U, aUp)
self.write(APDS9960._GOFFSET_D, aDown)
self.write(APDS9960._GOFFSET_L, aLeft)
self.write(APDS9960._GOFFSET_R, aRight)
@property
def gestureenable( self ) :
return self._gen
@gestureenable.setter
def gestureenable( self, aEnable ) :
self._gen = aEnable & 0x01
if not aEnable :
self._gmode = 0
self.writegc4()
self.writeenable()
self.resetCounts()
def colorenable( self, aEnable ) :
self._aen = aEnable & 0x01
self.writeenable()
@property
def colorintenable( self ) :
return self._aien
@colorintenable.setter
def colorintenable( self, aEnable ) :
self._aien = aEnable & 0x01
self.writeenable()
@property
def colordataready( self ) :
return self.status & 0x01
@property
def colordata( self ) :
#todo: Maybe try and read 16 bit data.
#NOTE: The l and h may be backwards here.
c = self.read(APDS9960._CDATAL)[0]
c |= self.read(APDS9960._CDATAH)[0] << 8
r = self.read(APDS9960._RDATAL)[0]
r |= self.read(APDS9960._RDATAH)[0] << 8
g = self.read(APDS9960._GDATAL)[0]
g |= self.read(APDS9960._GDATAH)[0] << 8
b = self.read(APDS9960._BDATAL)[0]
b |= self.read(APDS9960._BDATAH)[0] << 8
return (c, r, g, b)
def clearInterrupt( self ) :
#NOTE: The .ccp writes 0 bytes to this address. I don't know how
# to do that so I'm writing a 0 to AICLEAR.
self.write(APDS9960._AICLEAR, 0)
def intlimits( self, aLow, aHigh ) :
self.write(APDS9960._AILTL, aLow & 0xFF)
self.write(APDS9960._AILTH, aLow >> 8)
self.write(APDS9960._AIHTL, aHigh & 0xFF)
self.write(APDS9960._AIHTH, aHigh >> 8)
/////////////////////////////////
def readgesture( self ) :
#todo: implement
pass
def calculatecolortemp( self, aRed, aGreen, aBlue ) :
#todo: implement
pass
def calculatelux( self, aRed, aGreen, aBlue ) :
#todo: implement
pass
@property
def adcintegrationtime( self ):
return (256.0 - self.read(APDS9960._ATIME)[0]) * 2.78
@adcintegrationtime.setter
def adcintegrationtime( self, aValue ) :
temp = max(0.0, min(255.0, 256.0 - (aValue / 2.78)))
self.write(APSD9960._ATIME, temp)
@property
def avalid( self ) :
return self._status & 0x01
@property
def pvalid( self ) :
return self._status & 0x02
@property
def gint( self ) :
return self._status & 0x04
@property
def aint( self ) :
return self._status & 0x10
@property
def pint( self ) :
return self._status & 0x20
@property
def pgsat( self ) :
return self._status & 0x40
@property
def cpsat( self ) :
return self._status & 0x80
@property
def adcgain( self ):
return self._again
@ADCGain.setter
def adcgain( self, aValue ) :
self._again = aValue & 0x03
self.writecontrol()
@property
def proxgain( self ):
return self._pgain
@ProxGain.setter
def proxgain( self, aValue ) :
self._pgain = aValue & 0x03
self.writecontrol()
@property
def enabled( self ) :
return self._pon
@enabled.setter
def enabled( self, aValue ) :
self._pon = aValue
self.writeenable()
def proxpulse( self, aLen, aPulses ) :
self._pplen = aLen
self._ppulse = min(64, max(aPulses, 1)) - 1
self.write(APDS9960._PPULSE, self._pplen << 6 | self._ppulse)
def begin( self, aTime, aGain ) :
if self.read(APDS9960._ID)[0] != 0xAB :
raise Exception('Incorrect APDS9960 ID.')
# Set default integration time and gain
self.ADCIntegrationTime = APDS9960._DefaultIntTimeMS
self.ADCGain = APDS9960._DefaultAGain
self.gestureenable(False)
self.proximityenable(False)
self.colorenable(False)
self.colorintenable(False)
self.proximityintenable(False)
self.enabled = False
sleep_us(50)
self.enabled = True
sleep_us(50)
self.gesturedimensions(APDS9960._DIMENSIONS_ALL)
self.gesturefifothreshold(APDS9960._GFIFO_4)
self.gesturegain(APDS9960._GGAIN_4)
self.gestureproximitythreshold(50)
self.resetcounts()
self._gplen = APDS9960._GPULSE_32US
self._gpulse = 9
self.writegpulse()