Now I have more cleaning ups. The function GetKey loops until a pressing key causes a change in GPIO register (GP4~4 corresponding to Rows 0~3), then reads row and column, calculate the key number.
Next step is to add an option to GetKey to poll Interrupt Capture Register contents instaed of GPIO Port contents change.
def GetKey(registerBaseAddress, pollData):
GpioPortGP4ToGP7 = 0
IntCapICP4ToICP7 = 1
if (pollData == GpioPortGP4ToGP7):
LoopUntilRowDataByteChange(registerBaseAddress)
elif (pollData == IntCapICP4ToICP7):
LoopUntilInterruptCaptureByteChange(registerBaseAddress)
rowNumber = GetRowNumber(registerBaseAddress)
columnNumber = GetColumnNumber(registerBaseAddress)
keyNumber = GetKeyNumber(rowNumber, columnNumber)
return keyNumber
The sample output looks OK
#*** Program to test decimal keypad - v4.2 TL Fong 2013jan10 ***
#Press keypad 4 times.
#Key pressed = 01
#Key pressed = 04
#Key pressed = 07
#Key pressed = 10
#Interrupt flag nibble = 0111
#Interrupt flag nibble = 1111
#Interrupt flag nibble = 1111
#Interrupt flag nibble = 1110
#Interrupt flag nibble = 1101
#Interrupt flag nibble = 1011
#Interrupt flag nibble = 0111
#Interrupt flag nibble = 0111
# *****************************************************************************
# *** tiox42.py ***
# Program - Test MCP23008 and MCP23017
# Version - 4.2
# Date - 2012nov30
# Update - 2013jan08
# Author - tlfong01
# File - tiox42_2013jan10.py
# Blog - http://tlfong01.blogspot.hk/
# Purpose - test basics of Raspberry Pi GPIO
# License - GNU GPLv3
# Hardware - Raspberry Pi Model B Revsion 2.0 [2012oct/nov/dec]
# Software - Raspbian Wheezy (2012sep15), Python 2.7.3
# GPIO 0.4.1a http://pypi.python.org/pypi/RPi.GPIO/0.4.1a
# Wiring - RPi Board Numbering
# P1-02 5V, P1-04 5V, P1-06 Gnd
# P1-01 3V3, P1-03 I2C SDA1, P1-05 I2C SCL1
# P1-08 UART TxD (MCP23017 Reset)
# P1-10 UART RxD (MCP23017 INTB)
# P1-12 RPi GPIO_GEN1 (BCM18) LED (P1-12 > LED > 330R > Gnd)
# P1-14 Gnd
# P1-16 GPIO_GEN4 - Buzzer, 3V3 5mA (P1-16 > Buzzer > Gnd)
# P1-18 GPIO_GEN5 Button (3V3 > 10K > Contact 1/2 > 330R > Gnd)
# P1-20 Gnd
# P1-22 GPIO_GEN6 - MCP23008 INT / MCP23017 INTA
# *****************************************************************************
# *** Import Python modules ***
import smbus
import sys
import RPi.GPIO as GPIO
from time import sleep
import select # interrupt module
# *****************************************************************************
# * Rpi GPIO pin assignments for LED, buzzer, and button *
GPIO.setmode(GPIO.BOARD) # Use RPi GPIO numbering, Not BCM numbering
GPIO.setwarnings(False) # Disable linux's "pin already in use warning"
# * P1 pins numbering *
RPiGPIOgen1 = 12 # Brown (P1-12, BCM GPIO 18) LED
RPiGPIOgen4 = 16 # Yellow (P1-16, BCM GPIO 23) Buzzer
RPiGPIOgen5 = 18 # Green (P1-18, BCM GPIO 24) Button
RPiGPIOgen6 = 22 # Blue (P1-22, BCM GPIO 25) IOx Interrupt
RPiTxD = 8 # Orange (P1-08) UART TxD
RPiRxD = 10 # Yellow (P1-10) UART RxD
# * IO device pins assignment *
LEDpin = RPiGPIOgen1
BuzzerPin = RPiGPIOgen4
ButtonPin = RPiGPIOgen5
InterruptPin = RPiGPIOgen6
TxDpin = RPiTxD
RxDpin = RPiRxD
# * IO pins list *
OutputPinList = [LEDpin, BuzzerPin, TxDpin]
InputPinWithNoPullUpList = [ButtonPin, RxDpin]
InputPinWithPullUpList = [InterruptPin]
# *****************************************************************************
# * Global constants *
# * Loop counters *
TwoTimes = 2
FourTimes = 4
EightTimes = 8
TenTimes = 10
TwentyTimes = 20
FiftyTimes = 50
OneHundredTimes = 100
TwoHundredTimess = 200
FourHundredTimes = 400
# * Elapse times *
TwentyMilliSeconds = 0.02
FiftyMilliSeconds = 0.05
TenthSecond = 0.1
QuarterSecond = 0.25
HalfSecond = 0.5
OneSecond = 1
OneAndHalfSeconds = 1.5
TwoSeconds = 2
OnTime = TenthSecond
OffTime = QuarterSecond
ButtonDebouncingTime = QuarterSecond
TestTime = FiftyMilliSeconds
# * Nibble naming *
LowNibble = 0
HighNibble = 1
BothNibble = 2 # full byte of 8 bits
# * Nibble constants *
HighNibble1LowNibble0 = 0xf0
HighNibble0LowNibble1 = 0x0f
# * LED and buzzer states *
Off = False
On = True
# * Button states *
ButtonPressed = False
ButonReleased = True
# *****************************************************************************
# * GPIO functions *
# Note: 5V0 max = 50 mA, 3V3 max = 300 mA, per GPIO pin max = 17mA source, 12mA sink
# * Setup, read, write GPIO pins *
setupOutputPin = lambda oPin: GPIO.setup(oPin, GPIO.OUT) # set GPIO pin as output
setupInputPinWithNoPullUp = lambda iPin: GPIO.setup(iPin, GPIO.IN, pull_up_down=GPIO.PUD_OFF) # set GPIO pin as input, no pull up
setupInputPinWithPullUp = lambda iPin: GPIO.setup(iPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # set GPIO pin as input, with pull up
writeOutputPin = lambda oPin, oValue: GPIO.output(oPin, oValue) # write value to output pin
setupWriteOutputPin = lambda oPin, oValue: (setupOutputPin(oPin), writeOutputPin(oPin, oValue)) # set and write
readInputPin = lambda iPin: GPIO.input(ButtonPin) # read value from input pin
def SetupGPIOpins(outputPinList, inputPinWithNoPullUpList, inputPinWithPullUpList): # set up GPIO pins in InputPinList and OutputPinList
for oPin in outputPinList:
setupWriteOutputPin(oPin, Off)
for iPin in inputPinWithNoPullUpList:
setupInputPinWithPullUp(iPin)
for iPin in inputPinWithPullUpList:
setupInputPinWithPullUp(iPin)
def SetupGPIO(): # set up GPIO pins
SetupGPIOpins(OutputPinList, InputPinWithNoPullUpList, InputPinWithPullUpList )
# * pulse and echo functions *
def pulsePin(oPin, onTime, offTime): # blink LED or beep buzzer
writeOutputPin(oPin, On)
sleep(onTime)
writeOutputPin(oPin, Off)
sleep(offTime)
def echoPin(iPin, oPin): # echo input pin to output pin, e.g. button to LED or buzzer
while True:
if readInputPin(iPin) == ButonReleased:
pass
else:
pulsePin(oPin, OnTime, OffTime)
break
continue
def togglePin(oPin, toggleTime): # toggle pin
writeOutputPin(oPin, On)
sleep(toggleTime)
writeOutputPin(oPin, Off)
sleep(toggleTime)
# * Test Buzzer, LED, Button functions *
def TestBuzzer(): # beep 4 times
SetupGPIO()
for i in range (FourTimes):
pulsePin(BuzzerPin, OnTime, OffTime)
def TestLED(): # blink 8 times
SetupGPIO()
for i in range (EightTimes):
pulsePin(LEDpin, OnTime, OffTime)
def TestButtonEchoBuzzer(): #
SetupGPIO()
for i in range (TenTimes):
echoPin(ButtonPin, BuzzerPin)
def TestButtonEchoLED(): #
SetupGPIO()
for i in range (TenTimes):
echoPin(ButtonPin, LEDpin)
def TestToggleTxDpin():
while True:
togglePin(TxDpin, TwoSeconds)
# GPIO Interrupt function !!! not yet tested !!!
def TestInterruptPinFallingEdgeDetection(): # !!! Not tested !!!
GPIO.cleanup() # set all input pins no pull up, disable all interutp detection setting
SetupGPIO()
GPIO.set_low_event(InterruptPin) # set up low level detection
for i in range(30):
if GPIO.event_detected(InterruptPin):
break
else:
print "No interrupt detected.", i
sleep(1)
continue
GPIO.set_low_event(InterruptPin, enable = False) # disable detection
print "End of test, or interrupt detected"
# *****************************************************************************
# * Beep functions *
def Beep(count):
for i in range(count):
pulsePin(BuzzerPin, OnTime, OffTime)
def StartBeep():
Beep(TwoTimes)
sleep(1)
def EndBeep():
Beep(FourTimes)
def OneBeep():
Beep(1)
def FourBeeps():
Beep(4)
# *****************************************************************************
# * MCP23008 / MCP23017 IO Expander *
# * Bash script using i2cTools's i2cset command to toggle GPIO pins *
#!/bin/bash
# i2cset -y 1 0x20 0x00 0x00
# count=0
# while [ $count -lt 10 ];
# do
# i2cset -y 1 0x20 0x0a 0x00
# sleep 0.5
# i2cset -y 1 0x20 0x0a 0xff
# sleep 0.5
# let count++
# done
# To run i2c-X commands in user mode: sudo chmod 666 /dev/i2c-X
# sudo chmod 666 /dev/i2c-1
# To detect I2C device base addresses
# sudo i2cdetect -y 1
# * Setup SMBus *
I2C_BUS_NUMBER = 1 # P1-03 = SDA1, P1-05 = SCL1
smBus1 = smbus.SMBus(I2C_BUS_NUMBER) # global variable, cannot be set by a function
# * Register base addresses *
MCP23017BaseAddress1 = 0x22 # 1 LED, 1 button
MCP23008BaseAddress1 = 0x24 # 2 unipolar stepping motors
MCP23008BaseAddress2 = 0x25 # 1 decimal keypad
# * Port type *
PortA = 0
PortB = 1
# * Byte patterns *
# * Data bytes *
AllOutput = 0x00
AllHigh = 0xff
AllLow = 0x00
AlternateHighLow = 0xaa
AlternateLowHigh = 0x55
# * Direction setting bytes *
HalfHighHalfLow = 0xf0
HalfLowHalfHigh = 0x0f
Nibble1HighNibble2Low = 0xf0
Nibble1LowNibble2High = 0x0f
HighNibbleInputLowNibbleOutput = 0xf0
# * MCP23008/MCP23017 register address offsets *
InputOutputDirection = 0
InputPolarity = 1
InterruptOnChangeEnable = 2
InterruptOnChangeDefaultValue = 3
InterruptOnChangeMode = 4
Configuration = 5
PushPullOpenDrain = 6
InterruptFlag = 7
InterruptCapture = 8
PortStatus = 9
OutputLatch = 10
# * MCP23008/MCP23017 Band0/Band1 register address offset arrays *
RegisterAddressOffsetArray0 = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a]
RegisterAddressOffsetArray1 = [0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x11, 0x13, 0x15, 0x17, 0x19,
0x01, 0x03, 0x05, 0x07, 0x09, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a]
# * Setup MCP23008/MCP23017 ports all output *
def SetupMCP23008PortAllOutput(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)
def SetupMCP23017BothPortAllOutput(registerBaseAddress):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortB, AllOutput)
# * Write/Read MCP23008/MCP23017 registers *
def WriteDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType, dataByte):
if (portType == PortA) | (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
smBus1.write_byte_data(registerBaseAddress, addressOffset, dataByte)
def ReadDataByte(registerBaseAddress, registerAddressArray, dataRegisterIndex, portType):
if (portType == PortA):
addressOffset = registerAddressArray[dataRegisterIndex]
if (portType == PortB):
addressOffset = registerAddressArray[dataRegisterIndex + 11]
dataByte = smBus1.read_byte_data(registerBaseAddress, addressOffset)
return dataByte
# * Test MCP23008/MCP23017 toggle port functions *
def ToggleMCP23008GP(registerBaseAddress, toggleTime, toggleCount):
SetupMCP23008PortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllHigh)
sleep(toggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllLow)
sleep(toggleTime)
def ToggleMCP23017GP(registerBaseAddress, toggleTime, toggleCount):
SetupMCP23017BothPortAllOutput(registerBaseAddress)
for i in range(toggleCount):
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllHigh)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortB, AllHigh)
sleep(toggleTime)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllLow)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortB, AllLow)
sleep(toggleTime)
def TestToggleMCP23008GP():
ToggleTime = 0.5
ToggleCount = 4
ToggleMCP23008GP(MCP23008BaseAddress1, ToggleTime, ToggleCount)
def TestToggleMCP23017GP():
ToggleTime = 0.5
ToggleCount = 4
ToggleMCP23008GP(MCP23017BaseAddress1, ToggleTime, ToggleCount)
# * MCP23008/MCP23017 Interrupt functions *
# * MCP23008 Interrupt setting *
def EnableInterruptOnChangeHighNibble(registerBaseAddress):
EnableInterruptHighNibble = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InterruptOnChangeEnable, PortA, EnableInterruptHighNibble)
def SetInterruptOnChangeDefaultHighNibble(registerBaseAddress):
DefaultValueHighNibble = 0xf0 # GP4~7 (keypad rows input) interrupt default value = High
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InterruptOnChangeDefaultValue, PortA, DefaultValueHighNibble)
def SetInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress):
InterruptOnChangeDefaultValueHighNibble = 0xf0 # GP4~7 change from default value will cause interrupt
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InterruptOnChangeMode, PortA, InterruptOnChangeDefaultValueHighNibble)
def SetInterruptOutputPushPull(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
PushPull = 0b00111010 # 0x32, seq/slew disabled, interrupt output drive drive (push pull) active High
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PushPullOpenDrain, PortA, PushPull)
def SetInterruptOutputOpenDrain(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
OpenDrain = 0b00111000 # 0x34, seq/slew disabled, interrupt output open drain (don't care active High or Low)
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PushPullOpenDrain, PortA, OpenDrain)
def SetupInterruptHighNibbleCompareDefaultValueOpenDrainOutput(registerBaseAddress):
EnableInterruptOnChangeHighNibble(registerBaseAddress)
SetInterruptOnChangeDefaultHighNibble(registerBaseAddress)
SetInterruptOutputOpenDrain(registerBaseAddress)
# * Port A Interrupt checking *
def ReadInterruptFlagHighNibble(registerBaseAddress):
interruptFlagByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InterruptFlag, PortA)
interruptFlagNibble = interruptFlagByte >> 4
return interruptFlagNibble
def ReadInterruptCaptureHighNibble(registerBaseAddress):
interruptCaptureByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InterruptCapture, PortA)
interruptCaptureNibble = interruptCaptureByte >> 4
return interruptCaptureNibble
def ConvertIntegerToFourBitPattern(integer):
FourBitPattern = [""]
for k in range(4):
FourBitPattern = [i+j for i in ['0','1'] for j in FourBitPattern]
return FourBitPattern[integer]
def DetectInterrupt(registerBaseAddress):
while True:
interruptFlagNibble = ReadInterruptFlagHighNibble(registerBaseAddress)
interruptCaptureNibble = ReadInterruptCaptureHighNibble(registerBaseAddress)
print "Interrupt flag nibble = ", ConvertIntegerToFourBitPattern(interruptCaptureNibble)
sleep(2)
def TestDetectInterrupt():
RegisterBaseAddress = MCP23008BaseAddress2
SetupInterruptHighNibbleCompareDefaultValueOpenDrainOutput(RegisterBaseAddress)
DetectInterrupt(RegisterBaseAddress)
# *****************************************************************************
# * Unipolar Stepping Motor 28BYJ48/NPM-PF35/PX245 *
# Unipolar Stepping Motor Switching Sequence
# 1. Wave sequence = 1 - 3 - 2 - 4 (A-, B-, A+, B+)
# 2. Full step sequence = 13 - 14 - 24 - 23 (A-B-, A-B+, A+B+, A+B-)
# 3. Half step sequence = 13 - 1 - 14 - 4 - 24 - 2 - 23 - 3
# 4. One step swing = 1 - 3 - 1 - 3 (A-, B-, A-, B-)
# Winding A-(1) A+(2) B-(3) B+(4) COM
# NPM PF35 Black Yellow Brown Orange Red
# 28BYJ48 Blue Pink Yellow Orange Red
# PX245 Black Green Blue Red Yelow/White
# * Convert decimal pin number to hex *
def convert1PinToHex(p): # convert 1 of 8 high pin to hex
hexString = 0x01
for count in range(p-1):
hexString = hexString << 1
return hexString
def convert2PinToHex(p1, p2): # convert 2 of 8 high pins to hex
return (convert1PinToHex(p1) | convert1PinToHex(p2))
def convert2PinToHighNibble(p1, p2): # convert 2 of 8 high pins to high nibble
lowNibble = convert1PinToHex(p1) | convert1PinToHex(p2)
highNibble = lowNibble << 4
return highNibble
# * Move unipolar stepping motor *
def WriteMotorWindingWaveSequence1324(RegisterBaseAddress, NibbleType, StepCount, StepTime): # move motor using 13-24 sequence
# Set port all output
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)
if NibbleType == LowNibble:
hexString1 = convert2PinToHex(1, 3)
hexString2 = convert2PinToHex(2, 4)
else:
hexString1 = convert2PinToHighNibble(1, 3)
hexString2 = convert2PinToHighNibble(2, 4)
for i in range(StepCount):
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArray0, OutputLatch, PortA, hexString1)
sleep(StepTime)
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArray0, OutputLatch, PortA, hexString2)
sleep(StepTime)
def WriteMotorWindingFullStepSequence13232414(RegisterBaseAddress, NibbleType, StepCount, StepTime): #move motor using 13-23-24-14 sequence
# Set port all output
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)
if NibbleType == LowNibble:
motorWindingActivationPatternArray = (0x05, 0x06, 0x0a, 0x09)
else:
motorWindingActivationPatternArray = (0x50, 0x60, 0xa0, 0x90)
for i in range(StepCount):
for pattern in motorWindingActivationPatternArray:
WriteDataByte(MCP23008BaseAddress1, RegisterAddressOffsetArray0, OutputLatch, PortA, pattern)
sleep(StepTime)
def TestConvert1PinToHex(): # test convert 1 high pin to hex
print "*** Testing 1 pin number decimal 0 ~ 7 converted to hexdecimal 0x01 ~ 0x80"
for d in range(8):
print hex(convert1PinToHex(d))
def TestConvert2PinToHex(p1, p2): # test convert 2 high pins to hex
print "*** Testing 2 pin numbers decimal 0 ~ 7 converted to hexdecimal"
print "Pin 1 = ", p1, "Pin 2 = ", p2
print "Hex = ", hex(convert2PinToHex(p1, p2))
def TestConvert2PinToHighNibble(p1, p2): # test convert 2 of 8 high pins to high nibble
print "*** Testing 2 pin numbers decimal 0 ~ 7 converted to high nibble"
print "Pin 1 = ", p1, "Pin 2 = ", p2
print "HighNibble = ", hex(convert2PinToHighNibble(p1, p2))
def MoveTwoMotors(RegisterBaseAddress):
OneBeep()
WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, LowNibble, TwentyTimes, FiftyMilliSeconds)
OneBeep()
WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, HighNibble, TwentyTimes, FiftyMilliSeconds)
# OneBeep()
# WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, LowNibble, TwentyTimes, FiftyMilliSeconds)
# OneBeep()
# WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, HighNibble, TwentyTimes, FiftyMilliSeconds)
def TestMotor():
MotorRegisterBaseAddress = MCP23008BaseAddress1
MoveTwoMotors(MotorRegisterBaseAddress)
# *****************************************************************************
# * Decimal keypad *
# Keypad scanning procedure version 1.0
# 1. Set 3 column ports GP0, GP1, GP2 as output (GP3 don't care)
# 2. Set 4 row ports GP4, GP5, GP6, GP7 as input
# 3. Write Low to all column ports
# 4. Wait until any key pressed (pooling or interrupt)
# 5. Find rowNumber and column number
# 6. Calculate key number
# * keypad base address and smBus setting *
keypadRegisterBaseAddress = MCP23008BaseAddress2
keypadSmBus = smBus1
def SetupKeypad(registerBaseAddress):
HalfInputHalfOutput = 0xf0
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, HalfInputHalfOutput)
def LoopUntilRowDataByteChange(registerBaseAddress):
NoKeyPressed = 0xf0
rowDataByte = NoKeyPressed
AllLowByte = 0x00
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllLowByte)
while (rowDataByte == NoKeyPressed):
rowDataByte = GetRowDataByte(registerBaseAddress)
sleep(0.05) # debouncing time 50mS
def GetRowDataByte(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
return rowDataByte
def GetRowNumber(registerBaseAddress):
rowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
rowDataNibble = rowDataByte >> 4
if rowDataNibble == 0b1110:
rowNumber = 0
return rowNumber
elif rowDataNibble == 0b1101:
rowNumber = 1
return rowNumber
elif rowDataNibble == 0b1011:
rowNumber = 2
return rowNumber
elif rowDataNibble == 0b0111:
rowNumber = 3
return rowNumber
else:
rowNumber = 99
return rowNumber
def GetColumnNumber(registerBaseAddress):
oldRowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
oldRowDataNibble = oldRowDataByte >> 4
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf6)
newRowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
newDataNibble = newRowDataByte >> 4
if newDataNibble == oldRowDataNibble:
columnNumber = 0
return columnNumber
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf5)
newRowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
newDataNibble = newRowDataByte >> 4
if newDataNibble == oldRowDataNibble:
columnNumber = 1
return columnNumber
WriteDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf3)
newRowDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
newDataNibble = newRowDataByte >> 4
if newDataNibble == oldRowDataNibble:
columnNumber = 2
return columnNumber
columnNumber = 99
return columnNumber
def GetKeyNumber(rowNumber, columnNumber):
keyNumber = (rowNumber * 3) + (columnNumber + 1)
return keyNumber
def GetKey(registerBaseAddress, pollData):
GpioPortGP4ToGP7 = 0
IntCapICP4ToICP7 = 1
if (pollData == GpioPortGP4ToGP7):
LoopUntilRowDataByteChange(registerBaseAddress)
elif (pollData == IntCapICP4ToICP7):
LoopUntilInterruptCaptureByteChange(registerBaseAddress)
rowNumber = GetRowNumber(registerBaseAddress)
columnNumber = GetColumnNumber(registerBaseAddress)
keyNumber = GetKeyNumber(rowNumber, columnNumber)
return keyNumber
def GetKeyString(registerBaseAddress, pollData, count):
for i in range (count):
OneBeep()
keyNumber = GetKey(registerBaseAddress, pollData)
print "Key pressed = ", '{0:2}'.format(str(keyNumber).zfill(2).rjust(2))
def TestPollRowDataKeypad():
KeypadRegisterBaseAddress = MCP23008BaseAddress2
PollData = 0 # poll row data
Count = 4
print "Press keypad ", Count, "times."
SetupKeypad(KeypadRegisterBaseAddress)
GetKeyString(KeypadRegisterBaseAddress, PollData, Count)
def TestPollInterruptCaptureDataKeypad():
KeypadRegisterBaseAddress = MCP23008BaseAddress2
PollData = 1 # poll interrupt capture data
Count = 4
print "Press keypad ", Count, "times."
SetupKeypad(KeypadRegisterBaseAddress)
GetKeyString(KeypadRegisterBaseAddress, PollData, Count)
def TestKeypad(pollData, count):
KeypadRegisterBaseAddress = MCP23008BaseAddress2
SetupKeypad(KeypadRegisterBaseAddress)
print "Press keypad ", count, "times."
GetKeyString(KeypadRegisterBaseAddress, pollData, count)
def LoopUntilInterruptCaptureByteChange(registerBaseAddress):
pass
# ****************************************************************************
# * Program messages *
def StartMessage(message):
StartBeep()
print message
def EndMessage(message):
EndBeep
print message
# *****************************************************************************
# * Main test functions *
# * Setup RPi GPIO *
SetupGPIO()
StartMessage("*** Program to test decimal keypad - v4.2 TL Fong 2013jan10 ***")
# * Part 1 - Test RPi GPIO *
# TestBuzzer() # beep buzzer 4 times
# TestLED() # blink LED 8 tmes
# TestButtonEchoBuzzer() # echo buton with buzzer 10 times
# TestButtonEchoLED() # echo button with LED 10 times
# TestToggleTxDpin() # toggle TxD pin every 2 seconds
# * Part 2 - Test MCP23008/MCP23017 output ports *
# TestToggleMCP23008GP() # toggle MCP23008 output port
# TestToggleMCP23017GP() # toggle MCP23017 output ports
# * Part 3 - Test stepping motor *
# TestMotor() # move two stepping motors
# * Part 3 - Test decimal keypad *
TestKeypad(0, 4)
TestDetectInterrupt()
EndMessage("End of program")
# *****************************************************************************
# End of Program
# *****************************************************************************
#*** Program to test decimal keypad - v4.2 TL Fong 2013jan10 ***
#Press keypad 4 times.
#Key pressed = 01
#Key pressed = 04
#Key pressed = 07
#Key pressed = 10
#Interrupt flag nibble = 0111
#Interrupt flag nibble = 1111
#Interrupt flag nibble = 1111
#Interrupt flag nibble = 1110
#Interrupt flag nibble = 1101
#Interrupt flag nibble = 1011
#Interrupt flag nibble = 0111
#Interrupt flag nibble = 0111
.END
No comments:
Post a Comment