Wednesday, September 23, 2026

Retirement Project - Fixing up the SWTPc 6809

Given that it is 50 years old, the SWTPc 6800 Computer System which I call my retirement project has been in need of some "fixes". 

Having made the BBUG ROM monitor changes to allow for extended address decoding, it was time to do some surgery on the motherboard. Might as well make some fixes.
Post close-up

Posts

The original SWTPc kit held the motherboard in place with seven plastic clips along the edge. They were designed to be pushed down from the top and clip in to the chassis bottom. A plastic arrow held the motherboard in place and could be easily unclipped. In theory.

The sad reality is the clips never engaged correctly with the chassis bottom, and often one whole end of the motherboard would be loose in the box.

Seven posts
Around 1979, just before heading to the ISEF, I replaced these clips with #6 screws, lock washers and multiple nuts. Four nuts supply the spacing, with a fifth nut holding the motherboard in place. The #6 screws are a tight fit through the holes in the motherboard, but everything is aligned. 

I took some pictures of these beauties in case someone needs to replicate them.

Feet

Chassis bottom with new feet,
and the adhesive of the original.
The original SWTPc 6800 Computer System kit supplied rubberized stick-on feet. Honestly, they held up pretty well nearly 50 years. Along the way, one of them had fallen off and gotten lost, and the replacement foot wasn't quite tall enough. I replaced them with rubber feet held in place with a #6 screw.

This meant drilling some additional holes in the pan of the chassis. Not a big deal, nor was the placement critical. One foot borrowed the #6 screw holding the clamp for the power cord. The other three used new hardware.

I eyeballed the placement of the other three screws, and the results were acceptable -- certainly compared to the old stick-on feet.


LM7805 Bypass Caps

Input and output 0.1 uF caps
lap-soldered across LM7805.
Because the SWTPc uses an unregulated 8 volt supply, every board has one or more LM7805 +5 volt regulators. Examining my bit rate generator board, I wondered the regulator was properly bypassed. I remembered an issue in a different project where an LM78xx regulator oscillated because it wasn't bypassed correctly. 

A search of the data sheet provided a concise answer:
  • All LM7805 regulators should have 0.1 uF ceramics across the input and output.
  • LM7805 regulators that supply 50 mA (or more) current should have 10 uF per 100 mA on the output.
These were simple rules to follow. A quick survey of the SWTPc schematics made it clear that the designers had never heard of the first rule. There were no input bypass caps at all. Output electrolytic bypass caps were present on those drawing more current, with an occasional 0.1 uF cap. The Tanner and Gimix boards were more heavily bypassed. My home-brew boards were no better than the SWTPc designs.

This problem was easy to solve. I have a bunch of 0.1 uF multi-layer ceramic caps. I added them to the boards:
  • 0.1 uF on input of bit rate generators card
  • 0.1 uF on input and output of MP-S cards
  • 0.1 uF on input and output of MP-C (modified to MP-S) card
  • 0.1 uF on input and output of MP-LA card
  • 0.1 uF on input of MC68B09 V2 CPU card
  • 0.1 uF on input of MP-B motherboard
For the MP-S, MP-C and MP-LA cards,  I lap-soldered the caps on the back-hand side of the board, rather than drill holes. Easily done in a few minutes.

I added some small-value electrolytic caps to the output of some LM7805's. Generally, boards that include these caps have a 100 uF unit, which is good enough for 1 A of current -- overkill for some boards.
  • 22 uF on output of bit rate generator card (more than necessary, 15 uF would be enough)
  • 10 uF on output of MP-B motherboard 
It could be that none of these bypass caps are required, but seems like they can't hurt.

Extended Decoder

Dec 1986 decoder circuit
December 1986, I added an extended address decoding circuit to the motherboard. The decoding avoided aliasing of the xExxx pages that prevented access to RAM or other devices. With the MC6809E V1 CPU card, this worked fine with BBUG, but the OS/9 ROMs had a different idea on how to program the DAT, so it didn't work with OS/9. I disabled the decoder and didn't figure out the problem until much later.

When I switched to the MC68B09 V2 CPU card the problem had reversed -- the decoder would work with OS/9, but not with BBUG. 

With BBUG updated to initialize the DAT in a compatible way, I could fix the decoder. The picture shows  the original decoder was a hastily improvised circuit using a 74LS21 4-input AND gate to detect all "1" values on S0-S3, connected to IC6 Pin 6 (Enable).

