Merge branch 'master' into micropython

master
Zvonimir Haramustek 2022-02-10 11:24:01 +01:00 committed by GitHub
commit 01b0d1cd54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 872 additions and 438 deletions

View File

@ -0,0 +1,30 @@
from inkplate6_COLOR import Inkplate
from image import *
import time
display = Inkplate()
if __name__ == "__main__":
# Must be called before using, line in Arduino
display.begin()
for r in range(4):
# Sets the screen rotation
display.setRotation(r)
# All drawing functions
display.drawPixel(100, 100, display.BLACK)
display.drawRect(50, 50, 75, 75, display.GREEN)
display.drawCircle(200, 200, 30, display.BLUE)
display.fillCircle(300, 300, 30, display.BLACK)
display.drawFastHLine(20, 100, 50, display.BLACK)
display.drawFastVLine(100, 20, 50, display.ORANGE)
display.drawLine(100, 100, 400, 400, display.ORANGE)
display.drawRoundRect(100, 10, 100, 100, 10, display.BLACK)
display.fillRoundRect(10, 100, 100, 100, 10, display.YELLOW)
display.drawTriangle(300, 100, 400, 150, 400, 100, display.BLACK)
# Draws image from bytearray
display.setRotation(0)
display.drawBitmap(10, 160, image, 576, 100, display.BLUE)
display.display()

View File

