DIY Macro Pad PCB Design

Are you tired of using generic, off-the-shelf keyboards that don’t quite fit your needs? Why not design your own custom keyboard PCB using KiCad? With this powerful open-source electronics design software, you can create a keyboard that’s tailored to your exact preferences.

To get started, you’ll need to select the components for your keyboard. Key switches are a critical component, as they’re responsible for registering keystrokes. There are several types of switches available, each with different characteristics in terms of feel and sound. You’ll also need diodes to prevent ghosting (when multiple keys are registered at once), and a microcontroller to handle the key scanning and USB communication.

One microcontroller that’s gaining popularity in the keyboard community is the RP2040. This powerful and versatile chip is capable of running custom firmware and has ample processing power and memory for even the most demanding keyboards. It’s also relatively easy to work with, as it can be programmed using the C language and has extensive documentation and community support.

Once you’ve selected your components, it’s time to start designing your PCB in KiCad. The first step is to create a schematic that defines the connections between the components. This can be done using KiCad’s intuitive schematic editor, where you can drag and drop components and wire them together. Make sure to label all your connections and keep the schematic organized for easier troubleshooting later on.

Next, you’ll need to create a PCB layout based on your schematic. KiCad’s PCB layout editor allows you to place components on the board, define the trace routes between them, and add any necessary pads or vias. It’s important to keep in mind factors such as key spacing, switch orientation, and overall keyboard size when laying out the PCB.

When it comes to firmware, my personal favorite is QMK. It offers a wide range of keyboard layouts and features, but what really sets it apart for me is its support for Vial. This powerful tool allows you to remap keys on the fly without having to reflash the firmware. This means you can easily change your key mappings or add new functions without the need for additional software or complicated programming. As a QMK enthusiast myself, I can attest to its flexibility and ease of use, making it a great choice for both beginners and experienced keyboard enthusiasts alike.

Once you’re happy with your PCB design and firmware, it’s time to order the components and manufacture the board. There are many options for PCB fabrication, ranging from DIY methods like toner transfer and etching to professional services that can handle complex designs and high volumes.

After your PCB has been manufactured, it’s time to assemble the keyboard. This involves soldering the components to the PCB, attaching stabilizers to the larger keys, and programming the microcontroller with custom firmware.

In conclusion, designing your own keyboard PCB in KiCad is a rewarding and fulfilling project that allows you to create a keyboard that’s tailored to your exact preferences. With the RP2040 microcontroller, a careful selection of components, and QMK with Vial for firmware, you can create a keyboard that’s not only functional but also beautiful and unique. So grab your soldering iron and get started!

Programming BeeBest/Xiaomi A208

I found a BeeBest/Xiaomi? A208 walkie talkie at a shop near me for a very reasonable price. So I picked one up to give it a try. It seems to be a less-featured version of the fancy xiaomi radios that have bluetooth and digital features. This one seems to be just a 16 channel analog FM radio covering 400-470 at 5W.

Unfortunately, it would seem the programming must be done from Windows using a proprietary cable. Luckily for us, the programming cable appears to be a simple PL_2303 USB-TTL adapter and a micro USB plug!

Some searching around found this page, that has a diagram of the pinout.

This looks rather easily replicatable. as the NC pin is normally not connected in a Micro USB cable anyway.. I got an old cable, wired up the pins accordingly, and loaded up the software which you can get here:

By the way! The software can be easily changed to english:

I made up a simple cable with a CH340G TTL adapter I had spare, turned on the radio, and it works!

Make sure you select the correct MODEL NUMBER and SERIAL PORT in the software.

You can change the language of the radio prompts to ENGLISH or OFF in the advanced settings pane.

Booting ESXi on a Dell R720 from an NVMe Drive

I found a nifty trick with ESXi.
If you want to use an NVMe Drive as your main datastore, you can install to it as normal, but the Dell R720 will not boot to it. (at least in my case, using a Kingston A2000 NVMe SSD on an Orico PCIe Adapter card)