I sketched out some changes to decode several address lines, but I either never made those changes, or I removed them. The key to the MP-B motherboard is IC6 - a 74LS138 3 to 8 decoder. These other address changes messed with IC3 -- a different 74LS138. The MP-B I/O port data buffers are activated from IC6, so additional decoding against IC3 was an incorrect solution, as the data bus was active, even if no I/O slot was selected.

The new decoder board had simple requirements:
  • Disable Extended decode entirely
  • I/O accessible from FE000-FE07F (and FF780-FF7FF)
  • I/O accessible only from FF780-FF7FF
The I/O ports are aliased over a 2KB block -- each 16 byte I/O slot appears 128 times. This meant decoding S0-S3, A15-A12, A11, A6-A4. A15-A13 is handled by IC6, A6-A4 by IC3. A3-A0 is done by each I/O card. A10-A7 are not decoded. The decoder circuit just deals with S0-S3, A12 and A11.

Decoder showing jumpers
Decoder operation is jumper-selectable. This allows me to test each change and back out changes if something didn't work. The first jumper selects between the FFxxx I/O address or the FExxx / FFxxx aliased I/O address. The second jumper enables/disables extended decoding entirely. 

The 74LS21 has the first AND gate connected across S0-S3. The second gate is wired as a two-input AND that uses the output of the first AND gate and jumper-selectable A12 or a pull-up. The output of the second AND goes another jumper selecting IC6 pin 6 (Enable) to the output of the AND or a pull-up. A11 goes to IC6 pin 4 (Enable*) to ensure the I/O data bus buffers activate only on the lower 2 KB of the 4 KB memory page.

Clean mount of decoder
Circuit uses a bit of perf board and a 3M Scotchflex socket I've used for other projects. Surprisingly, I did not have a 74LS21 in my junk box. I salvaged the soldered unit I had hastily assembled in 1986. That worked out. The board is cleanly mounted on a spacer to the motherboard and all of the connections are made with wire-wrap wire.

Testing

Testing, much to my surprise, went perfectly. The disable jumper worked as before. Enabling the aliased extended decoding allowed me to use the xE pages of memory, and a special burn of the BBUG ROM allowed me to test I/O at FF780-FF7FF. This worked as expected. I could enable and use the FExxx block of RAM on the MC68B09 V2 CPU board and access it using the DAT,

Not sure why I was afraid of all these "fixes". I suppose I was shy about changing the motherboard in a way that might break the computer entirely.


Saturday, September 19, 2026

Cancer and my Absence

Cancer

I have yet to write about it here, but it is not a secret. December 2023, I was diagnosed with Stage IV Pancreatic cancer. Those who are close enough to follow me on Facebook know the whole story, so I won't repeat it here. I just want to acknowledge the issue.

Treatment

I've been treated since January 2024. I've undergone two different rounds of chemotherapy. The first, Abraxane / Gemzar cost me my hair, but ultimately was not sufficiently effective. Next was a Folfirinox regimen and remained through 18 treatments. While my oncologist decided the treatment was doing me more harm than good, each treatment has changed the landscape of my disease. I do not consider any of the effort wasted. The upside is, my hair grew back.

From July 2025-January 2026, I participated in a Phase I clinical trial for a type of immunotherapy. The sponsor ultimately cancelled the trial because it wasn't sufficiently effective.

Because of my otherwise good health and the relative stability of my main lesion, my doctors recommended this spring to treat my liver metastasises with Y90. Since the liver mets were where the action was, it seemed like a good course of action while I waited for another clinical trial.

The Y90 treatments were successful and appear to have eliminated the visible tumors on my liver. Unfortunately, this left a large amount of necrotic material around my liver.

Inactivity

I apologize for my recent inactivity. The area surrounding my liver became subject to a massive bacterial infection. Since mid-July, I had been subject to increased fatigue, pain and declining appetite which ultimately landed me in the hospital for eight days late in August. 

More Treatment

As with many advanced cancer patients, my issues were complex. Not only did I have a severe infection, turns out I had several gallstones and a large quantity of "gunk" blocking my common duct causing jaundice. Everyone was very surprised to discover the gallstones, since I had my gallbladder removed over 27 years ago. 

With the gallstones and gunk removed, and a drain on the large abscess near my liver, my improvement was immediately apparent on the labs the next day. 

Home

I've been home since early September, but progress has been slow. I'm using extremely strong IV antibiotics three times a day. my abdominal pain has gradually subsided. I'm eager to get back do working on projects and recently planned some for this fall.