@ -0,0 +1,62 @@
import network
import time
from inkplate6_COLOR import Inkplate
ssid = "e-radionica.com"
password = "croduino"
# More info here: https://docs.micropython.org/en/latest/esp8266/tutorial/network_basics.html
def do_connect():
import network
sta_if = network.WLAN(network.STA_IF)
if not sta_if.isconnected():
print("connecting to network...")
sta_if.active(True)
sta_if.connect(ssid, password)
while not sta_if.isconnected():
pass
print("network config:", sta_if.ifconfig())
# More info here: https://docs.micropython.org/en/latest/esp8266/tutorial/network_tcp.html
def http_get(url):
import socket
res = ""
_, _, host, path = url.split("/", 3)
addr = socket.getaddrinfo(host, 80)[0][-1]
s = socket.socket()
s.connect(addr)
s.send(bytes("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (path, host), "utf8"))
while True:
data = s.recv(100)
if data:
res += str(data, "utf8")
else:
break
s.close()
return res
# Calling functions defined above
do_connect()
response = http_get("http://micropython.org/ks/test.html")
# Initialise our Inkplate object
display = Inkplate()
display.begin()
# Print response in lines
cnt = 0
for x in response.split("\n"):
display.printText(
10, 10 + cnt, x.upper()
) # Default font has only upper case letters
cnt += 10
# Display image from buffer
display.display()

View File

@ -0,0 +1,15 @@
import os
import time
from inkplate6_COLOR import Inkplate
display = Inkplate()
display.begin()
# This prints all the files on card
print(os.listdir("/sd"))
f = open("sd/text.txt", "r")
# Print file contents
print(f.read())
f.close()

View File

@ -0,0 +1,55 @@
from inkplate6_COLOR import Inkplate
from image import *
display = Inkplate()
circle_x = 300
circle_y = 200
circle_r = 40
# main function used by micropython
if __name__ == "__main__":
display.begin()
# function to show text at the top of the screen
# need to be called every time we clear display
def topText():
display.setTextSize(2)
display.printText(
0, 10, "TOUCHPADS EXAMPLE! 1, 3 TO MOVE CIRCLE, 2 TO RESET")
topText()
# Touchpads definitions
touch1, touch2, touch3 = display.TOUCH1, display.TOUCH2, display.TOUCH3
# draw initial circle for touchpad demonstration
display.drawCircle(circle_x, circle_y, circle_r, display.BLACK)
display.display()
# Main loop that will run forever or until battery is dead
while True:
# check if touchpad is pressed
if touch1():
circle_x -= 40
display.clearDisplay()
topText()
display.drawCircle(circle_x, circle_y, circle_r, display.BLACK)
display.display()
if touch3():
circle_x += 40
display.clearDisplay()
topText()
display.drawCircle(circle_x, circle_y, circle_r, display.BLACK)
display.display()
if touch2():
circle_x = 300
circle_y = 200
circle_r = 40
display.clearDisplay()
topText()
display.drawCircle(circle_x, circle_y, circle_r, display.BLACK)
display.display()

View File

@ -30,26 +30,27 @@ Original effort done by [tve](https://github.com/tve/micropython-inkplate6).
to erase esp32 flash and then
```
//Linux/Mac
esptool.py --chip esp32 --port /dev/cu.usbserial-1420 write_flash -z 0x1000 esp32spiram-20210902-v1.17.bin
esptool.py --chip esp32 --port /dev/cu.usbserial-1420 write_flash -z 0x1000 esp32spiram-20220117-v1.18.bin
//Windows
esptool.py --chip esp32 --port COM5 write_flash -z 0x1000 esp32spiram-20210902-v1.17.bin
esptool.py --chip esp32 --port COM5 write_flash -z 0x1000 esp32spiram-20220117-v1.18.bin
```
to flash supplied firmware. Use esp flash from this repository since it's tested with Inkplate.
If you don't have esptool.py installed, install it from here: https://github.com/espressif/esptool, at minimum use version 1.15.
- Copy library files to your board, use inkplate6.py or inkplate10.py for respective versions, something like this:
```
//Linux/Mac
python3 pyboard.py --device /dev/ttyUSB0 -f cp mcp23017.py sdcard.py inkplate6.py image.py shapes.py gfx.py gfx_standard_font_01.py :
- Copy library files to your board, use inkplate6.py or inkplate10.py for respective versions, something like this:
```
//Linux/Mac
python3 pyboard.py --device /dev/ttyUSB0 -f cp mcp23017.py inkplate6.py image.py shapes.py gfx.py gfx_standard_font_01.py :
//Windows
//This one might need to be started twice
python pyboard.py --device COM5 -f cp inkplate6.py gfx.py gfx_standard_font_01.py mcp23017.py image.py shapes.py sdcard.py :
```
(You can find `pyboard.py` in the MicroPython tools directory or just download it from
GitHub: https://raw.githubusercontent.com/micropython/micropython/master/tools/pyboard.py)
//Windows
//This one might need to be started twice
python pyboard.py --device COM5 -f cp inkplate6.py gfx.py gfx_standard_font_01.py mcp23017.py image.py shapes.py :
```
(You can find `pyboard.py` in the MicroPython tools directory or just download it from
GitHub: https://raw.githubusercontent.com/micropython/micropython/master/tools/pyboard.py)
- Run `example.py`:
```

View File

@ -1,40 +0,0 @@
device ports can vary from device to device and from different ports device is connected to.
inkplate6.py and inkplate10.py are used for respective boards
erase linux/mac:
esptool.py --port /dev/cu.usbserial-1420 erase_flash
erase win:
esptool.py --port COM5 erase_flash
flash linux/mac:
esptool.py --chip esp32 --port /dev/cu.usbserial-1420 write_flash -z 0x1000 esp32spiram-20210418-v1.15.bin
flash win:
esptool.py --chip esp32 --port COM5 write_flash -z 0x1000 esp32spiram-20210418-v1.15.bin
copy all linux/mac:
python3 pyboard.py --device /dev/cu.usbserial-1420 -f cp inkplate6.py gfx.py gfx_standard_font_01.py mcp23017.py image.py shapes.py sdcard.py :
This one might need to be started twice
copy all win:
python pyboard.py --device COM5 -f cp inkplate6.py gfx.py gfx_standard_font_01.py mcp23017.py image.py shapes.py sdcard.py :
run linux/mac:
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/basicBW.py
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/basicGrayscale.py
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/exampleNetwork.py
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/exampleSd.py
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/batteryAndTemperatureRead.py
python3 pyboard.py --device /dev/cu.usbserial-1420 Examples/Inkplate6/touchpads.py
run win:
python pyboard.py --device COM5 "Examples/Inkplate6/basicBW.py"
python pyboard.py --device COM5 "Examples/Inkplate6/basicGrayscale.py"
python pyboard.py --device COM5 "Examples/Inkplate6/exampleNetwork.py"
python pyboard.py --device COM5 "Examples/Inkplate6/exampleSd.py"
python pyboard.py --device COM5 "Examples/Inkplate 6/batteryAndTemperatureRead.py"
python pyboard.py --device COM5 "Examples/Inkplate 6/touchpads.py"

Binary file not shown.

29
gfx.py
View File

@ -36,6 +36,8 @@ __version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_GFX.git"
# pylint: disable=invalid-name
class GFX:
# pylint: disable=too-many-instance-attributes
"""Create an instance of the GFX drawing class.
@ -59,6 +61,7 @@ class GFX:
The input shoudl be a properly formatted dict.
"""
# pylint: disable=too-many-arguments
def __init__(
self,
width,
@ -242,9 +245,8 @@ class GFX:
self.line(x2, y2, x0, y0, *args, **kwargs)
def fill_triangle(self, x0, y0, x1, y1, x2, y2, *args, **kwargs):
# pylint: disable=too-many-arguments, too-many-locals, too-many-statements, too-many-branches
"""Filled triangle drawing function. Will draw a filled triangle around
the points (x0, y0), (x1, y1), and (x2, y2)."""
# Filled triangle drawing function. Will draw a filled triangle around
# the points (x0, y0), (x1, y1), and (x2, y2).
if y0 > y1:
y0, y1 = y1, y0
x0, x1 = x1, x0
@ -258,6 +260,7 @@ class GFX:
b = 0
y = 0
last = 0
if y0 == y2:
a = x0
b = x0
@ -269,7 +272,7 @@ class GFX:
a = x2
elif x2 > b:
b = x2
self.hline(a, y0, b - a + 1, *args, **kwargs)
self.hline(a, y0, b-a+1, *args, **kwargs)
return
dx01 = x1 - x0
dy01 = y1 - y0
@ -288,15 +291,19 @@ class GFX:
if y1 == y2:
last = y1
else:
last = y1 - 1
for y in range(y0, last + 1):
last = y1-1
for y in range(y0, last+1):
a = x0 + sa // dy01
b = x0 + sb // dy02
sa += dx01
sb += dx02
if a > b:
a, b = b, a
self.hline(a, y, b - a + 1, *args, **kwargs)
self.hline(a, y, b-a+1, *args, **kwargs)
y = last
sa = dx12 * (y - y1)
sb = dx02 * (y - y0)
while y <= y2:
@ -306,7 +313,7 @@ class GFX:
sb += dx02
if a > b:
a, b = b, a
self.hline(a, y, b - a + 1, *args, **kwargs)
self.hline(a, y, b-a+1, *args, **kwargs)
y += 1
def round_rect(self, x0, y0, width, height, radius, *args, **kwargs):
@ -335,7 +342,8 @@ class GFX:
self.hline(
x0, y0 + height - radius + 1, width - 2 * radius + 1, *args, **kwargs
) # bottom
self.hline(x0, y0 - radius, width - 2 * radius + 1, *args, **kwargs) # top
self.hline(x0, y0 - radius, width - 2 *
radius + 1, *args, **kwargs) # top
while x < y:
if f >= 0:
y -= 1
@ -497,7 +505,8 @@ class GFX:
# make sure something is sent even if not in font dict
try:
self._place_char(x_roll, y_roll, char, size, *args, **kwargs)
self._place_char(x_roll, y_roll, char,
size, *args, **kwargs)
except KeyError:
self._place_char(
x_roll, y_roll, "?CHAR?", size, *args, **kwargs

View File

@ -3,9 +3,7 @@ import time
import micropython
import framebuf
import os
import sdcard
import machine
from machine import Pin, I2C, ADC
from machine import ADC, I2C, Pin, SDCard
from uarray import array
from mcp23017 import MCP23017
from micropython import const
@ -14,7 +12,7 @@ from shapes import Shapes
from gfx import GFX
from gfx_standard_font_01 import text_dict as std_font
#Raw display constants for Inkplate 10
# Raw display constants for Inkplate 10
D_ROWS = const(825)
D_COLS = const(1200)
@ -22,16 +20,14 @@ D_COLS = const(1200)
# Order of 4 values in each tuple: blk, dk-grey, light-grey, white
# Meaning of values: 0=dischg, 1=black, 2=white, 3=skip
# Uses "colors" 0 (black), 3, 5, and 7 (white) from 3-bit waveforms below
WAVE_2B = ( # original mpy driver for Ink 6, differs from arduino driver below
(0, 0, 0, 0),
(0, 0, 0, 0),
(1, 1, 2, 0),
(1, 1, 1, 0),
(0, 2, 1, 0),
(1, 2, 1, 0),
WAVE_2B = ( # For Inkplate 10, colors 0, 3, 5-tweaked, and 7 from arduino driver
(0, 1, 0, 0), # (arduino color 5 was too light and color 4 too dark)
(0, 2, 0, 0),
(0, 2, 0, 2),
(0, 1, 2, 2),
(0, 2, 1, 2),
(0, 2, 1, 2),
(1, 1, 2, 2),
(0, 0, 0, 0),
(0, 0, 0, 0)
)
# Ink10 WAVEFORM3BIT from arduino driver
# {{0,0,0,0,0,0,1,0},{0,0,2,2,2,1,1,0},{0,2,1,1,2,2,1,0},{1,2,2,1,2,2,1,0},
@ -732,21 +728,13 @@ class Inkplate:
self.displayMode = mode
try:
os.mount(
sdcard.SDCard(
machine.SPI(
1,
baudrate=80000000,
polarity=0,
phase=0,
bits=8,
firstbit=0,
sck=Pin(14),
mosi=Pin(13),
miso=Pin(12),
),
machine.Pin(15),
),
"/sd",
SDCard(
slot=3,
miso=Pin(12),
mosi=Pin(13),
sck=Pin(14),
cs=Pin(15)),
"/sd"
)
except:
print("Sd card could not be read")
@ -880,7 +868,7 @@ class Inkplate:
y -= h - 1
(self.ipm.fill_rect if self.displayMode == self.INKPLATE_1BIT else self.ipg.fill_rect)(
x, y, w, h, c
)
)
def writeFastVLine(self, x, y, h, c):
if self.rotation in (1, 3):
@ -894,7 +882,7 @@ class Inkplate:
y -= h - 1
(self.ipm.vline if self.displayMode == self.INKPLATE_1BIT else self.ipg.vline)(
x, y, h, c
)
)
def writeFastHLine(self, x, y, w, c):
if self.rotation in (1, 3):
@ -908,7 +896,7 @@ class Inkplate:
x -= w - 1
(self.ipm.hline if self.displayMode == self.INKPLATE_1BIT else self.ipg.hline)(
x, y, w, c
)
)
def writeLine(self, x0, y0, x1, y1, c):
self.GFX.line(x0, y0, x1, y1, c)

View File

@ -3,9 +3,7 @@ import time
import micropython
import framebuf
import os
import sdcard
import machine
from machine import Pin, I2C, ADC
from machine import ADC, I2C, Pin, SDCard
from uarray import array
from mcp23017 import MCP23017
from micropython import const
@ -24,21 +22,19 @@ D_COLS = const(800)
# Meaning of values: 0=dischg, 1=black, 2=white, 3=skip
# Uses "colors" 0 (black), 3, 5, and 7 (white) from 3-bit waveforms below
#add discharge to waveforms to try to fix them
# add discharge to waveforms to try to fix them
WAVE_2B = ( # original mpy driver for Ink 6, differs from arduino driver below
(0, 0, 0, 0),
(0, 0, 0, 0),
(1, 1, 2, 0),
(1, 1, 1, 0),
(0, 2, 1, 0),
(0, 1, 1, 0),
(0, 1, 1, 0),
(1, 2, 1, 0),
(1, 1, 2, 2),
(0, 0, 0, 0),
(0, 0, 0, 0)
(1, 1, 2, 0),
(1, 2, 2, 2),
)
# Ink6 WAVEFORM3BIT from arduino driver
# {{0,1,1,0,0,1,1,0},{0,1,2,1,1,2,1,0},{1,1,1,2,2,1,0,0},{0,0,0,1,1,1,2,0},
# {2,1,1,1,2,1,2,0},{2,2,1,1,2,1,2,0},{1,1,1,2,1,2,2,0},{0,0,0,0,0,0,2,0}};
# Ink6 WAVEFORM3BIT from arduino driver
# {{0,1,1,0,0,1,1,0},{0,1,2,1,1,2,1,0},{1,1,1,2,2,1,0,0},{0,0,0,1,1,1,2,0},
# {2,1,1,1,2,1,2,0},{2,2,1,1,2,1,2,0},{1,1,1,2,1,2,2,0},{0,0,0,0,0,0,2,0}};
TPS65186_addr = const(0x48) # I2C address
@ -735,21 +731,13 @@ class Inkplate:
self.displayMode = mode
try:
os.mount(
sdcard.SDCard(
machine.SPI(
1,
baudrate=80000000,
polarity=0,
phase=0,
bits=8,
firstbit=0,
sck=Pin(14),
mosi=Pin(13),
miso=Pin(12),
),
machine.Pin(15),
),
"/sd",
SDCard(
slot=3,
miso=Pin(12),
mosi=Pin(13),
sck=Pin(14),
cs=Pin(15)),
"/sd"
)
except:
print("Sd card could not be read")

619
inkplate6_COLOR.py Normal file
View File

@ -0,0 +1,619 @@
# Copyright © 2020 by Thorsten von Eicken.
import time
import os
from machine import ADC, I2C, SPI, Pin, SDCard
from micropython import const
from shapes import Shapes
from mcp23017 import MCP23017
from machine import Pin as mPin
from gfx import GFX
from gfx_standard_font_01 import text_dict as std_font
# ===== Constants that change between the Inkplate 6 and 10
# Connections between ESP32 and color Epaper
EPAPER_RST_PIN = const(19)
EPAPER_DC_PIN = const(33)
EPAPER_CS_PIN = const(27)
EPAPER_BUSY_PIN = const(32)
EPAPER_CLK = const(18)
EPAPER_DIN = const(23)
# Timeout for init of epaper(1.5 sec in this case)
# INIT_TIMEOUT 1500
pixelMaskGLUT = [0xF, 0xF0]
# Epaper registers
PANEL_SET_REGISTER = "\x00"
POWER_SET_REGISTER = "\x01"
POWER_OFF_SEQ_SET_REGISTER = "\x03"
POWER_OFF_REGISTER = "\x04"
BOOSTER_SOFTSTART_REGISTER = "\x06"
DEEP_SLEEP_REGISTER = "\x07"
DATA_START_TRANS_REGISTER = "\x10"
DATA_STOP_REGISTER = "\x11"
DISPLAY_REF_REGISTER = "\x12"
IMAGE_PROCESS_REGISTER = "\x13"
PLL_CONTROL_REGISTER = "\x30"
TEMP_SENSOR_REGISTER = "\x40"
TEMP_SENSOR_EN_REGISTER = "\x41"
TEMP_SENSOR_WR_REGISTER = "\x42"
TEMP_SENSOR_RD_REGISTER = "\x43"
VCOM_DATA_INTERVAL_REGISTER = "\x50"
LOW_POWER_DETECT_REGISTER = "\x51"
RESOLUTION_SET_REGISTER = "\x61"
STATUS_REGISTER = "\x71"
VCOM_VALUE_REGISTER = "\x81"
VCM_DC_SET_REGISTER = "\x02"
# Epaper resolution and colors
D_COLS = const(600)
D_ROWS = const(448)
MCP23017_INT_ADDR = const(0x20)
MCP23017_EXT_ADDR = const(0x20)
MCP23017_INT_PORTA = const(0x00)
MCP23017_INT_PORTB = const(0x01)
MCP23017_INT_NO_MIRROR = False
MCP23017_INT_MIRROR = True
MCP23017_INT_PUSHPULL = False
MCP23017_INT_OPENDRAIN = True
MCP23017_INT_ACTLOW = False
MCP23017_INT_ACTHIGH = True
MCP23017_IODIRA = const(0x00)
MCP23017_IPOLA = const(0x02)
MCP23017_GPINTENA = const(0x04)
MCP23017_DEFVALA = const(0x06)
MCP23017_INTCONA = const(0x08)
MCP23017_IOCONA = const(0x0A)
MCP23017_GPPUA = const(0x0C)
MCP23017_INTFA = const(0x0E)
MCP23017_INTCAPA = const(0x10)
MCP23017_GPIOA = const(0x12)
MCP23017_OLATA = const(0x14)
MCP23017_IODIRB = const(0x01)
MCP23017_IPOLB = const(0x03)
MCP23017_GPINTENB = const(0x05)
MCP23017_DEFVALB = const(0x07)
MCP23017_INTCONB = const(0x09)
MCP23017_IOCONB = const(0x0B)
MCP23017_GPPUB = const(0x0D)
MCP23017_INTFB = const(0x0F)
MCP23017_INTCAPB = const(0x11)
MCP23017_GPIOB = const(0x13)
MCP23017_OLATB = const(0x15)
# User pins on MCP for Inkplate COLOR
MCP23017_PIN_A0 = const(0)
MCP23017_PIN_A1 = const(1)
MCP23017_PIN_A2 = const(2)
MCP23017_PIN_A3 = const(3)
MCP23017_PIN_A4 = const(4)
MCP23017_PIN_A5 = const(5)
MCP23017_PIN_A6 = const(6)
MCP23017_PIN_A7 = const(7)
MCP23017_PIN_B0 = const(8)
MCP23017_PIN_B1 = const(9)
MCP23017_PIN_B2 = const(10)
MCP23017_PIN_B3 = const(11)
MCP23017_PIN_B4 = const(12)
MCP23017_PIN_B5 = const(13)
MCP23017_PIN_B6 = const(14)
MCP23017_PIN_B7 = const(15)
class Inkplate:
BLACK = const(0b00000000)
WHITE = const(0b00000001)
GREEN = const(0b00000010)
BLUE = const(0b00000011)
RED = const(0b00000100)
YELLOW = const(0b00000101)
ORANGE = const(0b00000110)
_width = D_COLS
_height = D_ROWS
rotation = 0
textSize = 1
_panelState = False
_framebuf = bytearray([0x11] * (D_COLS * D_ROWS // 2))
@classmethod
def __init__(self):
try:
os.mount(
SDCard(
slot=3,
miso=Pin(12),
mosi=Pin(13),
sck=Pin(14),
cs=Pin(15)),
"/sd"
)
except:
print("Sd card could not be read")
@classmethod
def begin(self):
self.wire = I2C(0, scl=Pin(22), sda=Pin(21))
self._mcp23017 = MCP23017(self.wire)
self.TOUCH1 = self._mcp23017.pin(10, Pin.IN)
self.TOUCH2 = self._mcp23017.pin(11, Pin.IN)
self.TOUCH3 = self._mcp23017.pin(12, Pin.IN)
self.spi = SPI(2)
self.spi.init(baudrate=2000000, firstbit=SPI.MSB, polarity=0, phase=0)
self.EPAPER_BUSY_PIN = Pin(EPAPER_BUSY_PIN, Pin.IN)
self.EPAPER_RST_PIN = Pin(EPAPER_RST_PIN, Pin.OUT)
self.EPAPER_DC_PIN = Pin(EPAPER_DC_PIN, Pin.OUT)
self.EPAPER_CS_PIN = Pin(EPAPER_CS_PIN, Pin.OUT)
self.framebuf = bytearray(D_ROWS * D_COLS // 2)
self.GFX = GFX(
D_COLS,
D_ROWS,
self.writePixel,
self.writeFastHLine,
self.writeFastVLine,
self.writeFillRect,
None,
None,
)
self.resetPanel()
_timeout = time.ticks_ms()
while not self.EPAPER_BUSY_PIN.value() and (time.ticks_ms() - _timeout) < 10000:
pass
if not self.EPAPER_BUSY_PIN.value():
return False
self.sendCommand(PANEL_SET_REGISTER)
self.sendData(b"\xef\x08")
self.sendCommand(POWER_SET_REGISTER)
self.sendData(b"\x37\x00\x23\x23")
self.sendCommand(POWER_OFF_SEQ_SET_REGISTER)
self.sendData(b"\x00")
self.sendCommand(BOOSTER_SOFTSTART_REGISTER)
self.sendData(b"\xc7\xc7\x1d")
self.sendCommand(PLL_CONTROL_REGISTER)
self.sendData(b"\x3c")
self.sendCommand(TEMP_SENSOR_REGISTER)
self.sendData(b"\x00")
self.sendCommand(VCOM_DATA_INTERVAL_REGISTER)
self.sendData(b"\x37")
self.sendCommand(b"\x60")
self.sendData(b"\x20")
self.sendCommand(RESOLUTION_SET_REGISTER)
self.sendData(b"\x02\x58\x01\xc0")
self.sendCommand(b"\xE3")
self.sendData(b"\xaa")
time.sleep_ms(100)
self.sendCommand(b"\x50")
self.sendData(b"\x37")
self.setMCPForLowPower()
self._panelState = True
return True
@classmethod
def setMCPForLowPower(self):
self._mcp23017.pin(10, mode=mPin.IN)
self._mcp23017.pin(11, mode=mPin.IN)
self._mcp23017.pin(12, mode=mPin.IN)
self._mcp23017.pin(9, value=0, mode=mPin.OUT)
for x in range(8):
self._mcp23017.pin(x, value=0, mode=mPin.OUT)
self._mcp23017.pin(8, value=0, mode=mPin.OUT)
self._mcp23017.pin(13, value=0, mode=mPin.OUT)
self._mcp23017.pin(14, value=0, mode=mPin.OUT)
self._mcp23017.pin(15, value=0, mode=mPin.OUT)
@classmethod
def getPanelDeepSleepState(self):
return self._panelState
@classmethod
def setPanelDeepSleepState(self, state):
_panelState = False if state == 0 else True
if _panelState:
self.begin()
else:
time.sleep_ms(10)
self.sendCommand(DEEP_SLEEP_REGISTER)
self.sendData(b"\xA5")
time.sleep_ms(100)
EPAPER_RST_PIN.value(0)
EPAPER_DC_PIN.value(0)
EPAPER_CS_PIN.value(0)
@classmethod
def resetPanel(self):
self.EPAPER_RST_PIN.value(0)
time.sleep_ms(1)
self.EPAPER_RST_PIN.value(1)
time.sleep_ms(1)
@classmethod
def sendCommand(self, command):
self.EPAPER_DC_PIN.value(0)
self.EPAPER_CS_PIN.value(0)
self.spi.write(command)
self.EPAPER_CS_PIN.value(1)
@classmethod
def sendData(self, data):
self.EPAPER_DC_PIN.value(1)
self.EPAPER_CS_PIN.value(0)
self.spi.write(data)
self.EPAPER_CS_PIN.value(1)
@classmethod
def clearDisplay(self):
self._framebuf = bytearray([0x11] * (D_COLS * D_ROWS // 2))
@classmethod
def display(self):
if not self._panelState:
return
self.sendCommand(b"\x61")
self.sendData(b"\x02\x58\x01\xc0")
self.sendCommand(b"\x10")
self.EPAPER_DC_PIN.value(1)
self.EPAPER_CS_PIN.value(0)
self.spi.write(self._framebuf)
self.EPAPER_CS_PIN.value(1)
self.sendCommand(POWER_OFF_REGISTER)
while not self.EPAPER_BUSY_PIN.value():
pass
self.sendCommand(DISPLAY_REF_REGISTER)
while not self.EPAPER_BUSY_PIN.value():
pass
self.sendCommand(POWER_OFF_REGISTER)
while self.EPAPER_BUSY_PIN.value():
pass
time.sleep_ms(200)
@classmethod
def clean(self):
if not self._panelState:
return
self.sendCommand(b"\x61")
self.sendData(b"\x02\x58\x01\xc0")
self.sendCommand(b"\x10")
self.EPAPER_DC_PIN.value(1)
self.EPAPER_CS_PIN.value(0)
self.spi.write(bytearray(0x11 for x in range(D_COLS * D_ROWS // 2)))
self.EPAPER_CS_PIN.value(1)
self.sendCommand(POWER_OFF_REGISTER)
while not self.EPAPER_BUSY_PIN.value():
pass
self.sendCommand(DISPLAY_REF_REGISTER)
while not self.EPAPER_BUSY_PIN.value():
pass
self.sendCommand(POWER_OFF_REGISTER)
while self.EPAPER_BUSY_PIN.value():
pass
time.sleep_ms(200)
@classmethod
def width(self):
return self._width
@classmethod
def height(self):
return self._height
# Arduino compatibility functions
@classmethod
def setRotation(self, x):
self.rotation = x % 4
if self.rotation == 0 or self.rotation == 2:
self._width = D_COLS
self._height = D_ROWS
elif self.rotation == 1 or self.rotation == 3:
self._width = D_ROWS
self._height = D_COLS
@classmethod
def getRotation(self):
return self.rotation
@classmethod
def drawPixel(self, x, y, c):
self.startWrite()
self.writePixel(x, y, c)
self.endWrite()
@classmethod
def startWrite(self):
pass
@classmethod
def writePixel(self, x, y, c):
if x > self.width() - 1 or y > self.height() - 1 or x < 0 or y < 0:
return
if self.rotation == 1:
x, y = y, x
x = self.height() - x - 1
elif self.rotation == 0:
x = self.width() - x - 1
y = self.height() - y - 1
elif self.rotation == 3:
x, y = y, x
y = self.width() - y - 1
_x = x // 2
_x_sub = x % 2
temp = self._framebuf[D_COLS * y // 2 + _x]
self._framebuf[D_COLS * y // 2 + _x] = (pixelMaskGLUT[_x_sub] & temp) |\
(c if _x_sub else c << 4)
@classmethod
def writeFillRect(self, x, y, w, h, c):
for j in range(w):
for i in range(h):
self.writePixel(x + j, y + i, c)
@classmethod
def writeFastVLine(self, x, y, h, c):
for i in range(h):
self.writePixel(x, y + i, c)
@classmethod
def writeFastHLine(self, x, y, w, c):
for i in range(w):
self.writePixel(x + i, y, c)
@classmethod
def writeLine(self, x0, y0, x1, y1, c):
self.GFX.line(x0, y0, x1, y1, c)
@classmethod
def endWrite(self):
pass
@classmethod
def drawFastVLine(self, x, y, h, c):
self.startWrite()
self.writeFastVLine(x, y, h, c)
self.endWrite()
@classmethod
def drawFastHLine(self, x, y, w, c):
self.startWrite()
self.writeFastHLine(x, y, w, c)
self.endWrite()
@classmethod
def fillRect(self, x, y, w, h, c):
self.startWrite()
self.writeFillRect(x, y, w, h, c)
self.endWrite()
@classmethod
def fillScreen(self, c):
self.fillRect(0, 0, self.width(), self.height(), c)
@classmethod
def drawLine(self, x0, y0, x1, y1, c):
self.startWrite()
self.writeLine(x0, y0, x1, y1, c)
self.endWrite()
@classmethod
def drawRect(self, x, y, w, h, c):
self.GFX.rect(x, y, w, h, c)
@classmethod
def drawCircle(self, x, y, r, c):
self.GFX.circle(x, y, r, c)
@classmethod
def fillCircle(self, x, y, r, c):
self.GFX.fill_circle(x, y, r, c)
@classmethod
def drawTriangle(self, x0, y0, x1, y1, x2, y2, c):
self.GFX.triangle(x0, y0, x1, y1, x2, y2, c)
@classmethod
def fillTriangle(self, x0, y0, x1, y1, x2, y2, c):
self.GFX.fill_triangle(x0, y0, x1, y1, x2, y2, c)
@classmethod
def drawRoundRect(self, x, y, q, h, r, c):
self.GFX.round_rect(x, y, q, h, r, c)
@classmethod
def fillRoundRect(self, x, y, q, h, r, c):
self.GFX.fill_round_rect(x, y, q, h, r, c)
@classmethod
def setDisplayMode(self, mode):
self.displayMode = mode
@classmethod
def selectDisplayMode(self, mode):
self.displayMode = mode
@classmethod
def getDisplayMode(self):
return self.displayMode
@classmethod
def setTextSize(self, s):
self.textSize = s
@classmethod
def setFont(self, f):
self.GFX.font = f
@classmethod
def printText(self, x, y, s, c=BLACK):
self.GFX._very_slow_text(x, y, s, self.textSize, c)
@classmethod
def readBattery(self):
self.VBAT_EN.value(0)
# Probably don't need to delay since Micropython is slow, but we do it anyway
time.sleep_ms(1)
value = self.VBAT.read()
self.VBAT_EN.value(1)
result = (value / 4095.0) * 1.1 * 3.548133892 * 2
return result
@classmethod
def drawBitmap(self, x, y, data, w, h, c=BLACK):
byteWidth = (w + 7) // 8
byte = 0
self.startWrite()
for j in range(h):
for i in range(w):
if i & 7:
byte <<= 1
else:
byte = data[j * byteWidth + i // 8]
if byte & 0x80:
self.writePixel(x + i, y + j, c)
self.endWrite()
# @classmethod
# def drawImageFile(self, x, y, path, invert=False):
# with open(path, "rb") as f:
# header14 = f.read(14)
# if header14[0] != 0x42 or header14[1] != 0x4D:
# return 0
# header40 = f.read(40)
# w = int(
# (header40[7] << 24)
# + (header40[6] << 16)
# + (header40[5] << 8)
# + header40[4]
# )
# h = int(
# (header40[11] << 24)
# + (header40[10] << 16)
# + (header40[9] << 8)
# + header40[8]
# )
# dataStart = int((header14[11] << 8) + header14[10])
# depth = int((header40[15] << 8) + header40[14])
# totalColors = int((header40[33] << 8) + header40[32])
# rowSize = 4 * ((depth * w + 31) // 32)
# if totalColors == 0:
# totalColors = 1 << depth
# palette = None
# if depth <= 8:
# palette = [0 for i in range(totalColors)]
# p = f.read(totalColors * 4)
# for i in range(totalColors):
# palette[i] = (
# 54 * p[i * 4] + 183 * p[i * 4 + 1] + 19 * p[i * 4 + 2]
# ) >> 14
# # print(palette)
# f.seek(dataStart)
# for j in range(h):
# # print(100 * j // h, "% complete")
# buffer = f.read(rowSize)
# for i in range(w):
# val = 0
# if depth == 1:
# px = int(
# invert
# ^ (palette[0] < palette[1])
# ^ bool(buffer[i >> 3] & (1 << (7 - i & 7)))
# )
# val = palette[px]
# elif depth == 4:
# px = (buffer[i >> 1] & (0x0F if i & 1 == 1 else 0xF0)) >> (
# 0 if i & 1 else 4
# )
# val = palette[px]
# if invert:
# val = 3 - val
# elif depth == 8:
# px = buffer[i]
# val = palette[px]
# if invert:
# val = 3 - val
# elif depth == 16:
# px = (buffer[(i << 1) | 1] << 8) | buffer[(i << 1)]
# r = (px & 0x7C00) >> 7
# g = (px & 0x3E0) >> 2
# b = (px & 0x1F) << 3
# val = (54 * r + 183 * g + 19 * b) >> 14
# if invert:
# val = 3 - val
# elif depth == 24:
# r = buffer[i * 3]
# g = buffer[i * 3 + 1]
# b = buffer[i * 3 + 2]
# val = (54 * r + 183 * g + 19 * b) >> 14
# if invert:
# val = 3 - val
# elif depth == 32:
# r = buffer[i * 4]
# g = buffer[i * 4 + 1]
# b = buffer[i * 4 + 2]
# val = (54 * r + 183 * g + 19 * b) >> 14
# if invert:
# val = 3 - val
# if self.getDisplayMode() == self.INKPLATE_1BIT:
# val >>= 1
# self.drawPixel(x + i, y + h - j, val)

View File

@ -3,9 +3,7 @@ import time
import micropython
import framebuf
import os
import sdcard
import machine
from machine import Pin, I2C, ADC
from machine import ADC, I2C, Pin, SDCard
from uarray import array
from mcp23017 import MCP23017
from micropython import const
@ -24,17 +22,15 @@ D_COLS = const(1024)
# Meaning of values: 0=dischg, 1=black, 2=white, 3=skip
# Uses "colors" 0 (black), 3, 5, and 7 (white) from 3-bit waveforms below
#add discharge to waveforms to try to fix them
#add discharge to waveforms to try to fix them
WAVE_2B = ( # original mpy driver for Ink 6, differs from arduino driver below
(0, 0, 0, 0),
(0, 0, 0, 0),
(1, 1, 2, 0),
(1, 1, 1, 0),
(0, 2, 1, 0),
(0, 1, 1, 0),
(0, 1, 1, 0),
(1, 2, 1, 0),
(1, 1, 2, 2),
(0, 0, 0, 0),
(0, 0, 0, 0)
(1, 1, 2, 0),
(1, 2, 2, 2),
)
# Ink6 WAVEFORM3BIT from arduino driver
# {{0,1,1,0,0,1,1,0},{0,1,2,1,1,2,1,0},{1,1,1,2,2,1,0,0},{0,0,0,1,1,1,2,0},
@ -175,7 +171,7 @@ class _Inkplate:
@classmethod
def frontlight(cls, value):
cls.FRONTLIGHT.value(value)
@classmethod
def setFrontlight(cls, value):
value = (63 - (value & 0b00111111))
@ -196,7 +192,7 @@ class _Inkplate:
cls.touchY = cls._yPos[0]
if(cls.touchX > x and cls.touchX < x2) and (cls.touchY > y and cls.touchY < y2):
return True
return True
return False
@classmethod
@ -228,7 +224,7 @@ class _Inkplate:
timeout = 1000
while (cls._tsFlag == False) and (timeout > 0):
time.sleep_ms(1)
timeout -= 1
timeout -= 1
if (timeout > 0):
cls._tsFlag = True
rb = cls._i2c.readfrom(TS_ADDR, 4)
@ -257,19 +253,19 @@ class _Inkplate:
if(_Inkplate.tsSoftwareReset() == False):
cls.ts_intr = Pin(TS_INT, mode=Pin.IN)
return False
_Inkplate.tsGetResolution()
_Inkplate.tsSetPowerState(powerState)
cls._tsFlag = True
return True
@classmethod
def tsShutdown(cls):
cls._mcp23017.pin(TOUCHSCREEN_EN, mode=Pin.OUT, value=1)
@classmethod
def tsGetRawData(cls):
data = bytearray(8)
data = bytearray(8)
data = cls._i2c.readfrom(TS_ADDR, 8)
return data
@ -286,7 +282,7 @@ class _Inkplate:
cls.yraw[i] = ( data[1 + offset] & 0x0F)
cls.yraw[i] <<= 8
cls.yraw[i] |= data[3 + offset]
@classmethod
def tsGetData(cls):
raw = bytearray(8)
@ -299,7 +295,7 @@ class _Inkplate:
fingers += 1
for i in range(0, 2):
cls.tsGetXY(raw, i)
if cls.rotation == 0:
cls._yPos[i] = (int)((cls.xraw[i] * D_ROWS - 1) / cls._tsXResolution)
cls._xPos[i] = (int)(D_COLS - 1 - ((cls.yraw[i] * D_COLS - 1) / cls._tsYResolution))
@ -344,13 +340,13 @@ class _Inkplate:
buf = bytearray(4)
_Inkplate.tsWriteRegs(TS_ADDR, powerStateReg)
cls._tsFlag = False
buf = _Inkplate.tsReadRegs(TS_ADDR)
return (buf[1] >> 3) & 1
buf = _Inkplate.tsReadRegs(TS_ADDR)
return (buf[1] >> 3) & 1
@classmethod
def tsAvailable(cls):
return cls._tsFlag
@classmethod
def i2cScan(cls):
return cls._i2c.scan()
@ -937,21 +933,13 @@ class Inkplate:
self.displayMode = mode
try:
os.mount(
sdcard.SDCard(
machine.SPI(
1,
baudrate=80000000,
polarity=0,
phase=0,
bits=8,
firstbit=0,
sck=Pin(14),
mosi=Pin(13),
miso=Pin(12),
),
machine.Pin(15),
),
"/sd",
SDCard(
slot=3,
miso=Pin(12),
mosi=Pin(13),
sck=Pin(14),
cs=Pin(15)),
"/sd"
)
except:
print("Sd card could not be read")

281
sdcard.py
View File

@ -1,281 +0,0 @@
"""
MicroPython driver for SD cards using SPI bus.
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
methods so the device can be mounted as a filesystem.
Example usage on pyboard:
import pyb, sdcard, os
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
pyb.mount(sd, '/sd2')
os.listdir('/')
Example usage on ESP8266:
import machine, sdcard, os
sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
os.mount(sd, '/sd')
os.listdir('/')
"""
from micropython import const
import time
_CMD_TIMEOUT = const(100)
_R1_IDLE_STATE = const(1 << 0)
# R1_ERASE_RESET = const(1 << 1)
_R1_ILLEGAL_COMMAND = const(1 << 2)
# R1_COM_CRC_ERROR = const(1 << 3)
# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
# R1_ADDRESS_ERROR = const(1 << 5)
# R1_PARAMETER_ERROR = const(1 << 6)
_TOKEN_CMD25 = const(0xFC)
_TOKEN_STOP_TRAN = const(0xFD)
_TOKEN_DATA = const(0xFE)
class SDCard:
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
self.cmdbuf = bytearray(6)
self.dummybuf = bytearray(512)
self.tokenbuf = bytearray(1)
for i in range(512):
self.dummybuf[i] = 0xFF
self.dummybuf_memoryview = memoryview(self.dummybuf)
# initialise the card
self.init_card()
def init_spi(self, baudrate):
try:
master = self.spi.MASTER
except AttributeError:
# on ESP8266
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
else:
# on pyboard
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
def init_card(self):
# init CS pin
self.cs.init(self.cs.OUT, value=1)
# init SPI bus; use low data rate for initialisation
self.init_spi(100000)
# clock card at least 100 cycles with cs high
for i in range(16):
self.spi.write(b"\xff")
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
break
else:
raise OSError("no SD card")
# CMD8: determine card version
r = self.cmd(8, 0x01AA, 0x87, 4)
if r == _R1_IDLE_STATE:
self.init_card_v2()
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
self.init_card_v1()
else:
raise OSError("couldn't determine SD card version")
# get the number of sectors
# CMD9: response R2 (R1 byte + 16-byte block read)
if self.cmd(9, 0, 0, 0, False) != 0:
raise OSError("no response from SD card")
csd = bytearray(16)
self.readinto(csd)
if csd[0] & 0xC0 == 0x40: # CSD version 2.0
self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
c_size = csd[6] & 0b11 | csd[7] << 2 | (csd[8] & 0b11000000) << 4
c_size_mult = ((csd[9] & 0b11) << 1) | csd[10] >> 7
self.sectors = (c_size + 1) * (2 ** (c_size_mult + 2))
else:
raise OSError("SD card CSD format not supported")
# print('sectors', self.sectors)
# CMD16: set block length to 512 bytes
if self.cmd(16, 512, 0) != 0:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
self.init_spi(1320000)
def init_card_v1(self):
for i in range(_CMD_TIMEOUT):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cdv = 512
# print("[SDCard] v1 card")
return
raise OSError("timeout waiting for v1 card")
def init_card_v2(self):
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, 4)
self.cdv = 1
# print("[SDCard] v2 card")
return
raise OSError("timeout waiting for v2 card")
def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
self.cs(0)
# create and send the command
buf = self.cmdbuf
buf[0] = 0x40 | cmd
buf[1] = arg >> 24
buf[2] = arg >> 16
buf[3] = arg >> 8
buf[4] = arg
buf[5] = crc
self.spi.write(buf)
if skip1:
self.spi.readinto(self.tokenbuf, 0xFF)
# wait for the response (response[7] == 0)
for i in range(_CMD_TIMEOUT):
self.spi.readinto(self.tokenbuf, 0xFF)
response = self.tokenbuf[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
for j in range(final):
self.spi.write(b"\xff")
if release:
self.cs(1)
self.spi.write(b"\xff")
return response
# timeout
self.cs(1)
self.spi.write(b"\xff")
return -1
def readinto(self, buf):
self.cs(0)
# read until start byte (0xff)
for i in range(_CMD_TIMEOUT):
self.spi.readinto(self.tokenbuf, 0xFF)
if self.tokenbuf[0] == _TOKEN_DATA:
break
else:
self.cs(1)
raise OSError("timeout waiting for response")
# read data
mv = self.dummybuf_memoryview
if len(buf) != len(mv):
mv = mv[: len(buf)]
self.spi.write_readinto(mv, buf)
# read checksum
self.spi.write(b"\xff")
self.spi.write(b"\xff")
self.cs(1)
self.spi.write(b"\xff")
def write(self, token, buf):
self.cs(0)
# send: start of block, data, checksum
self.spi.read(1, token)
self.spi.write(buf)
self.spi.write(b"\xff")
self.spi.write(b"\xff")
# check the response
if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
self.cs(1)
self.spi.write(b"\xff")
return
# wait for write to finish
while self.spi.read(1, 0xFF)[0] == 0:
pass
self.cs(1)
self.spi.write(b"\xff")
def write_token(self, token):
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(1)
self.spi.write(b"\xff")
def readblocks(self, block_num, buf):
nblocks = len(buf) // 512
assert nblocks and not len(buf) % 512, "Buffer length is invalid"
if nblocks == 1:
# CMD17: set read address for single block
if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
# release the card
self.cs(1)
raise OSError(5) # EIO
# receive the data and release card
self.readinto(buf)
else:
# CMD18: set read address for multiple blocks
if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
# release the card
self.cs(1)
raise OSError(5) # EIO
offset = 0
mv = memoryview(buf)
while nblocks:
# receive the data and release card
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
if self.cmd(12, 0, 0xFF, skip1=True):
raise OSError(5) # EIO
def writeblocks(self, block_num, buf):
nblocks, err = divmod(len(buf), 512)
assert nblocks and not err, "Buffer length is invalid"
if nblocks == 1:
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
raise OSError(5) # EIO
# send the data
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
raise OSError(5) # EIO
# send the data
offset = 0
mv = memoryview(buf)
while nblocks:
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
self.write_token(_TOKEN_STOP_TRAN)
def ioctl(self, op, arg):
if op == 4: # get number of blocks
return self.sectors