Dateien nach "/" hochladen
parent
eceea548f5
commit
860dfc6b37
|
@ -0,0 +1,84 @@
|
|||
{
|
||||
"version": 1,
|
||||
"author": "tech nik_hea",
|
||||
"editor": "wokwi",
|
||||
"parts": [
|
||||
{
|
||||
"type": "wokwi-pi-pico",
|
||||
"id": "pico",
|
||||
"top": 91.23,
|
||||
"left": 219.63,
|
||||
"attrs": { "env": "micropython-20230426-v1.20.0" }
|
||||
},
|
||||
{
|
||||
"type": "wokwi-analog-joystick",
|
||||
"id": "joystick1",
|
||||
"top": -10.64,
|
||||
"left": 2.9,
|
||||
"attrs": {}
|
||||
},
|
||||
{
|
||||
"type": "wokwi-max7219-matrix",
|
||||
"id": "matrix1",
|
||||
"top": -85.67,
|
||||
"left": 137.7,
|
||||
"attrs": { "chain": "2" }
|
||||
},
|
||||
{
|
||||
"type": "wokwi-lcd1602",
|
||||
"id": "lcd2",
|
||||
"top": -250.26,
|
||||
"left": 87.24,
|
||||
"attrs": { "pins": "i2c" }
|
||||
},
|
||||
{
|
||||
"type": "wokwi-pushbutton",
|
||||
"id": "btn1",
|
||||
"top": 0.7,
|
||||
"left": 461.13,
|
||||
"attrs": { "color": "yellow" }
|
||||
},
|
||||
{
|
||||
"type": "wokwi-pushbutton",
|
||||
"id": "btn2",
|
||||
"top": 60.93,
|
||||
"left": 400.96,
|
||||
"attrs": { "color": "red" }
|
||||
},
|
||||
{
|
||||
"type": "wokwi-buzzer",
|
||||
"id": "bz1",
|
||||
"top": 10.64,
|
||||
"left": 119.01,
|
||||
"attrs": { "volume": "1" }
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
[ "pico:GND.8", "joystick1:GND", "black", [ "h0" ] ],
|
||||
[ "pico:GND.8", "matrix1:GND", "black", [ "h196.92", "v-96.9", "h-22.25" ] ],
|
||||
[ "pico:VBUS", "matrix1:V+", "green", [ "h181.77", "v-90.21" ] ],
|
||||
[ "pico:GP2", "matrix1:CLK", "blue", [ "h234.99", "v-78.09" ] ],
|
||||
[ "pico:GP5", "matrix1:CS", "violet", [ "h200.88", "v-117.97" ] ],
|
||||
[ "pico:GP3", "matrix1:DIN", "gold", [ "h217.07", "v-109.68" ] ],
|
||||
[
|
||||
"pico:VBUS",
|
||||
"lcd2:VCC",
|
||||
"green",
|
||||
[ "h-6.92", "v-99.62", "h-173.32", "v-105.59", "h-110.86", "v-104.83" ]
|
||||
],
|
||||
[ "pico:GND.8", "lcd2:GND", "black", [ "h-171.33", "v-232.04", "h-88.56", "v-110.84" ] ],
|
||||
[ "pico:GP0", "lcd2:SDA", "green", [ "h-276.23", "v-302.1" ] ],
|
||||
[ "pico:GP1", "lcd2:SCL", "gold", [ "h-287.82", "v-301.02" ] ],
|
||||
[ "btn2:1.l", "pico:GP6", "green", [ "h-211.55", "v103.68" ] ],
|
||||
[ "btn1:1.l", "pico:GP7", "green", [ "h-283.22", "v177.51" ] ],
|
||||
[ "pico:3V3", "joystick1:VCC", "red", [ "h0" ] ],
|
||||
[ "joystick1:VERT", "pico:GP28", "green", [ "v66.89", "h282.35", "v-11.04" ] ],
|
||||
[ "joystick1:HORZ", "pico:GP27", "green", [ "v0" ] ],
|
||||
[ "joystick1:SEL", "pico:GP8", "green", [ "v0" ] ],
|
||||
[ "bz1:1", "pico:GND.4", "black", [ "v0" ] ],
|
||||
[ "pico:GP15", "bz1:2", "red", [ "h0" ] ],
|
||||
[ "pico:3V3", "btn2:2.l", "red", [ "h0" ] ],
|
||||
[ "pico:3V3", "btn1:2.l", "red", [ "h0" ] ]
|
||||
],
|
||||
"dependencies": {}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
import time
|
||||
|
||||
class LcdApi:
|
||||
|
||||
# Implements the API for talking with HD44780 compatible character LCDs.
|
||||
# This class only knows what commands to send to the LCD, and not how to get
|
||||
# them to the LCD.
|
||||
#
|
||||
# It is expected that a derived class will implement the hal_xxx functions.
|
||||
#
|
||||
# The following constant names were lifted from the avrlib lcd.h header file,
|
||||
# with bit numbers changed to bit masks.
|
||||
|
||||
# HD44780 LCD controller command set
|
||||
LCD_CLR = 0x01 # DB0: clear display
|
||||
LCD_HOME = 0x02 # DB1: return to home position
|
||||
|
||||
LCD_ENTRY_MODE = 0x04 # DB2: set entry mode
|
||||
LCD_ENTRY_INC = 0x02 # DB1: increment
|
||||
LCD_ENTRY_SHIFT = 0x01 # DB0: shift
|
||||
|
||||
LCD_ON_CTRL = 0x08 # DB3: turn lcd/cursor on
|
||||
LCD_ON_DISPLAY = 0x04 # DB2: turn display on
|
||||
LCD_ON_CURSOR = 0x02 # DB1: turn cursor on
|
||||
LCD_ON_BLINK = 0x01 # DB0: blinking cursor
|
||||
|
||||
LCD_MOVE = 0x10 # DB4: move cursor/display
|
||||
LCD_MOVE_DISP = 0x08 # DB3: move display (0-> move cursor)
|
||||
LCD_MOVE_RIGHT = 0x04 # DB2: move right (0-> left)
|
||||
|
||||
LCD_FUNCTION = 0x20 # DB5: function set
|
||||
LCD_FUNCTION_8BIT = 0x10 # DB4: set 8BIT mode (0->4BIT mode)
|
||||
LCD_FUNCTION_2LINES = 0x08 # DB3: two lines (0->one line)
|
||||
LCD_FUNCTION_10DOTS = 0x04 # DB2: 5x10 font (0->5x7 font)
|
||||
LCD_FUNCTION_RESET = 0x30 # See "Initializing by Instruction" section
|
||||
|
||||
LCD_CGRAM = 0x40 # DB6: set CG RAM address
|
||||
LCD_DDRAM = 0x80 # DB7: set DD RAM address
|
||||
|
||||
LCD_RS_CMD = 0
|
||||
LCD_RS_DATA = 1
|
||||
|
||||
LCD_RW_WRITE = 0
|
||||
LCD_RW_READ = 1
|
||||
|
||||
def __init__(self, num_lines, num_columns):
|
||||
self.num_lines = num_lines
|
||||
if self.num_lines > 4:
|
||||
self.num_lines = 4
|
||||
self.num_columns = num_columns
|
||||
if self.num_columns > 40:
|
||||
self.num_columns = 40
|
||||
self.cursor_x = 0
|
||||
self.cursor_y = 0
|
||||
self.implied_newline = False
|
||||
self.backlight = True
|
||||
self.display_off()
|
||||
self.backlight_on()
|
||||
self.clear()
|
||||
self.hal_write_command(self.LCD_ENTRY_MODE | self.LCD_ENTRY_INC)
|
||||
self.hide_cursor()
|
||||
self.display_on()
|
||||
|
||||
def clear(self):
|
||||
# Clears the LCD display and moves the cursor to the top left corner
|
||||
self.hal_write_command(self.LCD_CLR)
|
||||
self.hal_write_command(self.LCD_HOME)
|
||||
self.cursor_x = 0
|
||||
self.cursor_y = 0
|
||||
|
||||
def show_cursor(self):
|
||||
# Causes the cursor to be made visible
|
||||
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
|
||||
self.LCD_ON_CURSOR)
|
||||
|
||||
def hide_cursor(self):
|
||||
# Causes the cursor to be hidden
|
||||
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
|
||||
|
||||
def blink_cursor_on(self):
|
||||
# Turns on the cursor, and makes it blink
|
||||
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
|
||||
self.LCD_ON_CURSOR | self.LCD_ON_BLINK)
|
||||
|
||||
def blink_cursor_off(self):
|
||||
# Turns on the cursor, and makes it no blink (i.e. be solid)
|
||||
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
|
||||
self.LCD_ON_CURSOR)
|
||||
|
||||
def display_on(self):
|
||||
# Turns on (i.e. unblanks) the LCD
|
||||
self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
|
||||
|
||||
def display_off(self):
|
||||
# Turns off (i.e. blanks) the LCD
|
||||
self.hal_write_command(self.LCD_ON_CTRL)
|
||||
|
||||
def backlight_on(self):
|
||||
# Turns the backlight on.
|
||||
|
||||
# This isn't really an LCD command, but some modules have backlight
|
||||
# controls, so this allows the hal to pass through the command.
|
||||
self.backlight = True
|
||||
self.hal_backlight_on()
|
||||
|
||||
def backlight_off(self):
|
||||
# Turns the backlight off.
|
||||
|
||||
# This isn't really an LCD command, but some modules have backlight
|
||||
# controls, so this allows the hal to pass through the command.
|
||||
self.backlight = False
|
||||
self.hal_backlight_off()
|
||||
|
||||
def move_to(self, cursor_x, cursor_y):
|
||||
# Moves the cursor position to the indicated position. The cursor
|
||||
# position is zero based (i.e. cursor_x == 0 indicates first column).
|
||||
self.cursor_x = cursor_x
|
||||
self.cursor_y = cursor_y
|
||||
addr = cursor_x & 0x3f
|
||||
if cursor_y & 1:
|
||||
addr += 0x40 # Lines 1 & 3 add 0x40
|
||||
if cursor_y & 2: # Lines 2 & 3 add number of columns
|
||||
addr += self.num_columns
|
||||
self.hal_write_command(self.LCD_DDRAM | addr)
|
||||
|
||||
def putchar(self, char):
|
||||
# Writes the indicated character to the LCD at the current cursor
|
||||
# position, and advances the cursor by one position.
|
||||
if char == '\n':
|
||||
if self.implied_newline:
|
||||
# self.implied_newline means we advanced due to a wraparound,
|
||||
# so if we get a newline right after that we ignore it.
|
||||
pass
|
||||
else:
|
||||
self.cursor_x = self.num_columns
|
||||
else:
|
||||
self.hal_write_data(ord(char))
|
||||
self.cursor_x += 1
|
||||
if self.cursor_x >= self.num_columns:
|
||||
self.cursor_x = 0
|
||||
self.cursor_y += 1
|
||||
self.implied_newline = (char != '\n')
|
||||
if self.cursor_y >= self.num_lines:
|
||||
self.cursor_y = 0
|
||||
self.move_to(self.cursor_x, self.cursor_y)
|
||||
|
||||
def putstr(self, string):
|
||||
# Write the indicated string to the LCD at the current cursor
|
||||
# position and advances the cursor position appropriately.
|
||||
for char in string:
|
||||
self.putchar(char)
|
||||
|
||||
def custom_char(self, location, charmap):
|
||||
# Write a character to one of the 8 CGRAM locations, available
|
||||
# as chr(0) through chr(7).
|
||||
location &= 0x7
|
||||
self.hal_write_command(self.LCD_CGRAM | (location << 3))
|
||||
self.hal_sleep_us(40)
|
||||
for i in range(8):
|
||||
self.hal_write_data(charmap[i])
|
||||
self.hal_sleep_us(40)
|
||||
self.move_to(self.cursor_x, self.cursor_y)
|
||||
|
||||
def hal_backlight_on(self):
|
||||
# Allows the hal layer to turn the backlight on.
|
||||
# If desired, a derived HAL class will implement this function.
|
||||
pass
|
||||
|
||||
def hal_backlight_off(self):
|
||||
# Allows the hal layer to turn the backlight off.
|
||||
# If desired, a derived HAL class will implement this function.
|
||||
pass
|
||||
|
||||
def hal_write_command(self, cmd):
|
||||
# Write a command to the LCD.
|
||||
# It is expected that a derived HAL class will implement this function.
|
||||
raise NotImplementedError
|
||||
|
||||
def hal_write_data(self, data):
|
||||
# Write data to the LCD.
|
||||
# It is expected that a derived HAL class will implement this function.
|
||||
raise NotImplementedError
|
||||
|
||||
def hal_sleep_us(self, usecs):
|
||||
# Sleep for some time (given in microseconds)
|
||||
time.sleep_us(usecs)
|
|
@ -0,0 +1,201 @@
|
|||
import max7219
|
||||
from machine import Pin, SPI, ADC, PWM
|
||||
from machine import I2C
|
||||
from lcd_api import LcdApi
|
||||
from pico_i2c_lcd import I2cLcd
|
||||
import time
|
||||
import os
|
||||
import utime
|
||||
|
||||
#init buzzer
|
||||
|
||||
#read notes
|
||||
tonefile = open("tones.txt", 'r')
|
||||
tones = tonefile.read()
|
||||
tones = eval(tones)
|
||||
tonefile.close()
|
||||
|
||||
buzzer = PWM(Pin(15))
|
||||
buzzer.duty_u16(0)
|
||||
def tone(freq, duration):
|
||||
buzzer.freq(freq)
|
||||
buzzer.duty_u16(1000)
|
||||
time.sleep(duration)
|
||||
buzzer.duty_u16(0)
|
||||
|
||||
def playsong(song):
|
||||
for i in song:
|
||||
note = i.split(":")[0]
|
||||
duration = i.split(":")[1]
|
||||
tone(tones[note], float(duration))
|
||||
|
||||
introsong = ['DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'E4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'FS4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'G4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'GS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01', 'DS4:0.01']
|
||||
|
||||
playsong(introsong)
|
||||
|
||||
# init game display
|
||||
spi = SPI(0, baudrate=10000000, polarity=1, phase=0, sck=Pin(2), mosi=Pin(3))
|
||||
display = max7219.Matrix8x8(spi, Pin(5), 2)
|
||||
display.show()
|
||||
|
||||
# init text display
|
||||
I2C_ADDR = 0x27
|
||||
I2C_NUM_ROWS = 2
|
||||
I2C_NUM_COLS = 16
|
||||
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
|
||||
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)
|
||||
lcd.clear()
|
||||
lcd.putstr("booting...")
|
||||
time.sleep(1)
|
||||
lcd.clear()
|
||||
lcd.putstr("dot matrix...OK")
|
||||
time.sleep(0.1)
|
||||
lcd.clear()
|
||||
lcd.putstr("buzzer...OK")
|
||||
time.sleep(0.1)
|
||||
lcd.clear()
|
||||
lcd.putstr("LCD display...OK")
|
||||
|
||||
#init joystick
|
||||
time.sleep(0.1)
|
||||
lcd.clear()
|
||||
lcd.putstr("joystick...")
|
||||
class joystickc():
|
||||
def __init__(self):
|
||||
self.__vertpin = ADC(28)
|
||||
self.__horzpin = ADC(27)
|
||||
self.__selpin = Pin(8, Pin.IN, Pin.PULL_UP)
|
||||
|
||||
def getvertical(self):
|
||||
temp = self.__vertpin.read_u16()
|
||||
temp = temp * (3.3 / 65535)
|
||||
if temp > 2:
|
||||
return 1
|
||||
elif temp < 1:
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def gethorizontal(self):
|
||||
temp = self.__horzpin.read_u16()
|
||||
temp = temp * (3.3 / 65535)
|
||||
if temp > 2:
|
||||
return 1
|
||||
elif temp < 1:
|
||||
return -1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def getsel(self):
|
||||
while True:
|
||||
temp = self.__selpin.value()
|
||||
print(temp)
|
||||
if temp == 1:
|
||||
return True
|
||||
elif temp == 0:
|
||||
return False
|
||||
else:
|
||||
print("joystick error.")
|
||||
|
||||
joystick = joystickc()
|
||||
|
||||
lcd.clear()
|
||||
lcd.putstr("joystick...OK")
|
||||
|
||||
#init action buttons
|
||||
time.sleep(0.1)
|
||||
lcd.clear()
|
||||
lcd.putstr("action buttons...")
|
||||
|
||||
class actionbuttonsc():
|
||||
def __init__(self):
|
||||
self.button1 = False
|
||||
self.button2 = False
|
||||
|
||||
self.__action1butt = Pin(6, Pin.IN, Pin.PULL_DOWN)
|
||||
self.__action2butt = Pin(7, Pin.IN, Pin.PULL_DOWN)
|
||||
|
||||
self.__action1butt.irq(trigger=Pin.IRQ_RISING, handler=self.button1on)
|
||||
self.__action1butt.irq(trigger=Pin.IRQ_FALLING, handler=self.button1off)
|
||||
|
||||
self.__action2butt.irq(trigger=Pin.IRQ_RISING, handler=self.button2on)
|
||||
self.__action2butt.irq(trigger=Pin.IRQ_FALLING, handler=self.button2off)
|
||||
|
||||
def button1on(self):
|
||||
self.button1 = True
|
||||
|
||||
def button1off(self):
|
||||
self.button1 = False
|
||||
|
||||
def button2on(self):
|
||||
self.button2 = True
|
||||
|
||||
def button2off(self):
|
||||
self.button2 = False
|
||||
|
||||
actionbuttons = actionbuttonsc()
|
||||
|
||||
lcd.clear()
|
||||
lcd.putstr("action buttons...OK")
|
||||
|
||||
time.sleep(3)
|
||||
|
||||
def selectoption(title, options):
|
||||
selectedoption = 0
|
||||
while True:
|
||||
lcd.move_to(0, 0)
|
||||
lcd.clear()
|
||||
lcd.putstr(title)
|
||||
lcd.move_to(0, 1)
|
||||
lcd.putstr(options[selectedoption])
|
||||
while True:
|
||||
temp = joystick.gethorizontal()
|
||||
selected = joystick.getsel()
|
||||
if selected == True:
|
||||
break
|
||||
if temp == 1:
|
||||
if selectedoption != 0:
|
||||
selectedoption -= 1
|
||||
else:
|
||||
selectedoption = len(options)-1
|
||||
time.sleep(0.1)
|
||||
break
|
||||
elif temp == -1:
|
||||
if selectedoption != len(options)-1:
|
||||
selectedoption += 1
|
||||
else:
|
||||
selectedoption = 0
|
||||
time.sleep(0.1)
|
||||
break
|
||||
if selected == True:
|
||||
break
|
||||
lcd.move_to(0, 0)
|
||||
lcd.clear()
|
||||
return selectedoption
|
||||
|
||||
option = selectoption("select mode", ["test mode.", "game mode."])
|
||||
if option == 1:
|
||||
while True:
|
||||
lcd.clear()
|
||||
lcd.move_to(0, 0)
|
||||
lcd.putstr("horz: "+str(joystick.gethorizontal()))
|
||||
lcd.move_to(0, 1)
|
||||
lcd.putstr("vert: "+str(joystick.getvertical()))
|
||||
|
||||
lcd.clear()
|
||||
lcd.putstr("loading games...")
|
||||
|
||||
games = {}
|
||||
for i in os.listdir("games"):
|
||||
path = "games/"+i
|
||||
lcd.clear()
|
||||
lcd.putstr(i)
|
||||
codefile = open(path+"main.py", 'r')
|
||||
code = codefile.read()
|
||||
codefile.close()
|
||||
games[i] = code
|
||||
|
||||
lcd.clear()
|
||||
lcd.putstr("<- spiele ->")
|
||||
|
||||
buzzer.duty_u16(0)
|
|
@ -0,0 +1,98 @@
|
|||
"""
|
||||
MicroPython max7219 cascadable 8x8 LED matrix driver
|
||||
https://github.com/mcauser/micropython-max7219
|
||||
|
||||
MIT License
|
||||
Copyright (c) 2017 Mike Causer
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
"""
|
||||
from micropython import const
|
||||
import framebuf
|
||||
|
||||
_NOOP = const(0)
|
||||
_DIGIT0 = const(1)
|
||||
_DECODEMODE = const(9)
|
||||
_INTENSITY = const(10)
|
||||
_SCANLIMIT = const(11)
|
||||
_SHUTDOWN = const(12)
|
||||
_DISPLAYTEST = const(15)
|
||||
|
||||
class Matrix8x8:
|
||||
def __init__(self, spi, cs, num):
|
||||
"""
|
||||
Driver for cascading MAX7219 8x8 LED matrices.
|
||||
|
||||
>>> import max7219
|
||||
>>> from machine import Pin, SPI
|
||||
>>> spi = SPI(1)
|
||||
>>> display = max7219.Matrix8x8(spi, Pin('X5'), 4)
|
||||
>>> display.text('1234',0,0,1)
|
||||
>>> display.show()
|
||||
|
||||
"""
|
||||
self.spi = spi
|
||||
self.cs = cs
|
||||
self.cs.init(cs.OUT, True)
|
||||
self.buffer = bytearray(8 * num)
|
||||
self.num = num
|
||||
fb = framebuf.FrameBuffer(self.buffer, 8 * num, 8, framebuf.MONO_HLSB)
|
||||
self.framebuf = fb
|
||||
# Provide methods for accessing FrameBuffer graphics primitives. This is a workround
|
||||
# because inheritance from a native class is currently unsupported.
|
||||
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
|
||||
self.fill = fb.fill # (col)
|
||||
self.pixel = fb.pixel # (x, y[, c])
|
||||
self.hline = fb.hline # (x, y, w, col)
|
||||
self.vline = fb.vline # (x, y, h, col)
|
||||
self.line = fb.line # (x1, y1, x2, y2, col)
|
||||
self.rect = fb.rect # (x, y, w, h, col)
|
||||
self.fill_rect = fb.fill_rect # (x, y, w, h, col)
|
||||
self.text = fb.text # (string, x, y, col=1)
|
||||
self.scroll = fb.scroll # (dx, dy)
|
||||
self.blit = fb.blit # (fbuf, x, y[, key])
|
||||
self.init()
|
||||
|
||||
def _write(self, command, data):
|
||||
self.cs(0)
|
||||
for m in range(self.num):
|
||||
self.spi.write(bytearray([command, data]))
|
||||
self.cs(1)
|
||||
|
||||
def init(self):
|
||||
for command, data in (
|
||||
(_SHUTDOWN, 0),
|
||||
(_DISPLAYTEST, 0),
|
||||
(_SCANLIMIT, 7),
|
||||
(_DECODEMODE, 0),
|
||||
(_SHUTDOWN, 1),
|
||||
):
|
||||
self._write(command, data)
|
||||
|
||||
def brightness(self, value):
|
||||
if not 0 <= value <= 15:
|
||||
raise ValueError("Brightness out of range")
|
||||
self._write(_INTENSITY, value)
|
||||
|
||||
def show(self):
|
||||
for y in range(8):
|
||||
self.cs(0)
|
||||
for m in range(self.num):
|
||||
self.spi.write(bytearray([_DIGIT0 + y, self.buffer[(y * self.num) + m]]))
|
||||
self.cs(1)
|
|
@ -0,0 +1,86 @@
|
|||
import utime
|
||||
import gc
|
||||
|
||||
from lcd_api import LcdApi
|
||||
from machine import I2C
|
||||
|
||||
# PCF8574 pin definitions
|
||||
MASK_RS = 0x01 # P0
|
||||
MASK_RW = 0x02 # P1
|
||||
MASK_E = 0x04 # P2
|
||||
|
||||
SHIFT_BACKLIGHT = 3 # P3
|
||||
SHIFT_DATA = 4 # P4-P7
|
||||
|
||||
class I2cLcd(LcdApi):
|
||||
|
||||
#Implements a HD44780 character LCD connected via PCF8574 on I2C
|
||||
|
||||
def __init__(self, i2c, i2c_addr, num_lines, num_columns):
|
||||
self.i2c = i2c
|
||||
self.i2c_addr = i2c_addr
|
||||
self.i2c.writeto(self.i2c_addr, bytes([0]))
|
||||
utime.sleep_ms(20) # Allow LCD time to powerup
|
||||
# Send reset 3 times
|
||||
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
|
||||
utime.sleep_ms(5) # Need to delay at least 4.1 msec
|
||||
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
|
||||
utime.sleep_ms(1)
|
||||
self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
|
||||
utime.sleep_ms(1)
|
||||
# Put LCD into 4-bit mode
|
||||
self.hal_write_init_nibble(self.LCD_FUNCTION)
|
||||
utime.sleep_ms(1)
|
||||
LcdApi.__init__(self, num_lines, num_columns)
|
||||
cmd = self.LCD_FUNCTION
|
||||
if num_lines > 1:
|
||||
cmd |= self.LCD_FUNCTION_2LINES
|
||||
self.hal_write_command(cmd)
|
||||
gc.collect()
|
||||
|
||||
def hal_write_init_nibble(self, nibble):
|
||||
# Writes an initialization nibble to the LCD.
|
||||
# This particular function is only used during initialization.
|
||||
byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte]))
|
||||
gc.collect()
|
||||
|
||||
def hal_backlight_on(self):
|
||||
# Allows the hal layer to turn the backlight on
|
||||
self.i2c.writeto(self.i2c_addr, bytes([1 << SHIFT_BACKLIGHT]))
|
||||
gc.collect()
|
||||
|
||||
def hal_backlight_off(self):
|
||||
#Allows the hal layer to turn the backlight off
|
||||
self.i2c.writeto(self.i2c_addr, bytes([0]))
|
||||
gc.collect()
|
||||
|
||||
def hal_write_command(self, cmd):
|
||||
# Write a command to the LCD. Data is latched on the falling edge of E.
|
||||
byte = ((self.backlight << SHIFT_BACKLIGHT) |
|
||||
(((cmd >> 4) & 0x0f) << SHIFT_DATA))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte]))
|
||||
byte = ((self.backlight << SHIFT_BACKLIGHT) |
|
||||
((cmd & 0x0f) << SHIFT_DATA))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte]))
|
||||
if cmd <= 3:
|
||||
# The home and clear commands require a worst case delay of 4.1 msec
|
||||
utime.sleep_ms(5)
|
||||
gc.collect()
|
||||
|
||||
def hal_write_data(self, data):
|
||||
# Write data to the LCD. Data is latched on the falling edge of E.
|
||||
byte = (MASK_RS |
|
||||
(self.backlight << SHIFT_BACKLIGHT) |
|
||||
(((data >> 4) & 0x0f) << SHIFT_DATA))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte]))
|
||||
byte = (MASK_RS |
|
||||
(self.backlight << SHIFT_BACKLIGHT) |
|
||||
((data & 0x0f) << SHIFT_DATA))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
|
||||
self.i2c.writeto(self.i2c_addr, bytes([byte]))
|
||||
gc.collect()
|
Loading…
Reference in New Issue