[{"element_type":"markdown","content":"\u003cp\u003eThis demonstrates a CircuitPython driver for reading XInput USB gamepad events\nusing the Adafruit USB Host BFF (MAX3421E) and a QT Py ESP32-S3 dev board.\u003c/p\u003e\n","metadata":{"markdown":"This demonstrates a CircuitPython driver for reading XInput USB gamepad events\nusing the Adafruit USB Host BFF (MAX3421E) and a QT Py ESP32-S3 dev board.\n"}},{"element_type":"user_image","content":"https://cdn-learn.adafruit.com/user_assets/assets/000/001/094/original/usbgamepad-qtpys3.jpeg?1723014345","metadata":{"caption":""}},{"element_type":"markdown","content":"\u003ch2\u003eDemo Video\u003c/h2\u003e\n","metadata":{"markdown":"## Demo Video"}},{"element_type":"embed","content":"https://youtu.be/eY9yeAtAKsg?si=N9QmIcXbOIEqrMTQ"},{"element_type":"markdown","content":"\u003ch2\u003eHardware\u003c/h2\u003e\n\n\u003ch3\u003eParts\u003c/h3\u003e\n","metadata":{"markdown":"## Hardware\n\n\n### Parts\n"}},{"element_type":"product","content":"https://www.adafruit.com/product/5700","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5956","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5683","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/2886","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/5582","metadata":{}},{"element_type":"product","content":"https://www.adafruit.com/product/1099","metadata":{}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e1\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003ca href=\"https://www.8bitdo.com/sn30-pro-usb-gamepad/\" class=\"parts-name\" target=\"_blank\"\u003e8BitDo SN30 Pro USB gamepad\u003c/a\u003e\n      \u003cdiv class=\"parts-description\"\u003eUSB wired gamepad using XInput protocol\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n      \u003ca href=\"https://www.8bitdo.com/sn30-pro-usb-gamepad/\" class=\"parts-url btn-secondary\" target=\"_blank\"\u003eBuy Now\u003c/a\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"8BitDo SN30 Pro USB gamepad","url":"https://www.8bitdo.com/sn30-pro-usb-gamepad/","description":"USB wired gamepad using XInput protocol","quantity":"1"}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e1\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003cspan class=\"parts-name\"\u003eTamiya Universal Plate Set #70157\u003c/span\u003e\n      \u003cdiv class=\"parts-description\"\u003e3mm thick, 160x60mm ABS plates with 3mm holes on 5mm grid\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"Tamiya Universal Plate Set #70157","url":null,"description":"3mm thick, 160x60mm ABS plates with 3mm holes on 5mm grid","quantity":"1"}},{"element_type":"parts","content":"\n  \u003cdiv class=\"parts-details\"\u003e\n    \u003cdiv\u003e\n      \u003cspan class=\"parts-quantity\"\u003e5\u003c/span\u003e\u003cspan\u003e x \u003c/span\u003e\n        \u003cspan class=\"parts-name\"\u003eSmall cable ties\u003c/span\u003e\n      \u003cdiv class=\"parts-description\"\u003e(aka zip ties)\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"parts-action\"\u003e\n  \u003cdiv\u003e\n\n  \u003c/div\u003e\n\u003c/div\u003e\n\n  \u003cdiv class=\"clearfix\"\u003e\u003c/div\u003e\n","metadata":{"name":"Small cable ties","url":null,"description":"(aka zip ties)","quantity":"5"}},{"element_type":"markdown","content":"\u003ch3\u003eTools\u003c/h3\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003eSoldering iron\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eSolder\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eBreadboard (to help with soldering)\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eSoldering Vise (Adafruit \u003ca href=\"https://www.adafruit.com/product/3197\"\u003e#3197\u003c/a\u003e or\nsimilar)\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eFlush diagonal cutters\n(Adafruit \u003ca href=\"https://www.adafruit.com/product/152\"\u003e#152\u003c/a\u003e or similar)\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n","metadata":{"markdown":"### Tools\n\n- Soldering iron\n\n- Solder\n\n- Breadboard (to help with soldering)\n\n- Soldering Vise (Adafruit [#3197](https://www.adafruit.com/product/3197) or\n  similar)\n\n- Flush diagonal cutters\n  (Adafruit [#152](https://www.adafruit.com/product/152) or similar)\n"}},{"element_type":"markdown","content":"\u003ch3\u003ePinouts\u003c/h3\u003e\n\n\u003ctable\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003cth\u003eESP32-S3\u003c/th\u003e\n\u003cth\u003eMAX3421E\u003c/th\u003e\n\u003cth\u003emicroSD\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eA0\u003c/td\u003e\n\u003ctd\u003e5VEN\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eA1\u003c/td\u003e\n\u003ctd\u003eCS\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eA2\u003c/td\u003e\n\u003ctd\u003eIRQ\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eTX\u003c/td\u003e\n\u003ctd\u003e\u003c/td\u003e\n\u003ctd\u003eCS\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eSCK\u003c/td\u003e\n\u003ctd\u003eSCK\u003c/td\u003e\n\u003ctd\u003eSCK\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMI\u003c/td\u003e\n\u003ctd\u003eMISO\u003c/td\u003e\n\u003ctd\u003eMISO\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMO\u003c/td\u003e\n\u003ctd\u003eMOSI\u003c/td\u003e\n\u003ctd\u003eMOSI\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n","metadata":{"markdown":"### Pinouts\n\n| ESP32-S3 | MAX3421E | microSD |\n| -------- | -------- | ------- |\n|       A0 |   5VEN   |         |\n|       A1 |   CS     |         |\n|       A2 |   IRQ    |         |\n|       TX |          |   CS    |\n|      SCK |   SCK    |   SCK   |\n|       MI |   MISO   |   MISO  |\n|       MO |   MOSI   |   MOSI  |\n"}},{"element_type":"markdown","content":"\u003ch2\u003eAssemble the Hardware\u003c/h2\u003e\n\n\u003cp\u003eIf you are unfamiliar with soldering stacking headers, you might want to read:\u003c/p\u003e\n\n\u003cul\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools\"\u003eAdafruit Guide To Excellent Soldering\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e\u003ca href=\"https://learn.adafruit.com/how-to-solder-headers\"\u003eHow To Solder Headers\u003c/a\u003e\u003c/p\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003cp\u003eFor this build, I included an otherwise unused microSD card BFF board because\nit adds some mechanical stability. Also, I might want to use SD cards later. If\nyou don't care about SD cards, adjust these instructions accordingly (you might\nwant to select different headers).\u003c/p\u003e\n","metadata":{"markdown":"## Assemble the Hardware\n\nIf you are unfamiliar with soldering stacking headers, you might want to read:\n\n- [Adafruit Guide To Excellent Soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools)\n\n- [How To Solder Headers](https://learn.adafruit.com/how-to-solder-headers)\n\nFor this build, I included an otherwise unused microSD card BFF board because\nit adds some mechanical stability. Also, I might want to use SD cards later. If\nyou don't care about SD cards, adjust these instructions accordingly (you might\nwant to select different headers).\n"}},{"element_type":"markdown","content":"\u003ch3\u003eGetting Ready\u003c/h3\u003e\n\n\u003cp\u003eThere are three mildly tricky things about assembling the hardware for this\nproject:\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eIt's easy to assemble Qt Py boards in the wrong orientation. It will help\nto check the learn guides and pay close attention to the silk screen marks.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eYou need to carefully cut the longer header strips into pairs of headers\nthat are 7 positions long. For the stacking headers and female headers, you\ncan pull out one of the pins and carefully cut the plastic with your flush\ncutters. Once you separate a longer strip into two pieces, you can clean up\nthe edges by nibbling away excess material with the flush cutters.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eThe USB Host BFF has a jumper on \u003ccode class=\"inline\"\u003eA0\u003c/code\u003e which connects to the USB host port 5V\npower enable line. To solder the jumper closed, you will need to orient your\nheaders such that you don't block the jumper with plastic. I accomplished\nthat by using downward-pointing female headers on my ESP32-S3 board, then\nputting stacking headers on my USB host board with the pins coming out on\nthe same side as the \u003ccode class=\"inline\"\u003e5VEN\u003c/code\u003e jumper.\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"### Getting Ready\n\nThere are three mildly tricky things about assembling the hardware for this\nproject:\n\n1. It's easy to assemble Qt Py boards in the wrong orientation. It will help\n   to check the learn guides and pay close attention to the silk screen marks.\n\n2. You need to carefully cut the longer header strips into pairs of headers\n   that are 7 positions long. For the stacking headers and female headers, you\n   can pull out one of the pins and carefully cut the plastic with your flush\n   cutters. Once you separate a longer strip into two pieces, you can clean up\n   the edges by nibbling away excess material with the flush cutters.\n\n3. The USB Host BFF has a jumper on `A0` which connects to the USB host port 5V\n   power enable line. To solder the jumper closed, you will need to orient your\n   headers such that you don't block the jumper with plastic. I accomplished\n   that by using downward-pointing female headers on my ESP32-S3 board, then\n   putting stacking headers on my USB host board with the pins coming out on\n   the same side as the `5VEN` jumper.\n"}},{"element_type":"markdown","content":"\u003ch3\u003eOrder of Soldering\u003c/h3\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eAssemble the microSD BFF with male header pins on a breadboard and solder\nthe headers in place\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eRemove the microSD BFF from the breadboard and put a row of stacking header\nonto each row of the microSD board's header pins\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eBeing careful of board orientation, put the USB Host BFF onto the pins of\nthe stacking headers. Clamp the microSD and USB Host BFF sandwich in a vise,\nthen solder the USB Host board's pins. Be sure to solder the \u003ccode class=\"inline\"\u003eA0\u003c/code\u003e jumper\nclosed, but try not to make the blob of solder taller than necessary (to\navoid mechanical interference with the headers).\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003e(optional: trim stacking header pins with flush cutters to match the length\nof regular header pins)\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003ePut a row of female header onto each row of the USB Host board's stacking\nheader pins\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eBeing careful of board orientation, put the QT PY ESP32-S3 board on to the\npins of the female headers and solder them in place\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"### Order of Soldering\n\n1. Assemble the microSD BFF with male header pins on a breadboard and solder\n   the headers in place\n\n2. Remove the microSD BFF from the breadboard and put a row of stacking header\n   onto each row of the microSD board's header pins\n\n3. Being careful of board orientation, put the USB Host BFF onto the pins of\n   the stacking headers. Clamp the microSD and USB Host BFF sandwich in a vise,\n   then solder the USB Host board's pins. Be sure to solder the `A0` jumper\n   closed, but try not to make the blob of solder taller than necessary (to\n   avoid mechanical interference with the headers).\n\n4. (optional: trim stacking header pins with flush cutters to match the length\n   of regular header pins)\n\n5. Put a row of female header onto each row of the USB Host board's stacking\n   header pins\n\n6. Being careful of board orientation, put the QT PY ESP32-S3 board on to the\n   pins of the female headers and solder them in place\n"}},{"element_type":"markdown","content":"\u003ch3\u003eSmoke Test and Final Assembly\u003c/h3\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eTry plugging your board into a USB charger to make sure the LEDs light up\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eIf the LEDs light up, unplug the USB power cable, then plug your USB OTG\nhost cable into the USB Host BFF's USB port\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eSecure the QT Py board stack and otg cable to a Tamiya Universal Plate with\ncable ties. Trim the ends of the cable ties with your flush cutters.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003ePlug the USB gamepad into the otg cable's USB A port\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"### Smoke Test and Final Assembly\n\n1. Try plugging your board into a USB charger to make sure the LEDs light up\n\n2. If the LEDs light up, unplug the USB power cable, then plug your USB OTG\n   host cable into the USB Host BFF's USB port\n\n3. Secure the QT Py board stack and otg cable to a Tamiya Universal Plate with\n   cable ties. Trim the ends of the cable ties with your flush cutters.\n\n4. Plug the USB gamepad into the otg cable's USB A port\n"}},{"element_type":"markdown","content":"\u003ch2\u003eRunning the Gamepad Decoder\u003c/h2\u003e\n\n\u003cp\u003eThe next section has instructions for updating CircuitPython and copying the project bundle\ncode to your CIRCUITPY drive. But, for now, this is a preview of what the code looks like when\nit runs.\u003c/p\u003e\n\n\u003cp\u003eTo see output from \u003ccode class=\"inline\"\u003ecode.py\u003c/code\u003e, you will need to\n\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console\"\u003econnect to the serial console\u003c/a\u003e\nof your Qt Py board.\u003c/p\u003e\n\n\u003cp\u003eWhen \u003ccode class=\"inline\"\u003ecode.py\u003c/code\u003e starts with a supported gamepad connected (so far 8BitDo SN30 Pro\nUSB is the only one I've confirmed to work), it takes several seconds to reset the USB\nport and initialize the MAX3421E USB host controller chip. Once that's done, you\nshould see a message like this:\u003c/p\u003e\n","metadata":{"markdown":"## Running the Gamepad Decoder\n\nThe next section has instructions for updating CircuitPython and copying the project bundle\ncode to your CIRCUITPY drive. But, for now, this is a preview of what the code looks like when\nit runs.\n\nTo see output from `code.py`, you will need to\n[connect to the serial console](https://learn.adafruit.com/welcome-to-circuitpython/kattni-connecting-to-the-serial-console)\nof your Qt Py board.\n\nWhen `code.py` starts with a supported gamepad connected (so far 8BitDo SN30 Pro\nUSB is the only one I've confirmed to work), it takes several seconds to reset the USB\nport and initialize the MAX3421E USB host controller chip. Once that's done, you\nshould see a message like this:\n"}},{"element_type":"code","content":"Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.\ncode.py output:\nResetting USB bus...\nUSB Host Ready\nLooking for USB gamepads...\n...\nFound an XInput gamepad (045e:028e)...\nsetting configuration\n(     0,     0)  (     0,     0)","metadata":{"language":"terminal","linenums":false}},{"element_type":"markdown","content":"\u003cp\u003e\u003cstrong\u003eNOTE: USB hot plugging may be unreliable. Based on my limited testing, it\nseems like there may be bugs in my driver code or in the CircuitPython\n\u003ccode class=\"inline\"\u003emax3421e\u003c/code\u003e package. I got the best results when I plugged the gamepad in before\npowering up.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp\u003eIf you press buttons and move the sticks, you should see additional output with\ndecoded USB reports for gamepad events (XInput protocol) that like this:\u003c/p\u003e\n","metadata":{"markdown":"**NOTE: USB hot plugging may be unreliable. Based on my limited testing, it\nseems like there may be bugs in my driver code or in the CircuitPython\n`max3421e` package. I got the best results when I plugged the gamepad in before\npowering up.**\n\nIf you press buttons and move the sticks, you should see additional output with\ndecoded USB reports for gamepad events (XInput protocol) that like this:\n"}},{"element_type":"code","content":"(     0,     0)  (     0,     0)  dUp\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dUp\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dDn\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dDn\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dL\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dR\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dL\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  dR\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  B\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  A\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  Start\n(     0,     0)  (     0,     0)\n(     0,     0)  (     0,     0)  Select\n(     0,     0)  (     0,     0)\n( -1792,     0)  (     0,     0)\n(-22784,     0)  (     0,     0)\n(-32768,  2304)  (     0,     0)\n(-26624, 32767)  (     0,     0)\n( -1024, 32767)  (     0,     0)\n( 32767, 24832)  (     0,     0)\n( 32767, -1024)  (     0,     0)\n(   768,-32768)  (     0,     0)\n(-15360,-29440)  (     0,     0)\n(     0,     0)  (     0,     0)\n(     0,     0)  (-15616,-18688)\n(     0,     0)  (-32768,-32768)\n(     0,     0)  (-32768,  2304)\n(     0,     0)  (-19456, 32767)\n(     0,     0)  ( -2560, 32767)\n(     0,     0)  ( 23296, 31488)\n(     0,     0)  ( 32767,-16128)\n(     0,     0)  ( -2560,-32768)\n(     0,     0)  (-22016,-22016)\n(     0,     0)  (     0,     0)","metadata":{"language":"terminal","linenums":false}},{"element_type":"markdown","content":"\u003cp\u003eThe pairs of numbers in parentheses are (X, Y) coordinates for the left and\nright joysticks. The text labels on the right are printed for edge-triggered\ntransitions (not-pressed to pressed) of the gamepad's buttons. Lines with all\nzero coordinates and no button labels get printed when the last button is\nreleased. To see how it works, check out the code and comments in \u003ccode class=\"inline\"\u003ecode.py\u003c/code\u003e.\u003c/p\u003e\n","metadata":{"markdown":"The pairs of numbers in parentheses are (X, Y) coordinates for the left and\nright joysticks. The text labels on the right are printed for edge-triggered\ntransitions (not-pressed to pressed) of the gamepad's buttons. Lines with all\nzero coordinates and no button labels get printed when the last button is\nreleased. To see how it works, check out the code and comments in `code.py`.\n"}},{"element_type":"markdown","content":"\u003ch2\u003eUpdating CircuitPython\u003c/h2\u003e\n\n\u003cp\u003e\u003cstrong\u003eNOTE: To update CircuitPython on the ESP32-S3 with 2MB PSRAM and 4MB Flash,\nyou need to use the .BIN file (combination bootloader and CircuitPython core)\u003c/strong\u003e\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eDownload the CircuitPython 9.1.1 \u003cstrong\u003e.BIN\u003c/strong\u003e file from the\n\u003ca href=\"https://circuitpython.org/board/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/\"\u003eAdafruit QT Py ESP32-S3 4MB Flash/2MB PSRAM\u003c/a\u003e\npage on circuitpython.org\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eFollow the instructions in the\n\u003ca href=\"https://learn.adafruit.com/circuitpython-with-esp32-quick-start/web-serial-esptool\"\u003eWeb Serial ESPTool\u003c/a\u003e\nsection of the \"CircuitPython on ESP32 Quick Start\" learn guide to update\nyour board with CircuitPython 9.1.1. First erasing the board's contents,\nthen programming it with the .BIN file. \u003cstrong\u003e(CAUTION: the normal UF2 file\nmethod does not work on this board because it does not have a large enough\nflash drive to hold the CircuitPython UF2 file)\u003c/strong\u003e\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n","metadata":{"markdown":"## Updating CircuitPython\n\n**NOTE: To update CircuitPython on the ESP32-S3 with 2MB PSRAM and 4MB Flash,\nyou need to use the .BIN file (combination bootloader and CircuitPython core)**\n\n1. Download the CircuitPython 9.1.1 **.BIN** file from the\n   [Adafruit QT Py ESP32-S3 4MB Flash/2MB PSRAM](https://circuitpython.org/board/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/)\n   page on circuitpython.org\n\n2. Follow the instructions in the\n   [Web Serial ESPTool](https://learn.adafruit.com/circuitpython-with-esp32-quick-start/web-serial-esptool)\n   section of the \"CircuitPython on ESP32 Quick Start\" learn guide to update\n   your board with CircuitPython 9.1.1. First erasing the board's contents,\n   then programming it with the .BIN file. **(CAUTION: the normal UF2 file\n   method does not work on this board because it does not have a large enough\n   flash drive to hold the CircuitPython UF2 file)**\n"}},{"element_type":"markdown","content":"\u003ch2\u003eCircuitPython Code\u003c/h2\u003e\n\n\u003cp\u003eTo copy the project bundle files to your CIRCUITPY drive:\u003c/p\u003e\n\n\u003col\u003e\n\u003cli\u003e\u003cp\u003eDownload the project bundle .zip file using the button below.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eExpand the zip file by opening it, or use \u003ccode class=\"inline\"\u003eunzip\u003c/code\u003e in a Terminal. You should\nend up with a folder named prox-sensor-encoder-menu, which should contain a\n\u003ccode class=\"inline\"\u003eREADME.txt\u003c/code\u003e file and a \u003ccode class=\"inline\"\u003eCircuitPython 9.x\u003c/code\u003e folder.\u003c/p\u003e\u003c/li\u003e\n\u003cli\u003e\u003cp\u003eOpen the CircuitPython 9.x folder and copy all of its contents to your\nCIRCUITPY drive.\u003c/p\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\n\u003cp\u003eTo learn more about copying libraries to your CIRCUITPY drive, check out the\n\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries\"\u003eCircuitPython Libraries\u003c/a\u003e\nsection of the\n\u003ca href=\"https://learn.adafruit.com/welcome-to-circuitpython\"\u003eWelcome to CircuitPython!\u003c/a\u003e\nlearn guide.\u003c/p\u003e\n","metadata":{"markdown":"## CircuitPython Code\n\nTo copy the project bundle files to your CIRCUITPY drive:\n\n1. Download the project bundle .zip file using the button below.\n\n2. Expand the zip file by opening it, or use `unzip` in a Terminal. You should\n   end up with a folder named prox-sensor-encoder-menu, which should contain a\n   `README.txt` file and a `CircuitPython 9.x` folder.\n\n3. Open the CircuitPython 9.x folder and copy all of its contents to your\n   CIRCUITPY drive.\n\nTo learn more about copying libraries to your CIRCUITPY drive, check out the\n[CircuitPython Libraries](https://learn.adafruit.com/welcome-to-circuitpython/circuitpython-libraries)\nsection of the\n[Welcome to CircuitPython!](https://learn.adafruit.com/welcome-to-circuitpython)\nlearn guide.\n"}},{"element_type":"button","content":"https://github.com/samblenny/usbgamepad/releases/download/v0.1.1/usbgamepad-d130568.zip","metadata":{"class":"btn btn-large btn-block btn-primary","button_type":"primary","target":"_blank","zip_folder":"false"}},{"element_type":"markdown","content":"\u003ch3\u003eCIRCUITPY/code.py\u003c/h3\u003e\n","metadata":{"markdown":"### CIRCUITPY/code.py"}},{"element_type":"embed","content":"https://github.com/samblenny/usbgamepad/blob/v0.1.1/code.py"}]