Obviously, I haven't been able to dig the hole for the tower, When I started that, I never thought it would take six months to dig down four feet. It may take a while yet.

I feel very lucky as a pancreatic cancer patient. Most are not diagnosed until their cancer has reached a very advanced stage. They end up with very little time. Mine was caught a bit earlier, and for that I'm fortunate. 

Focus

Even without a lot of formal medical treatment for the last year and a half, I've been focused on my health. A key provision is keeping weight on. Although I weighed about 230 lbs in much of my adult life, I'm currently around 155 lbs -- having lost about 10 lbs during my last hospital stay. I'm working hard to get back to 165 lbs. Good nutrition is the key -- I don't eat junk. There's little added sugar, refined flour, or processed foods in my diet. This is what kills us. Lots of protein, fruits, vegetables, beans, nuts, seeds. Carefully choosing what you eat is probably the best medicine.

I'm also exercising. My other hobby teaching martial arts. I'm 5th Dan in Taekwondo, and I enjoy teaching at a local studio. I haven't been there in nearly three months now. I miss it greatly. Two weeks out of the hospital, and I'm finally strong enough to make some kicks. Once I'm off these IV antibiotics, I should be able to return.

Meditation and prayer are a part of my health focus. It's not just me praying -- I have a whole host of folks from a lot of different religious traditions. I seriously believe the appeals to the divine work. We're all connected to our Creator and each other in this way. I'm very thankful for those who pray for me.

Friday, May 1, 2026

Retirement Project: SWTPc 6800 (with 6809) Resurrection

In 2022, I documented my ancient SWTPc 6800 Computer System, which I had upgraded with several home-brew cards. It had been 25 years since I had last used the computer, but this ancient machine fascinated me. I wanted to record what I had done, as I'd forgotten a lot.

During this process, I plugged in one of the I/O cards incorrectly -- off by one pin. Normally, there's an index pin that prevents this, but some of my cards don't have the plug that blocks the pin. 

Sadly, when I powered it on, smoke was immediately released from one of the chips. After correcting that board, I found the system completely inoperable. This computer was 45 years old at the time, and I had many other projects that needed more attention. I decided that fixing it would be something I could do in my retirement. 

And, it remained broken until this year. You see, I've retired, so it was time debug this monstrosity.

When I originally built the CPU boards for this machine, I borrowed a 32-channel HP Logic analyzer. That allowed me to fix the bugs in the hardware and the software alike. But I long-ago lost access to such equipment. I had little more than the original kit manuals, schematics and notes, plus a digital voltmeter and an oscilloscope.

Symptoms

After the smoke let out, the machine crashed on reset. I could see from the front-panel LEDs that the CPU had gotten completely lost -- with every 4 KB block LED illuminating dimly. This is characteristic of a crash. 

Debugging

Initial step established what was working on the machine. I removed all the cards from the motherboard. I checked the power supply voltages on the motherboard:
  • +8v: +8.3v
  • +12v: +14.15v
  • -12v: -14.06
These unregulated voltages were nominally good. I verified that several of the bus signals were pulled high on the motherboard, such as RESET*. Everything seemed good.

I added the Bit Rate Generator board. It supplies all the serial bit rates on the SS-30 bus. I couldn't find any clock rates using the oscilloscope. Looking at the original schematic and the MC14411 data sheet, I found one thing missing. The data sheet recommends a 15 M Ω feedback resistor across the crystal. My circuit had none. Other designs used a 1 M Ω resistor. So I added one. Now I found all of the bit rate clocks present. Funny that it worked before. 

Next was the 6809 V2 CPU board. The LEDs would light up on reset, then go into the characteristic crash. Examining the important signals on the bus:

  • RESET* - goes low for 0.1-0.3s, then high
  • HALT*, BREQ*, MRDY, NMI*, IRQ*, FIRQ* -- all staying high. 
  • BA, BS - both low -- this means that the CPU is actively controlling the bus
  • E* and Q* - these clocks running at 2 MHz, as expected, this mean the CPU was alive at least
  • VMA* - cycling, meaning the CPU was attempting to access the bus
  • R/W* - cycling as expected
  • D0*-D7* - each data bus pin showed signs of normal activity
  • A0-A15 - the Address bus had problems on two pins
    • A3 - activity limited to 0v to 1v
    • A14 - activity stuck around 0v
This was good news. The CPU was working and attempting to process instructions, as evidence by the clocks, the BA/BS status pins, and the data bus activity. 

