Skip to content

MicroModemDriverDataFlow

Toby Schneider edited this page May 26, 2016 · 2 revisions

This page explains the logical flow of sending messages using the WHOI Micro-Modem in the Goby driver MMDriver.

A few things up front:

  • Goby uses index = 0 for all first indices of arrays, vectors, etc. (in conformance with standard programming practices). This is different than the modem with regard to the Packet Frame#. The WHOI Micro-Modem uses Frame# 1, 2, ... whereas Goby uses frames 0, 1, ... Thus all WHOI Micro-Modem frames are one greater than the corresponding Goby frame. Where ambiguous I will use "Goby frame" to mean the frame number used inside of Goby and "modem frame" to mean the WHOI Micro-Modem frame number.

I've split this into two sections as they are treated slightly different:

Local CCCYC (decentralized TDMA)

  1. First of all, everything is kicked off when someone (often goby::acomms::MACManager) calls: virtual DriverBase::handle_initiate_transmission(protobuf::ModemMsgBase* base_msg) = 0

    which calls (via standard C++ virtual inheritance) MMDriver::handle_initiate_transmission(protobuf::ModemMsgBase* base_msg)

    base_msg contains no data, just src (integer 0-127 which equals $CACFG,SRC in this (local) case), dest (integer 0-127), and rate (integer 0-5) for the requested transmission. Data are collected later.

  2. handle_initiate_transmission first caches the proper number of frames using the method cache_outgoing_data. This basically means calling the signal (or callback) signal_data_request(request_msg, &data_msg) N times where N is the number of frames in the request transmission (set in base_msg) (for example N = 8 for base_msg.rate()==5).

    We cache data now (ahead of the actual $CCCYC) for two reasons:

    • The provider of data (often goby::acomms:::QueueManager) may be slow, especially if on-the-fly encoding is done. This way, we can cache all data before starting the $CCCYC with the modem and avoid data timeouts (and use $CCCFG,DTO,1). In the future, I would like to have this pre-fetching initiated some time (say a few seconds) before handle_initiate_transmission is called by goby::acomms::MACManager. This way the TDMA cycle timing can be strictly maintained even the face of a slow data provider.
    • If there are no data to send, the first data_msg (for the first frame) is just returned unmodified (such that data_msg.data().size() == 0) and the $CCCYC is never sent (avoiding wasting power / channel time). Note that later (Goby frame > 0, modem frames > 1) frames can also be returned unmodified on calls to signal_data_request(request_msg, &data_msg) which tells Goby to send a blank frame to the Micro-Modem at that point. The Micro-Modem has a feature where multi-frame messages can be terminated in this fashion and will be sent at that point (without futher $CADRQ).
  3. Now, if the number of cached messages exceeds 0, a $CCCYC is sent using the values provided in base_msg and the ack_requested value of the first data message provided. If number of the cached messages is 0, nothing further is done (i.e. no $CCCYC).

  4. The Micro-Modem will now send the proper number of $CADRQ data requests, which are answered by MMDriver using the data cached above (or if no more data was cached, an empty message to end sending of $CADRQs) via the $CCTXD message. The ACK value is set to the ack_requested value given in the data_msg which must match (i.e. be either true or false) for all frames (a requirement of the WHOI Micro-Modem). It may be sensible to enforce this at the MMDriver level in the future but now it is the responsibility of the data provider to ensure all frames have matching ack_requested fields.

Remote CCCYC (Centralized TDMA or "Polling")

In this case, the transmission cycle (CCCYC + CCTXD) is split between two nodes (the example above has both tasks on a single node). We will call the node initiating the $CCCYC the master and the node sending the data the sender. The added value is here is the ease of controlling (and changing) the TDMA cycle from a ship-based master; the drawback is that the master has no knowledge of the data available for sending.

  1. Thus, on the master, someone calls virtual DriverBase::handle_initiate_transmission(protobuf::ModemMsgBase* base_msg) = 0 where base_msg->src() is the modem ID ($CCCFG,SRC) of the sender. This is ADR1 in the $CCCYC message. (base_msg->dest() is ADR2). Goby MMDriver initiates a $CCCYC with the correct values but does not cache any data (since the master isn't sending data).
  2. The sender receives a $CACYC without having cached data (local_cccyc_==false) since it didn't send the $CCCYC. The sender caches data using the method cache_outgoing_data as described in 2. under the Local CCCYC section above.
  3. These cached data are used to feed the modem $CCTXD values in the same way was described in 4. under the Local CCCYC section above.