Pages

Tuesday, January 08, 2013

MCP23008 IO Expander - Decimal Keypad

Now I have added sleep(x) to debounce the keys, but the result is not very satisfactory.  There are still wrong data from time to time.  In other words, the function need more refining.

*** Sample output ***

Key pressed = 01
Key pressed = 02
New DataByte 0xf3
Key pressed = 100

Key pressed = 04
Key pressed = 05
Key pressed = 298
Key pressed = 06
Key pressed = 07
Key pressed = 08
Key pressed = 09
Key pressed = 10
Key pressed = 298
Key pressed = 11
Key pressed = 12


.END

# *****************************************************************************
# *** tiox21.py ***
# Program  - Test MCP23008 and MCP23017
# Version  - 2.1
# Date     - 2012nov30
# Update   - 2013jan07
# Author   - tlfong01
# File     - tiox21_2013jan07.py
# Blog     -
http://tlfong01.blogspot.hk/
# Purpose  - test basics of Raspberry Pi GPIO
# 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

# *****************************************************************************
# * GPIO naming and setting up *
# * RPi.GPIO setting *
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)

# *****************************************************************************
#  * 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)

# *****************************************************************************
# * MCP23008 / MCP23017 *
# * 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
# * Toggle testing parameters *
ToggleTime = 0.2
ToggleCount = 4

# * MCP23008/MCP23017 register address offsets *
InputOutputDirection = 0
InputPolarity = 1
InterruptOnChangeEnable = 2
InterruptOnChangeDefaultValue = 3
InterruptOnChangeMode = 4
Configuration = 5
PullUpResistor = 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]

# * 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 TestToggleMCP23008Port(registerBaseAddress, toggleTime, toggleCount):
    # Set port all output
    writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)

    # Toggle port
    for i in range(toggleCount):
        writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllHigh)
 sleep(toggleTime)
        writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, AllLow)
  sleep(toggleTime)

def TestToggleMCP23017Ports(registerBaseAddress, toggleTime, toggleCount):
    # Set both ports all pins output
    writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, AllOutput)
    writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortB, AllOutput)

    # Toggle both ports
    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)

# * Interrupt functions *
ENABLE_INTERRUPT_HighNibble = 0xf0
DEFAULT_COMPARE_VALUE_HighNibble = 0xf0
INTERRUPT_CONTROL_COMPARE_DEFAULT_HighNibble = 0xf0
INTERRUPT_PIN_PUSH_PULL_DRIVER_HIGH_ACTIVE = 0b00111010 # 0x3a, no auto add incre, no slew rate
INTERRUPT_PIN_OPEN_DRAIN = 0b00111000 # 0x38, no auto add incre, no slew rate

# * Interrupt setting *
def enableInterruptOnChangeHighNibble(registerBaseAddress): # enable high nibble interrupt on change
    smBus1.write_byte_data(registerBaseAddress, INTERRUPT_ON_CHANGE_REGISTER, ENABLE_INTERRUPT_HighNibble)

def setInterruptOnChangeDefaultHighNibble(registerBaseAddress): # set high nibble default compare values
    smBus1.write_byte_data(registerBaseAddress, DEFAULT_COMPARE_VALUE_REGISTER, DEFAULT_COMPARE_VALUE_HighNibble)

def setInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress): # enable high nibble compare default
    smBus1.write_byte_data(registerBaseAddress, INTERRUPT_CONTROL_REGISTER, INTERRUPT_CONTROL_COMPARE_DEFAULT_HighNibble)

def setHighNibbleCompareDefault(registerBaseAddress): # set high nibble compare default
    enableInterruptOnChangeHighNibble(registerBaseAddress)
    setInterruptOnChangeDefaultHighNibble(registerBaseAddress)
    setInterruptOnChangeCompareDefaultHighNibble(registerBaseAddress)

def setInterruptPinPushPullHighActive(registerBaseAddress):  # interrupt pin push pull high active, no auto add inc, no slew rate
    smBus1.write_byte_data(registerBaseAddress, IO_CONTROL_REGISTER, INTERRUPT_PIN_PUSH_PULL_DRIVER_HIGH_ACTIVE)

def setInterruptPinOpenDrain(registerBaseAddress): # interrupt pin open drain, no auto add inc, no slew rate
    smBus1.write_byte_data(registerBaseAddress, IO_CONTROL_REGISTER, INTERRUPT_PIN_OPEN_DRAIN)

# * Interrupt reading *
def readInterruptFlagPinsHighNibble(registerBaseAddress): # read high nibble interrupt flag register
    hexByte = smBus1.read_byte_data(registerBaseAddress, INTERRUPT_FLAG_REGISTER)   
    hexNibble = hexByte >> 4
    return hexNibble  
   