The address bus seemed to be the source of difficulty. When the I/O board was plugged in incorrectly, one of the chips received -12v, and that same chip was also connected to A3. As there are no buffers on A2 or A3 between the SS-30 and SS-50 bus, it is possible the 74LS244 address bus buffers could have been damaged. That didn't explain A14, but it made sense.

I swapped out both 74LS244 chips, and the CPU board now acted correctly -- polling the E block of memory, where the I/O resides. The E LED was brightly lit.

An MP-S board was added next. Since it was not connected to the A3 line, it was unlikely to be damaged. I needed something to function as a terminal to connect to the MP-S. I fashioned a DB-25 to DB-9 cable and hooked it to a USB serial port on my MacBook Pro. Pressing RESET brought up the "BBUG v1.91" prompt. YES! After nearly four years of being non-functional, my old computer was able to run the ROM monitor. 

Using the capabilities of the BBUG monitor, I set about diagnosing the other parts of the system. Since the last time it was operation, I expanded the CPU board memory from 64 KB (really 56-60 KB) to 256 KB (really 248-252 KB). I set about testing to make sure all of this additional RAM was functional. Because the MC6809 processor can't access more than 64 KB of memory at once, I had to do this in steps. I manually re-programmed the DAT to use different blocks, leaving the D, E and F blocks alone. The additional memory worked great.

With the CPU card functional, I set about to determine what else was working. 

Working on the I/O slots, something was amiss with the MC6840 on the bit rate generator board. A 74LS04 inverter connected to the A3 bus line had apparently been damaged. Swapping it out restored operation to the MC6840.

The 5 1/4" Floppy Disk Controller (FDC) board was the one that had been plugged in wrong. A 74LS139 that let the smoke out had been replaced, and everything seemed to be working. Similarly for the 8" FDC board. Both boards would respond properly to basic commands, even with no disk drives connected.

The Tanner/Digital Research 64KB RAM board was next. It took some experimentation to discover how to address its extended memory address. I found that the BBUG "Q" command, which does a memory test, can be fooled by bus capacitance. That's a bug that needs to be fixed. While the memory appears to be present, at least some of the time, there appear to be some address or data convergence problems. I haven't quite sorted that out yet. 

Next Steps

There are still issues that need resolution. I've attempted to boot FLEX/09, but it fails rather quickly. It appears to be properly loading the boot loader off the first sector of the disk, but for some reason does not appear to be able to load FLEX.SYS. I think my problem is that I don't have 5 1/4" boot disks set up for these 80-track drives. Most of my use of FLEX was limited to 8" disks, and those drives aren't yet connected.

An attempt to boot into OS-9 Level I also failed, even though I have several 5 1/4" boot disks. That's going to take more time to diagnose. It could be there's other damage to the 5 1/4" FDC board that I haven't isolated yet.

Thursday, April 30, 2026

Claude Helps with the Automatic Antenna Selector

Automatic Antenna Selector
I thought I was nearly finished with the Auto Antenna Selector. During my first week of retirement, I finally managed to locate something I had been looking for months -- A male-to-male DE15 cable. 

This cable connects the Auto Antenna Selector to the AUX port of a K3. I bought two of these a couple of years ago, and I easily found one. But the second one eluded me. Without it, I couldn't test the Selector in Design C (Dual Radio) mode. I had done all my testing in Design B (Single Radio) mode. 

Having the proper cables, I did my testing and found several bugs. Some of them were going to be difficult to fix. Part of the problem was my approach. I had organized my antenna selection table by the selections, then by band. This made it difficult to determine the choices available per band. So, I organized the table by band, then listed the choices. From this, I could determine which choices were available for a given band, skipping over those that would conflict with an existing port. 

