from machine import Pin, I2C
import utime
from ssd1306 import SSD1306_I2C
debug = False
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000)
oled = SSD1306_I2C(128, 64, i2c)
keyName = [['1', '2', '3', '+'], ['4', '5', '6', '-'], ['7', '8', '9', '*'], ['c', '0', '=', '/']]
keyDescriptions = [['1', '2', '3', 'Addition (+)'], ['4', '5', '6', 'Subtraction (-)'], ['7', '8', '9', 'Multiplication (*)'], ['Clear (c)', '0', 'Equals (=)', 'Division (/)']]
keypadRowPins = [13, 12, 11, 10]
keypadColPins = [9, 8, 7, 6]
row = [Pin(i, Pin.IN, Pin.PULL_UP) for i in keypadRowPins]
col = [Pin(i, Pin.OUT) for i in keypadColPins]
keypadState = [[0] * 4 for _ in range(4)]
def solve(oprt, oprdA, oprdB):
if oprt == "+":
return oprdA + oprdB
elif oprt == "-":
return oprdA - oprdB
elif oprt == "*":
return oprdA * oprdB
elif oprt == "/":
return round(oprdA / oprdB, 6)
def calc(lst):
operand, operator = [], []
for i in lst:
if debug: print(i)
if i in ('+', '-', '*', '/'):
while operator and operator[-1] in ('*', '/', '-', '+'):
b, a, c = operand.pop(), operand.pop(), operator.pop()
operand.append(solve(c, a, b))
operator.append(i)
elif i == '(':
operator.append(i)
elif i == ')':
while operator[-1] != '(':
b, a, c = operand.pop(), operand.pop(), operator.pop()
operand.append(solve(c, a, b))
operator.pop()
else:
operand.append(i)
while operator:
b, a, c = operand.pop(), operand.pop(), operator.pop()
operand.append(solve(c, a, b))
return operand[0]
def keypadRead():
global row
j_ifPressed = i_ifPressed = -1
for i in range(len(col)):
col[i].low()
utime.sleep(0.005) # settling time
for j in range(len(row)):
pressed = not row[j].value()
if pressed and (keypadState[j][i] != pressed):
keypadState[j][i] = pressed
elif not pressed and (keypadState[j][i] != pressed):
keypadState[j][i] = pressed
j_ifPressed, i_ifPressed = j, i
col[i].high()
return keyName[j_ifPressed][i_ifPressed] if j_ifPressed != -1 and i_ifPressed != -1 else -1
def printOled(lst):
oledPos = {"x": 0, "y": 0}
oled.fill(0)
string = ''.join(map(str, lst))
for l in range(0, len(string), 16):
oled.text(string[l:l + 16], oledPos["x"], oledPos["y"])
oledPos["y"] += 10
oled.show()
shiftFlag, signFlag, inputList = False, False, ['']
oled.show()
oled.fill(0)
oled.show()
oled.text("Simple", 35, 15, 1)
oled.text("Calculator", 18, 30, 1)
oled.show()
# Print keybindings to console
print("Key Bindings:")
for i in range(len(keyName)):
for j in range(len(keyName[i])):
print(f"Key '{keyName[i][j]}' - {keyDescriptions[i][j]}")
while True:
key = keypadRead()
if key != -1:
if '0' <= key <= '9' or key == '.':
inputList[-1] += key
elif key in ('+', '-', '*', '/'):
if inputList and inputList[-1] and inputList[-1][-1] in ('+', '-', '*', '/'):
inputList[-1] = key
else:
inputList[-1] = float(inputList[-1]) if inputList[-1] else ''
inputList.extend([key, ''])
elif key == 's':
shiftFlag = not shiftFlag
elif key == 'a':
if shiftFlag:
if inputList[-1]:
inputList[-1] = float(inputList[-1])
inputList.extend([')', ''])
else:
inputList[-1] = ')'
inputList.append('')
shiftFlag = False
else:
signFlag = not signFlag
inputList[-1] = '-' + inputList[-1] if inputList[-1] and inputList[-1][0] != '-' else inputList[-1][1:]
elif key == 'b':
if shiftFlag:
inputList[-1] = '(' if not inputList[-1] else inputList[-1]
inputList.extend(['(', ''])
shiftFlag = False
else:
inputList[-1] = 3.14 if not inputList[-1] else inputList[-1]
inputList.extend([3.14, ''])
elif key == 'c':
if shiftFlag:
inputList = ['']
shiftFlag = False
else:
if inputList == ["error"]:
inputList = ['']
if inputList[-1]:
inputList[-1] = inputList[-1][:-1]
if not inputList[-1]:
inputList.pop(-1)
elif key == '=':
if not inputList[-1]:
inputList.pop(-1)
elif inputList[-1] != ')':
inputList[-1] = float(inputList[-1])
try:
ans = calc(inputList)
inputList = [str(ans)]
except:
ans = ''
inputList = []
inputList.append("error")
printOled(inputList)