def psleep(self): ''' Sleeps longer and longer to save power the more time in between updates. ''' if check_deadline(ticks_ms(), self._powersave_start) <= 60000: sleep(8 / 1000) elif check_deadline(ticks_ms(), self._powersave_start) >= 240000: sleep(180 / 1000) return
def check_timeout(flag, limit): """test for timeout waiting for specified flag""" timed_out = False if HAS_SUPERVISOR: start = supervisor.ticks_ms() while not timed_out and not flag(): if ticks_diff(supervisor.ticks_ms(), start) >= limit * 1000: timed_out = True else: start = time.monotonic() while not timed_out and not flag(): if time.monotonic() - start >= limit: timed_out = True return timed_out
def before_matrix_scan(self, keyboard): ''' Return value will be injected as an extra matrix update ''' now = ticks_ms() if now - self.last_tick < self.polling_interval: return self.last_tick = now x, y = self._read_raw_state() # I'm a shit coder, so offset is handled in software side s_x = self.getSignedNumber(x, 8) - self.x_offset s_y = self.getSignedNumber(y, 8) - self.y_offset # Evaluate Deadzone if s_x in range(-self.dead_x, self.dead_x) and s_y in range( -self.dead_y, self.dead_y ): # Within bounds, just die return else: # Set the X/Y from easypoint self.pointing_device.report_x[0] = x self.pointing_device.report_y[0] = y self.pointing_device.hid_pending = x != 0 or y != 0 return
def tick(self): now = ticks_ms() if ticks_diff(now, self.last_tick) >= self.period: self.last_tick = now return True else: return False
def operation_mode(self, val): assert 0 <= val <= 4 # Set the mode bits inside the operation mode register. op_mode = self._read_u8(_REG_OP_MODE) op_mode &= 0b11100011 op_mode |= val << 2 self._write_u8(_REG_OP_MODE, op_mode) # Wait for mode to change by polling interrupt bit. if HAS_SUPERVISOR: start = supervisor.ticks_ms() while not self.mode_ready: if ticks_diff(supervisor.ticks_ms(), start) >= 1000: raise TimeoutError("Operation Mode failed to set.") else: start = time.monotonic() while not self.mode_ready: if time.monotonic() - start >= 1: raise TimeoutError("Operation Mode failed to set.")
def __init__(self, powersave_pin=None): self.enable = False self.powersave_pin = powersave_pin # Powersave pin board object self._powersave_start = ticks_ms() self._usb_last_scan = ticks_ms() - 5000 self._psp = None # Powersave pin object self._i2c = 0 self._loopcounter = 0 make_key(names=('PS_TOG', ), on_press=self._ps_tog, on_release=handler_passthrough) make_key(names=('PS_ON', ), on_press=self._ps_enable, on_release=handler_passthrough) make_key(names=('PS_OFF', ), on_press=self._ps_disable, on_release=handler_passthrough)
def __init__( self, split_flip=True, split_side=None, split_type=SplitType.UART, split_target_left=True, uart_interval=20, data_pin=None, data_pin2=None, target_left=True, uart_flip=True, use_pio=False, debug_enabled=False, ): self._is_target = True self._uart_buffer = [] self.split_flip = split_flip self.split_side = split_side self.split_type = split_type self.split_target_left = split_target_left self.split_offset = None self.data_pin = data_pin self.data_pin2 = data_pin2 self.target_left = target_left self.uart_flip = uart_flip self._use_pio = use_pio self._uart = None self._uart_interval = uart_interval self._debug_enabled = debug_enabled self.uart_header = bytearray([0xB2]) # Any non-zero byte should work if self.split_type == SplitType.BLE: try: from adafruit_ble import BLERadio from adafruit_ble.advertising.standard import ( ProvideServicesAdvertisement, ) from adafruit_ble.services.nordic import UARTService self.BLERadio = BLERadio self.ProvideServicesAdvertisement = ProvideServicesAdvertisement self.UARTService = UARTService except ImportError: print('BLE Import error') return # BLE isn't supported on this platform self._ble_last_scan = ticks_ms() - 5000 self._connection_count = 0 self._split_connected = False self._uart_connection = None self._advertisment = None # Seems to not be used anywhere self._advertising = False self._psave_enable = False if self._use_pio: from kmk.transports.pio_uart import PIO_UART self.PIO_UART = PIO_UART
def after_matrix_scan(self, keyboard): if self._nav_key_activated: if self._next_interval <= ticks_ms(): # print("hello: ") # print(ticks_ms()) self._next_interval = ticks_ms() + self.ac_interval # print(self._next_interval) if self.move_step < self.max_speed: self.move_step = self.move_step + 1 if self._right_activated: self.pointing_device.report_x[0] = self.move_step if self._left_activated: self.pointing_device.report_x[0] = 0xFF & ( 0 - self.move_step) if self._up_activated: self.pointing_device.report_y[0] = 0xFF & ( 0 - self.move_step) if self._down_activated: self.pointing_device.report_y[0] = self.move_step # self.pointing_device.hid_pending = True return
def __init__(self, is_inverted=False): self.is_inverted = is_inverted self._state = None self._direction = None self._pos = 0 self._button_state = True self._button_held = None self._velocity = 0 self._movement = 0 self._timestamp = ticks_ms() # callback functions on events. Need to be defined externally self.on_move_do = None self.on_button_do = None
def set_timeout(self, after_ticks, callback): # We allow passing False as an implicit "run this on the next process timeouts cycle" if after_ticks is False: after_ticks = 0 if after_ticks == 0 and self._processing_timeouts: after_ticks += 1 timeout_key = ticks_add(ticks_ms(), after_ticks) if timeout_key not in self._timeouts: self._timeouts[timeout_key] = [] idx = len(self._timeouts[timeout_key]) self._timeouts[timeout_key].append(callback) return (timeout_key, idx)
def __init__( self, i2c, address=I2C_ADDRESS, y_offset=Y_OFFSET, x_offset=X_OFFSET, dead_x=DEAD_X, dead_y=DEAD_Y, ): self._i2c_address = address self._i2c_bus = i2c # HID parameters self.pointing_device = PointingDevice() self.polling_interval = 20 self.last_tick = ticks_ms() # Offsets for poor soldering self.y_offset = y_offset self.x_offset = x_offset # Deadzone self.dead_x = DEAD_X self.dead_y = DEAD_Y
def _process_timeouts(self): if not self._timeouts: return self # Copy timeout keys to a temporary list to allow sorting. # Prevent net timeouts set during handling from running on the current # cycle by setting a flag `_processing_timeouts`. current_time = ticks_ms() timeout_keys = [] self._processing_timeouts = True for k in self._timeouts.keys(): if ticks_diff(k, current_time) <= 0: timeout_keys.append(k) for k in sorted(timeout_keys): for callback in self._timeouts[k]: if callback: callback() del self._timeouts[k] self._processing_timeouts = False return self
def _reset_next_interval(self): if self._nav_key_activated == 1: self._next_interval = ticks_ms() + self.ac_interval self.move_step = 1
def psave_time_reset(self): self._powersave_start = ticks_ms()
def receive(self, *, keep_listening: bool = True, with_header: bool = False, with_ack: bool = False, timeout: Optional[float] = None) -> Optional[bytearray]: """Wait to receive a packet from the receiver. If a packet is found the payload bytes are returned, otherwise None is returned (which indicates the timeout elapsed with no reception). If keep_listening is True (the default) the chip will immediately enter listening mode after reception of a packet, otherwise it will fall back to idle mode and ignore any future reception. All packets must have a 4-byte header for compatibility with the RadioHead library. The header consists of 4 bytes (To,From,ID,Flags). The default setting will strip the header before returning the packet to the caller. If with_header is True then the 4 byte header will be returned with the packet. The payload then begins at packet[4]. If with_ack is True, send an ACK after receipt (Reliable Datagram mode) """ timed_out = False if timeout is None: timeout = self.receive_timeout if timeout is not None: # Wait for the payload_ready signal. This is not ideal and will # surely miss or overflow the FIFO when packets aren't read fast # enough, however it's the best that can be done from Python without # interrupt supports. # Make sure we are listening for packets. self.listen() timed_out = False if HAS_SUPERVISOR: start = supervisor.ticks_ms() while not timed_out and not self.rx_done(): if ticks_diff(supervisor.ticks_ms(), start) >= timeout * 1000: timed_out = True else: start = time.monotonic() while not timed_out and not self.rx_done(): if time.monotonic() - start >= timeout: timed_out = True # Payload ready is set, a packet is in the FIFO. packet = None # save last RSSI reading self.last_rssi = self.rssi # save the last SNR reading self.last_snr = self.snr # Enter idle mode to stop receiving other packets. self.idle() if not timed_out: if self.enable_crc and self.crc_error(): self.crc_error_count += 1 else: # Read the data from the FIFO. # Read the length of the FIFO. fifo_length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES) # Handle if the received packet is too small to include the 4 byte # RadioHead header and at least one byte of data --reject this packet and ignore it. if fifo_length > 0: # read and clear the FIFO if anything in it current_addr = self._read_u8( _RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR) self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr) packet = bytearray(fifo_length) # Read the packet. self._read_into(_RH_RF95_REG_00_FIFO, packet) # Clear interrupt. self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) if fifo_length < 5: packet = None else: if (self.node != _RH_BROADCAST_ADDRESS and packet[0] != _RH_BROADCAST_ADDRESS and packet[0] != self.node): packet = None # send ACK unless this was an ACK or a broadcast elif (with_ack and ((packet[3] & _RH_FLAGS_ACK) == 0) and (packet[0] != _RH_BROADCAST_ADDRESS)): # delay before sending Ack to give receiver a chance to get ready if self.ack_delay is not None: time.sleep(self.ack_delay) # send ACK packet to sender (data is b'!') self.send( b"!", destination=packet[1], node=packet[0], identifier=packet[2], flags=(packet[3] | _RH_FLAGS_ACK), ) # reject Retries if we have seen this idetifier from this source before if (self.seen_ids[packet[1]] == packet[2]) and ( packet[3] & _RH_FLAGS_RETRY): packet = None else: # save the packet identifier for this source self.seen_ids[packet[1]] = packet[2] if (not with_header and packet is not None): # skip the header if not wanted packet = packet[4:] # Listen again if necessary and return the result packet. if keep_listening: self.listen() else: # Enter idle mode to stop receiving other packets. self.idle() # Clear interrupt. self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) return packet
def send(self, data: ReadableBuffer, *, keep_listening: bool = False, destination: Optional[int] = None, node: Optional[int] = None, identifier: Optional[int] = None, flags: Optional[int] = None) -> bool: """Send a string of data using the transmitter. You can only send 252 bytes at a time (limited by chip's FIFO size and appended headers). This appends a 4 byte header to be compatible with the RadioHead library. The header defaults to using the initialized attributes: (destination,node,identifier,flags) It may be temporarily overidden via the kwargs - destination,node,identifier,flags. Values passed via kwargs do not alter the attribute settings. The keep_listening argument should be set to True if you want to start listening automatically after the packet is sent. The default setting is False. Returns: True if success or False if the send timed out. """ # Disable pylint warning to not use length as a check for zero. # This is a puzzling warning as the below code is clearly the most # efficient and proper way to ensure a precondition that the provided # buffer be within an expected range of bounds. Disable this check. # pylint: disable=len-as-condition assert 0 < len(data) <= 252 # pylint: enable=len-as-condition self.idle() # Stop receiving to clear FIFO and keep it clear. # Fill the FIFO with a packet to send. self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, 0x00) # FIFO starts at 0. # Combine header and data to form payload payload = bytearray(4) if destination is None: # use attribute payload[0] = self.destination else: # use kwarg payload[0] = destination if node is None: # use attribute payload[1] = self.node else: # use kwarg payload[1] = node if identifier is None: # use attribute payload[2] = self.identifier else: # use kwarg payload[2] = identifier if flags is None: # use attribute payload[3] = self.flags else: # use kwarg payload[3] = flags payload = payload + data # Write payload. self._write_from(_RH_RF95_REG_00_FIFO, payload) # Write payload and header length. self._write_u8(_RH_RF95_REG_22_PAYLOAD_LENGTH, len(payload)) # Turn on transmit mode to send out the packet. self.transmit() # Wait for tx done interrupt with explicit polling (not ideal but # best that can be done right now without interrupts). timed_out = False if HAS_SUPERVISOR: start = supervisor.ticks_ms() while not timed_out and not self.tx_done(): if ticks_diff(supervisor.ticks_ms(), start) >= self.xmit_timeout * 1000: timed_out = True else: start = time.monotonic() while not timed_out and not self.tx_done(): if time.monotonic() - start >= self.xmit_timeout: timed_out = True # Listen again if necessary and return the result packet. if keep_listening: self.listen() else: # Enter idle mode to stop receiving other packets. self.idle() # Clear interrupt. self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) return not timed_out
def ble_time_reset(self): '''Resets the rescan timer''' self._ble_last_scan = ticks_ms()
def ble_rescan_timer(self): '''If true, the rescan timer is up''' return not bool(check_deadline(ticks_ms(), self._ble_last_scan, 5000))
def usb_rescan_timer(self): return bool(check_deadline(ticks_ms(), self._usb_last_scan) > 5000)
mapped = in_delta else: mapped = 0.5 mapped *= out_max - out_min mapped += out_min if out_min <= out_max: return max(min(mapped, out_max), out_min) return min(max(mapped, out_max), out_min) # we're doing "analog" reading of touchA, so get our own baseline touchA_min = touchA.raw_value # because of long traces to touchB, we need to adjust threshold up a bit touchB.threshold += 500 last_press_time = ticks_ms() last_gate_time = ticks_ms() interval = 500 # milliseconds between gate_duration = 100 # milliseconds gate is high in tap tempo mode do_tap_tempo = False while True: switch.update() now = ticks_ms() # r = 0-255 mapped analog touch value on A output # g = tap-tempo beat, if any, on B output # b = on/off touch value on B output r = map_range(touchA.raw_value, touchA_min, touchA_min * 2, 0, 255) g = 0 b = 0
def usb_time_reset(self): self._usb_last_scan = ticks_ms() return
def velocity_event(self): if self.VELOCITY_MODE: new_timestamp = ticks_ms() self._velocity = new_timestamp - self._timestamp self._timestamp = new_timestamp
def __init__(self, period): self.period = period self.last_tick = ticks_ms()