summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-06-20 10:56:05 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-06-20 10:56:05 -0700
commit30ee7019ca651bce1fe966c1089fe977d51dc92b (patch)
tree0114b6f744dd175b7722dd8edcbe24f4ee84bb45 /drivers
parent97fcdfbd08c922efd7470d6482d7c7c703ffc0ae (diff)
parent869cdcfdfc860b1177baf9b0f8818915ba54f3f5 (diff)
Merge tag 'v1.9.1'2.0.0-alpha.0
Fixes for stmhal USB mass storage, lwIP bindings and VFS regressions This release provides an important fix for the USB mass storage device in the stmhal port by implementing the SCSI SYNCHRONIZE_CACHE command, which is now require by some Operating Systems. There are also fixes for the lwIP bindings to improve non-blocking sockets and error codes. The VFS has some regressions fixed including the ability to statvfs the root. All changes are listed below. py core: - modbuiltins: add core-provided version of input() function - objstr: catch case of negative "maxsplit" arg to str.rsplit() - persistentcode: allow to compile with complex numbers disabled - objstr: allow to compile with obj-repr D, and unicode disabled - modsys: allow to compile with obj-repr D and PY_ATTRTUPLE disabled - provide mp_decode_uint_skip() to help reduce stack usage - makeqstrdefs.py: make script run correctly with Python 2.6 - objstringio: if created from immutable object, follow copy on write policy extmod: - modlwip: connect: for non-blocking mode, return EINPROGRESS - modlwip: fix error codes for duplicate calls to connect() - modlwip: accept: fix error code for non-blocking mode - vfs: allow to statvfs the root directory - vfs: allow "buffering" and "encoding" args to VFS's open() - modframebuf: fix signed/unsigned comparison pendantic warning lib: - libm: use isfinite instead of finitef, for C99 compatibility - utils/interrupt_char: remove support for KBD_EXCEPTION disabled tests: - basics/string_rsplit: add tests for negative "maxsplit" argument - float: convert "sys.exit()" to "raise SystemExit" - float/builtin_float_minmax: PEP8 fixes - basics: convert "sys.exit()" to "raise SystemExit" - convert remaining "sys.exit()" to "raise SystemExit" unix port: - convert to use core-provided version of built-in import() - Makefile: replace references to make with $(MAKE) windows port: - convert to use core-provided version of built-in import() qemu-arm port: - Makefile: adjust object-file lists to get correct dependencies - enable micropython.mem_*() functions to allow more tests stmhal port: - boards: enable DAC for NUCLEO_F767ZI board - add support for NUCLEO_F446RE board - pass USB handler as parameter to allow more than one USB handler - usb: use local USB handler variable in Start-of-Frame handler - usb: make state for USB device private to top-level USB driver - usbdev: for MSC implement SCSI SYNCHRONIZE_CACHE command - convert from using stmhal's input() to core provided version cc3200 port: - convert from using stmhal's input() to core provided version teensy port: - convert from using stmhal's input() to core provided version esp8266 port: - Makefile: replace references to make with $(MAKE) - Makefile: add clean-modules target - convert from using stmhal's input() to core provided version zephyr port: - modusocket: getaddrinfo: Fix mp_obj_len() usage - define MICROPY_PY_SYS_PLATFORM (to "zephyr") - machine_pin: use native Zephyr types for Zephyr API calls docs: - machine.Pin: remove out_value() method - machine.Pin: add on() and off() methods - esp8266: consistently replace Pin.high/low methods with .on/off - esp8266/quickref: polish Pin.on()/off() examples - network: move confusingly-named cc3200 Server class to its reference - uos: deconditionalize, remove minor port-specific details - uos: move cc3200 port legacy VFS mounting functions to its ref doc - machine: sort machine classes in logical order, not alphabetically - network: first step to describe standard network class interface examples: - embedding: use core-provided KeyboardInterrupt object
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dht/dht.c4
-rw-r--r--drivers/display/lcd160cr.py474
-rw-r--r--drivers/display/lcd160cr_test.py171
-rw-r--r--drivers/display/ssd1306.py161
-rw-r--r--drivers/memory/spiflash.c200
-rw-r--r--drivers/memory/spiflash.h42
-rw-r--r--drivers/nrf24l01/nrf24l01.py114
-rw-r--r--drivers/nrf24l01/nrf24l01test.py4
-rw-r--r--drivers/onewire/ds18x20.py6
-rw-r--r--drivers/sdcard/sdcard.py26
10 files changed, 1134 insertions, 68 deletions
diff --git a/drivers/dht/dht.c b/drivers/dht/dht.c
index 1f0cffc6f..6bdda44b4 100644
--- a/drivers/dht/dht.c
+++ b/drivers/dht/dht.c
@@ -65,7 +65,7 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
// time pulse, should be 80us
ticks = machine_time_pulse_us(pin, 1, 150);
- if (ticks == (mp_uint_t)-1) {
+ if ((mp_int_t)ticks < 0) {
goto timeout;
}
@@ -73,7 +73,7 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
uint8_t *buf = bufinfo.buf;
for (int i = 0; i < 40; ++i) {
ticks = machine_time_pulse_us(pin, 1, 100);
- if (ticks == (mp_uint_t)-1) {
+ if ((mp_int_t)ticks < 0) {
goto timeout;
}
buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48);
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
new file mode 100644
index 000000000..dd9ab9985
--- /dev/null
+++ b/drivers/display/lcd160cr.py
@@ -0,0 +1,474 @@
+# Driver for official MicroPython LCD160CR display
+# MIT license; Copyright (c) 2017 Damien P. George
+
+from micropython import const
+from utime import sleep_ms
+from ustruct import calcsize, pack_into
+import uerrno, machine
+
+# for set_orient
+PORTRAIT = const(0)
+LANDSCAPE = const(1)
+PORTRAIT_UPSIDEDOWN = const(2)
+LANDSCAPE_UPSIDEDOWN = const(3)
+
+# for set_startup_deco; can be or'd
+STARTUP_DECO_NONE = const(0)
+STARTUP_DECO_MLOGO = const(1)
+STARTUP_DECO_INFO = const(2)
+
+_uart_baud_table = {
+ 2400: 0,
+ 4800: 1,
+ 9600: 2,
+ 19200: 3,
+ 38400: 4,
+ 57600: 5,
+ 115200: 6,
+ 230400: 7,
+ 460800: 8,
+}
+
+class LCD160CR:
+ def __init__(self, connect=None, *, pwr=None, i2c=None, spi=None, i2c_addr=98):
+ if connect in ('X', 'Y', 'XY', 'YX'):
+ i = connect[-1]
+ j = connect[0]
+ y = j + '4'
+ elif connect == 'C':
+ i = 2
+ j = 2
+ y = 'A7'
+ else:
+ if pwr is None or i2c is None or spi is None:
+ raise ValueError('must specify valid "connect" or all of "pwr", "i2c" and "spi"')
+
+ if pwr is None:
+ pwr = machine.Pin(y, machine.Pin.OUT)
+ if i2c is None:
+ i2c = machine.I2C(i, freq=1000000)
+ if spi is None:
+ spi = machine.SPI(j, baudrate=13500000, polarity=0, phase=0)
+
+ if not pwr.value():
+ pwr(1)
+ sleep_ms(10)
+ # else:
+ # alread have power
+ # lets be optimistic...
+
+ # set connections
+ self.pwr = pwr
+ self.i2c = i2c
+ self.spi = spi
+ self.i2c_addr = i2c_addr
+
+ # create temp buffers and memoryviews
+ self.buf16 = bytearray(16)
+ self.buf19 = bytearray(19)
+ self.buf = [None] * 10
+ for i in range(1, 10):
+ self.buf[i] = memoryview(self.buf16)[0:i]
+ self.buf1 = self.buf[1]
+ self.array4 = [0, 0, 0, 0]
+
+ # set default orientation and window
+ self.set_orient(PORTRAIT)
+ self._fcmd2b('<BBBBBB', 0x76, 0, 0, self.w, self.h) # viewport 'v'
+ self._fcmd2b('<BBBBBB', 0x79, 0, 0, self.w, self.h) # window 'y'
+
+ def _send(self, cmd):
+ i = self.i2c.writeto(self.i2c_addr, cmd)
+ if i == len(cmd):
+ return
+ cmd = memoryview(cmd)
+ n = len(cmd)
+ while True:
+ i += self.i2c.writeto(self.i2c_addr, cmd[i:])
+ if i == n:
+ return
+ sleep_ms(10)
+
+ def _fcmd2(self, fmt, a0, a1=0, a2=0):
+ buf = self.buf[calcsize(fmt)]
+ pack_into(fmt, buf, 0, 2, a0, a1, a2)
+ self._send(buf)
+
+ def _fcmd2b(self, fmt, a0, a1, a2, a3, a4=0):
+ buf = self.buf[calcsize(fmt)]
+ pack_into(fmt, buf, 0, 2, a0, a1, a2, a3, a4)
+ self._send(buf)
+
+ def _waitfor(self, n, buf):
+ t = 5000
+ while t:
+ self.i2c.readfrom_into(self.i2c_addr, self.buf1)
+ if self.buf1[0] >= n:
+ self.i2c.readfrom_into(self.i2c_addr, buf)
+ return
+ t -= 1
+ sleep_ms(1)
+ raise OSError(uerrno.ETIMEDOUT)
+
+ def oflush(self, n=255):
+ t = 5000
+ while t:
+ self.i2c.readfrom_into(self.i2c_addr + 1, self.buf1)
+ r = self.buf1[0]
+ if r >= n:
+ return
+ t -= 1
+ machine.idle()
+ raise OSError(uerrno.ETIMEDOUT)
+
+ def iflush(self):
+ t = 5000
+ while t:
+ self.i2c.readfrom_into(self.i2c_addr, self.buf16)
+ if self.buf16[0] == 0:
+ return
+ t -= 1
+ sleep_ms(1)
+ raise OSError(uerrno.ETIMEDOUT)
+
+ #### MISC METHODS ####
+
+ @staticmethod
+ def rgb(r, g, b):
+ return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | (r >> 3)
+
+ @staticmethod
+ def clip_line(c, w, h):
+ while True:
+ ca = ce = 0
+ if c[1] < 0:
+ ca |= 8
+ elif c[1] > h:
+ ca |= 4
+ if c[0] < 0:
+ ca |= 1
+ elif c[0] > w:
+ ca |= 2
+ if c[3] < 0:
+ ce |= 8
+ elif c[3] > h:
+ ce |= 4
+ if c[2] < 0:
+ ce |= 1
+ elif c[2] > w:
+ ce |= 2
+ if ca & ce:
+ return False
+ elif ca | ce:
+ ca |= ce
+ if ca & 1:
+ if c[2] < c[0]:
+ c[0], c[2] = c[2], c[0]
+ c[1], c[3] = c[3], c[1]
+ c[1] += ((-c[0]) * (c[3] - c[1])) // (c[2] - c[0])
+ c[0] = 0
+ elif ca & 2:
+ if c[2] < c[0]:
+ c[0], c[2] = c[2], c[0]
+ c[1], c[3] = c[3], c[1]
+ c[3] += ((w - 1 - c[2]) * (c[3] - c[1])) // (c[2] - c[0])
+ c[2] = w - 1
+ elif ca & 4:
+ if c[0] == c[2]:
+ if c[1] >= h:
+ c[1] = h - 1
+ if c[3] >= h:
+ c[3] = h - 1
+ else:
+ if c[3] < c[1]:
+ c[0], c[2] = c[2], c[0]
+ c[1], c[3] = c[3], c[1]
+ c[2] += ((h - 1 - c[3]) * (c[2] - c[0])) // (c[3] - c[1])
+ c[3] = h - 1
+ else:
+ if c[0] == c[2]:
+ if c[1] < 0:
+ c[1] = 0
+ if c[3] < 0:
+ c[3] = 0
+ else:
+ if c[3] < c[1]:
+ c[0], c[2] = c[2], c[0]
+ c[1], c[3] = c[3], c[1]
+ c[0] += ((-c[1]) * (c[2] - c[0])) // (c[3] - c[1])
+ c[1] = 0
+ else:
+ return True
+
+ #### SETUP COMMANDS ####
+
+ def set_power(self, on):
+ self.pwr(on)
+ sleep_ms(15)
+
+ def set_orient(self, orient):
+ self._fcmd2('<BBB', 0x14, (orient & 3) + 4)
+ # update width and height variables
+ self.iflush()
+ self._send(b'\x02g0')
+ self._waitfor(4, self.buf[5])
+ self.w = self.buf[5][1]
+ self.h = self.buf[5][2]
+
+ def set_brightness(self, value):
+ self._fcmd2('<BBB', 0x16, value)
+
+ def set_i2c_addr(self, addr):
+ # 0x0e set i2c addr
+ if addr & 3:
+ raise ValueError('must specify mod 4 aligned address')
+ self._fcmd2('<BBW', 0x0e, 0x433249 | (addr << 24))
+
+ def set_uart_baudrate(self, baudrate):
+ try:
+ baudrate = _uart_baud_table[baudrate]
+ except KeyError:
+ raise ValueError('invalid baudrate')
+ self._fcmd2('<BBB', 0x18, baudrate)
+
+ def set_startup_deco(self, value):
+ self._fcmd2('<BBB', 0x19, value)
+
+ def save_to_flash(self):
+ self._send(b'\x02fn')
+
+ #### PIXEL ACCESS ####
+
+ def set_pixel(self, x, y, c):
+ self._fcmd2b('<BBBBH', 0x41, x, y, c)
+
+ def get_pixel(self, x, y):
+ self._fcmd2('<BBBB', 0x61, x, y)
+ t = 1000
+ while t:
+ self.i2c.readfrom_into(self.i2c_addr, self.buf1)
+ if self.buf1[0] >= 2:
+ self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
+ return self.buf[3][1] | self.buf[3][2] << 8
+ t -= 1
+ sleep_ms(1)
+ raise OSError(uerrno.ETIMEDOUT)
+
+ def get_line(self, x, y, buf):
+ l = len(buf) // 2
+ self._fcmd2b('<BBBBB', 0x10, l, x, y)
+ l *= 2
+ t = 1000
+ while t:
+ self.i2c.readfrom_into(self.i2c_addr, self.buf1)
+ if self.buf1[0] >= l:
+ self.i2c.readfrom_into(self.i2c_addr, buf)
+ return
+ t -= 1
+ sleep_ms(1)
+ raise OSError(uerrno.ETIMEDOUT)
+
+ def screen_dump(self, buf, x=0, y=0, w=None, h=None):
+ if w is None:
+ w = self.w - x
+ if h is None:
+ h = self.h - y
+ if w <= 127:
+ line = bytearray(2 * w + 1)
+ line2 = None
+ else:
+ # split line if more than 254 bytes needed
+ buflen = (w + 1) // 2
+ line = bytearray(2 * buflen + 1)
+ line2 = memoryview(line)[:2 * (w - buflen) + 1]
+ for i in range(min(len(buf) // (2 * w), h)):
+ ix = i * w * 2
+ self.get_line(x, y + i, line)
+ buf[ix:ix + len(line) - 1] = memoryview(line)[1:]
+ ix += len(line) - 1
+ if line2:
+ self.get_line(x + buflen, y + i, line2)
+ buf[ix:ix + len(line2) - 1] = memoryview(line2)[1:]
+ ix += len(line2) - 1
+
+ def screen_load(self, buf):
+ l = self.w * self.h * 2+2
+ self._fcmd2b('<BBHBBB', 0x70, l, 16, self.w, self.h)
+ n = 0
+ ar = memoryview(buf)
+ while n < len(buf):
+ if len(buf) - n >= 0x200:
+ self._send(ar[n:n + 0x200])
+ n += 0x200
+ else:
+ self._send(ar[n:])
+ while n < self.w * self.h * 2:
+ self._send(b'\x00')
+ n += 1
+
+ #### TEXT COMMANDS ####
+
+ def set_pos(self, x, y):
+ self._fcmd2('<BBBB', 0x58, x, y)
+
+ def set_text_color(self, fg, bg):
+ self._fcmd2('<BBHH', 0x63, fg, bg)
+
+ def set_font(self, font, scale=0, bold=0, trans=0, scroll=0):
+ self._fcmd2('<BBBB', 0x46, (scroll << 7) | (trans << 6) | ((font & 3) << 4) | (bold & 0xf), scale & 0xff)
+
+ def write(self, s):
+ # TODO: eventually check for room in LCD input queue
+ self._send(s)
+
+ #### PRIMITIVE DRAWING COMMANDS ####
+
+ def set_pen(self, line, fill):
+ self._fcmd2('<BBHH', 0x50, line, fill)
+
+ def erase(self):
+ self._send(b'\x02\x45')
+
+ def dot(self, x, y):
+ if 0 <= x < self.w and 0 <= y < self.h:
+ self._fcmd2('<BBBB', 0x4b, x, y)
+
+ def rect(self, x, y, w, h, cmd=0x72):
+ if x + w <= 0 or y + h <= 0 or x >= self.w or y >= self.h:
+ return
+ elif x < 0 or y < 0:
+ left = top = True
+ if x < 0:
+ left = False
+ w += x
+ x = 0
+ if y < 0:
+ top = False
+ h += y
+ y = 0
+ if cmd == 0x51 or cmd == 0x72:
+ # draw interior
+ self._fcmd2b('<BBBBBB', 0x51, x, y, min(w, 255), min(h, 255))
+ if cmd == 0x57 or cmd == 0x72:
+ # draw outline
+ if left:
+ self._fcmd2b('<BBBBBB', 0x57, x, y, 1, min(h, 255))
+ if top:
+ self._fcmd2b('<BBBBBB', 0x57, x, y, min(w, 255), 1)
+ if x + w < self.w:
+ self._fcmd2b('<BBBBBB', 0x57, x + w, y, 1, min(h, 255))
+ if y + h < self.h:
+ self._fcmd2b('<BBBBBB', 0x57, x, y + h, min(w, 255), 1)
+ else:
+ self._fcmd2b('<BBBBBB', cmd, x, y, min(w, 255), min(h, 255))
+
+ def rect_outline(self, x, y, w, h):
+ self.rect(x, y, w, h, 0x57)
+
+ def rect_interior(self, x, y, w, h):
+ self.rect(x, y, w, h, 0x51)
+
+ def line(self, x1, y1, x2, y2):
+ ar4 = self.array4
+ ar4[0] = x1
+ ar4[1] = y1
+ ar4[2] = x2
+ ar4[3] = y2
+ if self.clip_line(ar4, self.w, self.h):
+ self._fcmd2b('<BBBBBB', 0x4c, ar4[0], ar4[1], ar4[2], ar4[3])
+
+ def dot_no_clip(self, x, y):
+ self._fcmd2('<BBBB', 0x4b, x, y)
+
+ def rect_no_clip(self, x, y, w, h):
+ self._fcmd2b('<BBBBBB', 0x72, x, y, w, h)
+
+ def rect_outline_no_clip(self, x, y, w, h):
+ self._fcmd2b('<BBBBBB', 0x57, x, y, w, h)
+
+ def rect_interior_no_clip(self, x, y, w, h):
+ self._fcmd2b('<BBBBBB', 0x51, x, y, w, h)
+
+ def line_no_clip(self, x1, y1, x2, y2):
+ self._fcmd2b('<BBBBBB', 0x4c, x1, y1, x2, y2)
+
+ def poly_dot(self, data):
+ if len(data) & 1:
+ raise ValueError('must specify even number of bytes')
+ self._fcmd2('<BBB', 0x71, len(data) // 2)
+ self._send(data)
+
+ def poly_line(self, data):
+ if len(data) & 1:
+ raise ValueError('must specify even number of bytes')
+ self._fcmd2('<BBB', 0x78, len(data) // 2)
+ self._send(data)
+
+ #### TOUCH COMMANDS ####
+
+ def touch_config(self, calib=False, save=False, irq=None):
+ self._fcmd2('<BBBB', 0x7a, (irq is not None) << 2 | save << 1 | calib, bool(irq) << 7)
+
+ def is_touched(self):
+ self._send(b'\x02T')
+ b = self.buf[4]
+ self._waitfor(3, b)
+ return b[1] >> 7 != 0
+
+ def get_touch(self):
+ self._send(b'\x02T') # implicit LCD output flush
+ b = self.buf[4]
+ self._waitfor(3, b)
+ return b[1] >> 7, b[2], b[3]
+
+ #### ADVANCED COMMANDS ####
+
+ def set_spi_win(self, x, y, w, h):
+ pack_into('<BBBHHHHHHHH', self.buf19, 0, 2, 0x55, 10, x, y, x + w - 1, y + h - 1, 0, 0, 0, 0xffff)
+ self._send(self.buf19)
+
+ def fast_spi(self, flush=True):
+ if flush:
+ self.oflush()
+ self._send(b'\x02\x12')
+ return self.spi
+
+ def show_framebuf(self, buf):
+ self.fast_spi().write(buf)
+
+ def set_scroll(self, on):
+ self._fcmd2('<BBB', 0x15, on)
+
+ def set_scroll_win(self, win, x=-1, y=0, w=0, h=0, vec=0, pat=0, fill=0x07e0, color=0):
+ pack_into('<BBBHHHHHHHH', self.buf19, 0, 2, 0x55, win, x, y, w, h, vec, pat, fill, color)
+ self._send(self.buf19)
+
+ def set_scroll_win_param(self, win, param, value):
+ self._fcmd2b('<BBBBH', 0x75, win, param, value)
+
+ def set_scroll_buf(self, s):
+ l = len(s)
+ if l > 32:
+ raise ValueError('length must be 32 or less')
+ self._fcmd2('<BBB', 0x11, l)
+ self._send(s)
+
+ def jpeg_start(self, l):
+ if l > 0xffff:
+ raise ValueError('length must be 65535 or less')
+ self.oflush()
+ self._fcmd2('<BBH', 0x6a, l)
+
+ def jpeg_data(self, buf):
+ self._send(buf)
+
+ def jpeg(self, buf):
+ self.jpeg_start(len(buf))
+ self.jpeg_data(buf)
+
+ def feed_wdt(self):
+ self._send(b'\x02\x17')
+
+ def reset(self):
+ self._send(b'\x02Y\xef\xbe\xad\xde')
+ sleep_ms(15)
diff --git a/drivers/display/lcd160cr_test.py b/drivers/display/lcd160cr_test.py
new file mode 100644
index 000000000..8b7ef4555
--- /dev/null
+++ b/drivers/display/lcd160cr_test.py
@@ -0,0 +1,171 @@
+# Driver test for official MicroPython LCD160CR display
+# MIT license; Copyright (c) 2017 Damien P. George
+
+import time, math, framebuf, lcd160cr
+
+def get_lcd(lcd):
+ if type(lcd) is str:
+ lcd = lcd160cr.LCD160CR(lcd)
+ return lcd
+
+def show_adc(lcd, adc):
+ data = [adc.read_core_temp(), adc.read_core_vbat(), 3.3]
+ try:
+ data[2] = adc.read_vref()
+ except:
+ pass
+ for i in range(3):
+ lcd.set_text_color((825, 1625, 1600)[i], 0)
+ if lcd.h == 160:
+ lcd.set_font(2)
+ lcd.set_pos(0, 100 + i * 16)
+ else:
+ lcd.set_font(2, trans=1)
+ lcd.set_pos(0, lcd.h-60 + i * 16)
+ lcd.write('%4s: ' % ('TEMP', 'VBAT', 'VREF')[i])
+ if i > 0:
+ s = '%6.3fV' % data[i]
+ else:
+ s = '%5.1f°C' % data[i]
+ if lcd.h == 160:
+ lcd.set_font(1, bold=0, scale=1)
+ else:
+ lcd.set_font(1, bold=0, scale=1, trans=1)
+ lcd.set_pos(45, lcd.h-60 + i * 16)
+ lcd.write(s)
+
+def test_features(lcd, orient=lcd160cr.PORTRAIT):
+ # if we run on pyboard then use ADC and RTC features
+ try:
+ import pyb
+ adc = pyb.ADCAll(12, 0xf0000)
+ rtc = pyb.RTC()
+ except:
+ adc = None
+ rtc = None
+
+ # set orientation and clear screen
+ lcd = get_lcd(lcd)
+ lcd.set_orient(orient)
+ lcd.set_pen(0, 0)
+ lcd.erase()
+
+ # create M-logo
+ mlogo = framebuf.FrameBuffer(bytearray(17 * 17 * 2), 17, 17, framebuf.RGB565)
+ mlogo.fill(0)
+ mlogo.fill_rect(1, 1, 15, 15, 0xffffff)
+ mlogo.vline(4, 4, 12, 0)
+ mlogo.vline(8, 1, 12, 0)
+ mlogo.vline(12, 4, 12, 0)
+ mlogo.vline(14, 13, 2, 0)
+
+ # create inline framebuf
+ offx = 14
+ offy = 19
+ w = 100
+ h = 75
+ fbuf = framebuf.FrameBuffer(bytearray(w * h * 2), w, h, framebuf.RGB565)
+ lcd.set_spi_win(offx, offy, w, h)
+
+ # initialise loop parameters
+ tx = ty = 0
+ t0 = time.ticks_us()
+
+ for i in range(300):
+ # update position of cross-hair
+ t, tx2, ty2 = lcd.get_touch()
+ if t:
+ tx2 -= offx
+ ty2 -= offy
+ if tx2 >= 0 and ty2 >= 0 and tx2 < w and ty2 < h:
+ tx, ty = tx2, ty2
+ else:
+ tx = (tx + 1) % w
+ ty = (ty + 1) % h
+
+ # create and show the inline framebuf
+ fbuf.fill(lcd.rgb(128 + int(64 * math.cos(0.1 * i)), 128, 192))
+ fbuf.line(w // 2, h // 2,
+ w // 2 + int(40 * math.cos(0.2 * i)),
+ h // 2 + int(40 * math.sin(0.2 * i)),
+ lcd.rgb(128, 255, 64))
+ fbuf.hline(0, ty, w, lcd.rgb(64, 64, 64))
+ fbuf.vline(tx, 0, h, lcd.rgb(64, 64, 64))
+ fbuf.rect(tx - 3, ty - 3, 7, 7, lcd.rgb(64, 64, 64))
+ for phase in (-0.2, 0, 0.2):
+ x = w // 2 - 8 + int(50 * math.cos(0.05 * i + phase))
+ y = h // 2 - 8 + int(32 * math.sin(0.05 * i + phase))
+ fbuf.blit(mlogo, x, y)
+ for j in range(-3, 3):
+ fbuf.text('MicroPython',
+ 5, h // 2 + 9 * j + int(20 * math.sin(0.1 * (i + j))),
+ lcd.rgb(128 + 10 * j, 0, 128 - 10 * j))
+ lcd.show_framebuf(fbuf)
+
+ # show results from the ADC
+ if adc:
+ show_adc(lcd, adc)
+
+ # show the time
+ if rtc:
+ lcd.set_pos(2, 0)
+ lcd.set_font(1)
+ t = rtc.datetime()
+ lcd.write('%4d-%02d-%02d %2d:%02d:%02d.%01d' % (t[0], t[1], t[2], t[4], t[5], t[6], t[7] // 100000))
+
+ # compute the frame rate
+ t1 = time.ticks_us()
+ dt = time.ticks_diff(t1, t0)
+ t0 = t1
+
+ # show the frame rate
+ lcd.set_pos(2, 9)
+ lcd.write('%.2f fps' % (1000000 / dt))
+
+def test_mandel(lcd, orient=lcd160cr.PORTRAIT):
+ # set orientation and clear screen
+ lcd = get_lcd(lcd)
+ lcd.set_orient(orient)
+ lcd.set_pen(0, 0xffff)
+ lcd.erase()
+
+ # function to compute Mandelbrot pixels
+ def in_set(c):
+ z = 0
+ for i in range(32):
+ z = z * z + c
+ if abs(z) > 100:
+ return i
+ return 0
+
+ # cache width and height of LCD
+ w = lcd.w
+ h = lcd.h
+
+ # create the buffer for each line and set SPI parameters
+ line = bytearray(w * 2)
+ lcd.set_spi_win(0, 0, w, h)
+ spi = lcd.fast_spi()
+
+ # draw the Mandelbrot set line-by-line
+ hh = ((h - 1) / 3.2)
+ ww = ((w - 1) / 2.4)
+ for v in range(h):
+ for u in range(w):
+ c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
+ if c < 16:
+ rgb = c << 12 | c << 6
+ else:
+ rgb = 0xf800 | c << 6
+ line[2 * u] = rgb
+ line[2 * u + 1] = rgb >> 8
+ spi.write(line)
+
+def test_all(lcd, orient=lcd160cr.PORTRAIT):
+ lcd = get_lcd(lcd)
+ test_features(lcd, orient)
+ test_mandel(lcd, orient)
+
+print('To run all tests: test_all(<lcd>)')
+print('Individual tests are: test_features, test_mandel')
+print('<lcd> argument should be a connection, eg "X", or an LCD160CR object')
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
new file mode 100644
index 000000000..53bcb0d2d
--- /dev/null
+++ b/drivers/display/ssd1306.py
@@ -0,0 +1,161 @@
+# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
+
+from micropython import const
+import time
+import framebuf
+
+
+# register definitions
+SET_CONTRAST = const(0x81)
+SET_ENTIRE_ON = const(0xa4)
+SET_NORM_INV = const(0xa6)
+SET_DISP = const(0xae)
+SET_MEM_ADDR = const(0x20)
+SET_COL_ADDR = const(0x21)
+SET_PAGE_ADDR = const(0x22)
+SET_DISP_START_LINE = const(0x40)
+SET_SEG_REMAP = const(0xa0)
+SET_MUX_RATIO = const(0xa8)
+SET_COM_OUT_DIR = const(0xc0)
+SET_DISP_OFFSET = const(0xd3)
+SET_COM_PIN_CFG = const(0xda)
+SET_DISP_CLK_DIV = const(0xd5)
+SET_PRECHARGE = const(0xd9)
+SET_VCOM_DESEL = const(0xdb)
+SET_CHARGE_PUMP = const(0x8d)
+
+
+class SSD1306:
+ def __init__(self, width, height, external_vcc):
+ self.width = width
+ self.height = height
+ self.external_vcc = external_vcc
+ self.pages = self.height // 8
+ self.buffer = bytearray(self.pages * self.width)
+ self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MVLSB)
+ self.poweron()
+ self.init_display()
+
+ def init_display(self):
+ for cmd in (
+ SET_DISP | 0x00, # off
+ # address setting
+ SET_MEM_ADDR, 0x00, # horizontal
+ # resolution and layout
+ SET_DISP_START_LINE | 0x00,
+ SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
+ SET_MUX_RATIO, self.height - 1,
+ SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
+ SET_DISP_OFFSET, 0x00,
+ SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
+ # timing and driving scheme
+ SET_DISP_CLK_DIV, 0x80,
+ SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
+ SET_VCOM_DESEL, 0x30, # 0.83*Vcc
+ # display
+ SET_CONTRAST, 0xff, # maximum
+ SET_ENTIRE_ON, # output follows RAM contents
+ SET_NORM_INV, # not inverted
+ # charge pump
+ SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
+ SET_DISP | 0x01): # on
+ self.write_cmd(cmd)
+ self.fill(0)
+ self.show()
+
+ def poweroff(self):
+ self.write_cmd(SET_DISP | 0x00)
+
+ def contrast(self, contrast):
+ self.write_cmd(SET_CONTRAST)
+ self.write_cmd(contrast)
+
+ def invert(self, invert):
+ self.write_cmd(SET_NORM_INV | (invert & 1))
+
+ def show(self):
+ x0 = 0
+ x1 = self.width - 1
+ if self.width == 64:
+ # displays with width of 64 pixels are shifted by 32
+ x0 += 32
+ x1 += 32
+ self.write_cmd(SET_COL_ADDR)
+ self.write_cmd(x0)
+ self.write_cmd(x1)
+ self.write_cmd(SET_PAGE_ADDR)
+ self.write_cmd(0)
+ self.write_cmd(self.pages - 1)
+ self.write_data(self.buffer)
+
+ def fill(self, col):
+ self.framebuf.fill(col)
+
+ def pixel(self, x, y, col):
+ self.framebuf.pixel(x, y, col)
+
+ def scroll(self, dx, dy):
+ self.framebuf.scroll(dx, dy)
+
+ def text(self, string, x, y, col=1):
+ self.framebuf.text(string, x, y, col)
+
+
+class SSD1306_I2C(SSD1306):
+ def __init__(self, width, height, i2c, addr=0x3c, external_vcc=False):
+ self.i2c = i2c
+ self.addr = addr
+ self.temp = bytearray(2)
+ super().__init__(width, height, external_vcc)
+
+ def write_cmd(self, cmd):
+ self.temp[0] = 0x80 # Co=1, D/C#=0
+ self.temp[1] = cmd
+ self.i2c.writeto(self.addr, self.temp)
+
+ def write_data(self, buf):
+ self.temp[0] = self.addr << 1
+ self.temp[1] = 0x40 # Co=0, D/C#=1
+ self.i2c.start()
+ self.i2c.write(self.temp)
+ self.i2c.write(buf)
+ self.i2c.stop()
+
+ def poweron(self):
+ pass
+
+
+class SSD1306_SPI(SSD1306):
+ def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
+ self.rate = 10 * 1024 * 1024
+ dc.init(dc.OUT, value=0)
+ res.init(res.OUT, value=0)
+ cs.init(cs.OUT, value=1)
+ self.spi = spi
+ self.dc = dc
+ self.res = res
+ self.cs = cs
+ super().__init__(width, height, external_vcc)
+
+ def write_cmd(self, cmd):
+ self.spi.init(baudrate=self.rate, polarity=0, phase=0)
+ self.cs(1)
+ self.dc(0)
+ self.cs(0)
+ self.spi.write(bytearray([cmd]))
+ self.cs(1)
+
+ def write_data(self, buf):
+ self.spi.init(baudrate=self.rate, polarity=0, phase=0)
+ self.cs(1)
+ self.dc(1)
+ self.cs(0)
+ self.spi.write(buf)
+ self.cs(1)
+
+ def poweron(self):
+ self.res(1)
+ time.sleep_ms(1)
+ self.res(0)
+ time.sleep_ms(10)
+ self.res(1)
diff --git a/drivers/memory/spiflash.c b/drivers/memory/spiflash.c
new file mode 100644
index 000000000..214610e0a
--- /dev/null
+++ b/drivers/memory/spiflash.c
@@ -0,0 +1,200 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016-2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "py/mperrno.h"
+#include "py/mphal.h"
+#include "extmod/machine_spi.h"
+#include "drivers/memory/spiflash.h"
+
+#define CMD_WRITE (0x02)
+#define CMD_READ (0x03)
+#define CMD_WRDI (0x04)
+#define CMD_RDSR (0x05)
+#define CMD_WREN (0x06)
+#define CMD_SEC_ERASE (0x20)
+#define WAIT_SR_TIMEOUT (1000000)
+
+#define PAGE_SIZE (256) // maximum bytes we can write in one SPI transfer
+#define SECTOR_SIZE (4096) // size of erase sector
+
+// Note: this code is not reentrant with this shared buffer
+STATIC uint8_t buf[SECTOR_SIZE];
+
+void mp_spiflash_init(mp_spiflash_t *self) {
+ mp_hal_pin_write(self->cs, 1);
+ mp_hal_pin_output(self->cs);
+ mp_hal_pin_write(self->spi.sck, 0);
+ mp_hal_pin_output(self->spi.sck);
+ mp_hal_pin_output(self->spi.mosi);
+ mp_hal_pin_input(self->spi.miso);
+}
+
+STATIC void mp_spiflash_acquire_bus(mp_spiflash_t *self) {
+ // can be used for actions needed to acquire bus
+ (void)self;
+}
+
+STATIC void mp_spiflash_release_bus(mp_spiflash_t *self) {
+ // can be used for actions needed to release bus
+ (void)self;
+}
+
+STATIC void mp_spiflash_transfer(mp_spiflash_t *self, size_t len, const uint8_t *src, uint8_t *dest) {
+ mp_machine_soft_spi_transfer(&self->spi.base, len, src, dest);
+}
+
+STATIC int mp_spiflash_wait_sr(mp_spiflash_t *self, uint8_t mask, uint8_t val, uint32_t timeout) {
+ uint8_t cmd[1] = {CMD_RDSR};
+ mp_hal_pin_write(self->cs, 0);
+ mp_spiflash_transfer(self, 1, cmd, NULL);
+ for (; timeout; --timeout) {
+ mp_spiflash_transfer(self, 1, cmd, cmd);
+ if ((cmd[0] & mask) == val) {
+ break;
+ }
+ }
+ mp_hal_pin_write(self->cs, 1);
+ if ((cmd[0] & mask) == val) {
+ return 0; // success
+ } else if (timeout == 0) {
+ return -MP_ETIMEDOUT;
+ } else {
+ return -MP_EIO;
+ }
+}
+
+STATIC int mp_spiflash_wait_wel1(mp_spiflash_t *self) {
+ return mp_spiflash_wait_sr(self, 2, 2, WAIT_SR_TIMEOUT);
+}
+
+STATIC int mp_spiflash_wait_wip0(mp_spiflash_t *self) {
+ return mp_spiflash_wait_sr(self, 1, 0, WAIT_SR_TIMEOUT);
+}
+
+STATIC void mp_spiflash_write_cmd(mp_spiflash_t *self, uint8_t cmd) {
+ mp_hal_pin_write(self->cs, 0);
+ mp_spiflash_transfer(self, 1, &cmd, NULL);
+ mp_hal_pin_write(self->cs, 1);
+}
+
+STATIC int mp_spiflash_erase_sector(mp_spiflash_t *self, uint32_t addr) {
+ // enable writes
+ mp_spiflash_write_cmd(self, CMD_WREN);
+
+ // wait WEL=1
+ int ret = mp_spiflash_wait_wel1(self);
+ if (ret != 0) {
+ return ret;
+ }
+
+ // erase the sector
+ mp_hal_pin_write(self->cs, 0);
+ uint8_t cmd[4] = {CMD_SEC_ERASE, addr >> 16, addr >> 8, addr};
+ mp_spiflash_transfer(self, 4, cmd, NULL);
+ mp_hal_pin_write(self->cs, 1);
+
+ // wait WIP=0
+ return mp_spiflash_wait_wip0(self);
+}
+
+STATIC int mp_spiflash_write_page(mp_spiflash_t *self, uint32_t addr, const uint8_t *src) {
+ // enable writes
+ mp_spiflash_write_cmd(self, CMD_WREN);
+
+ // wait WEL=1
+ int ret = mp_spiflash_wait_wel1(self);
+ if (ret != 0) {
+ return ret;
+ }
+
+ // write the page
+ mp_hal_pin_write(self->cs, 0);
+ uint8_t cmd[4] = {CMD_WRITE, addr >> 16, addr >> 8, addr};
+ mp_spiflash_transfer(self, 4, cmd, NULL);
+ mp_spiflash_transfer(self, PAGE_SIZE, src, NULL);
+ mp_hal_pin_write(self->cs, 1);
+
+ // wait WIP=0
+ return mp_spiflash_wait_wip0(self);
+}
+
+void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest) {
+ mp_spiflash_acquire_bus(self);
+ uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr};
+ mp_hal_pin_write(self->cs, 0);
+ mp_spiflash_transfer(self, 4, cmd, NULL);
+ mp_spiflash_transfer(self, len, dest, dest);
+ mp_hal_pin_write(self->cs, 1);
+ mp_spiflash_release_bus(self);
+}
+
+int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src) {
+ // TODO optimise so we don't need to erase multiple times for successive writes to a sector
+
+ // align to 4096 sector
+ uint32_t offset = addr & 0xfff;
+ addr = (addr >> 12) << 12;
+
+ // restriction for now, so we don't need to erase multiple pages
+ if (offset + len > sizeof(buf)) {
+ printf("mp_spiflash_write: len is too large\n");
+ return -MP_EIO;
+ }
+
+ mp_spiflash_acquire_bus(self);
+
+ // read sector
+ uint8_t cmd[4] = {CMD_READ, addr >> 16, addr >> 8, addr};
+ mp_hal_pin_write(self->cs, 0);
+ mp_spiflash_transfer(self, 4, cmd, NULL);
+ mp_spiflash_transfer(self, SECTOR_SIZE, buf, buf);
+ mp_hal_pin_write(self->cs, 1);
+
+ // erase sector
+ int ret = mp_spiflash_erase_sector(self, addr);
+ if (ret != 0) {
+ mp_spiflash_release_bus(self);
+ return ret;
+ }
+
+ // copy new block into buffer
+ memcpy(buf + offset, src, len);
+
+ // write sector in pages of 256 bytes
+ for (int i = 0; i < SECTOR_SIZE; i += 256) {
+ ret = mp_spiflash_write_page(self, addr + i, buf + i);
+ if (ret != 0) {
+ mp_spiflash_release_bus(self);
+ return ret;
+ }
+ }
+
+ mp_spiflash_release_bus(self);
+ return 0; // success
+}
diff --git a/drivers/memory/spiflash.h b/drivers/memory/spiflash.h
new file mode 100644
index 000000000..d2e817450
--- /dev/null
+++ b/drivers/memory/spiflash.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H
+#define MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H
+
+#include "extmod/machine_spi.h"
+
+typedef struct _mp_spiflash_t {
+ mp_hal_pin_obj_t cs;
+ // TODO replace with generic SPI object
+ mp_machine_soft_spi_obj_t spi;
+} mp_spiflash_t;
+
+void mp_spiflash_init(mp_spiflash_t *self);
+void mp_spiflash_read(mp_spiflash_t *self, uint32_t addr, size_t len, uint8_t *dest);
+int mp_spiflash_write(mp_spiflash_t *self, uint32_t addr, size_t len, const uint8_t *src);
+
+#endif // MICROPY_INCLUDED_DRIVERS_MEMORY_SPIFLASH_H
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
index 3c79650bf..b45c137c6 100644
--- a/drivers/nrf24l01/nrf24l01.py
+++ b/drivers/nrf24l01/nrf24l01.py
@@ -2,7 +2,7 @@
"""
from micropython import const
-import pyb
+import utime
# nRF24L01+ registers
CONFIG = const(0x00)
@@ -53,22 +53,24 @@ class NRF24L01:
def __init__(self, spi, cs, ce, channel=46, payload_size=16):
assert payload_size <= 32
- # init the SPI bus and pins
- spi.init(spi.MASTER, baudrate=4000000, polarity=0, phase=0, firstbit=spi.MSB)
- cs.init(cs.OUT_PP, cs.PULL_NONE)
- ce.init(ce.OUT_PP, ce.PULL_NONE)
+ self.buf = bytearray(1)
# store the pins
self.spi = spi
self.cs = cs
self.ce = ce
+ # init the SPI bus and pins
+ self.init_spi(4000000)
+ cs.init(cs.OUT, value=1)
+ ce.init(ce.OUT, value=0)
+
# reset everything
- self.ce.low()
- self.cs.high()
+ self.ce(0)
+ self.cs(1)
self.payload_size = payload_size
self.pipe0_read_addr = None
- pyb.delay(5)
+ utime.sleep_ms(5)
# set address width to 5 bytes and check for device present
self.reg_write(SETUP_AW, 0b11)
@@ -98,29 +100,45 @@ class NRF24L01:
self.flush_rx()
self.flush_tx()
+ def init_spi(self, baudrate):
+ try:
+ master = self.spi.MASTER
+ except AttributeError:
+ self.spi.init(baudrate=baudrate, polarity=0, phase=0)
+ else:
+ self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
+
def reg_read(self, reg):
- self.cs.low()
- self.spi.send_recv(reg)
- buf = self.spi.recv(1)
- self.cs.high()
- return buf[0]
-
- def reg_write(self, reg, buf):
- self.cs.low()
- status = self.spi.send_recv(0x20 | reg)[0]
- self.spi.send(buf)
- self.cs.high()
- return status
+ self.cs(0)
+ self.spi.readinto(self.buf, reg)
+ self.spi.readinto(self.buf)
+ self.cs(1)
+ return self.buf[0]
+
+ def reg_write_bytes(self, reg, buf):
+ self.cs(0)
+ self.spi.readinto(self.buf, 0x20 | reg)
+ self.spi.write(buf)
+ self.cs(1)
+ return self.buf[0]
+
+ def reg_write(self, reg, value):
+ self.cs(0)
+ self.spi.readinto(self.buf, 0x20 | reg)
+ ret = self.buf[0]
+ self.spi.readinto(self.buf, value)
+ self.cs(1)
+ return ret
def flush_rx(self):
- self.cs.low()
- self.spi.send(FLUSH_RX)
- self.cs.high()
+ self.cs(0)
+ self.spi.readinto(self.buf, FLUSH_RX)
+ self.cs(1)
def flush_tx(self):
- self.cs.low()
- self.spi.send(FLUSH_TX)
- self.cs.high()
+ self.cs(0)
+ self.spi.readinto(self.buf, FLUSH_TX)
+ self.cs(1)
# power is one of POWER_x defines; speed is one of SPEED_x defines
def set_power_speed(self, power, speed):
@@ -144,8 +162,8 @@ class NRF24L01:
# address should be a bytes object 5 bytes long
def open_tx_pipe(self, address):
assert len(address) == 5
- self.reg_write(RX_ADDR_P0, address)
- self.reg_write(TX_ADDR, address)
+ self.reg_write_bytes(RX_ADDR_P0, address)
+ self.reg_write_bytes(TX_ADDR, address)
self.reg_write(RX_PW_P0, self.payload_size)
# address should be a bytes object 5 bytes long
@@ -157,7 +175,7 @@ class NRF24L01:
if pipe_id == 0:
self.pipe0_read_addr = address
if pipe_id < 2:
- self.reg_write(RX_ADDR_P0 + pipe_id, address)
+ self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
else:
self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
@@ -168,15 +186,15 @@ class NRF24L01:
self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
if self.pipe0_read_addr is not None:
- self.reg_write(RX_ADDR_P0, self.pipe0_read_addr)
+ self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
self.flush_rx()
self.flush_tx()
- self.ce.high()
- pyb.udelay(130)
+ self.ce(1)
+ utime.sleep_us(130)
def stop_listening(self):
- self.ce.low()
+ self.ce(0)
self.flush_tx()
self.flush_rx()
@@ -186,10 +204,10 @@ class NRF24L01:
def recv(self):
# get the data
- self.cs.low()
- self.spi.send(R_RX_PAYLOAD)
- buf = self.spi.recv(self.payload_size)
- self.cs.high()
+ self.cs(0)
+ self.spi.readinto(self.buf, R_RX_PAYLOAD)
+ buf = self.spi.read(self.payload_size)
+ self.cs(1)
# clear RX ready flag
self.reg_write(STATUS, RX_DR)
@@ -198,9 +216,9 @@ class NRF24L01:
# blocking wait for tx complete
def send(self, buf, timeout=500):
send_nonblock = self.send_start(buf)
- start = pyb.millis()
+ start = utime.ticks_ms()
result = None
- while result is None and pyb.elapsed_millis(start) < timeout:
+ while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
result = self.send_done() # 1 == success, 2 == fail
if result == 2:
raise OSError("send failed")
@@ -209,19 +227,19 @@ class NRF24L01:
def send_start(self, buf):
# power up
self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
- pyb.udelay(150)
+ utime.sleep_us(150)
# send the data
- self.cs.low()
- self.spi.send(W_TX_PAYLOAD)
- self.spi.send(buf)
+ self.cs(0)
+ self.spi.readinto(self.buf, W_TX_PAYLOAD)
+ self.spi.write(buf)
if len(buf) < self.payload_size:
- self.spi.send(b'\x00' * (self.payload_size - len(buf))) # pad out data
- self.cs.high()
+ self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data
+ self.cs(1)
# enable the chip so it can send the data
- self.ce.high()
- pyb.udelay(15) # needs to be >10us
- self.ce.low()
+ self.ce(1)
+ utime.sleep_us(15) # needs to be >10us
+ self.ce(0)
# returns None if send still in progress, 1 for success, 2 for fail
def send_done(self):
diff --git a/drivers/nrf24l01/nrf24l01test.py b/drivers/nrf24l01/nrf24l01test.py
index 264bc21c8..a25194d38 100644
--- a/drivers/nrf24l01/nrf24l01test.py
+++ b/drivers/nrf24l01/nrf24l01test.py
@@ -43,7 +43,7 @@ def master():
timeout = True
if timeout:
- print('failed, respones timed out')
+ print('failed, response timed out')
num_failures += 1
else:
@@ -57,7 +57,7 @@ def master():
# delay then loop
pyb.delay(250)
- print('master finished sending; succeses=%d, failures=%d' % (num_successes, num_failures))
+ print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures))
def slave():
nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8)
diff --git a/drivers/onewire/ds18x20.py b/drivers/onewire/ds18x20.py
index 342f4b28a..72adcbfd4 100644
--- a/drivers/onewire/ds18x20.py
+++ b/drivers/onewire/ds18x20.py
@@ -7,11 +7,11 @@ temperature sensors. It supports multiple devices on the same 1-wire bus.
The following example assumes the ground of your DS18x20 is connected to
Y11, vcc is connected to Y9 and the data pin is connected to Y10.
->>> from pyb import Pin
+>>> from machine import Pin
>>> gnd = Pin('Y11', Pin.OUT_PP)
->>> gnd.low()
+>>> gnd.off()
>>> vcc = Pin('Y9', Pin.OUT_PP)
->>> vcc.high()
+>>> vcc.on()
>>> from ds18x20 import DS18X20
>>> d = DS18X20(Pin('Y10'))
diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
index 191630aeb..e749d5376 100644
--- a/drivers/sdcard/sdcard.py
+++ b/drivers/sdcard/sdcard.py
@@ -130,7 +130,7 @@ class SDCard:
raise OSError("timeout waiting for v2 card")
def cmd(self, cmd, arg, crc, final=0, release=True):
- self.cs.low()
+ self.cs(0)
# create and send the command
buf = self.cmdbuf
@@ -142,7 +142,7 @@ class SDCard:
buf[5] = crc
self.spi.write(buf)
- # wait for the repsonse (response[7] == 0)
+ # wait for the response (response[7] == 0)
for i in range(_CMD_TIMEOUT):
response = self.spi.read(1, 0xff)[0]
if not (response & 0x80):
@@ -150,12 +150,12 @@ class SDCard:
for j in range(final):
self.spi.write(b'\xff')
if release:
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
return response
# timeout
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
return -1
@@ -164,15 +164,15 @@ class SDCard:
self.spi.read(1, 0xff) # ignore stuff byte
for _ in range(_CMD_TIMEOUT):
if self.spi.read(1, 0xff)[0] == 0xff:
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
return 0 # OK
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
return 1 # timeout
def readinto(self, buf):
- self.cs.low()
+ self.cs(0)
# read until start byte (0xff)
while self.spi.read(1, 0xff)[0] != 0xfe:
@@ -186,11 +186,11 @@ class SDCard:
self.spi.write(b'\xff')
self.spi.write(b'\xff')
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
def write(self, token, buf):
- self.cs.low()
+ self.cs(0)
# send: start of block, data, checksum
self.spi.read(1, token)
@@ -200,7 +200,7 @@ class SDCard:
# check the response
if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
return
@@ -208,18 +208,18 @@ class SDCard:
while self.spi.read(1, 0xff)[0] == 0:
pass
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
def write_token(self, token):
- self.cs.low()
+ self.cs(0)
self.spi.read(1, token)
self.spi.write(b'\xff')
# wait for write to finish
while self.spi.read(1, 0xff)[0] == 0x00:
pass
- self.cs.high()
+ self.cs(1)
self.spi.write(b'\xff')
def count(self):