print("Hello, Pi Pico W!")
from machine import Pin
from utime import sleep
# led=Pin(28, Pin.OUT)
# while True:
# led.value(1)
# sleep(1)
# led.value(0)
# sleep(1)
# library of 7.5 inch e paper
from machine import Pin, SPI,PWM, I2C
from micropython import const
import framebuf
import utime,time
from time import sleep
import binascii
import os
_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)
buzz = PWM(Pin(22))
# Display resolution
width = 800
height = 480
RST_PIN = 12
DC_PIN = 8
CS_PIN = 9
BUSY_PIN = 13
class E_paper:
def __init__(self):
self.reset_pin = Pin(RST_PIN, Pin.OUT)
self.busy_pin = Pin(BUSY_PIN, Pin.IN, Pin.PULL_UP)
self.cs_pin = Pin(CS_PIN, Pin.OUT)
self.width = width
self.height = height
self.spi = SPI(1) # SPI 1
self.spi.init(baudrate=4000_000)
self.dc_pin = Pin(DC_PIN, Pin.OUT)
self.buffer_black = bytearray(self.height * self.width // 8)
self.buffer_red = bytearray(self.height * self.width // 8)
self.imageblack = framebuf.FrameBuffer(self.buffer_black, self.width, self.height, framebuf.MONO_HLSB)
self.imagered = framebuf.FrameBuffer(self.buffer_red, self.width, self.height, framebuf.MONO_HLSB)
self.init()
def pin_write(self, pin, value):
pin.value(value)
def pin_read(self, pin):
return pin.value()
#SPI write
def writebyte(self, data):
self.spi.write(bytearray(data))
# delay in millisecond
def delay(self, delaytime):
utime.sleep(delaytime / 500.0)#1000
def exit(self):
self.pin_write(self.reset_pin, 0)
def send_command(self, command):
self.pin_write(self.dc_pin, 0)
self.pin_write(self.cs_pin, 0)
self.writebyte([command])
self.pin_write(self.cs_pin, 1)
# Hardware reset
def reset(self):
self.pin_write(self.reset_pin, 1)
self.delay(200)
self.pin_write(self.reset_pin, 0)
self.delay(2)
self.pin_write(self.reset_pin, 1)
self.delay(200)
def send_data(self, data):
self.pin_write(self.dc_pin, 1)
self.pin_write(self.cs_pin, 0)
self.writebyte([data])
self.pin_write(self.cs_pin, 1)
def wait(self):
print("display busy")
while(self.pin_read(self.busy_pin) == 0): # Wait until the busy_pin goes LOW
self.delay(20)
self.delay(20)
print("display busy release")
def turn_on_Display(self):
self.send_command(0x12) # DISPLAY REFRESH
self.delay(100) #!!!The delay here is necessary, 200uS at least!!!
self.wait()
def init(self):
# EPD hardware init start
self.reset()
self.send_command(0x06) # btst
self.send_data(0x17)
self.send_data(0x17)
self.send_data(0x28) # If an exception is displayed, try using 0x38
self.send_data(0x17)
# self.send_command(0x01) # POWER SETTING
# self.send_data(0x07)
# self.send_data(0x07) # VGH=20V,VGL=-20V
# self.send_data(0x3f) # VDH=15V
# self.send_data(0x3f) # VDL=-15V
self.send_command(0x04) # POWER ON
self.delay(100)
self.wait()
self.send_command(0X00) # PANNEL SETTING
self.send_data(0x0F) # KW-3f KWR-2F BWROTP 0f BWOTP 1f
self.send_command(0x61) # tres
self.send_data(0x03) # source 800
self.send_data(0x20)
self.send_data(0x01) # gate 480
self.send_data(0xE0)
self.send_command(0X15)
self.send_data(0x00)
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING
self.send_data(0x11)
self.send_data(0x07)
self.send_command(0X60) # TCON SETTING
self.send_data(0x22)
self.send_command(0x65) # Resolution setting
self.send_data(0x00)
self.send_data(0x00) # 800*480
self.send_data(0x00)
self.send_data(0x00)
return 0;
def clear_screen(self):
high = self.height
if( self.width % 8 == 0) :
wide = self.width // 8
else :
wide = self.width // 8 + 1
self.send_command(0x10)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0xff)
self.send_command(0x13)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0x00)
self.turn_on_Display()
def clear_red_screen(self):
high = self.height
if( self.width % 8 == 0) :
wide = self.width // 8
else :
wide = self.width // 8 + 1
self.send_command(0x10)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0xff)
self.send_command(0x13)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0xff)
self.turn_on_Display()
def clear_black_screen(self):
high = self.height
if( self.width % 8 == 0) :
wide = self.width // 8
else :
wide = self.width // 8 + 1
self.send_command(0x10)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0x00)
self.send_command(0x13)
for j in range(0, high):
for i in range(0, wide):
self.send_data(0x00)
self.turn_on_Display()
def display(self):
high = self.height
if( self.width % 8 == 0) :
wide = self.width // 8
else :
wide = self.width // 8 + 1
# send black data
self.send_command(0x10)
for j in range(0, high):
for i in range(0, wide):
self.send_data(self.buffer_black[i + j * wide])
# send red data
self.send_command(0x13)
for j in range(0, high):
for i in range(0, wide):
self.send_data(self.buffer_red[i + j * wide])
self.turn_on_Display()
def sleep(self):
self.send_command(0x02) # power off
self.wait()
self.send_command(0x07) # deep screen_sleep
self.send_data(0xa5)
class SDCard:
def __init__(self):
spi=SPI(0,sck=Pin(18),mosi=Pin(19),miso=Pin(16))
cs = Pin(17)
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
time.sleep_ms(1)
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
class RTC(object):
# 12:00:00 Thrusday 20 October 2022
# sec min hour week day month year
NowTime = b'\x00\x00\x12\x11\x20\x10\x22'
w = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
address = 0x68
start = 0x00
alarm = 0x07
control = 0x0e
status = 0x0f
def __init__(self):
self.bus = I2C(1)
def set_time(self,new_time):
hour = new_time[0] + new_time[1]
minute = new_time[3] + new_time[4]
second = new_time[6] + new_time[7]
week = "0" + str(self.w.index(new_time.split(",",2)[1])+1)
year = new_time.split(",",2)[2][2] + new_time.split(",",2)[2][3]
month = new_time.split(",",2)[2][5] + new_time.split(",",2)[2][6]
day = new_time.split(",",2)[2][8] + new_time.split(",",2)[2][9]
now_time = binascii.unhexlify((second + " " + minute + " " + hour + " " + week + " " + day + " " + month + " " + year).replace(' ',''))
self.bus.writeto_mem(int(self.address),int(self.start),now_time)
def read_time(self):
data = self.bus.readfrom_mem(int(self.address),int(self.start),7)
a = data[0]&0x7F #second
b = data[1]&0x7F #minute
c = data[2]&0x3F #hour
d = data[3]&0x07 #week
e = data[4]&0x3F #day
f = data[5]&0x1F #month
return "20%x/%02x/%02x %02x:%02x:%02x %s" %(data[6],data[5],data[4],data[2],data[1],data[0],self.w[data[3]-1])
def _twos_complement(self, input_value: int, num_bits: int) -> int:
mask = 2 ** (num_bits - 1)
return -(input_value & mask) + (input_value & ~mask)
def temperature(self):
t = self.bus.readfrom_mem(self.address, 0x11, 2)
i = t[0] << 8 | t[1]
return self._twos_complement(i >> 6, 10) * 0.25
class Buzzer:
def tone(frequency,sound_duration,silence_duration):
# Set duty cycle to a positive value to emit sound from buzzer
buzz.duty_u16(int(65536*0.1))
# Set frequency
buzz.freq(frequency)
# wait for sound duration
sleep(sound_duration)
# Set duty cycle to zero to stop sound
buzz.duty_u16(int(65536*0))
# Wait for sound interrumption, if needed
sleep(silence_duration)
e_paper = E_paper()
e_paper.imageblack.fill(0xff)
e_paper.imagered.fill(0x00)
e_paper.imageblack.text("SB COMPONENTS", 5, 10, 0x00)
e_paper.imagered.text("EnkPi 7.5 inch", 5, 40, 0xff)
e_paper.display()