The UEFI simply doesnt see it as a drive.

But what you can do is create a 4GB HDD partition on the vFlash SD card, and install ESXi to that.

While smaller than the minimum disk size of 8GB, the installer will run correctly.

You can then reboot the system, and boot off the 4GB vFlash partition.

Somehow ESXi seems to realise what’s going on and switches over to the NVMe drive!

When it boots up, you will find that your datastore resides on the NVMe drive.

Setting up a Hamshack Hotline Trunk in 3CX PBX

I have a 3CX PBX at home I use for a few things, and I also have a Cisco SPA504g that I use with HamShack Hotline.

I have a second extension setup on the SPA504g for my 3CX system, but I figured it might be a good idea to get the 3CX system to register to HH as a trunk as well! That way I can also make and receive HH calls from my phone and the amazing 3CX application.

I applied for a new trunk line via the HH Support Center, and received it the following morning.

They provided me with three pieces of information;
User: 30027 – This is the extension number assigned to my trunk (Try calling me!)
Password: aprettygoodpasswordwashere
IAX Host:

The IAX Host is the SIP server, and should accept a SIP Register on port 5060 with the authentication info above.

In the 3CX Management Console, I went to Trunks and clicked Add SIP Trunk.

I selected Generic as the country, and Generic VoIP Provider as the provider.
The Main Trunk Number should be the extension provided above.

I filled out the info where it needs to go, and set the destination for calls to the main trunk number to go straight to my extension, so Ill get them on my mobile or PC.

This SHOULD be all that’s required!
But alas, I am not that lucky today.

The trunk is failing to register.
If we switch over to the 3CX Event Log, we can see the failed registration attempt.

Its worth noting here, that while the log shows the user as, this is merely a graphical confusion, as 10001 is the internal number assigned to the trunk by 3CX, and not the actual user that it attempts to register with. 3CX Uses the SIP User ID we entered above to register, but I am still receiving a 403 Forbidden from the (which currently resolves to server.

I thought this may be happening due to the second connection I already have from this address, the Cisco SPA504g handset, so I connected to my Unifi Controller and shutdown the PoE to the port the phone is connected to.

Once the phone went offline I tried registering again through 3CX, and this time it gives an error that the service is not available…

I have reached out to the HHOPS team to see if there is any issues currently with the server, and will update my post here when I hear back, or if I otherwise resolve the issue.


I heard back from HHOPS!

They gave a few suggestions, and I was able to get things up and running!

Rather than Generic SIP Provider I have used Asterisk as the type, and rather than 5060 for the port, I have used 4569.
It is now successfully registered and appears to be working!

To finalise, I have also setup an Outbound Rule for Hamshack Hotline, where calls to numbers with a length of 5 digits get routed out the new Hamshack Hotline trunk.

Cheap dummy load

Dummy loads are very simple devices, they are a resistor, with 50ohm impedance, and a heatsink to dissipate heat.

I picked up a 50w heatsink from rs components, for $4.80 delivered overnight.

Arrived this morning, attach an SO239 and good to go.

For short bursts of power I’ll be using this for, <5-25w while tuning down commercial radios to legal limit it should do.

But I’ll need to add a heatsink for anything more or anything sustained.

Designing an even cheaper isolated digital interface for amateur radios

A few months ago, the ACMA made changes to the amateur LCD that allowed foundation class licensees to operate digital modes.

Excited to get into this in the new year, I begun looking into digital interfaces for the radios I already have. There’s many different ways this can be done, from as simple as not using a cable and relying on microphones and speakers, creating a straight through cable from the PC mic input to the radio speaker output and visa versa, to expensive isolated interface boards custom made in the USA.

I wanted an isolated board, because I have enough trouble with interference and noise in my apartment already, so the first two were out (although I did make a straight through cable for my Baofeng UV-5R for SSTV on 2m/70cm).

So I turned to the expensive isolated interfaces.

There’s plenty to choose from l, with different feature levels and prices! From the $230USD RigBlaster, the $200AUD SignalLink USB, and even the cheapest of the bunch, the Easy-Digi coming in at $30-50AUD shipped with slow shipping…

Naturally being a cheap ass I wasn’t overly satisfied with these options..

Luckily though, the Easy-Digi, saved the day! It’s such a simple design, with a published schematic, that it’s not too hard to roll your own with a few changes!

I jumped into EasyEDA and learnt how to do a basic schematic, then designed the interface circuit for audio using two 600:600ohm isolation transformers, and a PTT circuit using a DB9 rs232 connector because it’s easy, although I plan to replace that with a USB-C connector and a ch340 rs232 IC in a later revision!

I used components that I either already have laying around, or can get easily from JayCar for the most part.

The connectors and transformers I ordered from China at about $4-5 for 10pcs each.

With the layout done, I generated a PCB, and moved components around into a rough layout I was happy with, and hit the autoroute button :^)

