-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathkeypad16.py
115 lines (102 loc) · 4.1 KB
/
keypad16.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/python
#
# keypad16.py
#
# Jan.25/2015: v1.00 released
#
# 4x4 matrix keypad via MCP23017 I2C I/O expander Python library
# for the Raspberry Pi. Please see URL below for the introductory article.
#
# http://www.mikronauts.com/raspberry-pi/raspberry-pi-4x4-keypad-i2c-MCP23017-howto/
#
# Copyright 2015 William Henning
# http://Mikronauts.com
#
# If the smbus module is re-entrant (ie allows multiple Python clients, keypad16
# supports multiple keypad modules simultaneously, requires one port of an
# MCP23017 I2C I/O port expander per keypad
#
# tested with generic 4x4 matrix keypad, right side up and up side down
#
# should also work unchanged with 4x3 keypad
#
# modified by Stephen B. Kirby to work with MCP23008 and added function getkey for
# calls from an external loop - December 2, 2016
import smbus
import time
#keypad_module(i2c_address, port_offset, upside_down)
class keypad_module:
I2CADDR = 0x20 # valid range is 0x20 - 0x27
UPSIDEDOWN = 1 # direction keypad is facing in
PORT = 0 # 0 for GPIOA, 1 for GPIOB
# settings for MCP23008
IODIRA = 0x00 # I/O direction register base address
PULUPA = 0x06 # PullUp enable register base address
GPIOA = 0x09 # GPIO pin register base address
OLATA = 0x0A # Output Latch register base address
# settings for MCP23017
# IODIRA = 0x00 # I/O direction register base address
# PULUPA = 0x0C # PullUp enable register base address
# GPIOA = 0x12 # GPIO pin register base address
# OLATA = 0x14 # Output Latch register base address
# Keypad Column output values
KEYCOL = [0b11110111,0b11111011,0b11111101,0b11111110]
# Keypad Keycode matrix
KEYCODE = [['1','4','7','*'], # KEYCOL0
['2','5','8','0'], # KEYCOL1
['3','6','9','#'], # KEYCOL2
['A','B','C','D']] # KEYCOL3
# Decide the row
DECODE = [0,0,0,0, 0,0,0,0, 0,0,0,1, 0,2,3,0]
# initialize I2C comm, 1 = rev2 Pi, 0 for Rev1 Pi
i2c = smbus.SMBus(1)
# get a keystroke from the keypad
def getch(self):
while 1:
for col in range(0,4):
time.sleep(0.01)
self.i2c.write_byte_data(self.I2CADDR, self.OLATA+self.port, self.KEYCOL[col]) # write 0 to lowest four bits
key = self.i2c.read_byte_data(self.I2CADDR, self.GPIOA+self.port) >> 4
if (key) != 0b1111:
row = self.DECODE[key]
time.sleep(0.01)
while (self.i2c.read_byte_data(self.I2CADDR, self.GPIOA+self.port) >> 4) != 15: # commented out by sbk
time.sleep(0.01)
if self.UPSIDEDOWN == 0:
return self.KEYCODE[col][row] # keypad right side up
else:
return self.KEYCODE[3-row][3-col] # keypad upside down
# get a keystroke from the keypad if called from external loop - sbk
def getkey(self):
for col in range(0,4):
time.sleep(0.01)
self.i2c.write_byte_data(self.I2CADDR, self.OLATA+self.port, self.KEYCOL[col]) # write 0 to lowest four bits
key = self.i2c.read_byte_data(self.I2CADDR, self.GPIOA+self.port) >> 4
if (key) != 0b1111:
row = self.DECODE[key]
time.sleep(0.01)
#while (self.i2c.read_byte_data(self.I2CADDR, self.GPIOA+self.port) >> 4) != 15: # commented out by sbk
#time.sleep(0.01)
if self.UPSIDEDOWN == 0:
return self.KEYCODE[col][row] # keypad right side up
else:
return self.KEYCODE[3-row][3-col] # keypad upside down
# initialize the keypad class
def __init__(self,addr,ioport,upside):
self.I2CADDR = addr
self.UPSIDEDOWN = upside
self.port = ioport
self.i2c.write_byte_data(self.I2CADDR, self.IODIRA + self.port, 0xF0) # upper 4 bits are inputs
self.i2c.write_byte_data(self.I2CADDR, self.PULUPA + self.port, 0xF0) # enable upper 4 bits pullups
# test code
def main():
keypad = keypad_module(0x20,0,0)
while 1:
ch = keypad.getch()
print ch
time.sleep(0.5) # sbk
if ch == 'D':
exit()
# don't runt test code if we are imported
if __name__ == '__main__':
main()