seesaw.py
  1  # SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  # Adafruit Seesaw / CRICKIT driver for MicroPython
  6  # MIT License by Adafruit Industries Limor Fried
  7  # Copy onto the micro:bit with main.py using Mu Files icon
  8  from microbit import i2c
  9  import struct
 10  import time
 11  
 12  _SIGNALS = (2, 3, 40, 41, 11, 10, 9, 8)
 13  _PWMS = (14, 15, 16, 17, 19, 18, 22, 23, 42, 43, 12, 13)
 14  _SERVOS = (17, 16, 15, 14)
 15  _MOTORS = (22, 23, 19, 18)
 16  _DRIVES = (13, 12, 43, 42)
 17  _TOUCHES = (0, 1, 2, 3)
 18  _ADDR = 0x49
 19  
 20  reg_buf = bytearray(2)
 21  pwm_buf = bytearray(3)
 22  
 23  def _read(reghi, reglo, n, delay_s=0.01):
 24      reg_buf[0] = reghi
 25      reg_buf[1] = reglo
 26      i2c.write(_ADDR, reg_buf)
 27      time.sleep(delay_s)
 28      return i2c.read(_ADDR, n)
 29  
 30  def _write(reghi, reglo, cmd):
 31      reg_buf[0] = reghi
 32      reg_buf[1] = reglo
 33      #print("sswrite: ", [hex(i) for i in reg_buf+cmd])
 34      i2c.write(_ADDR, reg_buf+cmd)
 35  
 36  # t is between 1 and 4
 37  def read_touch(t):
 38      return struct.unpack(">H", _read(0x0F, 0x10+_TOUCHES[t-1], 2))[0]
 39  
 40  def pwm_write(pwm, val):
 41      pwm_buf[0] = _PWMS.index(pwm)
 42      pwm_buf[1] = val >> 8
 43      pwm_buf[2] = val & 0xFF
 44      _write(0x08, 0x01, pwm_buf)
 45  
 46  def set_pwmfreq(pwm, freq):
 47      pwm_buf[0] = _PWMS.index(pwm)
 48      pwm_buf[1] = freq >> 8
 49      pwm_buf[2] = freq & 0xFF
 50      _write(0x08, 0x02, pwm_buf)
 51  
 52  # signal is between 1 and 8
 53  def analog_read(signal):
 54      return struct.unpack(">H", _read(0x09, 0x07+signal-1, 2))[0]
 55  
 56  def pin_config(pin, mode, pull=None, val=None):
 57      if pin >= 32:
 58          cmd = struct.pack(">I", 1 << (pin - 32))
 59          cmd = bytearray(4) + cmd
 60      else:
 61          cmd = struct.pack(">I", 1 << pin)
 62      if 0 <= mode <= 1:
 63          _write(0x01, 0x03-mode, cmd)
 64      if pull is not None and 0 <= pull <= 1:
 65          _write(0x01, 0x0C-pull, cmd)
 66      if val is not None and 0 <= val <= 1:
 67          _write(0x01, 0x06-val, cmd)
 68  
 69  
 70  def init():
 71      i2c.init()
 72      while not _ADDR in i2c.scan():
 73          print("Crickit not found!")
 74          time.sleep(1)
 75      reg_buf[0] = 0x7F
 76      reg_buf[1] = 0xFF
 77      i2c.write(_ADDR, reg_buf)
 78  
 79  # s is between 1 and 4
 80  def servo(s, degree, min=1.0, max=2.0):
 81      set_pwmfreq(_SERVOS[s-1], 50)
 82      val = 3276*min + (max-min)*3276*degree/180
 83      pwm_write(_SERVOS[s-1], int(val))
 84  
 85  # d is between 1 and 4
 86  def drive(d, frac, freq=1000):
 87      set_pwmfreq(_DRIVES[d-1], freq)
 88      pwm_write(_DRIVES[d-1], int(frac*65535))
 89  
 90  # m is 1 or 2
 91  def motor(m, frac, freq=1000):
 92      m -= 1  # start with 1
 93      pin1,pin2 = _MOTORS[m*2:m*2+2]
 94      set_pwmfreq(pin1, freq)
 95      set_pwmfreq(pin2, freq)
 96      if frac < 0:
 97          pin1, pin2 = pin2, pin1
 98      pwm_write(pin1, 0)
 99      pwm_write(pin2, abs(int(frac*65535)))
100  
101  # signal is between 1 and 8, val is 0 or 1
102  def write_digital(signal, val):
103      pin_config(_SIGNALS[signal-1], 1, 0, val) # output, pullup, value
104  
105  # signal is between 1 and 8
106  def read_digital(signal):
107      pin = _SIGNALS[signal-1]
108      pin_config(pin, 0, 1, 1) # input, pullup, pullvalue
109      ret = _read(0x01, 0x04, 8)
110      b = 0
111      if pin > 32:
112          b = 4
113          pin -= 32
114      b += 3 - (pin // 8)
115      return (ret[b] & 1<<(pin % 8)) != 0