I’ve long been into keyboards, but I’ve never taken the time or invested the money into really building my own fully custom keyboard. When I finally pulled the trigger, I decided on the Monstargear XO V3 Alu keyboard kit. It came with a PCB that would allow me to customize it how I saw fit (or so I thought) using an open source firmware project called QMK or quantum mechanical keyboard.
Once I received the keyboard and got it all assembled, I decided to modify my keymap to add some functions like volume controls. When I looked into what I needed to do, instead of compiling from source, I had to use some strange website with an IP address in China. This was disappointing to say the least, but not the end of the world for me since it would still do most of what I wanted. I followed the directions and uploaded my keymap files to the website and...got an error...great.
I jumped on to the company’s Discord server and asked for some help. I was quickly asked a few questions and their support person uploaded the files himself and was able to get a hex file for me to flash to my board. Excited, I put my keyboard in DFU mode and flashed the new firmware. Unfortunately, it didn’t work. The keyboard still worked, but none of the custom keymaps worked. I told support person what had happened and they made me another firmware to try. This time, when I flashed the firmware, the keyboard became unresponsive. I tried to enter DFU mode again, but they keyboard would not respond at all. It was suggested that I try to open my keyboard and jump the reset pins to attempt to get into the bootloader that way, but again, no luck. My brand new expensive custom keyboard was bricked.
At the request of support, I reached out to someone higher up in the company. He got back to me, apologized, took my information, and promptly sent me out a new PCB for my keyboard. When I asked him about the source for the firmware, he told me that their manufacturer had refused to give it to them because they were afraid someone would copy it. They had tried several things to get them to release it, but with no luck. Even though they had paid to have it made for them, they were never provided with the complete source. It was hard for me to be upset with them over this since they were essentially in the same boat I was. They were at the mercy of some factory in China.
This is where I could have ended the story. I could have just received my new board, installed it, and moved on. That, however, is not an acceptable solution for me. I needed to know more. I needed to know why. I couldn’t just throw this PCB away. It was already broken and it wasn't like I was going to break it more and so, I rolled up my sleeves and got to tinkering.
The first thing I did is notice that there are seven pins next to the reset pins on the PCB. These had to be there for a reason, right? So I grabbed my multi-meter and started to trace them out. I compared my findings on which pins on the board went to which pins on the chip with the documentation from the chip manufacturer. The chip was an Atmel at90usb646 so there is plenty of information on it out there. When I was done, I had identified them as VCC, SCLK, MOSI, MISO, RESET, no connection, and GND. After a bit of Google work, I found out that these pins are the ISP interface of the chip.
ISP stands for in system programming. It’s designed to allow you to read and write to the microcontroller without desoldering it. Now all I needed was a way to test it out. I went on to Amazon and ordered the first ISP flasher that I saw. Unfortunately it was lost in the mail (thanks USPS!). I was about to order a new one when I noticed an article where someone had used an Arduino Uno for this same purpose. I had one sitting in my drawer that I had purchased almost 10 years ago to the day. I loaded up the sketch he provided on the site and followed his directions on which pins were which. I plugged the Arduino into the PCB and my computer, crossed my fingers, and issued the first command to read the firmware, and it worked! At this point I was only able to read an empty chip, but I knew that it was at least alive.
Now the fun part. I went back to Atmel and found the stock bootloader that they use. I knew this wouldn’t be the correct one for this setup, but it would be a good one to test. I wrote the bootloader with the ISP flasher I had made, and it was successful. I plugged the PCB back into my computer and it was recognized as a DFU device. I had successfully unbricked my PCB. All I needed now was a working firmware. I tried to flash the factory firmware at this point, but it just bricked the board again requiring another ISP flash. I incorrectly assumed that the issue was something with the fuse settings on the chip. This was a big mistake on my part.
When playing around with the fuse settings, I ended up somehow setting them all to zero. This caused the board to become completely unresponsive even to ISP. I thought for sure I had killed it for good this time. I did a little more searching online and found out that I had probably disabled the internal clock on the chip. My only solution was to inject a clock signal of my own. I thought I was going to have to find a crystal and build a circuit to do this, but it turns out that since I’m not the first person to do this, someone had modified the Arduino sketch that I was using to also output a clock signal. There was no connection on the board that I could find that I could use to inject the clock signal, so I literally just held the wire against the correct pin while attempting another ISP flash. To my surprise, this actually worked. The board came back to life. I issued a command to reset the fuses back to the factory state. Crisis averted.
I reached out to the company again and let them know what I had found out. They were very excited and happy to help me with whatever they could. They sent me everything that had on this PCB. Some pictures of the board layout and a very early, very broken, source code. I tried to compile the source code as is. When I flashed it to the PCB, it was recognized as a keyboard but only a handful of keys worked and none of the LEDs worked. I tried to put it in DFU mode and flash the stock firmware from the website, but once again, it bricked the board.
At this point, I knew I was close to something. I went back and started to read everything I could on QMK. After many much trial and error and tons of flashes, I had figured out the entire key matrix and had every key working. I showed the company what I had and gave them all the info that I had found in hopes they would be able to help anyone else that had bricked their board.
All that was really left to do was to get the RGB lighting working. Through some more trial and error, I figured out the pins, LED ordering, and driver that it needed. I lost track of how many times I had flashed my board at this point, but I do know that I didn’t bother even putting the screws back in my keyboard because I was taking it apart so much from bad flashes. Once the LEDs were all identified, it was easy enough to set up the layout for the animations and write some code to control the caps lock, scroll lock, and num lock LEDs.
After all was said and done, I had a keyboard that had 99% of the functionality that it came with, but with a fully open source firmware that I had written myself. The only thing the factory keyboard could do that I couldn’t was control the LEDs with some software they had made.
I decided to look into something called VIA. VIA is a graphical configuration program for QMK firmware that allows you to remap the keys without flashing and also has the ability to control the LEDs in some cases. I went back to reading page after page of documentation and in a few hours, I had a working connection to VIA and was able to remap my board. The LED control didn’t work since they didn’t yet officially support RGB matrix keyboards. Luckily, I met a helpful guy on Discord that showed me a workaround to get it working. With his help, I was able to get this working too. Now, not only did I have the same functionality as the stock board, I actually had more!
I was pretty much done with making everything the way I had wanted it, so I put all my information together on Github and once again shared it with the company that made the keyboard. They were so happy to have a fully open sourced VIA enabled firmware that the company offered me a free keyboard of my choice, a lifetime discount from their website, and even sent me a few of their other PCBs to take a look at for them too. They are now flashing all of their new boards with my firmware before they ship them to their customers. I've also submitted a PR to both QMK and VIA and have had them both accepted, so now, everything just works.
Before this started, I had never even heard of QMK, ISP, used Atmel AVR programming, or written anything in C. Today, I had completely reverse engineered my keyboard’s PCB and added support for it to an open source project. Being a big fan of open source software, I’m glad that I could do this for the community. It’s disappointing that the manufacturer won’t release the source that they are required by law to release, but had they, I might not have had this great learning experience. Big thanks to Monstargear for helping me with all the information they had and for the brand-new keyboard.
If you want to take a look at my findings, you can find all the information on my Github here.
Once I received the keyboard and got it all assembled, I decided to modify my keymap to add some functions like volume controls. When I looked into what I needed to do, instead of compiling from source, I had to use some strange website with an IP address in China. This was disappointing to say the least, but not the end of the world for me since it would still do most of what I wanted. I followed the directions and uploaded my keymap files to the website and...got an error...great.
I jumped on to the company’s Discord server and asked for some help. I was quickly asked a few questions and their support person uploaded the files himself and was able to get a hex file for me to flash to my board. Excited, I put my keyboard in DFU mode and flashed the new firmware. Unfortunately, it didn’t work. The keyboard still worked, but none of the custom keymaps worked. I told support person what had happened and they made me another firmware to try. This time, when I flashed the firmware, the keyboard became unresponsive. I tried to enter DFU mode again, but they keyboard would not respond at all. It was suggested that I try to open my keyboard and jump the reset pins to attempt to get into the bootloader that way, but again, no luck. My brand new expensive custom keyboard was bricked.
At the request of support, I reached out to someone higher up in the company. He got back to me, apologized, took my information, and promptly sent me out a new PCB for my keyboard. When I asked him about the source for the firmware, he told me that their manufacturer had refused to give it to them because they were afraid someone would copy it. They had tried several things to get them to release it, but with no luck. Even though they had paid to have it made for them, they were never provided with the complete source. It was hard for me to be upset with them over this since they were essentially in the same boat I was. They were at the mercy of some factory in China.
This is where I could have ended the story. I could have just received my new board, installed it, and moved on. That, however, is not an acceptable solution for me. I needed to know more. I needed to know why. I couldn’t just throw this PCB away. It was already broken and it wasn't like I was going to break it more and so, I rolled up my sleeves and got to tinkering.
The first thing I did is notice that there are seven pins next to the reset pins on the PCB. These had to be there for a reason, right? So I grabbed my multi-meter and started to trace them out. I compared my findings on which pins on the board went to which pins on the chip with the documentation from the chip manufacturer. The chip was an Atmel at90usb646 so there is plenty of information on it out there. When I was done, I had identified them as VCC, SCLK, MOSI, MISO, RESET, no connection, and GND. After a bit of Google work, I found out that these pins are the ISP interface of the chip.
ISP stands for in system programming. It’s designed to allow you to read and write to the microcontroller without desoldering it. Now all I needed was a way to test it out. I went on to Amazon and ordered the first ISP flasher that I saw. Unfortunately it was lost in the mail (thanks USPS!). I was about to order a new one when I noticed an article where someone had used an Arduino Uno for this same purpose. I had one sitting in my drawer that I had purchased almost 10 years ago to the day. I loaded up the sketch he provided on the site and followed his directions on which pins were which. I plugged the Arduino into the PCB and my computer, crossed my fingers, and issued the first command to read the firmware, and it worked! At this point I was only able to read an empty chip, but I knew that it was at least alive.
Now the fun part. I went back to Atmel and found the stock bootloader that they use. I knew this wouldn’t be the correct one for this setup, but it would be a good one to test. I wrote the bootloader with the ISP flasher I had made, and it was successful. I plugged the PCB back into my computer and it was recognized as a DFU device. I had successfully unbricked my PCB. All I needed now was a working firmware. I tried to flash the factory firmware at this point, but it just bricked the board again requiring another ISP flash. I incorrectly assumed that the issue was something with the fuse settings on the chip. This was a big mistake on my part.
When playing around with the fuse settings, I ended up somehow setting them all to zero. This caused the board to become completely unresponsive even to ISP. I thought for sure I had killed it for good this time. I did a little more searching online and found out that I had probably disabled the internal clock on the chip. My only solution was to inject a clock signal of my own. I thought I was going to have to find a crystal and build a circuit to do this, but it turns out that since I’m not the first person to do this, someone had modified the Arduino sketch that I was using to also output a clock signal. There was no connection on the board that I could find that I could use to inject the clock signal, so I literally just held the wire against the correct pin while attempting another ISP flash. To my surprise, this actually worked. The board came back to life. I issued a command to reset the fuses back to the factory state. Crisis averted.
I reached out to the company again and let them know what I had found out. They were very excited and happy to help me with whatever they could. They sent me everything that had on this PCB. Some pictures of the board layout and a very early, very broken, source code. I tried to compile the source code as is. When I flashed it to the PCB, it was recognized as a keyboard but only a handful of keys worked and none of the LEDs worked. I tried to put it in DFU mode and flash the stock firmware from the website, but once again, it bricked the board.
At this point, I knew I was close to something. I went back and started to read everything I could on QMK. After many much trial and error and tons of flashes, I had figured out the entire key matrix and had every key working. I showed the company what I had and gave them all the info that I had found in hopes they would be able to help anyone else that had bricked their board.
All that was really left to do was to get the RGB lighting working. Through some more trial and error, I figured out the pins, LED ordering, and driver that it needed. I lost track of how many times I had flashed my board at this point, but I do know that I didn’t bother even putting the screws back in my keyboard because I was taking it apart so much from bad flashes. Once the LEDs were all identified, it was easy enough to set up the layout for the animations and write some code to control the caps lock, scroll lock, and num lock LEDs.
After all was said and done, I had a keyboard that had 99% of the functionality that it came with, but with a fully open source firmware that I had written myself. The only thing the factory keyboard could do that I couldn’t was control the LEDs with some software they had made.
I decided to look into something called VIA. VIA is a graphical configuration program for QMK firmware that allows you to remap the keys without flashing and also has the ability to control the LEDs in some cases. I went back to reading page after page of documentation and in a few hours, I had a working connection to VIA and was able to remap my board. The LED control didn’t work since they didn’t yet officially support RGB matrix keyboards. Luckily, I met a helpful guy on Discord that showed me a workaround to get it working. With his help, I was able to get this working too. Now, not only did I have the same functionality as the stock board, I actually had more!
I was pretty much done with making everything the way I had wanted it, so I put all my information together on Github and once again shared it with the company that made the keyboard. They were so happy to have a fully open sourced VIA enabled firmware that the company offered me a free keyboard of my choice, a lifetime discount from their website, and even sent me a few of their other PCBs to take a look at for them too. They are now flashing all of their new boards with my firmware before they ship them to their customers. I've also submitted a PR to both QMK and VIA and have had them both accepted, so now, everything just works.
Before this started, I had never even heard of QMK, ISP, used Atmel AVR programming, or written anything in C. Today, I had completely reverse engineered my keyboard’s PCB and added support for it to an open source project. Being a big fan of open source software, I’m glad that I could do this for the community. It’s disappointing that the manufacturer won’t release the source that they are required by law to release, but had they, I might not have had this great learning experience. Big thanks to Monstargear for helping me with all the information they had and for the brand-new keyboard.
If you want to take a look at my findings, you can find all the information on my Github here.
Comments
Post a Comment