def readInterruptCapturePinsHighNibble(registerBaseAddress): # read high nibble interrupt capture register
    hexByte = smBus1.read_byte_data(registerBaseAddress, INTERRUPT_CAPTURE_REGISTER)   
    hexNibble = hexByte >> 4
    return hexNibble 

# * Testing interrupt *
def TestInterruptPinFallingEdgeDetection():
    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"

# *****************************************************************************
# * 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      Yellow/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 TestMove2Motors(RegisterBaseAddress): # move 2 motors one after another
 OneBeep()
 WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, LowNibble, TwentyTimes, FiftyMilliSeconds)
 OneBeep()
 WriteMotorWindingWaveSequence1324(MCP23008BaseAddress1, HighNibble, TwentyTimes, FiftyMilliSeconds)
 #OneBeep()
 #WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, LowNibble, TwentyTimes, FiftyMilliSeconds)
 #OneBeep()
 #WriteMotorWindingFullStepSequence13232414(MCP23008BaseAddress1, HighNibble, TwentyTimes, FiftyMilliSeconds)

# *****************************************************************************
# * 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 for interrupt
# 5. Pressing any key would cause an interrupt
# 6. When interrupt occurs check which row reads LOW
# 7. Write LOW only to column GP0, if row port still LOW, then this column 0
#    has a key pressed, if not, check if column 1, if not column 3.
# 8. Calculate the key using the column and row data.

## * keypad base address and smBus setting *
keypadRegisterBaseAddress = MCP23008BaseAddress2
keypadSmBus = smBus1

# * Set, write, read keypad pins *
def SetupKeypad(registerBaseAddress):
   # Set IO port high nibble input, low nibble output
   writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, InputOutputDirection, PortA, HighNibbleInputLowNibbleOutput)
   # Write all zeros to keypad rows (GP0~2)
   writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf0)

def ReadKeypadRows(registerBaseAddress):
    dataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
    return dataByte 

def LoopUntilKeyPressAndGetRowDataByte(registerBaseAddress):
    NoPressingKey = 0xf0
    rowDataByte = 0xf0
    while (rowDataByte == NoPressingKey):
        rowDataByte = ReadKeypadRows(registerBaseAddress)
    sleep(0.05) # !!!!! debounce key 50mS !!!!!
    rowDataByte = ReadKeypadRows(registerBaseAddress)
    return rowDataByte

def GetRowNumber(rowDataByte):
    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, oldDataByte):
   writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf6)
   newDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
   newDataNibble = newDataByte >> 4
   oldDataNibble = oldDataByte >> 4
   # print "New Data Nibble", hex(newDataNibble)
   if newDataNibble == oldDataNibble:
       columnNumber = 0
       return columnNumber

   writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf5)
   newDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
   newDataNibble = newDataByte >> 4
   oldDataNibble = oldDataByte >> 4
   # print "New Data Nibble", hex(newDataNibble)
   if newDataNibble == oldDataNibble:
       columnNumber = 1
       return columnNumber

   writeDataByte(registerBaseAddress, RegisterAddressOffsetArray0, OutputLatch, PortA, 0xf3)
   newDataByte = ReadDataByte(registerBaseAddress, RegisterAddressOffsetArray0, PortStatus, PortA)
   newDataNibble = newDataByte >> 4
   oldDataNibble = oldDataByte >> 4
   # print "New Data Nibble", hex(newDataNibble)
   if newDataNibble == oldDataNibble:
       columnNumber = 2
       return columnNumber

   print "New DataByte", hex(newDataByte)
   columnNumber = 99
   return columnNumber

def GetKeyNumber(rowNumber, columnNumber):
    keyNumber = (rowNumber * 3) + (columnNumber + 1)
    return keyNumber

def TestKeypad(registerBaseAddress):
    while True:
        OneBeep()
        SetupKeypad(registerBaseAddress)
        rowDataByte = LoopUntilKeyPressAndGetRowDataByte(registerBaseAddress)
        # print "There is a pressing key, Row data (GP4~7) = ", hex(rowDataByte)
        rowNumber = GetRowNumber(rowDataByte)
        # print "Row number = ", rowNumber
        columnNumber = GetColumnNumber(registerBaseAddress, rowDataByte)
        # print "Column number = ", columnNumber
        keyNumber = GetKeyNumber(rowNumber, columnNumber)
        print "Key pressed = ", '{0:2}'.format(str(keyNumber).zfill(2).rjust(2))
        sleep(1)

# ***********************************************************************************88
# !!! old functions to discard !!!

