15. Physical service
org.arl.unet.Services.PHYSICAL
Agents offering the PHYSICAL service are most commonly modem drivers and modem simulators. They support messages and parameters that are explained below. PHYSICAL service providers may also provide optional capabilities to send frames triggered at a specified time, or send timestamped frames where the timestamp is embedded in the transmitted frame.
Agents implementing the PHYSICAL service typically directly access the channel, bypassing any MAC protocol that may be in use in the network. It is highly recommended that clients wishing to use the PHYSICAL service consult with the MAC service for advice on when it is safe to access the channel, so as not to adversely affect the network performance. |
15.1. Overview
All agents supporting the PHYSICAL service must also support the DATAGRAM service ( Chapter 14 ).
15.1.1. Messages
Agents supporting the PHYSICAL service provide a set of messages to manage frame transmission and reception:
-
TxFrameReq
⇒AGREE
/REFUSE
/FAILURE
— transmit a frame -
TxRawFrameReq
⇒AGREE
/REFUSE
/FAILURE
— transmit a frame without headers -
ClearReq
⇒AGREE
/REFUSE
/FAILURE
— cancel all ongoing and pending transmissions -
RxFrameNtf
— sent to agent’s topic when a frame addressed to the node is received, and the agent’sSNOOP
sub-topic when a frame addressed to other nodes is overheard -
TxFrameNtf
— sent to requestor when a frame is transmitted -
RxFrameStartNtf
— sent to agent’s topic when a frame is detected -
TxFrameStartNtf
— sent to agent’s topic when a frame transmission is started -
BadFrameNtf
— sent to agent’s topic when a bad frame is received -
CollisionNtf
— sent to agent’s topic when a frame is detected (and dropped) while another frame is being received
The
TxFrameReq
class extends a
DatagramReq
to add physical layer options, and the
RxFrameNtf
class extends a
DatagramNtf
to add physical layer metadata.
15.1.2. Parameters
Agents offering the PHYSICAL service support the following parameters:
-
rxEnable
— true if reception is enabled, false otherwise -
propagationSpeed
— signal propagation speed in m/s -
time
— current physical layer clock time in microseconds -
busy
— true if modem is busy transmitting/receiving (carrier sense), false if modem is idle -
refPowerLevel
— reference source level in dB (re micro-Pascals @ 1m for underwater modems) -
maxPowerLevel
— maximum allowable transmission power in dB rerefPowerLevel
-
minPowerLevel
— minimum allowable transmission power in dB rerefPowerLevel
-
rxSensitivity
— reference receive sensitivity (dB re micro Pascals for underwater modems)
All physical layer timestamps are in microseconds as per the clock provided by the
time
parameter. This clock is generally not synchronized with the platform clock (system time).
|
In addition to the above parameters, agents also support indexed (frame type) parameters:
-
frameDuration
— frame duration in seconds (maximum duration in case of variable frame length) -
powerLevel
— transmission power in dB rerefPowerLevel
-
errorDetection
— number of bytes used for error detection -
frameLength
— frame length in bytes (maximum length in case of variable frame length) -
maxFrameLength
— maximum possible frame length in bytes -
fec
— forward error correction (FEC) code (0 = none/default, otherwise base 1 index from fecList) -
fecList
— list of available FEC code names (in the order of increasing robustness), may be null if FEC change not supported -
dataRate
— effective frame data rate (bps) -
llr
— true to enable log-likelihood ratio reporting inBadFrameNtf
, false otherwise
Two frame types are defined:
15.1.3. Capabilities
Agents may support several optional capabilities:
Agents advertising this capability are able to transmit frames with a transmission timestamp (start of transmission) encapsulated in the frame. This is requested through the
timestamped
flag in the
TxFrameReq
message. In order to do the timestamping, the frame has to be scheduled for transmission after a short delay. This delay is configured via an additional parameter:
-
timestampedTxDelay
— delay in seconds to transmit timestamped frames
Agents advertising this capability are able to start transmitting a frame at a specified time (on a best effort basis). The time is given in the
txTime
attribute of the
TxFrameReq
message.
If an agent supports the ANEP-87 JANUS standard, it advertises this capability. An additional frame type (indexed parameter set) is defined:
-
JANUS
frame = 3
The JANUS capability also adds one parameter:
-
janus
— true for JANUS frame type, false for all other frame types
It also adds two JANUS-specific messages that are supported:
-
TxJanusFrameReq
⇒AGREE
/REFUSE
/FAILURE
— transmit a JANUS frame -
RxJanusFrameNtf
— sent to agent’s topic when a JANUS frame is received
If an agent advertises this capability, it supports an additional request to perform FEC decoding:
-
FecDecodeReq
⇒AGREE
/REFUSE
/FAILURE
— attempt FEC decoding a frame, and if successful, send out aRxFrameNtf
15.2. CONTROL and DATA channels
The physical layer in UnetStack typically supports 2 logical channels (3 if JANUS is supported). The CONTROL channel provides low-rate, robust communication that allows exchange of small amounts of control information in the network. The DATA channel is a usually a higher rate communication link, but may require tuning to operate well in various environmental conditions.
The configurable parameters of the CONTROL and DATA channels depend strongly on the device (modem) in use. The Unet simulator provides a simplified physical layer (
HalfDuplexModem
) that captures the essential aspects of the communication using the two channels, exposing only a limited set of parameters. When configuring a real network, you should refer to your modem’s manual on advise on how best to set up the physical layer parameters.
|
Fire up the 2-node network simulation and connect to node A’s shell. If you simply type
phy
, you can explore the physical layer parameters for the node:
> phy
« Half-duplex modem »
Generic half duplex modem simulator.
[org.arl.unet.DatagramParam]
MTU ⤇ 56
RTU ⤇ 56
[org.arl.unet.phy.PhysicalParam]
busy ⤇ false
maxPowerLevel = 0.0
minPowerLevel = -96.0
propagationSpeed ⤇ 1534.4574
refPowerLevel = 185.0
rxEnable = true
rxSensitivity = -200.0
time ⤇ 2178921675
timestampedTxDelay = 1.0
The
phy.MTU
and
phy.RTU
parameters tells us the maximum and recommended amount of user data that can be transmitted in a single frame (56 bytes in this case) respectively. This is based on the DATA channel, as we will see shortly, since
DatagramReq
are fulfilled using the DATA channel. The
PhysicalParam
parameters provide us information on whether the channel is busy, transmission power levels supported, receiver sensitivity, and propagation speed of the signal (e.g. speed of sound for underwater modems). The
phy.time
parameter is a microsecond resolution clock that is used to timestamp all physical layer events such as frame transmission, reception, etc.
We can dig deeper into the parameters for the CONTROL and DATA channel separately:
> phy[CONTROL]
« PHY »
[org.arl.unet.DatagramParam]
MTU ⤇ 16
RTU ⤇ 16
[org.arl.unet.phy.PhysicalChannelParam]
dataRate = 202.10527
errorDetection ⤇ 1
fec ⤇ 0
fecList ⤇ null
frameDuration ⤇ 0.95
frameLength = 24
janus = false
llr ⤇ false
maxFrameLength = 128
powerLevel = -10.0
> phy[DATA]
« PHY »
[org.arl.unet.DatagramParam]
MTU ⤇ 56
RTU ⤇ 56
[org.arl.unet.phy.PhysicalChannelParam]
dataRate = 731.4286
errorDetection ⤇ 1
fec ⤇ 0
fecList ⤇ null
frameDuration ⤇ 0.7
frameLength = 64
janus = false
llr ⤇ false
maxFrameLength = 512
powerLevel = -10.0
The values you see above are specific to this simulated network, and will generally be different for different networks, depending on the devices that are being used and the environment that they are deployed in. |
Here are a few important parameters to take note of:
-
Note that
MTU
for the CONTROL channel is 16 bytes, whereas DATA channel’sMTU
is 56 bytes. CONTROL frames typically carry less data, but are more robust. -
The
frameLength
for the CONTROL and DATA channels are 8 bytes longer than the correspondingMTU
. The difference is due to header information that the frames carry. The number of bytes taken by the header is device dependent, and also a function of network configuration (e.g. changes innode.addressSize
may change header size). -
Typically physical layer agents allow setting of the
frameLength
parameter, and theMTU
parameter is automatically determined based on the necessary headers. ThemaxFrameLength
parameter indicates the maximum size of the frame supported. -
The
frameDuration
for the CONTROL channel is about 0.95 seconds, whereas that for the DATA channel is 0.7 seconds. While the CONTROL frames carry less data, they also have lower data rate and so may have comparable duration as the DATA frames. -
The
dataRate
reported by the channel is the effective data rate in bps including the header bits, i.e., it is the frame length in bits divided by the frame duration. -
The
powerLevel
parameter controls the transmission power used by the channel. This value is in dB, with reference to thephy.refPowerLevel
, and may range betweenphy.minPowerLevel
andphy.maxPowerLevel
. -
The
errorDetection
parameter reports the number of bytes used for error detection CRC (value of 1 indicates that we are using a 8-bit CRC). Some modems will allow you to set this to 2 to switch to 16-bit CRC, if you desire a lower probability of accepting a frame with some bit errors.
15.3. Modem physical layer
In the previous section, we explored several parameters from a simplified simulated physical layer. Next let’s look at a real modem. If you are lucky enough to own one with UnetStack on it, you can connect to it’s shell now. Otherwise, we can use Unet audio SDOAM as our test modem:
$ bin/unet audio
Modem web: http://localhost:8080/
On the web shell for the modem:
> phy
« Physical layer »
Provides software-defined physical layer communication services (including error detection & correction).
[org.arl.unet.DatagramParam]
MTU ⤇ 31
RTU ⤇ 31
[org.arl.unet.phy.PhysicalParam]
busy ⤇ false
maxPowerLevel ⤇ 0.0
minPowerLevel ⤇ -138.0
propagationSpeed = 1500.0
refPowerLevel ⤇ 0.0
rxEnable = true
rxSensitivity ⤇ 0.0
time = 4167772
timestampedTxDelay = 1.0
[org.arl.yoda.ModemParam]
adcrate ⤇ 48000.0
bbsblk ⤇ 6000
bbscnt = 0
bpfilter = true
clockCalib = 1.0
dacrate ⤇ 96000.0
downconvRatio = 4.0
fan = false
fanctl = 45.0
fullduplex = false
gain = 0.0
hpc = false
inhibit = 120
isc = true
loopback = false
model ⤇ Unet audio
mute = true
noise ⤇ -105.6
npulses = 1
pbsblk = 65536
pbscnt = 0
post = null
poweramp = false
preamp = true
pulsedelay = 0
serial ⤇ unetaudio
standby = 15
upconvRatio ⤇ 8.0
vendor ⤇ UnetStack
voltage ⤇ 0.0
wakeupdelay = 400
wakeuplen = 8000
For brevity, we have omitted the baseband service and scheduler service parameters in the listing above. Even then, there are many parameters that allow you to configure the SDOAM. We cannot cover each parameter in detail here, but we encourage you to explore the help pages for the parameters by simply typing
help phy.
followed by the parameter name.
Further, let’s look at the indexed parameters for the CONTROL channel:
> phy[CONTROL]
« PHY »
[org.arl.unet.DatagramParam]
MTU ⤇ 13
RTU ⤇ 13
[org.arl.unet.phy.PhysicalChannelParam]
dataRate ⤇ 70.588234
errorDetection ⤇ true
fec = 1
fecList ⤇ [ICONV2]
frameDuration ⤇ 2.04
frameLength = 18
janus = false
llr = false
maxFrameLength ⤇ 796
powerLevel = -42.0
[org.arl.yoda.FhbfskParam]
chiplen = 1
fmin = 9520.0
fstep = 160.0
hops = 13
scrambler = 0
sync = true
tukey = true
[org.arl.yoda.ModemChannelParam]
basebandExtra = 0
basebandRx = false
modulation = fhbfsk
preamble = (480 samples)
test = false
threshold = 0.25
valid ⤇ true
Again, we cannot cover all the parameters in detail here, but will draw your attention to a few important ones. You see that the
modulation
for the CONTROL channel is set to
'fhbfsk'
(frequency-hopping binary frequency shift keying). Depending on your modem, different modulations may be supported. Once a modulation scheme is chosen, you see additional modulation-dependent parameters. In this case, these are the
org.arl.yoda.FhbfskParam
parameters such as
fmin
,
fstep
,
hops
,
chiplen
,
tukey
, etc. These parameters allow you to control the modulation’s frequency band, number of hops, chip duration, windowing, etc.
If you change modulation parameters, you have to remember to do it on all your modems in the network. Otherwise they will be speaking different
languages
, and they won’t be able to understand each other. Not all combination of modulation parameters are valid. The
valid
parameter tells us if the current setting is valid or not. If the setting is invalid, all transmission requests will be refused.
|
The
preamble
parameter determines a detection preamble that is transmitted before each frame. This is used by the receiving modem to determine the start of a frame. The
threshold
parameter controls the detection probability and false alarm rate for frame detection. A lower threshold will improve detection probability, but increase false alarm rate.
If the
test
flag is set on the transmission and reception modems, each transmit frame is filled with known test data. This allows the receiving modem to compute the bit error rate (BER), even when the frame has too many errors for FEC to be able to correct.
15.4. Transmitting & receiving using Unet audio
If you have two computers with speakers and microphones, you could run Unet audio on both, and communicate between the two. If you happen to have only one computer handy, do not worry — we can get one Unet audio instance to transmit and receive at the same time. This is full-duplex communication!
Real modems typically cannot do full-duplex communication because the weak incoming signals are masked by clutter from the strong outgoing signal. However, by adjusting the volume of your computer carefully, you can easily do full-duplex communication on your Unet audio SDOAM. |
On Unet audio shell, enable full-duplex operation and try a transmission (you should be able to hear it from your computer speaker!). Your output might not look exactly the same, but let’s go over all the notifications we got and see if we can understand all of them:
> phy.fullduplex = true
true
> subscribe phy
> phy << new TxFrameReq()
AGREE
phy >> TxFrameStartNtf:INFORM[type:CONTROL txTime:79322682] (1)
phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:79309353 detector:0.87] (2)
phy >> RxFrameStartNtf:INFORM[type:DATA rxTime:80659519 detector:0.26] (3)
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:79310432] (4)
phy >> RxFrameNtf:INFORM[type:CONTROL from:1 rxTime:79309353 rssi:-29.3] (5)
phy >> BadFrameNtf:INFORM[type:DATA rxTime:80659519 rssi:-38.5 (18 bytes)] (6)
1 | Transmission of our requested CONTROL frame has started. |
2 | Our frame being transmitted was detected as a CONTROL frame, and reception has started. |
3 | Our frame being transmitted was wrongly detected (false alarm) as a DATA frame. |
4 | Transmission of our frame was completed. |
5 | Reception of the frame was completed, and successful. |
6 | The wrongly detected frame resulted in data that did not satisfy CRC, and hence reported as a bad frame. |
To get rid of the false alarm on the DATA channel, we could either increase the detection threshold or turn off the detector completely (
phy[DATA].threshold = 0
). For now, we’ll do the latter. Let’s also turn on the
phy[CONTROL].test
flag so that we can measure communication performance in terms of BER. To measure BER before error correction, we also need to turn off
phy[CONTROL].fec
:
> phy[DATA].threshold = 0
0
> phy[CONTROL].test = true
true
> phy[CONTROL].fec = 0
0
Now we can make 10 transmissions, 2 seconds apart, and watch the BER of the received frames:
> 10.times { phy << new TxFrameReq(); delay(2000); }
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:204359766]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:204385187 rssi:-28.9 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:205578432]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:205603853 rssi:-28.4 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:207567766]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:207589186 rssi:-28.5 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:209583766]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:209609187 rssi:-28.2 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:211573099]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:211594519 rssi:-28.3 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:213589099]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:213614520 rssi:-28.1 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:215578432]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:215599853 rssi:-28.5 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:217594432]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:217619853 rssi:-28.2 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:219583766]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:219605186 rssi:-28.0 cfo:0.0 ber:0/144 (18 bytes)]
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:221599766]
phy >> RxFrameNtf:INFORM[type:CONTROL rxTime:221625187 rssi:-27.7 cfo:0.0 ber:0/144 (18 bytes)]
For brevity, we have omitted the
TxFrameStartNtf
and
RxFrameStartNtf
messages. We see that no bits were in error, out of 144 transmitted bits. We had perfect communication, even without FEC! This is not surprising since the speaker and microphone are very close (and hence good signal-to-noise ratio), but real channels are rarely so forgiving. You can try this between 2 computers, and things may not be as rosy.
Feel free to play around with the parameters of the modulation scheme and try transmissions to get a feel for how the parameters affect communication performance. Since your transmission and reception modems are the same, you only need to set the parameters once! In real life, you’ll need to set the same parameters on all modems in your network.
Remember to turn off the
phy[CONTROL].test
flag before trying any data transfer. While the flag is on, no user data can be carried by the transmitted frames.
|
15.5. Timed and timestamped transmissions
To explore timed and timestamped transmissions, let’s go back to our 2-node network simulation. On the shell for node A:
> phy << new CapabilityReq()
CapabilityListRsp:INFORM[TIMESTAMPED_TX,TIMED_BBREC,TIMED_BBTX,TIMED_TX]
We see that the
phy
agent supports the
TIMESTAMPED_TX
and
TIMED_TX
optional capabilities. Let us try them out. On node B:
> subscribe phy
Going back to node A, send a timestamped frame:
> phy << new TxFrameReq(timestamped: true)
AGREE
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:2489196375]
We see that the frame was transmitted at time 2489196375 (when you try this, the time will of course be different). You should see the
RxFrameNtf
for this frame on node B:
phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:687419054]
phy >> RxFrameNtf:INFORM[type:CONTROL from:232 rxTime:687419054 txTime:2489196375]
Note that the
RxFrameNtf
now has an additional
txTime
field that’s populated, and the timestamp in there is the same as the
txTime
on node A’s
TxFrameNtf
. The frame was timestamped before transmission, and transmitted at exactly the intended time.
Timestamps take up bits in the transmitted frame. Your effective
MTU
for frames with timestamps is 6 bytes less than the advertised
MTU
.
|
Do bear in mind that the
phy.time
clocks on node A and B may not be synchronized. So timestamps from one node cannot be directly compared with timestamps on another node. In the above example, the
rxTime
was 687,419,054 microseconds, whereas the
txTime
was 2,489,196,375 microseconds. This does not mean that the frame was received before it was transmitted! It’s just that node A and B have an offset between their clocks.
|
Sometimes you may not need to transmit a timestamped frame, but you do want the frame to be transmitted at a specified time. On node A:
> t = phy.time + 5000000; println(t); phy << new TxFrameReq(txTime: t) (1)
3174864375 (2)
AGREE
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:3174864375] (3)
1 |
t
is the current time + 5 seconds. We ask for a frame to be transmitted at time
t
.
|
2 |
The value of time
t
is printed immediately (due to the
println(t)
).
|
3 |
The
TxFrameNtf
message will appear after a few seconds, once the transmission is made. Note that the actual
txTime
when the transmission occurred matches with our requested value
t
.
|
If you check node B’s shell, you’ll find the corresponding
RxFrameNtf
, but it will not have a
txTime
field, as the frame transmitted was not timestamped.
The transmission time is honored on a best effort basis, which means that there could be a small difference between the requested time and the actual transmit time. |
15.6. Snooping frames meant for other nodes
If you’re familiar with Ethernet network interface cards, you may have come across promiscuous mode . In this mode, the network card receives all packets that it hears, not just the ones that are addressed to the node. Agents providing the PHYSICAL service essentially do this continuously, but they send the notifications for frames intended for other nodes on a special sub-topic called SNOOP.
With the 2-node network simulation, let’s first only subscribe to the
phy
agent’s topic on node B:
> subscribe phy
From node A, transmit a frame to node B and to node C (node C does not exist in this network):
> phy << new TxFrameReq(to: host('B'))
AGREE
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:4622534375]
> phy << new TxFrameReq(to: host('C'))
AGREE
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:4623823375]
On node B, you’ll find that it receives the
RxFrameStartNtf
for both transmissions, but only the
RxFrameNtf
for the transmission addressed to node B:
phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:2820757054]
phy >> RxFrameNtf:INFORM[type:CONTROL from:232 to:31 rxTime:2820757054]
phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:2822046054]
The
RxFrameStartNtf
is sent when a frame is detected. At that point in time, the agent has no idea whom the frame is intended for, because the frame contents have not yet arrived. Only when the frame is received and decoded does the agent know the destination address. Seeing that the second frame was intended for node C, node B does not report a
RxFrameNtf
for it.
If you were interested in snooping conversations between other nodes, you could subscribe to the SNOOP topic on node B:
> subscribe topic(phy, org.arl.unet.phy.Physical.SNOOP)
Now try transmitting another frame from node A to node C. On node A:
> phy << new TxFrameReq(to: host('C'))
AGREE
phy >> TxFrameNtf:INFORM[type:CONTROL txTime:4899843375]
Now you’ll see on node B that the corresponding
RxFrameNtf
is received:
phy >> RxFrameStartNtf:INFORM[type:CONTROL rxTime:3098066054]
phy >> RxFrameNtf:INFORM[type:CONTROL from:232 to:74 rxTime:3098066054]
The
to
address of 74 corresponds to
host('C')
, but the frame is available for agents on node B through the SNOOP topic.
<<< [Datagram service] | [Baseband service] >>> |