This greatly simplified the code for making the mode selections, which are very different in Design B (Single Radio) and Design C (Dual Radios). In Design B, the first selection is assigned to the first port, so there can only be three additional choices. In Design C, only one port is selected per radio, so we can potentially use all four selections (so long as there's no conflict with the other radio).

Design C bugs were all addressed, and Design B worked better than ever.

Before I retired, I'd been messing around with Anthropic's Claude Code. I was curious what Claude might think of the firmware, so I requested an in-depth code review.

Claude Code came up with a number of good suggestions. It found some dead code, made several type suggestions, a minor code re-organization, and way better comments.

What impressed me, though, was that Claude Code had a deeper understanding of the particular PIC processor that I did. It suggested I turn on the Watch-Dog Timer (WDT). That I change how Timer 0 (TMR0) was used. And, that I use the PMD register to power-down the modules that I wasn't using in the device. 

I thought I was using TMR0 correctly. And I knew about the WDT, I just didn't think it was necessary. But the PMD register I knew nothing about. All of these suggestions seemed like a good idea to me, so I made them.

All in all, Claude Code did eight rounds of review of this code. It made a couple of suggestions that I knew were wrong, and it took corrections well. 

The next day, I burned a chip and plugged it in the unit for testing.

It bricked, Nothing. Not even a single flash of the LEDs on startup.

Somewhere in the midst of Claude's suggestions, we had changed the software in a way that it no longer worked at all. 

I made a new branch of the code and backed out some suggestions. I determined it had nothing to do with the WDT or PMD register. That left something amiss with TMR0. This could be a problem with Microchip Code Configurator (MCC).

I had switched TMR0 to use the HFINTOSC. It was programmed to generate an interrupt every 5 ms. Except it didn't work. I switched it back to us the LFINTOSC, also programmed for every 5 ms, and it worked as expected. I'm not sure why it didn't work with the HFINTOSC, but having several oscillators gives one options. I'm happy it works.

Once it was working again, I walked through all of the Design B and Design C test scenarios. Everything worked with flying colors. 

AI is certainly useful, even for amateur radio projects. Just don't blindly trust it. Remain in the loop for all changes.


Sunday, March 22, 2026

Polishing Up the Rx Antenna Controller

Many software projects are never fully complete, as there's always something to add with a small change to the software. The Rx Antenna Controller isn't any different. 

The initial version of this project was basically done. But pressing the antenna selection buttons resulted in a response on the serial port. This could cause problems with computer control if the response was not anticipated.

I added a new command: &AI; and &AIn;. This gets and sets the Auto-Info mode, respectively. With &AI1;, pressing an antenna button results in an &ARn; response on the serial port. &AI0; turns off Auto-Info mode -- button presses do not result in a serial port response. The default is &AI0;.

I"m very happy with the way this project has turned out. While I have ideas for a Version 2, it mostly involves hardware changes to the remote switching box to allow selection of the AUX antenna for diversity reception.



Saturday, February 21, 2026

Rx Antenna Controller

Rx Antenna Controller is QRV.
I started building this unit a couple of months ago. I called it the Beverage Controller, because my motivation was to select amoung the three Beverage antennas I had erected. Yes, I've managed to erect three 500 foot Beverages, one to the NE, SE and NW.

Performance of these antennas is convincing -- 1-2 S-units lower noise than the inverted-L or dipole antennas I use on 160 and 80m, respectively, plus a directional signal boost if the beverage is pointed in the right direction.

I discussed my design issues with this unit in the previous article. Debugging the serial port took another month.

Serial Port Debugging

The reason I had chosen the PIC16F18426 for this design was because of the built-in EUSART. Receiving worked just fine. I could send commands to the controller and it would act on the commands. But it sent no response. 

I had configured the PIC to use RC5 (pin 5) for the EUSART receive input, and RA5 (pin 2) for the EUSART transmit output. After a bit of troubleshooting, I found no action on RA5. It remained at 4.5 V the entire time. Was this a wiring problem, or a programming problem?

I ended up writing another PIC project and setting up a chip on a solder less breadboard to solve this. This project simply sent "Hello World!" at 300 baud every 5 seconds. It also drive two LEDS on the C port pins. The LEDs which alternate during a 1-second startup. When transmitting, the second LED would light up. 

My serial test project worked perfectly. LED 2 flashed for about 1/2 second every five seconds, just as expected. So, why didn't the beverage controller project work?

I modified the beverage controller project to also send "Hello World!" every 5 seconds. Except it didn't work. I traced the wiring in the controller head. RA5 was connected to the MAX232E pin 11. It was the MAX232E that was driving the pin to 4.5 V. With the MAX232E out of the circuit, RA5 stayed at 0 V all the time. It was like the software had configured RA5 as an input, not an output.

I got to the point that I could test both projects on the solder less breadboard. I even programmed the same chip with the serial test project -- and it worked. Programmed the same chip with the beverage controller project -- and it didn't. This was definitely a programming problem.

I tried several modifications of the configuration, eventually applying the serial test project configurations to the beverage controller project. At some point, it started working. I still don't understand what I changed to make it work.

Putting It Together
Remote relay box

After such a struggle, I was happy to finish. I re-programmed the chips to send and receive at 9600 baud. This is plenty fast enough for this purpose.

The controller supports one Kenwood/Elecraft-style command, which takes two forms - a Get and a Set operation:
  • Get - &AR; -- responds with &ARn; where n is 1 through 5
  • Set - &ARn; where n is 1 through 5 -- selects the antenna specified by n, responds with &ARn;
With the serial port transmit working, I could remotely interrogate the controller to determine which receiving antenna was currently selected. And selecting an antenna would respond to ensure that the controller had received my command.

The controller mounts nicely on the equipment shelf. I used some temporary stick-on labels until I find my computerized label-maker. 

What's Next

The current firmware sends an &ARn; response when a button is tapped. I probably need to make that configurable with a serial command.

I've also thought about adding a scanning feature. The controller could automatically switch antennas after a few seconds. Holding a button could add/remove that antenna from the scan.

However, after a couple of months of using the controller, I've found a glaring deficiency in my design. The Rx Antenna Controller only selects one antenna for the RX ANT port. I use a broadband splitter to also connect to the AUX port for diversity reception. But this only permits diversity reception of one receiving antenna against the transmit antenna. I can't do diversity reception between two receiving antennas. 

What would be nice is to have the remote relay box select the antenna for the RX ANT and AUX port. This would require twice as many relays and a way to control them individually. Doing this requires a re-design of both the remote relay box and the controller box. 

Wednesday, February 4, 2026

Beverage Controller

Remote and controller boxes laid 
out for wiring.
With these Beverage antennas, I needed a way to switch between them quickly and easily. 

Taking a cue from the K9AY Controller, I didn't want to just hook up a rotary switch. I wanted a push-button controller. Plus, a lot of the time I'm remotely operating my station on FT8 from the house, I wanted that capability as well. 

Design

I planned for at least three Beverages, maybe more. Plus I had the K9AY loops. That's at least four antennas, having a fifth would give me a spare.

The buttons and indicators needed to be convenient to operate, up front in the station without being intrusive. 

The receiving antenna feed lines also needed to terminate at the Single Point Ground (SPG). Best option was a remote relay box to do the switching, and a small controller box containing the buttons and indicators.

Test positioning the Controller
Adding a serial port to the controller allowed the antenna selection to be interrogated and selected. I already the PIC16F18426 chips on hand. This 14-pin device has a built-in EUSART. A MAX232 would handle the RS-232 level conversion.

Construction

I found a small Bud box in my junk box for the remote. I ordered a die-cast aluminum box for the controller. It was small, but it fit very nicely up under the shelf supporting the P3. Convenient and unobtrusive.

Remote mounted on SPG
The remote has six RF connectors - four F-connectors for the Beverages, one BNC for the K9AY, and another BNC to connect to the K3. SPDT relays are used. When selected, the relay connects the antenna port to the K3 port. When unselected, an appropriate resistor connects across the antenna port. ( I used 82-ohm resistors for the F-connectors, 51-ohm for the BNC -- closest I had to 75 and 50 ohms, respectively )

I used 12 V relays. Unlike the KK1L 2x6 Antenna Switch, I didn't want to activate each relay with a separate line for +12 V. Instead, I sent +12 V to the remote box on a common conductor and then returned a signal for each relay to be grounded by the open drain pins on the PIC. 

This lead to a design problem. The PIC doesn't support true open drain outputs. Each pin is clamped to Vdd, which in this case is +5 V. That left about 6 or so volts across each relay, pulling them all in. 

To solve this, I added 2N3904 NPN transistors to the relay box as open collector drivers for each relay. A 3 K resistor connects the base of each transistor back to the PIC. Instead of a logic 0 activating the relay, a logic 1 does the same job.

The controller box is really tight. I borrowed five switches from the K1EL Keyer. The LEDs and switches barely fit. The controller itself is simple. Five RA port pins connect to the pushbuttons. Five RC port pins drive the LED indicators and NPN relay driver. One RA pin and one RC pin communicate with the serial port. 

Changing the sense of the relay switching required re-wiring of the LEDs. Before, they were tied to +12 with the cathode of each LED brought to ground by the PIC. Except that didn't work due to the design problem. Instead the cathodes went through a common 330 ohm resistor to ground, and the anodes were connected across the activation lines for each relay.

Debugging

I debugged this design in parts, starting with the controller box, then the relay box separately. Once I connected them together, I found the design problem that required much re-wiring. 

The button selection worked great. The serial port has been more of a problem. While the PIC receives commands correctly, it doesn't appear to transmit anything at all. It is a puzzlement.