After publishing the article MTR2000 and STM32-DVM-MTR2K: Analog + Digital, Playing Nice Together, the question almost immediately came up about availability and cost of MTR2000 Auxiliary I/O boards (CLN1206). Apparently, they’re not very easy to find, and can be prohibitively expensive. I said to myself, “How hard can it be to replicate the I/O functions of the Aux I/O board?”.
There isn’t a detailed service manual for the MTR2000, but the “Field Service Manual” sections on the Station Control Module (SCM, CLN1465) and Auxiliary I/O Board do provide an amazing amount of information on how these modules communicate. As it turns out, it’s a not entirely straightforward implementation (mode 3) of SPI (Serial Peripheral Interface). SPI isn’t the same as the typical serial port you find on a PC. I won’t go into details, but will note that it’s a synchronous serial bus with a single master device and one or more slaves. The master is almost always a microcontroller and slaves are typically hardware modules such as I/O expanders, sensors, memory devices, etc.
The driving force behind V2.0 of the STM32-DVM-MTR2K was to replicate the physical GPIO capability of the Aux I/O board, but there were a few other improvements too. The complete list is as follows:
- Add an additional display connector from the SBC
- Re-factor the analog circuit design (remove unnecessary components)
- Add functions of the original MTR2000 Aux. I/O card
- Create a virtual gateway between the SBC (NanoPi) and the SCM via the Aux I/O board GPIOs.
- Provide expansion bus access for the SBC on the J5 System Connector.
Thanks to the detailed theory of operation description in the MTR2000 Field Service Manual, figuring out how the SCM and I/O board communicate was easy. Unfortunately, what they were “saying” to each other was not included in the manual. As luck would have it – rarely the case with Motorola – the pattern turned out to be quite straightforward and reverse-engineered without much trouble. The MTR2000 SPI bus uses 16 bit datagrams, separated into two 8-bit bursts (in the same transaction). The GPIs (General Purpose Inputs) and GPOs (General Purpose Outputs) are treated as two separate SPI slaves on the bus. Each “slave” consisted of a pair of serially connected 8-bit shift registers on the Aux I/O board. The MTR2000 manual, RSS, etc. lists GPIs and GPOs by number. In fact, these are sequential and simply duplicated in the bit positions of the shift registers. That is to say, GPO_2 (they start numbering at 0), for example, is the 3rd least significant bit of the 16 bit datagram. This is depicted in the image below.
The Motorola MTR200 Aux I/O card is all logic hardware. No microprocessor. To put in four shift registers and re-gain the hardware I/O would have been easy. But in addition to the physical I/O, I wanted to build a “virtual bridge” between the MTR2000 SCM and the NanoPi NEO which would allow the Pi to both read and set the GPIO lines, virtually. The NanoPi NEO is not able to directly do this via the MTR2000 SPI Bus, and it lacks the GPIO pin count necessary to interface with discrete digital connections for each GPIO from the MTR2000. It became clear I would need to add a dedicated I/O processor.
The NanoPi NEO is running a general purpose operating system. While the NanoPi NEO’s CPU (AllWinner H3) has a hardware SPI interface, the use case for this interface is as a master. As a slave there are some very critical timing events that are better served in dedicated processing. Adding a separate, dedicated processor has an added benefit of ensuring any real physical GPIO functions continue to work if the NanoPi is offline (during a reboot, on power-up, etc.)
I chose the Atmel ATMEGA 328P for the job: It’s under $2, I know it well, has great C/C++ support, and I can use the Arduino IDE for programming (and so can you!) What’s not to like? The ATMEGA 328P is typical of devices in it’s class and only has a single 8-bit hardware SPI interface. The challenge became getting a single 8-bit SPI interface to act like the 2 separate 16-bit SPI interfaces that the MTR2000 was looking for. Since microcontrollers are generally not used as SPI slaves there’s little information about using them that way beyond the manufacturer’s data sheet. There was none at all about making them work with 16-bit data and reconfiguring on the fly to act as two separate slaves. I was on my own to find a solution.
I was triumphant! had I failed, you wouldn’t be reading this. As I type, the PCBs for V2.0a are in production at JLCPCB. I will be sharing all files for the PCB files, schematics, I/O processor software, etc. (look for my work on GitHub) I’m waiting to see the production PCBs work before I upload, but it should all be available within the next couple of weeks.
My goal with the V2.0 board was to both add new features, but also to create something of a blank canvas for others to expand on. Folks may wish to run their own custom code in the ATMEGA 328P to expand its capabilities or even the NanoPi’s. To that end, I’ve connected the I2C buses for both the Pi and the ATMEGA to the J5 System Connector on the back of the station (pads for I2C pull-up resistors are supplied). The NanoPI NEO and ATMEGA 328P communicate with each other over a standard asynchronous serial interface – I’m including the Arduino bootloader on the ATMEGA 328P as well, making it a snap to upload new code remotely. The only catch is that you can’t use the async port on the NanoPi for an MMDVM display AND have the NanoPi and ATMEGA 328P connected to each other. The ATMEGA can still be used, it just cannot communicate with the NanoPi in this situation. Not enough serial ports to go around – but the serial repeater through the MODEM is still available, and I can’t image too many folks wanting to run two displays on an MMDVM repeater.
Once again, I will be pointing folks to Scott Zimmerman over at Repeater Builder who want to buy this board with Scott’s full commercial production and support. I will be building and selling them directly as well, but I’m not set up to provide the full commercial support that Scott does.
Finally, I need to thank Keith Neufeld for the use of his Saleae logic analyzer. When I reached the point that my oscilloscope’s protocol analysis feature wasn’t enough, Keith’s logic analyzer made the job a whole lot easier.