diff options
Diffstat (limited to 'recourses/Keypad.py')
| -rw-r--r-- | recourses/Keypad.py | 202 |
1 files changed, 0 insertions, 202 deletions
diff --git a/recourses/Keypad.py b/recourses/Keypad.py deleted file mode 100644 index f762b4b..0000000 --- a/recourses/Keypad.py +++ /dev/null | |||
| @@ -1,202 +0,0 @@ | |||
| 1 | #!/usr/bin/env python3 | ||
| 2 | |||
| 3 | import RPi.GPIO as GPIO | ||
| 4 | import time | ||
| 5 | #class Key:Define some of the properties of Key | ||
| 6 | class Key(object): | ||
| 7 | NO_KEY = '\0' | ||
| 8 | #Defines the four states of Key | ||
| 9 | IDLE = 0 | ||
| 10 | PRESSED = 1 | ||
| 11 | HOLD = 2 | ||
| 12 | RELEASED = 3 | ||
| 13 | #define OPEN and CLOSED | ||
| 14 | OPEN = 0 | ||
| 15 | CLOSED =1 | ||
| 16 | #constructor | ||
| 17 | def __init__(self): | ||
| 18 | self.kchar = self.NO_KEY | ||
| 19 | self.kstate = self.IDLE | ||
| 20 | self.kcode = -1 | ||
| 21 | self.stateChanged = False | ||
| 22 | |||
| 23 | class Keypad(object): | ||
| 24 | NULL = '\0' | ||
| 25 | LIST_MAX = 10 #Max number of keys on the active list. | ||
| 26 | MAPSIZE = 10 #MAPSIZE is the number of rows (times 16 columns) | ||
| 27 | bitMap = [0]*MAPSIZE | ||
| 28 | key = [Key()]*LIST_MAX | ||
| 29 | holdTime = 500 #key hold time | ||
| 30 | holdTimer = 0 | ||
| 31 | startTime = 0 | ||
| 32 | #Allows custom keymap, pin configuration, and keypad sizes. | ||
| 33 | def __init__(self,usrKeyMap,row_Pins,col_Pins,num_Rows,num_Cols): | ||
| 34 | GPIO.setmode(GPIO.BOARD) | ||
| 35 | self.rowPins = row_Pins | ||
| 36 | self.colPins = col_Pins | ||
| 37 | self.numRows = num_Rows | ||
| 38 | self.numCols = num_Cols | ||
| 39 | |||
| 40 | self.keymap = usrKeyMap | ||
| 41 | self.setDebounceTime(10) | ||
| 42 | #Returns a single key only. Retained for backwards compatibility. | ||
| 43 | def getKey(self): | ||
| 44 | single_key = True | ||
| 45 | if(self.getKeys() and self.key[0].stateChanged and (self.key[0].kstate == self.key[0].PRESSED)): | ||
| 46 | return self.key[0].kchar | ||
| 47 | single_key = False | ||
| 48 | return self.key[0].NO_KEY | ||
| 49 | #Populate the key list. | ||
| 50 | def getKeys(self): | ||
| 51 | keyActivity = False | ||
| 52 | #Limit how often the keypad is scanned. | ||
| 53 | if((time.time() - self.startTime) > self.debounceTime*0.001): | ||
| 54 | self.scanKeys() | ||
| 55 | keyActivity = self.updateList() | ||
| 56 | self.startTime = time.time() | ||
| 57 | return keyActivity | ||
| 58 | #Hardware scan ,the result store in bitMap | ||
| 59 | def scanKeys(self): | ||
| 60 | #Re-intialize the row pins. Allows sharing these pins with other hardware. | ||
| 61 | for pin_r in self.rowPins: | ||
| 62 | GPIO.setup(pin_r,GPIO.IN,pull_up_down = GPIO.PUD_UP) | ||
| 63 | #bitMap stores ALL the keys that are being pressed. | ||
| 64 | for pin_c in self.colPins: | ||
| 65 | GPIO.setup(pin_c,GPIO.OUT) | ||
| 66 | GPIO.output(pin_c,GPIO.LOW) | ||
| 67 | for r in self.rowPins: #keypress is active low so invert to high. | ||
| 68 | self.bitMap[self.rowPins.index(r)] = self.bitWrite(self.bitMap[self.rowPins.index(r)],self.colPins.index(pin_c),not GPIO.input(r)) | ||
| 69 | #Set pin to high impedance input. Effectively ends column pulse. | ||
| 70 | GPIO.output(pin_c,GPIO.HIGH) | ||
| 71 | GPIO.setup(pin_c,GPIO.IN) | ||
| 72 | #Manage the list without rearranging the keys. Returns true if any keys on the list changed state. | ||
| 73 | def updateList(self): | ||
| 74 | anyActivity = False | ||
| 75 | kk = Key() | ||
| 76 | #Delete any IDLE keys | ||
| 77 | for i in range(self.LIST_MAX): | ||
| 78 | if(self.key[i].kstate == kk.IDLE): | ||
| 79 | self.key[i].kchar = kk.NO_KEY | ||
| 80 | self.key[i].kcode = -1 | ||
| 81 | self.key[i].stateChanged = False | ||
| 82 | # Add new keys to empty slots in the key list. | ||
| 83 | for r in range(self.numRows): | ||
| 84 | for c in range(self.numCols): | ||
| 85 | button = self.bitRead(self.bitMap[r],c) | ||
| 86 | keyChar = self.keymap[r * self.numCols +c] | ||
| 87 | keyCode = r * self.numCols +c | ||
| 88 | idx = self.findInList(keyCode) | ||
| 89 | #Key is already on the list so set its next state. | ||
| 90 | if(idx > -1): | ||
| 91 | self.nextKeyState(idx,button) | ||
| 92 | #Key is NOT on the list so add it. | ||
| 93 | if((idx == -1) and button): | ||
| 94 | for i in range(self.LIST_MAX): | ||
| 95 | if(self.key[i].kchar == kk.NO_KEY): #Find an empty slot or don't add key to list. | ||
| 96 | self.key[i].kchar = keyChar | ||
| 97 | self.key[i].kcode = keyCode | ||
| 98 | self.key[i].kstate = kk.IDLE #Keys NOT on the list have an initial state of IDLE. | ||
| 99 | self.nextKeyState(i,button) | ||
| 100 | break #Don't fill all the empty slots with the same key. | ||
| 101 | #Report if the user changed the state of any key. | ||
| 102 | for i in range(self.LIST_MAX): | ||
| 103 | if(self.key[i].stateChanged): | ||
| 104 | anyActivity = True | ||
| 105 | return anyActivity | ||
| 106 | #This function is a state machine but is also used for debouncing the keys. | ||
| 107 | def nextKeyState(self,idx, button): | ||
| 108 | self.key[idx].stateChanged = False | ||
| 109 | kk = Key() | ||
| 110 | if(self.key[idx].kstate == kk.IDLE): | ||
| 111 | if(button == kk.CLOSED): | ||
| 112 | self.transitionTo(idx,kk.PRESSED) | ||
| 113 | self.holdTimer = time.time() #Get ready for next HOLD state. | ||
| 114 | elif(self.key[idx].kstate == kk.PRESSED): | ||
| 115 | if((time.time() - self.holdTimer) > self.holdTime*0.001): #Waiting for a key HOLD... | ||
| 116 | self.transitionTo(idx,kk.HOLD) | ||
| 117 | elif(button == kk.OPEN): # or for a key to be RELEASED. | ||
| 118 | self.transitionTo(idx,kk.RELEASED) | ||
| 119 | elif(self.key[idx].kstate == kk.HOLD): | ||
| 120 | if(button == kk.OPEN): | ||
| 121 | self.transitionTo(idx,kk.RELEASED) | ||
| 122 | elif(self.key[idx].kstate == kk.RELEASED): | ||
| 123 | self.transitionTo(idx,kk.IDLE) | ||
| 124 | |||
| 125 | def transitionTo(self,idx,nextState): | ||
| 126 | self.key[idx].kstate = nextState | ||
| 127 | self.key[idx].stateChanged = True | ||
| 128 | #Search by code for a key in the list of active keys. | ||
| 129 | #Returns -1 if not found or the index into the list of active keys. | ||
| 130 | def findInList(self,keyCode): | ||
| 131 | for i in range(self.LIST_MAX): | ||
| 132 | if(self.key[i].kcode == keyCode): | ||
| 133 | return i | ||
| 134 | return -1 | ||
| 135 | #set Debounce Time, The default is 50ms | ||
| 136 | def setDebounceTime(self,ms): | ||
| 137 | self.debounceTime = ms | ||
| 138 | #set HoldTime,The default is 500ms | ||
| 139 | def setHoldTime(self,ms): | ||
| 140 | self.holdTime = ms | ||
| 141 | # | ||
| 142 | def isPressed(keyChar): | ||
| 143 | for i in range(self.LIST_MAX): | ||
| 144 | if(self.key[i].kchar == keyChar): | ||
| 145 | if(self.key[i].kstate == self.self.key[i].PRESSED and self.key[i].stateChanged): | ||
| 146 | return True | ||
| 147 | return False | ||
| 148 | # | ||
| 149 | def waitForKey(): | ||
| 150 | kk = Key() | ||
| 151 | waitKey = kk.NO_KEY | ||
| 152 | while(waitKey == kk.NO_KEY): | ||
| 153 | waitKey = getKey() | ||
| 154 | return waitKey | ||
| 155 | |||
| 156 | def getState(): | ||
| 157 | return self.key[0].kstate | ||
| 158 | # | ||
| 159 | def keyStateChanged(): | ||
| 160 | return self.key[0].stateChanged | ||
| 161 | |||
| 162 | def bitWrite(self,x,n,b): | ||
| 163 | if(b): | ||
| 164 | x |= (1<<n) | ||
| 165 | else: | ||
| 166 | x &=(~(1<<n)) | ||
| 167 | return x | ||
| 168 | def bitRead(self,x,n): | ||
| 169 | if((x>>n)&1 == 1): | ||
| 170 | return True | ||
| 171 | else: | ||
| 172 | return False | ||
| 173 | |||
| 174 | ROWS = 4 | ||
| 175 | COLS = 4 | ||
| 176 | keys = [ '1','2','3','A', | ||
| 177 | '4','5','6','B', | ||
| 178 | '7','8','9','C', | ||
| 179 | '*','0','#','D' ] | ||
| 180 | rowsPins = [12,16,18,22] | ||
| 181 | colsPins = [19,15,13,11] | ||
| 182 | |||
| 183 | def loop(): | ||
| 184 | keypad = Keypad(keys,rowsPins,colsPins,ROWS,COLS) | ||
| 185 | keypad.setDebounceTime(50) | ||
| 186 | while(True): | ||
| 187 | key = keypad.getKey() | ||
| 188 | if(key != keypad.NULL): | ||
| 189 | print ("You Pressed Key : %c "%(key) ) | ||
| 190 | |||
| 191 | if __name__ == '__main__': # Program start from here | ||
| 192 | print ("Program is starting ... ") | ||
| 193 | try: | ||
| 194 | loop() | ||
| 195 | except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed. | ||
| 196 | pass | ||
| 197 | GPIO.cleanup() | ||
| 198 | |||
| 199 | |||
| 200 | |||
| 201 | |||
| 202 | |||