I forgot to label the PC side connectors for the first revision, but I imagine there will be plenty of other changes I make anyway.

I uploaded the gerbers to JLCPCB to produce a test run of the PCB, which I should have within 2 weeks with the cheap shipping :^)

So if everything goes according to plan, I cluding parts and PCB manufacturing for 10 boards, I’ll have spend about $30-35 total, and I should be able to sell some of the boards to friends for $5-10 each offsetting my costs even more !

Yaesu FT-1500m restoration

A few years ago I picked up a Yaesu FT-1500m 50w VHF transceiver for a small amount, it was in pretty bad shape when I got it so it was pretty cheap.

I ordered a new microphone right away but because the previous owner super glued the old one in, I was never able to replace it.

I had trouble finding exactly the correct 6p6c Jack to replace the ruined one too.

I checked many places online, many stores in Singapore sim Lim, and many in Tokyo akihabara, until I finally found one that appeared to be close enough to use!

The new one wasn’t a perfect fit, I had to shave the corner of it down a bit, and drill out a small part of the radio housing to accommodate it, as it sits much more inside the radio than the stock one, but the pinout and height of the jack itself work ok. They’re logically correct too, despite being upside down compared to the stock.

I removed the stock Jack by carefully cutting away i at it with flush cutters until there was just pins left, then I desoldered those one by one, and cleaned up with some braid.

Installed the new jack, but it had plastic PCB mount rather than metal mounts I could solder. I decided to add some copper wire for a little bit of extra mechanical support. I added some liquid electrical tape to attach the wire to the jack.

After that was all done, I was more or less finished with what I can do!

I replaced the manky old M5 bolts with clean new ones, and will give the unit a general cleanup!

Unfortunately the rubber buttons are beginning to disintegrate, so I’ll have to figure out something to do there.. I cannot locate a replacement for those :/

The volume potentiometer has seen better days but still functions perfectly. But I may replace it in the near future.

Lasercut Server Rack Blanking Panels

To my surprise, I cannot find any sort of blanking panel template for laser cutting on the internet. Considering how common laser cutters are becoming, I expected to find at least some… oh well, I have made my own and will share it with you here!

I threw this together in Illustrator and share with you three files, an AI, an SVG and a DXF for cutting or whatever you want.


1U and 2U Blanking Panels DXF

Edit: cut and tested some they fit well 🙂

IKEA Server / Comms Cabinet


I have had for the last few years, a growing pile of electronics that I called my homelab. It looked a bit sad.

This was it recently…
This was back in 2017 😭🙃

I decided recently that it really deserved some love, and it’s really very rewarding to put in a bit of effort for something that looks good.

So I started looking into ideas on how to clean it up.

Initially I was planning on getting either a 9u or 12u rack/cabinet, and just leaving it in the same place. But as much as I love my servers and gadgets, I don’t think a black metal box in the living room/ kitchen looks great to guests. So I figured I should try something that looks better.

