Guest User

Untitled

a guest
Mar 28th, 2020
306
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.12 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # Somewhat minimal Adafruit Arcade Bonnet handler.  Runs in background,
  4. # translates inputs from MCP23017 port expander to virtual USB keyboard
  5. # events.  Not -quite- as efficient or featuretastic as retrogame, but
  6. # still reasonably lightweight and may be easier and/or more reliable than
  7. # retrogame for some users.  Supports ONE port expander, no regular GPIO
  8. # (non-port-expander) or "Vulcan nerve pinch" features.
  9. # Prerequisites:
  10. # sudo apt-get install python-pip python-smbus python-dev
  11. # sudo pip install evdev
  12. # Be sure to enable I2C via raspi-config.  Also, udev rules will need to
  13. # be set up per retrogame directions.
  14. # Credit to Pimoroni for Picade HAT scripts as starting point.
  15.  
  16. import os
  17. import time
  18. import RPi.GPIO as gpio
  19. from evdev import uinput, UInput, ecodes as e
  20. from smbus import SMBus
  21.  
  22. key = [ # EDIT KEYCODES IN THIS TABLE TO YOUR PREFERENCES:
  23.     # See /usr/include/linux/input.h for keycode names
  24.     # Keyboard        Bonnet        EmulationStation
  25.     e.KEY_LEFTCTRL, # 1A            'A' button
  26.     e.KEY_LEFTALT,  # 1B            'B' button
  27.     e.KEY_A,        # 1C            'X' button
  28.     e.KEY_S,        # 1D            'Y' button
  29.     e.KEY_5,        # 1E            'Select' button
  30.     e.KEY_1,        # 1F            'Start' button
  31.     0,              # Bit 6 NOT CONNECTED on Bonnet
  32.     0,              # Bit 7 NOT CONNECTED on Bonnet
  33.     e.KEY_DOWN,     # 4-way down    D-pad down
  34.     e.KEY_UP,       # 4-way up      D-pad up
  35.     e.KEY_RIGHT,    # 4-way right   D-pad right
  36.     e.KEY_LEFT,     # 4-way left    D-pad left
  37.     e.KEY_L,        # Analog right
  38.     e.KEY_H,        # Analog left
  39.     e.KEY_J,        # Analog down
  40.     e.KEY_K         # Analog up
  41. ]
  42.  
  43. addr   = 0x26 # I2C Address of MCP23017
  44. irqPin = 17   # IRQ pin for MCP23017
  45.  
  46. os.system("sudo modprobe uinput")
  47.  
  48. ui      = UInput({e.EV_KEY: key}, name="retrogame", bustype=e.BUS_USB)
  49. bus     = SMBus(1)
  50. IODIRA  = 0x00
  51. IOCONA  = 0x0A
  52. INTCAPA = 0x10
  53.  
  54. # Initial MCP23017 config:
  55. bus.write_byte_data(addr, 0x05  , 0x00) # If bank 1, switch to 0
  56. bus.write_byte_data(addr, IOCONA, 0x44) # Bank 0, INTB=A, seq, OD IRQ
  57.  
  58. # Read/modify/write remaining MCP23017 config:
  59. cfg = bus.read_i2c_block_data(addr, IODIRA, 14)
  60. cfg[ 0] = 0xFF # Input bits
  61. cfg[ 1] = 0xFF
  62. cfg[ 2] = 0x00 # Polarity
  63. cfg[ 3] = 0x00
  64. cfg[ 4] = 0xFF # Interrupt pins
  65. cfg[ 5] = 0xFF
  66. cfg[12] = 0xFF # Pull-ups
  67. cfg[13] = 0xFF
  68. bus.write_i2c_block_data(addr, IODIRA, cfg)
  69.  
  70. # Clear interrupt by reading INTCAP and GPIO registers
  71. x        = bus.read_i2c_block_data(addr, INTCAPA, 4)
  72. oldState = x[2] | (x[3] << 8)
  73.  
  74. # Callback for MCP23017 interrupt request
  75. def mcp_irq(pin):
  76.     global oldState
  77.     x = bus.read_i2c_block_data(addr, INTCAPA, 4)
  78.     newState = x[2] | (x[3] << 8)
  79.     for i in range(16):
  80.         bit = 1 << i
  81.         lvl = newState & bit
  82.         if lvl != (oldState & bit):
  83.             ui.write(e.EV_KEY, key[i], 0 if lvl else 1)
  84.     ui.syn()
  85.     oldState = newState
  86.  
  87. # GPIO init
  88. gpio.setwarnings(False)
  89. gpio.setmode(gpio.BCM)
  90.  
  91. # Enable pullup and callback on MCP23017 IRQ pin
  92. gpio.setup(irqPin, gpio.IN, pull_up_down=gpio.PUD_UP)
  93. gpio.add_event_detect(irqPin, gpio.FALLING, callback=mcp_irq)
  94.  
  95. while True: time.sleep(1)
Advertisement
Add Comment
Please, Sign In to add comment