Merge branch 'master' into micropython
commit
01b0d1cd54
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
25
README.md
25
README.md
|
@ -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`:
|
||||
```
|
||||
|
|
40
SCRIPTS.md
40
SCRIPTS.md
|
@ -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
29
gfx.py
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
44
inkplate6.py
44
inkplate6.py
|
@ -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")
|
||||
|
|
|
@ -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)
|
|
@ -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
281
sdcard.py
|
@ -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
|
Loading…
Reference in New Issue