An IKEA lack was off the table, as it’s much too large for something up against the wall in my opinion, so I browsed the website for a while until I came across the TRYSIL. It’s a chest of r draws, that extends a mere 40cm from front to back. Perfect for up against the wall! And at only $129, it was just $4.05 more expensive than a 9u rack.

So I ordered one and picked it up Friday night. Assembly was pretty straightforward, just follow the pictures as you would expect. But what I didn’t do was install the bottom two draws, I left that section completely open.

I purchased two metal strips for.the hardware for about $0.80 each, and laid the two draw fronts together about the correct spacing apart, and bolted them together using the metal strips.

I then measured out and attached two butt hinfes ($4.95 for the pair) to the new door and cabinet.

I had this wall-mount server rack thing left over from a previous intention to wall mount my servers in the garage, and flipping it on its side gave me a perfect 3u mounting space.

I used M5 bolts and some washers to secure it in place, and it’s not going ANYWHERE.

This fits really well, leaving a bit of space on either side for cable management and other things.

I then test fit a PowerPoint art he back and started on my way to cutting out a hole in the base to mount a pair of 200mm fans for airflow.

In Australia you can’t do mains voltage work without a license, so I called over a sparky friend do wire things up for me.

I went out to my local Jaycar to pickup a few things I would need, and while I was there I found a 4 Port USB outlet for only $15! I grabbed this and a mounting box for it as well, this will be useful for odd things like an esp8266 to monitor temperature and drive LEDs, and the Mi-Light wifi bridge.

Now that sparky mate has installed those for me I went back to working on cutting out my hole for the fans. I probably could have cut it out before assembly but I was in the mood to get things done in one day so I didn’t want to trek out to Robots and Dinosaurs with some wood to cut out using their tools!

I cut a hole on the upper left side for a cable feed hole for ethernet connectivity, but I’m thinking I’ll replace this with a 6 way Keystone plate to keep the cabinet modular. I want to move the nbn cable NTD into the roof, so that rather than an RG-6 cable to deal with I just have CAT6…

I also got an IEC socket installed on the back to be fed from the external UPS which is too large to fit inside, this also means it’s relatively simple to unplug and move should I have to do that.

Once I had the holes cut out to my satisfaction, keeping in mind that they won’t really be seen so I wasn’t too fussed, I used cable ties to hold the two 200mm fans together, and screwed them into the underside of the cabinet over the hole.

Oh I also attached the $2.95 magnetic latch you see here.

Once I had mounted and wired up my fans, it was time to start moving my network hardware over.

I started with the switch as it will serve as the shelf for the other hardware. (don’t worry it’s properly bolted in)

I then installed the power distribution bar, NTD and pfsense router. I blacked out the pfsense because it’s a surprise for another post soon.

I affixed the Mi-Light bridge and zigbee2mqtt devices using command Velcro, and screwed in a fan controller harvested from the same PC the fans came from.

I began to test fit the various power supplies inside, there’s a few because I’m using micro PC’s as servers… I’m considering consolidating the Synology units into a single 150w PSU though.

I test fit and began cabling everything in, I have ordered a brushed 1u panel to clean up the wiring a bit more but it will be a few weeks from china.

Once everything was in, I did a final test to make sure I was happy with the airflow and the path the air seems to be taking through the cabinet, which will improve after I install the brushed plate and a blank panel.

With ally tests done and happy, I hooked up the ups and turned on all the servers one after another. I monitored them as they came back online to ensure all VMs and services started correctly, and so far only Wireguard refuses to start! 🙁

Good enough for me!

And with that the move was virtually complete!

I have since added some lights, and a DHT22 temp/humidity sensor inside to keep track of how it’s going, but temps so far seem very acceptable.

The 120mm fans bolted directly to the cabinet are audible so I would like to replace them with noctuas, mounted via rubber or foam dampeners.

Overall I’m super happy with how it turned out, everything fit perfectly, it was fun to work on and build, it looks so much better than an ominous pile of electronics next to the kitchen and dust will hopefully be a bit less an issue now!

