Imagine gaming on a mac (insert crying emoji). I love playing snake, but I don’t like the apple keyboard, so I made the world’s smallest gaming keyboard. In a 3x3 grid, there are WASD/Arrow, shift, escape, tab, space, and layer switch keys. Because I coded HID, there is no config or driver install needed–it’s plug and play.
I learend a lot in this project. Normally, I would do this in python becuase libraries but I really wanted to learn how 1) I2C communication worked between the MCU and OLED and 2) how USB communication worked between the MCU and host device. I learned wayy more than I can include here (everything’s commented on my repo though!), but I have gained a huge apprecaition for python libraries and not having to HARD CODE LETTERS AS BITMASKS. I also got an appreciation for CMake and how it made the compilation process easier. For my next project, though, I think I’ll use just Make because CMake was pretty slow. Overall great project, though, and it was a bunch of fun making it.
Cleaned up my git repo! This session was primarily to make my work presentable. I made my readme, which gives a breif overview of the project, and includes a demo video. I also wrote firmware and hardware isntructions if someone wants to recreate it.
Here’s the link to the demo video: https://youtube.com/shorts/ai6QLhHT9NE?si=4pOMcnLnvPT2tYLt
Log in to leave a comment
There were a couple of errors, but they were fairely minor. The main thing is getting used to C syntax–I normally work in python, and I forgot to add some semicolons here and there. Additionally, the OLED logic needed some revision such that itll work on a 128x32 display. Overall not too much work. Here’s a breif video demo–I’m going to be making a nicer video (and documenting it!) in the new year.
Wrote main.c! Hopefully this is the last major update–in this document, I call all the methods I wrote >:). This made things a bit easier, becasue the hard part is done, now we get to work at the high level. One thing I noticed is that the physical orientation of my hardware looks better 90 degrees CCW, so I implemented that through creating logic that transforms the physical orientation to a logical orientation, and then performs action based on the logical orientation. Now time to compile and test!
Log in to leave a comment
mega devlog again! In this session, I coded the implementation of tinyusb. This was a big learning experience, becasue I havn’t worked with this yet. Thankfully, the documentation for this is very clear, and there are numerous implementations online. The first part of implementing this is writing teh config file, which tinyusb in CMAKE will read to compile the other usb files. Then I made the interface for USB HID, which makes sure that the rp2040 gets read as a human interface device. This wasn’t too bad because of online documentation. The usb descriptor file got written last, because that imported all 3 of the files before. In this file, it was just writing the algorithms that allow the target device to exchange information with the rp2040. The tinyusb stack was especially important here, since this file was mainley understanding the enumuration process.
I belive most of this code can be reused in future projects, however, the tinyusb config might need to be changed to accomodate what usb feature the project intends to do. One thing I really admire about this protocol is how they made it lightweight through only installing the packages needed for the specific implementation: i.e., in my device, I don’t need code for MIDI.
Log in to leave a comment
Figured out how tiny usb works! I wrote tusb_config.h, which oversees the configuration of all the different drivers. Ultimatly, the msot important bits of code were setting the buffer size and enabiling the HID driver. This was definelty a process, though: I was coding while reading teh documentation, so it took a bit of time. In the comments, I documented what each function does, so it should be easier to port into another project. From my understanding, CMAKE will interpret this file and encode the tinyusb features.
Log in to leave a comment
okay mega devlog. In this log, I have made the interface and functions to communicate with an OLED using I2C. Big shout out to adafruit for linking the docs for the 1306 chip on my oled. The first thing I did was make the font for the letters I would use. I realized there wasn’t a library, so I hardcoded each letter as an array of 5 numbers, which when in binary show the letter. I then implemneted algorithms for I2C, such as teh start, stop and write. Then I wrote helper functions for commands and data. Then i wrote the initilaization script (which took the longest) where I had to use low-level commands for the oled to work. I scraped most of tehse from the documentation. I then moved a tad more abstract, where I implemneted clearing, updating, and drawing algorithms. In this process, I think the biggest thing I learned is how I2C works; before I just imported a python library haha. I made sure to add comments such that this code can be re-used for later projects. I think the next thing I will be workign on is the USB HID, which hopefully won’t take this long.
Log in to leave a comment
wrote the encoder interface and methods! Most of the time was to figure out how to represent the encoder rotations. I created an 8 bit variable that tracks the old and new state. States are determined per a lookup table I constructed by creating change between [00, 01, 10, 11] by itself. The result was 16 possible outputs for which way the rotation could be. The first method I made was a static method that updated the encoder state and encoder delta. Then, I realized i forgot to initialize it (haha) so I made that and used callbacks to not have to do a while(true) polling loop.
I think I wrote the bulk of the matrix logic! To represent the 9 keys, I chose to implement a bitmask structure where the position of a “1” indicates which key is pressed. Finished most of the code for matrix.c and wrote its interface.
Log in to leave a comment
wrote the config based on my PCB schematic! I chose to use my macropad project that I made earlier because I did not want to order and wait for a pcb. In a future itteration may change that, and will change the key morphology accordingly. But for now, we are working with a 3x3 switch grid and an encoder. the config file is just defining constants that we’ll use in the project, such as which gpio pins each row/col are, how much the debounce is, ect… Now time to code the header files with which functions I anticipate I’ll need!
wrote the pico_SDK_import.cmake! big shout out to reddit shich helped a ton with the algorithm! I hope this helps others bc now the whole sdk import algorihtm is compiled. This should be copy-pastable into other projects (assuming it works (it probbaly dosnt but debugging shouldnt be that bad))
Log in to leave a comment
Wrote the CMakeLists.txt!
Something more I want to accomplish with this project is making hardware coding more accessible. To do this, I wrote comments under each line outlining what it does. I remember when I first got into hardware coding, it was challenging because you had to know a lot just to get started. I want to make that process easier.
Log in to leave a comment