# * Test polling/interrupt keypad *
def scanKeypad(registerBaseAddress):  
    SetupKeypad(registerBaseAddress)
    #setInterruptPinOpenDrain(registerBaseAddress) # *** interrupt pin open drain !!!

    writeColumnPins(registerBaseAddress, ColumnAllLow)
    #setHighNibbleCompareDefault(registerBaseAddress) # *** testing interrupt ***
    # Loop until one key pressed
    keyPressed = False
    while True:
        nibble = readRowPins()
        if nibble == Row0Low:
     row = 0
            keyPressed = True 
            print "Row 0 key pressed"
        elif  nibble == Row1Low:
     row = 1
            keyPressed = True
            print "Row 1 key pressed"
        elif  nibble == Row2Low:
     row = 2
            keyPressed = True
            print "Row 2 key pressed"     
        elif  nibble == Row3Low:
     row = 3
            keyPressed = True
            print "Row 3 key pressed"
        else:
     row = 9
            #print "No key or more than one key pressed"                

        if keyPressed == True:
     # Check which column the key is pressed
      column = 9
     writeColumnPins(registerBaseAddress, Column0Low)
     nibble = readRowPins()    
     if nibble != RowAllHigh:
         column = 0
                print "Column 0 key pressed"
            else:
                writeColumnPins(registerBaseAddress, Column1Low)
                nibble = readRowPins()    
                if nibble != RowAllHigh:
                    column = 1
                    print "Column 1 key pressed"
                else:
                    writeColumnPins(registerBaseAddress, Column2Low)
                    nibble = readRowPins()    
                    if nibble != RowAllHigh:
                        column = 2
                        print "Column 2 key pressed"
                    else: 
                        print "Error"

            # Calculate which key pressed
            keyNumber = (row * 3) + (column + 1)
            print "Key pressed              = ", '{0:8}'.format(str(keyNumber).zfill(2).rjust(10))
            # *******************************************************************************
     # checking interrupt
            # *******************************************************************************
     # Check which column interrupt

            interruptFlagNibble = readInterruptFlagPinsHighNibble(registerBaseAddress)
            interruptCaptureNibble = readInterruptCapturePinsHighNibble(registerBaseAddress)

            print "Interrupt flag nibble    = ", '{0:8}'.format((str(bin(interruptFlagNibble)).zfill(4)).rjust(10))
            print "Interrupt capture nibble = ", '{0:8}'.format((str(bin(interruptCaptureNibble)).zfill(4)).rjust(10))

     keyPressed = False
     sleep(1)
        else:
            pass

def TestScanKeypad():
    scanKeypad(MCP23008BaseAddress2)

# *****************************************************************************
# * Old test functions *
# testLEDandBuzzer()
# testButton() !!! not working !!!
# blink8LEDsIOx1()
# blink4LEDsIOx2()
# testConvert1PinToHex()
# blink4LEDsIOx2()
# move1MotorUsingMCP23008_2(MCP23008BaseAddress2, HalfSecond,
#                           OneSecond, FourTimes, TwentyTimes, OneSecond)

# *****************************************************************************
# *** Old test functions ***
# * Test RPi GPIO *
# TestBuzzer() # beep buzzer 4 times
# TestLED() # blink LED 8 tmes
# TestButtonEchoBuzzer() # echo buton with buzzer 10 times
# TestButtonEchoLED() # echo buton with LED 10 times
# TestToggleTxDpin() # toggle TxD pin every 2 seconds

# * Test stepping motors *
# TestMove2Motors(MCP23008BaseAddress1)

# *****************************************************************************
# * Main test functions *
SetupGPIO()
StartBeep()

# * Test MCP23008/MCP23017 GP *
TestToggleMCP23008Port(MCP23008BaseAddress1, 0.3, 2) # x second, y times
TestToggleMCP23017Ports(MCP23017BaseAddress1, 0.3, 2) # x second, y times

# * Test decimal keypad *
#TestReadKeypadRows(MCP23008BaseAddress2)
TestKeypad(MCP23008BaseAddress2)

# *****************************************************************************
# End of Program
# *****************************************************************************


*** Execution log - 2013jan08 ***
pi@raspberrypi ~/python_programs/test_basic $ date
Tue Jan  8 03:21:53 UTC 2013
pi@raspberrypi ~/python_programs/test_basic $ sudo python tiox21.py
Key pressed =  01
Key pressed =  02
New DataByte 0xf3
Key pressed =  100
Key pressed =  04
Key pressed =  05
Key pressed =  298
Key pressed =  06
Key pressed =  07
Key pressed =  08
Key pressed =  09
Key pressed =  10
Key pressed =  298
Key pressed =  11
Key pressed =  12


.END

No comments:

Post a Comment