summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
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):