diff --git a/lib/APDS9960.py b/lib/APDS9960.py index 4c69c3f..1f98bc4 100644 --- a/lib/APDS9960.py +++ b/lib/APDS9960.py @@ -1,10 +1,26 @@ -# MicroPython APDS9960 motion detection device driver. +# MicroPython apds9960 motion detection device driver. + +#todo: Have a mix of styles here. Some use properties for setters while others use functions. import pyb +from utime import * -class APDS9960(object) : +def setvalue( aOriginal, aPosBits, aValue ) : + '''Set a specific bit on a variable. aPosBits = 0xpm (p = pos, m = # mask bits).''' + mask = (1 << (aPosBits & 0xf)) - 1 + pos = aPosBits >> 4 + aOriginal &= ~(mask << pos) + return aOriginal | (aValue & mask) << pos - _ADDRESS = 0x39 +def getvalue( aOriginal, aPosBits ) : + '''Get a specific bit from a variable. aPosBits = 0xpm (p = pos, m = # mask bits).''' + mask = (1 << (aPosBits & 0xf)) - 1 + pos = aPosBits >> 4 + return (aOriginal >> pos) & mask + +class apds9960(object) : + + _ADDRESS = const(0x39) _RAM = const(0x00) _ENABLE = const(0x80) _ATIME = const(0x81) @@ -56,161 +72,278 @@ class APDS9960(object) : _GFIFO_L = const(0xFE) _GFIFO_R = const(0xFF) + #Device IDs + _ID_1 = const(0xAB) + _ID_2 = const(0x9C) + #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 + _AGAIN_1X = const(0) #No gain + _AGAIN_4X = const(1) #2x gain + _AGAIN_16X = const(2) #16x gain + _AGAIN_64X = const(3) #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 + _PGAIN_1X = const(0) #1x gain + _PGAIN_2X = const(1) #2x gain + _PGAIN_4X = const(2) #4x gain + _PGAIN_8X = const(3) #8x gain #Pulse Length - _PPULSELEN_4US = 0x00 #4uS - _PPULSELEN_8US = 0x40 #8uS - _PPULSELEN_16US = 0x80 #16uS - _PPULSELEN_32US = 0xC0 #32uS + _PPULSELEN_4US = const(0) #4uS + _PPULSELEN_8US = const(1) #8uS + _PPULSELEN_16US = const(2) #16uS + _PPULSELEN_32US = const(3) #32uS #LED Drive - _LEDDRIVE_100MA = const(0x00) #100mA - _LEDDRIVE_50MA = const(0x40) #50mA - _LEDDRIVE_25MA = const(0x80) #25mA - _LEDDRIVE_12MA = const(0xC0) #12.5mA + _LEDDRIVE_100MA = const(0) #100mA + _LEDDRIVE_50MA = const(1) #50mA + _LEDDRIVE_25MA = const(2) #25mA + _LEDDRIVE_12MA = const(3) #12.5mA #LED Boost - _LEDBOOST_100PCNT = const(0x00) #100% - _LEDBOOST_150PCNT = const(0x10) #150% - _LEDBOOST_200PCNT = const(0x20) #200% - _LEDBOOST_300PCNT = const(0x30) #300% + _LEDBOOST_100 = const(0) #100% + _LEDBOOST_150 = const(1) #150% + _LEDBOOST_200 = const(2) #200% + _LEDBOOST_300 = const(3) #300% #Dimensions - _DIMENSIONS_ALL = const(0x00) - _DIMENSIONS_UP_DOWM = const(0x01) - _DIMENSIONS_LEFT_RIGHT = const(0x02) + _DIMENSIONS_ALL = const(0) + _DIMENSIONS_UP_DOWM = const(1) + _DIMENSIONS_LEFT_RIGHT = const(2) #FIFO - _GFIFO_1 = const(0x00) - _GFIFO_4 = const(0x01) - _GFIFO_8 = const(0x02) - _GFIFO_16 = const(0x03) + _GFIFO_1 = const(0) + _GFIFO_4 = const(1) + _GFIFO_8 = const(2) + _GFIFO_16 = const(3) #G Gain - _GGAIN_1 = const(0x00), - _GGAIN_2 = const(0x01), - _GGAIN_4 = const(0x02), - _GGAIN_8 = const(0x03), + _GGAIN_1 = const(0) + _GGAIN_2 = const(1) + _GGAIN_4 = const(2) + _GGAIN_8 = const(3) #G Pulse - _GPULSE_4US = const(0x00) - _GPULSE_8US = const(0x01) - _GPULSE_16US = const(0x02) - _GPULSE_32US = const(0x03) + _GPULSE_4US = const(0) + _GPULSE_8US = const(1) + _GPULSE_16US = const(2) + _GPULSE_32US = const(3) + + #Following are the bytes describing the data packed into each 8 bit value on the chip. + #Nibble 1 = position, 0 = bits + + ENABLE_PON = const(0x01) + ENABLE_AEN = const(0x11) + ENABLE_PEN = const(0x21) + ENABLE_WEN = const(0x31) + ENABLE_AIEN = const(0x41) + ENABLE_PIEN = const(0x51) + ENABLE_GEN = const(0x61) + + PERS_APERS = const(0x04) + PERS_PPERS = const(0x44) + + PPULSE_PPULSE = const(0x06) + PPULSE_PPLEN = const(0x62) + + CONTROL_AGAIN = const(0x02) + CONTROL_PGAIN = const(0x22) + CONTROL_LDRIVE = const(0x42) + + CONFIG2_LED_BOOST = const(0x42) + CONFIG2_CPSIEN = const(0x61) #Clear photo diode saturation int enable. + CONFIG2_PSIEN = const(0x71) #Proximity saturation interrupt enable. + + CONFIG3_PMASK_R = const(0x01) + CONFIG3_PMASK_L = const(0x11) + CONFIG3_PMASK_D = const(0x21) + CONFIG3_PMASK_U = const(0x31) + CONFIG3_SAI = const(0x41) + CONFIG3_PCMP = const(0x51) + + GCONFIG1_GEXPERS = const(0x02) + GCONFIG1_GEXMSK = const(0x24) + GCONFIG1_GFIFOTH = const(0x62) + + GCONFIG2_GWTIME = const(0x03) + GCONFIG2_GLDRIVE = const(0x32) + GCONFIG2_GGAIN = const(0x52) + + GCONFIG3_GDIMS = const(0x02) + + GCONFIG4_GMODE = const(0x01) + GCONFIG4_GIEN = const(0x12) + + GPULSE_GPULSE = const(0x06) + GPULSE_GPLEN = const(0x62) + + STATUS_AVALID = const(0x01) + STATUS_PVALID = const(0x11) + STATUS_GINT = const(0x21) + STATUS_AINT = const(0x41) + STATUS_PINT = const(0x51) + STATUS_PGSTAT = const(0x61) + STATUS_CPSTAT = const(0x71) + + GSTATUS_GVALID = const(0x01) + GSTATUS_GFOV = const(0x11) + +# Gesture wait time values + _GWTIME_0MS = const(0) + _GWTIME_2_8MS = const(1) + _GWTIME_5_6MS = const(2) + _GWTIME_8_4MS = const(3) + _GWTIME_14_0MS = const(4) + _GWTIME_22_4MS = const(5) + _GWTIME_30_8MS = const(6) + _GWTIME_39_2MS = const(7) + + _NONE = const(0) + _UP = const(1) + _DOWN = const(2) + _LEFT = const(3) + _RIGHT = const(4) + + _DefaultIntTimeMS = const(10) def __init__( self, aLoc ) : """aLoc I2C pin location is either 1, 'X', 2 or'Y'.""" - self.i2c = pyb.I2C(aLoc, pyb.I2C.MASTER) + self._i2c = pyb.I2C(aLoc, pyb.I2C.MASTER) - #Gesture Config 1. - self._gexpers = 0 - self._gexmsk = 0 - self._gfifoth = 0 + #Mirrors data on the controller. + self._enable = 0 #Enable + self._pers = 0 #Pers + self._ppulse = 0 #PPulse + self._gpulse = 0 #GPulse + self._control = 0 #Control + self._config2 = 0 #Config 2. + self._config3 = 0 #Config 3. + self._gconfig1 = 0 #Gesture Config 1. + self._gconfig2 = 0 #Gesture Config 2 + self._gconfig3 = 0 #Gesture Config 3 + self._gconfig4 = 0 #Gesture Config 4. + self._status = 0 #Status + self._gstatus = 0 #GStatus - #Gesture Config 2 - self._gwtime = 0 - self._gldrive = 0 - self._ggain = 0 + self.resetcounts() - #Gesture Config 3 - self._gdims = 0 + self._millis = 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 + self._b1 = bytearray(1) + self._b2 = bytearray(2) 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) + """Read 8 bit value and return.""" + self._i2c.mem_read(self._b1, _ADDRESS, aLoc) + return self._b1[0] - 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 read16( self, aLoc ) : + """Read 16 bit value and return.""" + self._i2c.mem_read(self._b2, _ADDRESS, aLoc) + return (self._b2[1] << 8) | self._b2[0] + + def write( self, aLoc, aVal ) : + """Write 8 bit value to given address. aVal may be a byte array.""" + self._i2c.mem_write(aVal, _ADDRESS, aLoc) + + def write16( self, aLoc, aVal ) : + """Write 16 bit value to given address.""" + self._b2[0] = aVal + self._b2[1] = aVal >> 8 + self._i2c.mem_write(self._b2, _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) + #Enable + def setenable( self, aMember, aValue ) : + self._enable = setvalue(self._enable, aMember, aValue) + self.write(_ENABLE, self._enable) - def writegc2( self ) : - v = (self._ggain << 5) | (self._gldrive << 3) | self._gwtime - self.write(APDS9960._GCONF2, v) + def getenable( self, aMember ) : + return getvalue(self._enable, aMember) - def writegc1( self ) : - v = (self._gfifoth << 7) | (self._gexmsk << 5) | self._gexpers - self.write(APDS9960._GCONF1, v) + #Pers + def setpers( self, aMember, aValue ) : + self._pers = setvalue(self._pers, aMember, aValue) + self.write(_PERS, self._pers) - def writegc4( self ) : - v = (self._gien << 1) | self._gmode - self.write(APDS9960._GCONF4, v) + def getpers( self, aMember ) : + return getvalue(self._pers, aMember) - def writegpulse( self ) : - v = (self._plen << 6) | self._gpulse - self.write(APDS9960._GPULSE, v) + #Control + def setcontrol( self, aMember, aValue ) : + self._control = setvalue(self._control, aMember, aValue) + self.write(_CONTROL, self._control) - def writepers( self ) : - v = (self._ppers << 4) | self._apers - self.write(APDS9960._PERS, v) + def getcontrol( self, aMember ) : + return getvalue(self._control, aMember) - def writecontrol( self ) : - v = (self._ldrive << 6) | (self._pgain << 2) | self._again - self.write(APSD9960._CONTROL, v) + #Config 3 + def setconfig2( self, aMember, aValue ) : + self._config2 = setvalue(self._config2, aMember, aValue) + self.write(_CONFIG2, self._config2) - 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 getconfig2( self, aMember ) : + return getvalue(self._config2, aMember) - def resetCounts( self ) : + #Config 3 + def setconfig3( self, aMember, aValue ) : + self._config3 = setvalue(self._config3, aMember, aValue) + self.write(_CONFIG3, self._config3) + + def getconfig3( self, aMember ) : + return getvalue(self._config3, aMember) + + #GConfig 1 + def setgconfig1( self, aMember, aValue ) : + self._gconfig1 = setvalue(self._gconfig1, aMember, aValue) + self.write(_GCONF1, self._gconfig1) + + def getgconfig1( self, aMember ) : + return getvalue(self._gconfig1, aMember) + + #GConfig 2 + def setgconfig2( self, aMember, aValue ) : + self._gconfig2 = setvalue(self._gconfig2, aMember, aValue) + self.write(_GCONF2, self._gconfig2) + + def getgconfig2( self, aMember ) : + return getvalue(self._gconfig2, aMember) + + #GConfig 3 + def setgconfig3( self, aMember, aValue ) : + self._gconfig3 = setvalue(self._gconfig3, aMember, aValue) + self.write(_GCONF3, self._gconfig3) + + def getgconfig3( self, aMember ) : + return getvalue(self._gconfig3, aMember) + + #GConfig 4 + def setgconfig4( self, aMember, aValue ) : + self._gconfig4 = setvalue(self._gconfig4, aMember, aValue) + self.write(_GCONF4, self._gconfig4) + + def getgconfig4( self, aMember ) : + return getvalue(self._gconfig4, aMember) + + #Status + def getstatus( self, aMember ) : + '''Get member of status''' + self._status = self.read(_STATUS) + return getvalue(self._status, aMember) + + #GStatus + def getgstatus( self, aMember ) : + self._gstatus = self.read(_GSTATUS) + return getvalue(self._gstatus, aMember) + + def resetcounts( self ) : self._gestCnt = 0 #todo - put these in an array. self._ucount = 0 @@ -218,261 +351,218 @@ class APDS9960(object) : 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() + def enableproximityint( self, aValue ) : + self.setenable(ENABLE_PIEN, aValue) 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() + self.write(_PILT, aValue & 0xFF) + self.write(_PIHT, aValue >> 8) + self.setpers(PERS_PPERS, min(aPersistance, 7)) - @property - def proximityint( self ) : - return self.status & 0x20 - - @property def proximity( self ) : - return self.read(APDS9960._PDATA)[0] + return self.read(_PDATA) + + def gestureenterthreshold( self, aValue ) : + self.write(_GPENTH, aValue) + + def gestureexitthreshold( self, aValue ) : + self.write(_GEXTH, aValue) + + def gestureoffset( self, aUp, aDown, aLeft, aRight ) : + self.write(_GOFFSET_U, aUp) + self.write(_GOFFSET_D, aDown) + self.write(_GOFFSET_L, aLeft) + self.write(_GOFFSET_R, aRight) + + def enablegesture( self, aEnable ) : + #If disabling make sure we aren't currently in gesture mode. + # Gesture mode is auto entered when proximity enter threshold is hit + # so we don't need to enable it. + if not aEnable : + self.setgconfig4(GCONFIG4_GMODE, False) + self.setenable(ENABLE_GEN, aEnable) + self.resetcounts() @property def gesturevalid( self ) : - return self.gstatus & 0x01 + """Return True if gesture data exists.""" + return self.getgstatus(GSTATUS_GVALID) - @property - def gesturedims( self ) : - return self._gdims + def gesturedata( self ) : + """Read gesture data and return as (u,d,l,r). Returns None of no data ready.""" + level = self.read(_GFLVL) + if level == 0 : + return # no data + fifo_u = self.read(_GFIFO_U) + fifo_d = self.read(_GFIFO_D) + fifo_l = self.read(_GFIFO_L) + fifo_r = self.read(_GFIFO_R) - @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() + return (fifo_u, fifo_d, fifo_l, fifo_r) @property def colordataready( self ) : - return self.status & 0x01 + """Return true if color data ready to read.""" + return self.getstatus(STATUS_AVALID) - @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 color data as (c,r,g,b).""" + c = self.read16(_CDATAL) + r = self.read16(_RDATAL) + g = self.read16(_GDATAL) + b = self.read16(_BDATAL) 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) + self.write(_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) + self.write16(_AILTL, aLow) + self.write16(_AIHTL, aHigh) -///////////////////////////////// - - 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() + t = max(0.0, min(255.0, 256.0 - (aValue / 2.78))) + self.write(_ATIME, int(t)) @property def enabled( self ) : - return self._pon + return self.getenable(ENABLE_PON) @enabled.setter def enabled( self, aValue ) : - self._pon = aValue - self.writeenable() + self.setenable(ENABLE_PON, aValue) 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) + setvalue(self._ppulse, PPULSE_PPULSE, min(64, max(aPulses, 1)) - 1) + setvalue(self._ppulse, PPULSE_PPLEN, aLen) + self.write(PPULSE_PPULSE, self._ppulse) - def begin( self, aTime, aGain ) : - if self.read(APDS9960._ID)[0] != 0xAB : - raise Exception('Incorrect APDS9960 ID.') + def gpulse( self, aLen, aPulses ) : + setvalue(self._gpulse, GPULSE_GPULSE, min(64, max(aPulses, 1)) - 1) + setvalue(self._gpulse, GPULSE_GPLEN, aLen) + self.write(PPULSE_PPULSE, self._gpulse) - # 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) + def begin( self ) : + id = self.read(_ID) + if id != _ID_1 and id != _ID_2: + raise Exception('Incorrect apds9960 ID {}.'.format(id)) self.enabled = False sleep_us(50) + + # Set default integration time and gain + self.adcintegrationtime(_DefaultIntTimeMS) + self.write(_WTIME, 249) + self.write(_POFFSET_UR, 0) + self.write(_POFFSET_DL, 0) + self.write(_CONFIG1, 0x60) + self.setcontrol(CONTROL_LDRIVE, _LEDDRIVE_100MA) + self.setcontrol(CONTROL_AGAIN, _AGAIN_16X) + self.setcontrol(CONTROL_PGAIN, _PGAIN_8X) + + self.proxpulse(_PPULSELEN_16US, 10) + self.gpulse(_GPULSE_32US, 9) + + self.proximityintthreshold(0x3200, 1) + self.enableproximityint(False) #Proximity Interrupt +# self.intlimits(0xFFFF, 0) + + #100 makes the results a bit more erratic, No value boosts distance. It seems + # the higher the boost the more stable the data is. + self.setconfig2(CONFIG2_LED_BOOST, _LEDBOOST_300) + + #NOTE: This must be 1 if enter threshold is < exit or we will never get gesture input because we + # won't stay in the gesture state for more than 1 cycle. + self.setgconfig1(GCONFIG1_GFIFOTH, _GFIFO_1) + self.setgconfig2(GCONFIG2_GWTIME, _GWTIME_2_8MS) + self.setgconfig2(GCONFIG2_GGAIN, _GGAIN_4) + self.setgconfig3(GCONFIG3_GDIMS, _DIMENSIONS_ALL) + #NOTE: An enter value lower than the exit value means we are constantly entering/exiting the state machine. + # If we don't do this we will not get proximity and color input because those are not updated when in gesture state. + self.gestureenterthreshold(5) #When proximity value is above this we enter the gesture state machine. + self.gestureexitthreshold(255) #When all gesture values are below this we exit the gesture state machine. + self.gestureoffset(0, 0, 0, 0) + + self.setenable(ENABLE_PEN, True) #enable proximity + self.setenable(ENABLE_AEN, True) #enable color + self.enablegesture(True) + 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() + def readgesture( self ) : + #todo: implement + while True : + ud_diff = 0 + lr_diff = 0 + gesturereceived = 0 + if not self.gesturevalid : + return 0 - self._gplen = APDS9960._GPULSE_32US - self._gpulse = 9 - self.writegpulse() + sleep_us(20) #todo: find correct value for this. + + toread = self.read(_GFLVL) + buf = self._i2c.mem_read(toread, _ADDRESS, _GFIFO_U) + + diff = buf[0] - buf[1] + if abs(diff) > 13 : + ud_diff += diff + + diff = buf[2] - buf[3] + if abs(diff) > 13 : + lr_diff += diff + + if ud_diff != 0 : + if ud_diff < 0 : + if self._dcount > 0 : + gesturereceived = _UP + else: + self._ucount += 1 + elif ud_diff > 0 : + if self._ucount > 0 : + gesturereceived = _DOWN + else: + self._dcount += 1 + + if lr_diff != 0 : + if lr_diff < 0 : + if self._rcount > 0 : + gesturereceived = _LEFT + else: + self._lcount += 1 + elif lr_diff > 0 : + if self._lcount > 0 : + gesturereceived = _RIGHT + else: + self._rcount += 1 + + if (ud_diff != 0) or (lr_diff != 0) : + self._millis = ticks_ms() + + if gesturereceived or (ticks_ms() - self._millis > 300) : + self.resetcounts() + + return gesturereceived + +# def calculatecolortemp( self, aRed, aGreen, aBlue ) : +# x = (-0.14282 * aRed) + (1.54924 * aGreen) + (-0.95641 * aBlue) +# y = self.calculatelux(aRed, aGreen, aBlue) +# z = (-0.68202 * aRed) + (0.77073 * aGreen) + (0.56332 * aBlue) +# +# den = x + y + z +# xc = x / den +# yc = y / den +# +# n = (xc - 0.332) / (0.1858 - yc) +# +# cct = (449.0 * pow(n, 3)) + (35250 * pow(n, 2)) + (6823.3 * n) + 5520.33 +# +# return cct +# +# def calculatelux( self, aRed, aGreen, aBlue ) : +# return (-0.32466 * aRed) + (1.57837 * aGreen) + (-0.73191 * aBlue) diff --git a/main.py b/main.py index d0173a8..480dfb9 100644 --- a/main.py +++ b/main.py @@ -4,13 +4,14 @@ #from sysfont import * # from terminalfont import * import gc +from time import sleep_ms print(gc.mem_free()) def reboot( ) : pyb.hard_reset() #pyt = 0 #if pyt : -# from ST7735 import makeg +# from st7735 import makeg # t = makeg() #else: # t = pyb.TFT("x", "X1", "X2") @@ -20,10 +21,10 @@ def reboot( ) : pyb.hard_reset() # #print(gc.mem_free()) -# import TFT -# TFT.run(t) +# import tft +# tft.run(t) -# Display animated circle on TFT ------------------------- +# Display animated circle on tft ------------------------- #from bombs import bomber #t.rotation(2) @@ -32,8 +33,8 @@ def reboot( ) : pyb.hard_reset() # Accelerometer display ---------------------------------- -# import Balance -# Balance.main() +# import balance +# balance.main() # Carpenter level display using accelerometer ------------ @@ -41,7 +42,7 @@ def reboot( ) : pyb.hard_reset() # l = Level(t) # l.run() -# PIR motion sensor -------------------------------------- +# pir motion sensor -------------------------------------- # import motion # m = motion.motion(t) @@ -53,30 +54,30 @@ def reboot( ) : pyb.hard_reset() # tt = TreatThrower.TreatThrower(m) # tt.run() -# L2082 Motor control ------------------------------------ +# l2082 Motor control ------------------------------------ -# from L298N import Motor -# m1 = Motor('Y1', 'Y2', ('Y3', 4)) -# m2 = Motor('Y5', 'Y6', ('Y4', 4)) +# from l298n import motor +# m1 = motor('Y1', 'Y2', ('Y3', 4)) +# m2 = motor('Y5', 'Y6', ('Y4', 4)) # IR or SR04 distance display ---------------------------- -# from IRDistance import IRDistance +# from irdistance import IRDistance # r = IRDistance("X12") -# from SR04Distance import SR04Distance -# r = SR04Distance("Y2", "Y1") +# from sr04distance import sr04distance +# r = sr04distance("Y2", "Y1") # t.rotation(2) -# from DistanceDisplay import Display -# d = Display(t, r) +# from distancedisplay import display +# d = display(t, r) # d.run() # Bluetooth board ---------------------------------------- -# from JYMCU import JYMCU +# from jymcu import jymcu -# u = JYMCU(6, 57600) +# u = jymcu(6, 57600) # u.write("Testing.") # u.readline() # u.setrepl() @@ -93,9 +94,9 @@ def reboot( ) : pyb.hard_reset() # WIFI board ---------------------------------------- -# from ESP8266 import WIFI +# from esp8266 import wifi -# v = WIFI(6) +# v = wifi(6) # from pyb import Pin # p = Pin("X11", Pin.IN, Pin.PULL_DOWN) @@ -103,11 +104,11 @@ def reboot( ) : pyb.hard_reset() # Accelerometer board ---------------------------------------- -#from GY521 import Accel +#from gy521 import accel # print(gc.mem_free()) # -#a = Accel(1) +#a = accel(1) #def d(): return a.acceltemprot # #print(gc.mem_free()) @@ -124,11 +125,53 @@ print(gc.mem_free()) # #print(gc.mem_free()) -def do( ) : - return pyb.MPU6050('x', 0) +#def do( ) : +# return pyb.MPU6050('x', 0) #def prnt( dev, font ) : # dev.text((10, 10), "Hello!", 1, font, 1) # dev.text((10, 30), "Hi Again?", 1, font, 3) +from apds9960 import * +a = apds9960(1) +from oled import oled +from terminalfont import * + +o = oled(2) + +def check(): + empty = (0,0,0,0) + while True: + cr = a.colordataready + c = a.colordata() if cr else empty + p = a.proximity() + v = a.gesturedata() + if v == None : + v = empty + + o.clear() + o.text((0, 10), "{:3}".format(p), 1, terminalfont) + o.text((0, 20), "{:3} {:3} {:3} {:3}".format(*v), 1, terminalfont) + o.text((0, 30), "{:3} {:3} {:3} {:3}".format(*c), 1, terminalfont) + o.display() + sleep_ms(100) + +check() + +#b = bytearray(4) +#b[0] = 0x66 +#b[1] = 0x66 +#b[2] = 0x02 +#b[3] = 0x56 +# +#u = pyb.UART(1, 115200) +# +#def rd( aData ) : +# v = u.read(aData) +# print("-----") +# for e in v : +# print("{:02x}".format(e)) + +#from cjmcu import * +#u = cjmcu(1)