2016-04-10 20:17:45 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2017 INRIA
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2017-12-19 10:46:43 +01:00
|
|
|
* @defgroup net_gnrc_gomach GoMacH
|
2016-04-10 20:17:45 +02:00
|
|
|
* @ingroup net_gnrc
|
2017-12-19 10:46:43 +01:00
|
|
|
* @brief A traffic-adaptive multi-channel MAC
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* GoMacH is, "a General, nearly Optimal MAC protocol for multi-Hop communications",
|
|
|
|
* for IEEE 802.15.4 IoT/WSNs networks. It is designed to be a traffic adaptive MAC
|
|
|
|
* protocol that provides high traffic adaptability, high energy efficiency and high
|
|
|
|
* robustness.
|
|
|
|
*
|
|
|
|
* ## GoMacH's main features
|
|
|
|
* - doesn't rely on global synchronization.
|
|
|
|
* - supports for multi-hop and mesh network.
|
|
|
|
* - adopts a duty-cycle scheme to conserve power.
|
|
|
|
* - provides high traffic adaptation for handling burst or dynamic traffics.
|
|
|
|
* It achieves this by dynamically allocating transmission slots to intensive
|
|
|
|
* senders (that have pending packets), which enables one (or more) sender(s)
|
|
|
|
* to burst transmit all of its (their) buffered packets (for the same destination) to
|
|
|
|
* the receiver in one shot (or during a shot notice). The burst slotted-transmissions
|
|
|
|
* will be ordered by the receiver device in a TDMA period.
|
|
|
|
* - adopts a multi-channel scheme for avoiding/reducing wireless interference jam.
|
|
|
|
*
|
2016-04-10 20:17:45 +02:00
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Implementation of GoMacH protocol
|
|
|
|
*
|
|
|
|
* @author Shuguo Zhuo <shuguo.zhuo@inria.fr>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef NET_GNRC_GOMACH_GOMACH_H
|
|
|
|
#define NET_GNRC_GOMACH_GOMACH_H
|
|
|
|
|
|
|
|
#include "periph/rtt.h"
|
|
|
|
#include "kernel_types.h"
|
|
|
|
#include "net/gnrc/netif.h"
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The default duration of GoMacH's wake-up period (WP).
|
|
|
|
*
|
|
|
|
* GoMacH adopts the duty-cycle scheme that, by default, a node only wakes up
|
|
|
|
* for a short period of @ref GNRC_GOMACH_CP_DURATION_US in each cycle. In the
|
|
|
|
* rest of the cycle (except vTDMA), the node turns off the radio to conserve
|
|
|
|
* power. @ref GNRC_GOMACH_CP_DURATION_US should be at least longer than
|
|
|
|
* @ref GNRC_GOMACH_MAX_PREAM_INTERVAL_US, thus to guarantee that the receiver
|
|
|
|
* will not miss the preamble packet.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_CP_DURATION_US
|
|
|
|
#define GNRC_GOMACH_CP_DURATION_US (10U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief GoMacH's superframe duration, i.e., time between two consecutive wake-ups.
|
|
|
|
*
|
|
|
|
* This macro governs power consumption and GoMacH's reactiveness to traffic loads.
|
|
|
|
* In GoMacH, nodes adopt duty-cycle scheme to conserve power. That is,
|
|
|
|
* time is divided into repeated cycles (superframes), and in each
|
|
|
|
* cycle, a node only wakes up for a short period of time for receiving potential
|
|
|
|
* incoming packets for itself. This macro defines the wake-up interval, or,
|
|
|
|
* in other words, defines the cycle duration used in GoMacH. If the wake-up
|
|
|
|
* interval is short, nodes will wake up more frequently, which leads to quicker
|
|
|
|
* reactiveness of the MAC protocol for handling packet reception and transmission,
|
|
|
|
* but also results in higher power consumption due to more idle listening.
|
|
|
|
* In GoMacH, by default, we regard the wake-up period (WP) as the beginning of
|
|
|
|
* a cycle.
|
|
|
|
*
|
|
|
|
* Note that, GoMacH's superframe duration @ref GNRC_GOMACH_SUPERFRAME_DURATION_US
|
|
|
|
* should not be shorter than 10 times of @ref GNRC_GOMACH_CP_DURATION_US and not
|
|
|
|
* shorter than the RTT tickle interval.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_SUPERFRAME_DURATION_US
|
|
|
|
#define GNRC_GOMACH_SUPERFRAME_DURATION_US (300LU * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
2019-11-21 09:22:30 +01:00
|
|
|
#ifndef RTT_FREQUENCY
|
|
|
|
#error "RTT_FREQUENCY undefined."
|
|
|
|
#else
|
2016-04-10 20:17:45 +02:00
|
|
|
#if ((GNRC_GOMACH_SUPERFRAME_DURATION_US < ((1000LU *US_PER_MS) / RTT_FREQUENCY)) || \
|
|
|
|
(GNRC_GOMACH_SUPERFRAME_DURATION_US < (10 *GNRC_GOMACH_CP_DURATION_US)))
|
|
|
|
#undef GNRC_GOMACH_SUPERFRAME_DURATION_US
|
|
|
|
#if (((1000LU *US_PER_MS) / RTT_FREQUENCY) > (10 * GNRC_GOMACH_CP_DURATION_US))
|
|
|
|
#define GNRC_GOMACH_SUPERFRAME_DURATION_US ((1000LU * US_PER_MS) / RTT_FREQUENCY)
|
|
|
|
#else
|
|
|
|
#define GNRC_GOMACH_SUPERFRAME_DURATION_US (10 * GNRC_GOMACH_CP_DURATION_US)
|
|
|
|
#endif
|
|
|
|
#endif
|
2019-11-21 09:22:30 +01:00
|
|
|
#endif
|
2016-04-10 20:17:45 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The maximum duration of the random period at the end of GoMacH's
|
|
|
|
* wake-up period (WP).
|
|
|
|
*
|
|
|
|
* Currently, GoMacH's WP is actually composed of @ref GNRC_GOMACH_CP_DURATION_US
|
|
|
|
* and (+) @ref GNRC_GOMACH_CP_RANDOM_END_US. We currently introduced this random
|
|
|
|
* period to avoid beacon collision among neighbor nodes. This macro may be removed
|
|
|
|
* in the future.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_CP_RANDOM_END_US
|
|
|
|
#define GNRC_GOMACH_CP_RANDOM_END_US (1U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The maximum duration of GoMacH's wake-up period (WP).
|
|
|
|
*
|
|
|
|
* @ref GNRC_GOMACH_CP_DURATION_MAX_US defines the allowed maximum duration
|
|
|
|
* of GoMacH's WP period. A node will quit WP once it reaches this maximum
|
|
|
|
* duration.
|
|
|
|
* Note that, in GoMacH's WP, after each normal packet reception (except
|
|
|
|
* broadcast packet), a receiver will automatically extends the WP period
|
|
|
|
* (reset WP timeout), to receiver more potential incoming packets, before
|
|
|
|
* WP reaches this @ref GNRC_GOMACH_CP_DURATION_MAX_US duration.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_CP_DURATION_MAX_US
|
|
|
|
#define GNRC_GOMACH_CP_DURATION_MAX_US (5LU * GNRC_GOMACH_CP_DURATION_US)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The maximum time for waiting the receiver's beacon in GoMacH.
|
|
|
|
*
|
|
|
|
* After transmissions in the WP, if the sender still has pending packets
|
|
|
|
* for the receiver, it will wait for the receiver's incoming beacon that
|
|
|
|
* allocates dynamic transmission slots to it. @ref GNRC_GOMACH_WAIT_BEACON_TIME_US
|
|
|
|
* defines the maximum waiting time for the beacon. Once the beacon-waiting
|
|
|
|
* timeout expires, the sender will quit the vTMDA (slotted transmission)
|
|
|
|
* procedure, and restarts transmissions (started with normal CSMA attempts
|
|
|
|
* in the receiver's WP) in the next cycle for sending the pending packets
|
|
|
|
* to the same receiver.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_WAIT_BEACON_TIME_US
|
|
|
|
#define GNRC_GOMACH_WAIT_BEACON_TIME_US (GNRC_GOMACH_CP_DURATION_MAX_US)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The minimum gap between neighbor nodes' wake-up phases in GoMacH.
|
|
|
|
*
|
|
|
|
* To reduce beacon collisions and transmission collisions, GoMacH intends
|
|
|
|
* to avoid neighbor nodes' phases being too close to each other. This macro
|
|
|
|
* defines the minimum gap between two nodes's wake-up phases. If the sender
|
|
|
|
* finds its wake-up phase too closed to its receiver's, it will randomly
|
|
|
|
* select a new phase for itself.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_CP_MIN_GAP_US
|
|
|
|
#define GNRC_GOMACH_CP_MIN_GAP_US (25U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Timeout duration for waiting @ref NETDEV_EVENT_RX_COMPLETE in GoMacH.
|
|
|
|
*
|
|
|
|
* Sometimes in GoMacH, if a node finds RX ongoing when it is just about to
|
|
|
|
* enter the next MAC state, it will set up a timeout for waiting this packet
|
|
|
|
* reception complete with a timeout of this @ref GNRC_GOMACH_WAIT_RX_END_US
|
|
|
|
* duration.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_WAIT_RX_END_US
|
|
|
|
#define GNRC_GOMACH_WAIT_RX_END_US (6U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Timeout duration for confirming TX-No-ISR event in GoMacH.
|
|
|
|
*
|
|
|
|
* This macro is used to confirm/catch a case that a transmission doesn't have its
|
|
|
|
* @ref NETDEV_EVENT_TX_COMPLETE interrupt event, which is considered as a hardware
|
|
|
|
* abnormal event. Upon this timeout expiration, GoMach will accordingly take
|
|
|
|
* actions to maintain its state-machine.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_NO_TX_ISR_US
|
|
|
|
#define GNRC_GOMACH_NO_TX_ISR_US (50U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Maximum time interval between two consecutive preamble packets in GoMacH.
|
|
|
|
*
|
|
|
|
* In GoMacH, a sender first uses preamble stream to track the receiver's wake-up
|
|
|
|
* phase (WP), if the receiver's WP is unknown. This macro defines the maximum
|
|
|
|
* time interval between twoconsecutive preamble packets.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_MAX_PREAM_INTERVAL_US
|
|
|
|
#define GNRC_GOMACH_MAX_PREAM_INTERVAL_US (6U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Time interval between two consecutive preamble packets in GoMacH.
|
|
|
|
*
|
|
|
|
* In GoMacH, after a preamble is sent, the sender sets a timeout with
|
|
|
|
* @ref GNRC_GOMACH_PREAMBLE_INTERVAL_US duration for waiting to send the next
|
|
|
|
* preamble. Notably, this macro is with a very small value. In GoMacH, for
|
|
|
|
* receiving the preamble-ACK packet, the sender doesn't wait for the whole
|
|
|
|
* reception of the preamble-ACK. Instead, it only waits for the
|
|
|
|
* @ref NETDEV_EVENT_RX_STARTED event which leads to shorter time interval
|
|
|
|
* between two consecutive preamble transmissions.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_PREAMBLE_INTERVAL_US
|
|
|
|
#define GNRC_GOMACH_PREAMBLE_INTERVAL_US (2U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Time interval between two consecutive broadcast packets in GoMacH.
|
|
|
|
*
|
|
|
|
* In GoMacH, when sending a broadcast packet, the sender broadcasts the same
|
|
|
|
* packet frame on its two public channels simultaneously, with a total duration
|
|
|
|
* of @ref GNRC_GOMACH_SUPERFRAME_DURATION_US to guarantee that all neighbors
|
|
|
|
* will get a copy. This macro defines the time interval between sending two
|
|
|
|
* consecutive broadcast copies.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_BCAST_INTERVAL_US
|
|
|
|
#define GNRC_GOMACH_BCAST_INTERVAL_US (1U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The Maximum preamble duration time of GoMacH.
|
|
|
|
*
|
|
|
|
* Since GoMacH adopts duty-cycle scheme, to probe receiver's wake-up period
|
|
|
|
* a sender sends preamble streams to notice the receiver for communication.
|
|
|
|
* To ensure that the receiver will catch at least one preamble packet
|
|
|
|
* in a critical case that one public channel is jammed, the sender repeatedly
|
|
|
|
* broadcasts a stream of preamble packets with the broadcast duration
|
|
|
|
* (preamble duration) slightly longer than twice
|
|
|
|
* of @ref GNRC_GOMACH_SUPERFRAME_DURATION_US.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_PREAMBLE_DURATION_US
|
|
|
|
#define GNRC_GOMACH_PREAMBLE_DURATION_US (21LU * GNRC_GOMACH_SUPERFRAME_DURATION_US / 10)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief The transmission slot size in GoMacH.
|
|
|
|
*
|
|
|
|
* GoMacH adopts dynamic slots allocation scheme to allocate transmission
|
|
|
|
* slots to senders that have pending packets. Each slot is for one data packet
|
|
|
|
* with ACK transmission. @ref GNRC_GOMACH_VTDMA_SLOT_SIZE_US is right sufficient
|
|
|
|
* for the transmission of the longest packet in IEEE 802.15.4 with ACK. Should
|
|
|
|
* not be changed.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_VTDMA_SLOT_SIZE_US
|
|
|
|
#define GNRC_GOMACH_VTDMA_SLOT_SIZE_US (5U * US_PER_MS)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Maximum times of CSMA TX attempts under busy-indication in the WP
|
|
|
|
* period of the receiver.
|
|
|
|
*
|
|
|
|
* Senders in GoMacH adopt CSMA scheme to send data packets in the WP period of
|
|
|
|
* the receiver. In case of having medium-busy feedback in WP and the TX failure
|
|
|
|
* count (due to busy) is below @ref GNRC_GOMACH_TX_BUSY_THRESHOLD, the sender
|
|
|
|
* continue to send the packet with CSMAin the receiver's WP, with the consideration
|
|
|
|
* that there may be multi-senderssimultaneously competing in WP and the WP will
|
|
|
|
* be continuously extended (thus the packet can be received).
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_TX_BUSY_THRESHOLD
|
|
|
|
#define GNRC_GOMACH_TX_BUSY_THRESHOLD (5U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Maximum WP period extension number in GoMacH.
|
|
|
|
*
|
|
|
|
* In GoMacH, the WP period of a receiver will be extended upon each successful
|
|
|
|
* packet reception (except receiving broadcast or preamble packet) to receive
|
|
|
|
* more potentialincoming packets. This macro defines the maximum WP period
|
|
|
|
* extension number allowed in GoMacH.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_CP_EXTEND_THRESHOLD
|
|
|
|
#define GNRC_GOMACH_CP_EXTEND_THRESHOLD (5U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief GoMacH's check-duplicate-packet unit life time in cycle count.
|
|
|
|
*
|
|
|
|
* In GoMacH, to avoid receiving duplicate-packet, we currently introduce a
|
|
|
|
* data type of @ref gnrc_gomach_dupchk_unit_t to record the recent senders'
|
|
|
|
* information (especially MAC TX sequence). This macro defines the
|
|
|
|
* check-duplicate-packet data unit's life time in cycle count. Once expired,
|
|
|
|
* the related data unit will be reset. This macro maybe removed in the future.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_RX_DUPCHK_UNIT_LIFE
|
|
|
|
#define GNRC_GOMACH_RX_DUPCHK_UNIT_LIFE (30U)
|
|
|
|
#endif
|
|
|
|
|
2017-12-11 11:31:39 +01:00
|
|
|
/**
|
|
|
|
* @brief Maximum number of senders allowed to be allocated slots in one cycle.
|
|
|
|
*
|
|
|
|
* Exclude the static GoMacH MAC header payload in the beacon, which is 20 bytes,
|
|
|
|
* we have 107 bytes left for constructing the sender-ID list and the related slots-number
|
|
|
|
* list. A combined slots allocation information pair (sender ID with its corresponded
|
|
|
|
* allocate slots number) will cost 9 (8+1) bytes, thus we can hold a maximum of 11
|
|
|
|
* i.e., ((127 - 20) / 9), sender IDs in the beacon.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_MAX_ALLOC_SENDER_NUM
|
|
|
|
#define GNRC_GOMACH_MAX_ALLOC_SENDER_NUM (11U)
|
|
|
|
#endif
|
|
|
|
|
2016-04-10 20:17:45 +02:00
|
|
|
/**
|
|
|
|
* @brief Maximum t2k attempts before going to t2u in GoMacH.
|
|
|
|
*
|
|
|
|
* After phase-locked with the receiver, a sender runs a t2k (transmit-to-known)
|
|
|
|
* procedure to transmit packet to the phase-known device. However, due to
|
|
|
|
* factors like timer driftor busy-channel, a transmission attempt may fail
|
|
|
|
* in t2k. If the t2k failure count has reached this
|
|
|
|
* @ref GNRC_GOMACH_REPHASELOCK_THRESHOLD, the sender regards phase-locked failed
|
|
|
|
* due to timer drift. In this case, it will adopt t2u (transmit-to-unknown)
|
|
|
|
* procedure to get re-phase-locked with the receiver.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_REPHASELOCK_THRESHOLD
|
|
|
|
#define GNRC_GOMACH_REPHASELOCK_THRESHOLD (4U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Maximum t2u attempts before dropping data packet in GoMacH.
|
|
|
|
*
|
|
|
|
* In case the receiver's phase is unknown to the sender, the sender adopts
|
|
|
|
* the t2u (transmit-to-unknown) procedure to get phase-locked with the
|
|
|
|
* receiver. This macrodefines the maximum t2u attempts before dropping the
|
|
|
|
* data packet in GoMacH.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_T2U_RETYR_THRESHOLD
|
|
|
|
#define GNRC_GOMACH_T2U_RETYR_THRESHOLD (2U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Maximum t2u attempts before re-initiate radio in GoMacH.
|
|
|
|
*
|
|
|
|
* After a long period of run time, a radio may be in wrong condition which
|
|
|
|
* needs to be re-calibrated. This is indicated by having a series of
|
|
|
|
* continuous t2u failures (no preambleACK) in GoMacH. In cast we have
|
|
|
|
* @ref GNRC_GOMACH_MAX_T2U_RETYR_THRESHOLD number of t2u failures, then we
|
|
|
|
* re-initiate the radio, trying to re-calibrate the radio for bringing it
|
|
|
|
* back to normal condition.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_MAX_T2U_RETYR_THRESHOLD
|
|
|
|
#define GNRC_GOMACH_MAX_T2U_RETYR_THRESHOLD (10U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Default message queue size to use for the GoMacH thread.
|
|
|
|
*
|
|
|
|
* The value of this macro should be enough for supporting the manipulation of
|
|
|
|
* GoMacH.
|
|
|
|
*/
|
|
|
|
#ifndef GNRC_GOMACH_IPC_MSG_QUEUE_SIZE
|
|
|
|
#define GNRC_GOMACH_IPC_MSG_QUEUE_SIZE (8U)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Creates an IEEE 802.15.4 GoMacH network interface
|
|
|
|
*
|
2020-03-26 14:37:44 +01:00
|
|
|
* @param[out] netif The interface. May not be `NULL`.
|
2016-04-10 20:17:45 +02:00
|
|
|
* @param[in] stack The stack for the GoMacH network interface's thread.
|
|
|
|
* @param[in] stacksize Size of @p stack.
|
|
|
|
* @param[in] priority Priority for the GoMacH network interface's thread.
|
|
|
|
* @param[in] name Name for the GoMacH network interface. May be NULL.
|
|
|
|
* @param[in] dev Device for the interface
|
|
|
|
*
|
|
|
|
* @see @ref gnrc_netif_create()
|
|
|
|
*
|
2019-12-19 19:23:15 +01:00
|
|
|
* @return 0 on success
|
|
|
|
* @return negative number on error
|
2016-04-10 20:17:45 +02:00
|
|
|
*/
|
2019-12-19 19:23:15 +01:00
|
|
|
int gnrc_netif_gomach_create(gnrc_netif_t *netif, char *stack, int stacksize,
|
|
|
|
char priority, char *name, netdev_t *dev);
|
2016-04-10 20:17:45 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* NET_GNRC_GOMACH_GOMACH_H */
|
|
|
|
/** @} */
|