Best of all, it looks nothing like a server cabinet!

A Smarter Smart TV

My TV at home features both Google TV through a Xiaomi Mi Box, and Kodi running on an old Chromebox. This alone is what most would call, a ‘smart tv’

However Is it really smart if you still have to turn it on? and change channel?
In some occasions, HDMI CEC can help here, as it is capable of turning the TV on and changing to the input it needs ! However for my use case, this doesnt work. and it is rarely able to turn OFF the TV.

Luckily, in one of my recent posts I covered how I added RS232 control to the TV. so actually changing inputs and power on and off are now discrete commands we have at our disposal!

Using some simple logic in Node-Red it was a simple case of checking which device changes to playing, and then switching the TV on, and changing over the input to match!

There is probably a more streamlined way to do this but this is what I have come up with:

It works like so;

First we have this state changed node that outputs true, if the device is not playing.

If it IS playing, it outputs a false, which triggers the ‘Turn on TV’ call service node.

followed by a wait until node, just to add a 1 second delay to allow the TV to startup.

and finally another call service node to actually change the input!

Meanwhile, if the TV state is anything OTHER than playing, it will first go to this wait until node, and wait 60 minutes in case it begins playing again (this gives time to choose the next video or show using a remote ! I will probably shorten this though)

finally followed by the turn off switch for the TV.

I also need to get around to renaming the entities of the switches used here, as they’re not very well named at present.

Ill include the flow below!

[{"id":"4e63a44b.f401bc","type":"server-state-changed","z":"e94d3e8b.2d81e","name":"When Kodi stops Playing","server":"33a2704d.0e654","version":1,"entityidfilter":"media_player.kodi_libreelec_local","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"playing","halt_if_type":"str","halt_if_compare":"is_not","outputs":2,"output_only_on_state_change":true,"x":290,"y":760,"wires":[["9a3def91.d13ae"],["432da1ba.4b195"]]},{"id":"432da1ba.4b195","type":"api-call-service","z":"e94d3e8b.2d81e","name":"Turn on TV","server":"33a2704d.0e654","version":"1","service_domain":"homeassistant","service":"turn_on","entityId":"switch.sharp_tv_rs232","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":850,"y":700,"wires":[["9be17d6c.92cdf"]]},{"id":"11a5db01.9c8e75","type":"api-call-service","z":"e94d3e8b.2d81e","name":"Turn off TV","server":"33a2704d.0e654","version":1,"service_domain":"homeassistant","service":"turn_on","entityId":"switch.turn_off","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":850,"y":780,"wires":[[]]},{"id":"9a3def91.d13ae","type":"ha-wait-until","z":"e94d3e8b.2d81e","name":"","server":"33a2704d.0e654","outputs":2,"entityId":"media_player.kodi_libreelec_local","property":"state","comparator":"is","value":"playing","valueType":"str","timeout":"60","timeoutUnits":"minutes","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":620,"y":760,"wires":[["432da1ba.4b195"],["11a5db01.9c8e75"]]},{"id":"9f2ad7cf.baa538","type":"api-call-service","z":"e94d3e8b.2d81e","name":"Change Input","server":"33a2704d.0e654","version":1,"service_domain":"switch","service":"turn_on","entityId":"switch.displayport","data":"","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1200,"y":680,"wires":[[]]},{"id":"9be17d6c.92cdf","type":"ha-wait-until","z":"e94d3e8b.2d81e","name":"","server":"33a2704d.0e654","outputs":2,"entityId":"switch.displayport_2","property":"state","comparator":"is","value":"on","valueType":"str","timeout":"1","timeoutUnits":"seconds","entityLocation":"","entityLocationType":"none","checkCurrentState":true,"blockInputOverrides":true,"x":1000,"y":680,"wires":[["9f2ad7cf.baa538"],["9f2ad7cf.baa538"]]},{"id":"33a2704d.0e654","type":"server","z":"","name":"Home Assistant [Lewys]","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]