import utime
from machine import Pin
# ============================
# SHIFT REGISTER (74HC595)
# ============================
DS = Pin(7, Pin.OUT) # serial data
STCP = Pin(8, Pin.OUT) # latch
SHCP = Pin(9, Pin.OUT) # clock
def shift_out(byte):
"""Send 8 bits to 74HC595"""
for i in range(8):
SHCP.value(0)
DS.value((byte >> (7 - i)) & 1)
SHCP.value(1)
STCP.value(0)
STCP.value(1)
# ============================
# LCD via 74HC595
# ============================
class ShiftLCD:
# LCD bit positions on 74HC595:
RS = 0
E = 1
D4 = 2
D5 = 3
D6 = 4
D7 = 5
def __init__(self):
self.init_lcd()
def send_nibble(self, nibble, rs_value):
"""Output 4 bits to LCD through the shift register"""
byte = 0
byte |= (rs_value << self.RS)
byte |= (1 << self.E) # E HIGH
byte |= ((nibble >> 0) & 1) << self.D4
byte |= ((nibble >> 1) & 1) << self.D5
byte |= ((nibble >> 2) & 1) << self.D6
byte |= ((nibble >> 3) & 1) << self.D7
shift_out(byte)
# Toggle E to latch nibble
utime.sleep_us(1)
byte &= ~(1 << self.E) # E LOW
shift_out(byte)
utime.sleep_us(50)
def send_byte(self, byte, rs):
self.send_nibble(byte >> 4, rs)
self.send_nibble(byte & 0x0F, rs)
def command(self, cmd):
self.send_byte(cmd, 0)
def write_char(self, ch):
self.send_byte(ord(ch), 1)
def clear(self):
self.command(0x01)
utime.sleep_ms(2)
def putstr(self, text):
for c in text:
if c == "\n":
self.command(0xC0) # Line 2
else:
self.write_char(c)
def init_lcd(self):
utime.sleep_ms(20)
self.send_nibble(0x03, 0)
utime.sleep_ms(5)
self.send_nibble(0x03, 0)
utime.sleep_us(150)
self.send_nibble(0x03, 0)
self.send_nibble(0x02, 0) # 4-bit mode
self.command(0x28) # 2-line, 5x8 font
self.command(0x0C) # Display ON
self.command(0x06) # Entry mode
self.clear()
# Create LCD Object
lcd = ShiftLCD()
# ============================
# KEYPAD
# ============================
col_list = [4, 14, 15, 17]
row_list = [18, 27, 22, 21]
for x in range(4):
row_list[x] = Pin(row_list[x], Pin.OUT, value=1)
for x in range(4):
col_list[x] = Pin(col_list[x], Pin.IN, Pin.PULL_UP)
key_map = [
["D", "#", "0", "*"],
["C", "9", "8", "7"],
["B", "6", "5", "4"],
["A", "3", "2", "1"]
]
def Keypad4x4Read(cols, rows):
for r in rows:
r.value(0)
result = [c.value() for c in cols]
if min(result) == 0:
key = key_map[rows.index(r)][result.index(0)]
utime.sleep(0.2)
r.value(1)
return key
r.value(1)
return None
PINCode = "1234"
invalidPIN = False
def waitForInputPIN():
global invalidPIN
while True:
lcd.clear()
if invalidPIN:
lcd.putstr("Wrong PIN,\ntry again:")
else:
lcd.putstr("Enter your PIN:")
inputedPIN = ""
key = None
while key != '#':
key = Keypad4x4Read(col_list, row_list)
if key and key != "#":
lcd.write_char("*")
inputedPIN += key
utime.sleep(0.2)
if inputedPIN == PINCode:
lcd.clear()
lcd.putstr("Welcome!")
utime.sleep(1.5)
return True
else:
invalidPIN = True
def getMessageFromKeypad():
lcd.clear()
lcd.putstr("Enter text:\n")
message = ""
key = None
while True:
key = Keypad4x4Read(col_list, row_list)
if key:
if key == '#':
lcd.clear()
lcd.putstr("Final Msg:\n" + message)
break
elif key == '*':
if len(message) > 0:
message = message[:-1]
lcd.clear()
lcd.putstr("Enter text:\n" + message)
else:
message += key
lcd.clear()
lcd.putstr("Enter text:\n" + message)
utime.sleep(0.2)
# ============================
# RUN PROGRAM
# ============================
if waitForInputPIN():
getMessageFromKeypad()