Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
This page explains the logical flow of sending messages using the WHOI Micro-Modem in the Goby driver
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)
First of all, everything is kicked off when someone (often
virtual DriverBase::handle_initiate_transmission(protobuf::ModemMsgBase* base_msg) = 0
which calls (via standard C++ virtual inheritance)
base_msgcontains 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.
handle_initiate_transmissionfirst 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
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_transmissionis 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).
- The provider of data (often
Now, if the number of cached messages exceeds 0, a $CCCYC is sent using the values provided in
ack_requestedvalue of the first data message provided. If number of the cached messages is 0, nothing further is done (i.e. no $CCCYC).
The Micro-Modem will now send the proper number of $CADRQ data requests, which are answered by
MMDriverusing 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_requestedvalue given in the
data_msgwhich 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
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.
- Thus, on the master, someone calls
virtual DriverBase::handle_initiate_transmission(protobuf::ModemMsgBase* base_msg) = 0where
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
MMDriverinitiates a $CCCYC with the correct values but does not cache any data (since the master isn't sending data).
- 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_dataas described in 2. under the Local CCCYC section above.
- 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.