Monday, March 13, 2017

MMDVMHost Architecture

I've been spending time on a new implementation of DMR repeater for MMDVM-speakers. Of course, with Homebrew protocol, I could just spend time on the backend components, which leaves quite a bit of work to do. But before doing this, I need to clarify what is getting received from the radio by the host. Sadly, documentation for the MMDVM specification is out-of-date, so we're left with the MMDVMHost code as the "living specification". Rabbit holes and so on led me to digging deep into the architecture of MMDVMHost.

Conceptually, MMDVMHost is built around the modem & peer setup and the main loop in MMDVMHost.cpp. In the loop, data is polled from the modem and peer. Since I am mostly interested in DMR, I'll look at the DMR functionality.

The loop polls the modem object for data. This is done by calls to readDMRData1() and readDMRData2(). Notice the 1 and 2? This is because DMR data is already separated into timeslots by the modem object instance (from Modem.h/Modem.cpp, and we will see later, this happens by the modem itself). Data returned by these two methods are collected during the modem clock tick that occurs as part of this loop by a m_modem.clock() call.

If data is picked up via readDMRData1() or readDMRData2(), it is passed via the writeModemSlot1() or writeModemSlot2() method to the instantiated CDMRControl object. These methods are proxies for CDMRSlot instances (DMRSlot.cpp) which write to network (hence, modem write is modem SOURCED data).

For data received from the Homebrew network, the CDMRControl object is polled via the readModemSlot1() and readModemSlot2() methods. After checking whether or not there is buffer for the timeslot on the modem, the modem object's writeDMRData1() and writeDMRData2() methods may be called to queue up the data for transmission.

Similar to the modem, the underlying CDMRSlot instance buffers are filled by a call to the CDMRControl clock() method. This polls the socket to get the data.

No comments:

Post a Comment