def _update(self): with self._mutex: done = False while not done: done = True # get amount of data available numToRead = hal.readSPIAutoReceivedData( self._port, self._buf, 0, 0) # only get whole responses numToRead -= numToRead % self._xferSize if numToRead > self._xferSize * self.kAccumulateDepth: numToRead = self._xferSize * self.kAccumulateDepth done = False if numToRead == 0: return # no samples # read buffered data hal.readSPIAutoReceivedData(self._port, self._buf, numToRead, 0) # loop over all responses off = 0 while True: if off > numToRead: break # convert from bytes resp = self._struct.unpack_from(self._buf, off)[0] # process response if (resp & self._validMask) == self._validValue: # valid sensor data extract data field data = resp >> self._dataShift data &= self._dataMax - 1 # 2s complement conversion if signed MSB is set if (self._isSigned and (data & self._dataMsbMask) != 0): data -= self._dataMax # center offset data -= self._center # only accumulate if outside deadband if (data < -self._deadband or data > self._deadband): self._value += data self._count += 1 self._lastValue = data else: # no data from the sensor just clear the last value self._lastValue = 0 off += self._xferSize
def readAutoReceivedData(self, buffer: bytes, numToRead: int, timeout: float) -> Tuple[int, bytes]: """Read data that has been transferred by the automatic SPI transfer engine. Transfers may be made a byte at a time, so it's necessary for the caller to handle cases where an entire transfer has not been completed. Each received data sequence consists of a timestamp followed by the received data bytes, one byte per word (in the least significant byte). The length of each received data sequence is the same as the combined size of the data and zeroSize set in setAutoTransmitData(). Blocks until numToRead words have been read or timeout expires. May be called with numToRead=0 to retrieve how many words are available. :param buffer: A ctypes c_uint32 buffer to read the data into :param numToRead: number of words to read :param timeout: timeout in seconds (ms resolution) :returns: Number of words remaining to be read """ if len(buffer) < numToRead: raise ValueError("buffer is too small, must be at least %s" % numToRead) return hal.readSPIAutoReceivedData(self.port, buffer, numToRead, timeout)
def readAutoReceivedData( self, buffer: bytes, numToRead: int, timeout: float ) -> Tuple[int, bytes]: """Read data that has been transferred by the automatic SPI transfer engine. Transfers may be made a byte at a time, so it's necessary for the caller to handle cases where an entire transfer has not been completed. Each received data sequence consists of a timestamp followed by the received data bytes, one byte per word (in the least significant byte). The length of each received data sequence is the same as the combined size of the data and zeroSize set in setAutoTransmitData(). Blocks until numToRead words have been read or timeout expires. May be called with numToRead=0 to retrieve how many words are available. :param buffer: A ctypes c_uint32 buffer to read the data into :param numToRead: number of words to read :param timeout: timeout in seconds (ms resolution) :returns: Number of words remaining to be read """ if len(buffer) < numToRead: raise ValueError("buffer is too small, must be at least %s" % numToRead) return hal.readSPIAutoReceivedData(self.port, buffer, numToRead, timeout)
def readAutoReceivedData(self, buffer, numToRead: int, timeout: float) -> (int, bytes): """Read data that has been transferred by the automatic SPI transfer engine. Transfers may be made a byte at a time, so it's necessary for the caller to handle cases where an entire transfer has not been completed. Blocks until numToRead bytes have been read or timeout expires. May be called with numToRead=0 to retrieve how many bytes are available. :param buffer: A ctypes c_uint8 buffer to read the data into :param numToRead: number of bytes to read :param timeout: timeout in seconds (ms resolution) :returns: Number of bytes remaining to be read """ if len(buffer) < numToRead: raise ValueError("buffer is too small, must be at least %s" % numToRead) return hal.readSPIAutoReceivedData(self.port, buffer, numToRead, timeout)
def _update(self) -> None: with self._mutex: done = False while not done: done = True # get amount of data available numToRead = hal.readSPIAutoReceivedData( self._port, self._buf, 0, 0) # only get whole responses numToRead -= numToRead % self._xferSize if numToRead > self._xferSize * self.kAccumulateDepth: numToRead = self._xferSize * self.kAccumulateDepth done = False if numToRead == 0: return # no samples # read buffered data hal.readSPIAutoReceivedData(self._port, self._buf, numToRead, 0) # loop over all responses for off in range(0, numToRead, self._xferSize): # get timestamp from first word timestamp = self._buf[off] & 0xFFFFFFFF # convert from bytes resp = 0 if self._bigEndian: for i in range(1, self._xferSize): resp <<= 8 resp |= self._buf[off + i] & 0xFF else: for i in range(self._xferSize - 1, 0): resp <<= 8 resp |= self._buf[off + i] & 0xFF # process response if (resp & self._validMask) == self._validValue: # valid sensor data extract data field data = resp >> self._dataShift data &= self._dataMax - 1 # 2s complement conversion if signed MSB is set if self._isSigned and (data & self._dataMsbMask) != 0: data -= self._dataMax # center offset dataNoCenter = data data -= self._center # only accumulate if outside deadband if data < -self._deadband or data > self._deadband: self._value += data if self._count != 0: # timestamps use the 1us FPGA clock; also handle rollover if timestamp >= self._lastTimestamp: self._integratedValue = ( dataNoCenter * (timestamp - self._lastTimestamp) * 1e-6 - self._integratedCenter) else: self._integratedValue += ( dataNoCenter * ((1 << 32) - self._lastTimestamp + timestamp) * 1e-6 - self._integratedCenter) self._count += 1 self._lastValue = data else: # no data from the sensor just clear the last value self._lastValue = 0 self._lastTimestamp = timestamp
def _update(self) -> None: with self._mutex: done = False while not done: done = True # get amount of data available numToRead = hal.readSPIAutoReceivedData(self._port, self._buf, 0, 0) # only get whole responses numToRead -= numToRead % self._xferSize if numToRead > self._xferSize * self.kAccumulateDepth: numToRead = self._xferSize * self.kAccumulateDepth done = False if numToRead == 0: return # no samples # read buffered data hal.readSPIAutoReceivedData(self._port, self._buf, numToRead, 0) # loop over all responses for off in range(0, numToRead, self._xferSize): # get timestamp from first word timestamp = self._buf[off] & 0xFFFFFFFF # convert from bytes resp = 0 if self._bigEndian: for i in range(1, self._xferSize): resp <<= 8 resp |= self._buf[off + i] & 0xFF else: for i in range(self._xferSize - 1, 0): resp <<= 8 resp |= self._buf[off + i] & 0xFF # process response if (resp & self._validMask) == self._validValue: # valid sensor data extract data field data = resp >> self._dataShift data &= self._dataMax - 1 # 2s complement conversion if signed MSB is set if self._isSigned and (data & self._dataMsbMask) != 0: data -= self._dataMax # center offset dataNoCenter = data data -= self._center # only accumulate if outside deadband if data < -self._deadband or data > self._deadband: self._value += data if self._count != 0: # timestamps use the 1us FPGA clock; also handle rollover if timestamp >= self._lastTimestamp: self._integratedValue = ( dataNoCenter * (timestamp - self._lastTimestamp) * 1e-6 - self._integratedCenter ) else: self._integratedValue += ( dataNoCenter * ( (1 << 32) - self._lastTimestamp + timestamp ) * 1e-6 - self._integratedCenter ) self._count += 1 self._lastValue = data else: # no data from the sensor just clear the last value self._lastValue = 0 self._lastTimestamp = timestamp