Wireless Core API
The Wireless Core API is the set of public functions that applications can use to access the Wireless Core functionalities.
Initialization
Before starting to use the Wireless Core, the user must first fully initialize it. The Wireless Core provides a lot of flexibility to accommodate a wide range of applications. Hence, many parameters are configurable.
The Wireless Core initialization steps are the same for every application. Only the configuration supplied at each step is different depending on specific application needs. Here is a flowchart of the whole initialization process.
Figure 56: Wireless Core initialization flowchart
Certain API calls are optional, such as connection callback setters, while some others can be called several times, like the one that adds RF channels to a connection. The configuration has been broken down into several API calls. Each API call takes care of configuring a specific level or component, such as a wireless connection or a wireless node.
Wireless Core Configuration
The Wireless Core configuration contains settings that have a global effect on the system. The configuration structure is as follows:
typedef struct swc_cfg {
/*! Network schedule as an array of timeslot durations in microseconds */
const uint32_t *timeslot_sequence;
/*! Number of timeslots in the timeslot sequence */
uint32_t timeslot_sequence_length;
/*! RF channels as an array of channel numbers */
const uint32_t *channel_sequence;
/*! Number of channels in the channel sequence */
uint32_t channel_sequence_length;
/*! Concurrency mode */
swc_concurrency_mode_t concurrency_mode;
/*! Memory pool instance from which memory allocation is done */
uint8_t *memory_pool;
/*! Memory pool size in bytes */
uint32_t memory_pool_size;
} swc_cfg_t;
timeslot_sequence
This is the sequence of timeslots, represented by their length in microseconds, that the Node will use to communicate over the SPARK network. This sequence is commonly called the TDMA schedule, or simply schedule. The Node will go through the timeslots in the schedule one by one until it reaches the end, at which point the schedule will repeat.
For example, for a repeating schedule of two timeslots of length 250 us and 750 us, the timeslot_sequence variable would be set like this:
uint32_t timeslot_sequence[] = {250, 750};
swc_cfg_t cfg;
cfg.timeslot_sequence = timeslot_sequence;
timeslot_sequence_length
This is the length of the sequence of timeslots, or how many timeslots there are in the schedule. For example, if the timeslot sequence is
{250, 750}, the value would be 2.
channel_sequence
This is the sequence of channels, represented by their frequency in increments of 40.96 MHz, used for frequency switching.
For example, if the frequency switching pattern is to go from 6.676 GHz to 6.963 Ghz to 7.249 GHz, the channel_sequence would be set like this:
uint32_t channel_sequence[] = {163, 170, 177};
swc_cfg_t cfg;
cfg.channel_sequence = channel_sequence;
The configured frequencies must be within the operating range of the transceiver in use.
channel_sequence_length
This is the number of channels in the channel sequence. For example, if the channel sequence is
{163, 170, 177}, the value would be 3.
concurrency_mode
The Spark Wireless Core API allow user to configure 2 pre-defined preset for the concurrency, low and high performance mode.
The low performance mode is targeted for low power MCU that are not fast enough to handle the high frequency of event coming from the radio. It will use Random Datarate Offset Protocol (RDO) as the main concurrency mechanism paired with a randomization of the channel sequence to allow minimal concurrency.
The high performance mode is targeted for higher speed MCU and uses the Distributed De-Synchronization Concurrency Algorithm (DDCM) paired with a randomization of the channel sequence to allow better concurrency.
Note that when using the SR1120, the MCU is not affected by the frequency of the radio event since the radio now handle the Clear Channel Assessment (CCA) event internally, which allow low power MCU to benefits from the high performance mode.
Valid values are SWC_CONCURRENCY_MODE_HIGH_PERFORMANCE and SWC_CONCURRENCY_MODE_LOW_PERFORMANCE.
Here is a table summarizing available concurrency mode
High Performance |
Low Performance |
|---|---|
DDCM Enabled |
DDCM Disabled |
RDO Disabled |
RDO Enabled |
2 CCA try with Abort action |
1 CCA try with Abort action |
Delay between retry of 25us |
N/A |
Note
Random channel sequence is always enabled.
High Performance |
Low Performance |
|---|---|
DDCM Enabled |
DDCM Enabled |
RDO Disabled |
RDO Disabled |
2 CCA try with Abort action |
2 CCA try with Abort action |
Delay between retry of 25us |
Delay between retry of 25us |
Note
Random channel sequence is always enabled.
memory_pool
This is the chunk of memory the Wireless Core uses when creating (or allocating) structures like the ones for the Node, connections and channels. It works much like the C Heap, and enables the Wireless Core to internally manage the memory.
For example, if a memory pool of 6000 bytes is needed, its declaration and configuration would look like this:
#define SWC_MEMORY_POOL_SIZE 6000
static uint8_t swc_memory_pool[SWC_MEMORY_POOL_SIZE];
swc_cfg_t cfg;
cfg.memory_pool = swc_memory_pool;
cfg.memory_pool_size = SWC_MEMORY_POOL_SIZE;
If the memory pool is not large enough to accommodate every memory allocation needed by a particular configuration, the SWC_ERR_NOT_ENOUGH_MEMORY error code is returned by the faulty API call.
memory_pool_size
This is the size in bytes of the memory pool.
Configure Concurrency
The Spark Wireless Core offers 3 differents algorithm for the concurrency mechanism: the Random Datarate Offset Protocol (RDO), the Distributed De-Synchronization Concurrency Algorithm (DDCM) and the randomization of channel sequence. Each offers their own respective advantage and are used when using the 2 differents concurrency mode.
For user wanting more control over these algorithm when configuring the concurrency, this API call can be used after the core has been initialized using swc_init
void swc_set_concurrency_cfg(swc_concurrency_cfg_t cfg, swc_error_t *err);
This fonction configuration structure will allow user to enable or disable each of the available algorithm:
typedef struct swc_concurrency_cfg { /*! Enable random channel sequence concurrency mechanism */ bool random_channel_sequence_enabled; /*! Enable the random datarate offset concurrency mechanism */ bool rdo_enabled; /*! Enable the distributed desync concurrency mechanism */ bool ddcm_enabled; } swc_concurrency_cfg_t;
random_channel_sequence_enabled
This enables or disables the random channel sequence feature. This is one of the features enabling concurrency operations. Other concurrency mechanisms must be enabled for optimal coexistence. See rdo_enabled (Core) as well as Configure Concurrency. See Concurrency for more details.
rdo_enabled (Core)
This enables or disables the random data rate offset feature. This is one of the features enabling concurrency operations. Other concurrency mechanisms must be enabled for optimal coexistence. See random_channel_sequence_enabled in Wireless Core Configuration as well as as Configure Concurrency. See Random Datarate Offset Protocol (RDO) and Concurrency for more details.
ddcm_enabled
This enables or disables the distributed de-synchronization concurrency mechanism. This is one of the features enabling concurrency operations. Other concurrency mechanisms must be enabled for optimal coexistence. See random_channel_sequence_enabled in Wireless Core Configuration as well as Configure Concurrency. See Distributed De-Synchronization Concurrency Algorithm (DDCM) and Concurrency for more details.
Note
To be able to customize the Clear Channel Assessment (CCA) part of the concurrency, please refer to the section Configure Clear Channel Assessment
Wireless Node Configuration
The Wireless Node configuration contains Node settings. All devices on a network are considered to be Nodes. A Node can have a specific role on a network. The configuration structure is as follows:
typedef struct swc_node_cfg {
/*! Network role */
swc_role_t role;
/*! Personal area network 12-bit ID */
uint16_t pan_id;
/*! Coordinator device's 8-bit address; Same as local_address if local device is the Coordinator */
uint8_t coordinator_address;
/*! Local device's 8-bit address */
uint8_t local_address;
} swc_node_cfg_t;
role
There are two roles on the network. A Node can be a Coordinator (Coordinator role) or a simple Node (Node role). Synchronization is achieved when the Node receives frames from the Coordinator. The Coordinator must provide frames on a continuous basis or synchronization can be lost. Valid values are NETWORK_COORDINATOR and NETWORK_NODE.
pan_id
The Personal Area Network Identification is a 12-bit number used to identify a specific Network. Nodes can only communicate with other Nodes using the same PAN ID.
coordinator_address
This is the 8-bit address of the Coordinator. If the Node being configured is the Coordinator Node, this address must be the same as the local address.
local_address
This is the 8-bit address of the device being configured.
Wireless Radio Module Initialization
After initializing the Wireless Core node, the radio modules must be init by invoking this API:
/** @brief Initializes a specified radio module within the given node.
*
* @note This function configures a radio module with default settings and performs necessary initializations
* including power cycling, reading from non-volatile memory (NVM), and calibrating the radio according
* to these settings. This must be called for every radio module connected to the device. Most systems
* operate a single radio, but a dual radio configuration is also supported for specific use cases.
*
*
* @param[in] node A pointer to the node handle structure.
* @param[in] radio_id The identifier of the radio module to initialize.
* @param[in] calibrate Choose between recalibrating the module afresh or using previously saved calibration data.
* @param[out] err Wireless Core error code.
*
* @note This function must be called for each radio module connected to the device to ensure proper operation.
* Errors are reported back via the `err` parameter, and the function will halt on the first encountered error.
*/
void swc_radio_module_init(swc_node_t *const node, swc_radio_id_t radio_id, bool calibrate, swc_error_t *err);
Description Initializes a radio module by configuring it with default settings, which includes power cycling, reading from non-volatile memory (NVM), and, depending on the parameter, calibrating the radio. This function must be invoked for each radio module connected to the system. While most systems utilize a single radio, configurations supporting dual radios are also accommodated.
- Default Settings Applied
irq_polarity = IRQ_ACTIVE_HIGH;
std_spi = FAST SPI;
- PLL configuration:
PLL Enable
PLL clock source internal
Crystal oscillator source internal
- Parameters:
node: Pointer to the node structure representing the radio.radio_id: An enum value for specific transceiver index.SWC_RADIO_ID_1
SWC_RADIO_ID_2
calibrate: A boolean value determining whether to calibrate the radio.
Calibration
Typically, a minimum wait of 1 second is required for the transceiver’s crystal frequency to stabilize upon power up. Once stabilized, calibration can be performed. The Wireless Core does this by initiating the calibration procedure 1 second after power up. It is assumed that the shutdown pin is set low at power up before the timer starts counting.
This means that calibration will start 1 second after startup regardless of the shutdown pin’s state. Shutdown pin control remains accessible, but the Wireless Core does not monitor its state.
The reason for this behavior is that using shutdown mode for power savings is marginally beneficial and may approach leakage current values. Thus, shutdown mode is generally avoided.
In cases where it is still desirable to use the shutdown mode, ensure that calibration starts 1 second after the pin is held low.
irq_polarity
/** @brief Set the state of the radio IRQ pin when asserted.
*
* @note Default SWC_IRQ_ACTIVE_HIGH is used if this function is not called.
*
* @note This function must be invoked after `swc_radio_module_init` to take affect.
*
* @param[in] node Node handle.
* @param[in] radio_id Radio number.
* @param[in] irq_polarity Radio's IRQ polarity.
* @param[out] err Wireless Core error code.
*/
void swc_node_set_radio_irq_polarity(swc_node_t *node, swc_radio_id_t radio_id, swc_irq_polarity_t irq_polarity,
swc_error_t *err);
Sets the IRQ polarity for a specified radio module within a node. This setting determines the active voltage level of the transceiver’s IRQ pin when an interrupt request is made.
Parameters:
node(swc_node_t*) - A pointer to the node structure where the radio module is located.
radio_id(swc_radio_id_t) - The identifier of the radio module whose IRQ polarity is to be set.
irq_polarity(swc_irq_polarity_t) - The polarity of the IRQ pin. Valid values are:
IRQ_ACTIVE_LOW - Sets the IRQ pin to be active at low voltage level.
IRQ_ACTIVE_HIGH - Sets the IRQ pin to be active at high voltage level.
err(swc_error_t*) - Pointer to a variable where any error code will be stored.Default Behavior: If this function is not invoked, the default IRQ polarity is set to
IRQ_ACTIVE_HIGH.
Note
This function must be called after
swc_radio_module_init()to ensure that the polarity setting takes effect properly.It is essential to configure the IRQ polarity according to the microcontroller’s interrupt handling specifications to avoid improper IRQ handling.
std_spi
/** @brief Set the radio's SPI interface timing setting.
*
* @note Default SWC_SPI_STANDARD is used if this function is not called.
*
* @note This function must be invoked after `swc_radio_module_init` to take affect.
*
* @param[in] node Node handle.
* @param[in] radio_id Radio number.
* @param[in] spi_mode Radio's SPI mode.
* @param[out] err Wireless Core error code.
*/
void swc_node_set_radio_spi_mode(swc_node_t *node, swc_radio_id_t radio_id, swc_spi_mode_t spi_mode, swc_error_t *err);
Configures the SPI communication mode for a specified radio module within a node. This setting adjusts the timing characteristics of the SPI interface to either adhere to standard SPI protocols or to optimize for high-speed data transfer.
- Parameters:
node(swc_node_t*) - A pointer to the node structure where the radio module is located.radio_id(swc_radio_id_t) - The identifier of the radio module whose SPI mode is to be configured.spi_mode(swc_spi_mode_t) - The SPI communication mode. Valid options are: - SPI_STANDARD - Follows the standard SPI protocol, suitable for most applications. - SPI_FAST - Implements a faster SPI communication by adjusting the timing for high capacitive loads. Useful in scenarios where the radio is distanced from the MCU or high throughput is necessary.err(swc_error_t*) - Pointer to a variable where any error code will be stored.
Default Behavior: If this function is not invoked, the default SPI mode is set to
FAST_SPI.
Note
This function should be called after
swc_radio_module_init()to ensure that the SPI mode setting is applied effectively.The
SPI_FASTmode adjusts the timing such that the MISO signal is latched on the falling edge of the SPI clock, allowing for reliable communication over longer distances or higher electronic noise environments without requiring modifications to the MCU’s SPI configuration.
Wireless Connection Configuration
The Wireless Connection configuration contains settings for a specific connection. See Connection for more details. The configuration structure is as follows:
typedef struct swc_connection_cfg {
/*! Name of the connection as a character string */
const char *name;
/*! Address of the transmitting node */
uint8_t source_address;
/*! Address of the receiving node */
uint8_t destination_address;
/*! Maximum size in bytes the payload can ever be */
uint8_t max_payload_size;
/*! Queue size in number of frames */
uint16_t queue_size;
/*! ID of timeslots used by the connection */
const int32_t *timeslot_id;
/*! Number of timeslots used by the connection */
uint32_t timeslot_count;
} swc_connection_cfg_t;
name
This parameter specifies the name of the connection as a string of characters. It is mostly used when printing statistics and/or debugging.
source_address
This 8-bit address specifies the device that will be transmitting on the connection. If it is set to the Node’s own address (local_address), then the connection will be used to send frames (TX connection).
destination_address
This 8-bit address specifies the device that will be receiving on the connection. If it is set to the Node’s own address (local_address), then the connection will be used to receive frames (RX connection) on that Node. If this field is set to the broadcast address (0xFF) on the transmitter (TX), then the destination becomes every Node on the Network (i.e. using the same PAN ID).
Warning
Setting the destination_address as broadcast address (0xFF) must only be done on the transmitter (TX) side. Setting the receiver’s (RX) destination_address to 0xFF will generate an error. For a Node to receive a broadcast, set the connection’s code:destination_address equal to its local_address, as you would normally do to receive from a unicast connection.
max_payload_size
This parameter specifies the maximum amount of application payload bytes that can be transmitted or received on this connection. The maximum supported value depends on the Wireless Core configuration, as some optional features require additional bytes appended to the header. Depending on the configuration, the maximum supported value can range from 118 to 124 bytes. See the Header Configuration section for more details.
queue_size
This parameter specifies the size (or length) of the queue managing the inbound and outbound data on a connection. It is specified in number of frames. When a Node transmits on a connection, the data goes into a transmit queue before being transmitted over-the-air. When a Node receives on a connection, it retrieves its data from a receive queue. Queue size values will depend on application requirements. The minimum value is 2.
timeslot_id
This represents which timeslots in the schedule are associated with the connection, each used either for transmitting or receiving. Since a connection represents a unidirectional link, all the timeslots it uses are either for transmitting or receiving, but not both. Aside from transmitting or receiving, the timeslots can be of two different types, main timeslots, or auto timeslots (payload in the auto-reply). This can be done by registering the timeslots with the use of the MAIN_TIMESLOT() and AUTO_TIMESLOT() macros. See Timeslot Events for more details.
For example, if the first timeslot and the third timeslot of a schedule are to be used by a connection for regular data transfers, the timeslot_id would be set like this:
int32_t timeslot_id[] = {MAIN_TIMESLOT(0), MAIN_TIMESLOT(2)};
swc_connection_cfg_t cfg;
cfg.timeslot_id = timeslot_id;
Note that the timeslots ID starts at 0. That is why the first and third timeslot have ID 0 and 2 respectively.
timeslot_count
This is the number of timeslots the connection uses.
credit_flow_ctrl_enabled
This parameter enables the credit flow control mechanism when sending data packets. The credit value will represent the number of packets that device can send during the connection. Each packet transmission consumes one credit. When the credit reaches zero, the receiver must grant more credits to allow more packets to be sent. This feature requires ACK frames, the ack_enabled setting must be set to true for this feature to work. Creating an auto-reply connection is optional. However, if it is created, the number of main connections assigned to the time slot must be equal to the number of auto-reply connections.
Wireless Beacon Connection Configuration
A helper function can be used to obtain a pre-configured beacon connection configuration (swc_connection_cfg_t). It can then be used to initialize a connection using the usual method.
swc_connection_cfg_t swc_get_beacon_connection_config(const swc_node_t *const node, uint8_t source_address,
Wireless Channel Configuration
The Wireless Channel configuration contains settings for a specific channel. A channel is a logical entity that corresponds to a RF band used for over-the-air transmissions. A connection can make use of several channels if frequency switching is desired. A connection requires at least one channel to operate. The configuration structure is as follows:
typedef struct swc_channel_cfg {
/*! Frequency of the channel in increments of 40.96 MHz (e.g., 183 for 7.5 GHz) */
uint8_t frequency;
/*! Pulses number of the transmitted frames, from 1 to 3 */
uint8_t tx_pulse_count;
/*! Pulses width of the transmitted frames, from 0 (narrow) to 7 (large) */
uint8_t tx_pulse_width;
/*! Pulses amplitude of the transmitted frames, from 0 (max gain: 0 dB) to 3 (min gain: -1.8 dB) */
uint8_t tx_pulse_gain;
/*! Pulses number of the received frames, from 1 to 3, corresponding to the tx_pulse_count
* of the incoming frames
*/
uint8_t rx_pulse_count;
} swc_channel_cfg_t;
frequency
This is the center frequency of the transmitted pulses. This value is commonly called the channel frequency. The value is specified in increments of 40.96 MHz. For example, if a channel frequency of 6.5 GHz is desired, this value should be set to 159.
tx_pulse_count
This is the number of pulses used for transmission. The value ranges from 1 to 3. More pulses translate to higher output power. On an RX connection with ACK enabled, this setting controls the pulse count of the Auto-Replied ACK. This setting is not required on an RX connection with ack_enabled set to false.
tx_pulse_width
This is the width of the pulses. The width ranges from 0 (narrow) to 7 (wide). A wider pulse translates to higher output power. On an RX connection with ACK enabled, this setting controls the pulse width of the Auto-Replied ACK. This setting is not required on an RX connection with ack_enabled set to false.
tx_pulse_gain
This is the power amplifier gain. It is sometimes referred to as a backoff, as higher values result in lower output power. The gain values range from 0 (max gain: 0 dB) to 3 (min gain: -1.8 dB). On an RX connection with ACK enabled, this setting controls the power amplifier gain of the Auto-Replied ACK. This setting is not required on an RX connection with ack_enabled set to false.
rx_pulse_count
This is the number of pulses of the frames received on the connection, from 1 to 3. For a TX connection, the frames received will be auto-replies (if activated).
Enable Fast Synchronization
To enable the fast synchronization mechanism on all connections, simply use this API call after the core has been initialized using swc_init
void swc_set_fast_sync(bool enabled, swc_error_t *err);
See Synchronization Methods for more details.
Enable Certification mode
When certification is enable, all connections will be used at maximum capacity automatically without application intervention needed. The power output will the maximum allowed by user connection’s configuration. In the case where multiple connections are assigned to a time slot, the first connection added the time slot will used for certification.
To enable this feature, simply use this API call after the core has been initialized using swc_init
void swc_set_certification_mode(bool enabled, swc_error_t *err);
See Certification mode for more details.
Configure Sleep Level
The sleep level denotes the depth of sleep the transceiver will enter when not actively transmitting or receiving. By default, the lightest sleep mode (idle) is configured. See Sleep Modes for more details.
The sleep level can be configured to another mode simply by using this API call after the node has been initialized using swc_node_init
void swc_node_set_sleep_level(swc_node_t *node, swc_sleep_level_t sleep_level, swc_error_t *err);
Alternativelly, if the SR1120 is used, the sleep level can be configured for each timeslot individually by using this API call after the node has been initialized using swc_node_init
void swc_set_time_slots_sleep_level(swc_sleep_level_t *sleep_level, swc_error_t *err);
Configure FEC Ratio
The SPARK transceiver uses the forward error correction ratio (FEC) methods to recover from bit corruption which might occur during over-the-air transmissions. The default FEC ratio configured is SWC_FEC_1_6_6 (1.66x).
The FEC ratio can be configured to another value simply by using this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_fec_ratio(swc_connection_t *conn, swc_fec_ratio_t ratio, swc_error_t *err);
Valid values are SWC_FEC_1_0_0, SWC_FEC_1_3_3, SWC_FEC_1_6_6 and SWC_FEC_2_0_0. See the Forward Error Correction (FEC) Ratio section for more details.
Configure Modulation
The default connection’s encoding method is MODULATION_IOOK. The modulation can be configured to another method by simply using this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_modulation(swc_connection_t *conn, swc_modulation_t modulation, swc_error_t *err);
Valid values are MODULATION_IOOK and MODULATION_2BITPPM. See Modulation for more details.
Valid values are MODULATION_IOOK, MODULATION_OOK, MODULATION_PPM and MODULATION_2BITPPM. See Modulation for more details.
Configure Auto Synchronization
If enabled, the Wireless Core will automatically transmit a short synchronization frame if the transmission queue is empty at the start of a transmission timeslot instead of keeping the transceiver asleep. This feature should be used when the Coordinator is not guaranteed to send at least one frame every 10 ms to each Node.
To enable this feature, simply use this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_auto_sync(swc_connection_t *conn, bool enabled, swc_error_t *err);
Configure Latency Optimization
Enabling this parameter allows for latency optimization in the target connection. When activated, the Wireless Core introduces a delay to the wakeup event when there is an empty timeslot. This extra processing time extends the frame unqueuing process in the WPS, leading to a decrease in the minimum latency experienced.
To enable this feature, simply use this API call after the target connection has been initialized using swc_connection_init
void swc_connection_optimized_latency(swc_connection_t *conn, swc_node_t *node, uint8_t auto_reply_payload_size,
Important
This feature only supports CCA fail action of SWC_CCA_ABORT_TX.
Important
Take extra care when using this feature with CCA enabled. Incorrectly adjusting the CCA while enabling this feature can cause synchronization issues between two transceivers.
Warning
This feature should only be enabled on a TX connection that is not an auto-reply. Incorrect usage of this feature could potentially disrupt synchronization and result in unpredictable behavior.
Configure Fragmentation
By default, when initializing a connection, the fragmentation capabilities of the Wireless Core are disabled. Once this is enabled, users will be able to send payloads larger than the provided maximum payload size during connection configuration when using the swc_connection_send method.
To enable this feature, simply use this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_fragmentation(swc_connection_t *conn, swc_error_t *err);
Configure Throttling
The data rate throttling support on a connection can be enabled simply by using this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_throttling_active_ratio(const swc_connection_t *const conn, uint8_t active_ratio,
This feature allows the connection to disable timeslots to reduce power consumption. Once enabled, an application can call the following function to change the ratio of active timeslots.
void swc_connection_set_throttling_active_ratio(const swc_connection_t *const conn, uint8_t active_ratio,
Enable Connection Priority
The following functions enable the Connection Priority feature on the connection. When enabled, the Wireless Core will include a connection ID in the MAC header field of every frame transmitted on this connection. The connection ID is an 8-bit value that is used by the Wireless Core to identify the connection on the receiver side. See Connection Priority for more details.
A lower priority number has higher priority. The value can range from 0 to 2. Only 3 connections can be added to a timeslot. If the same priority is used for multiple connections, the order in which the connections were added to the timeslot will be used.
The following function enables the Connection Priority feature on the connection with a single priority on all timeslots.
void swc_connection_set_connection_priority(swc_node_t *node, swc_connection_t *conn, uint8_t priority,
The following function enables the Connection Priority feature with priorities for the particular timeslots used by the connection. priority and slots_priority cannot be used in the same time. If used, it must specify a priority for each timeslot used by the connection. This meant that the size of the slots_priority table must be equal to the value of timeslot_count. This option may be useful when there is a necessity to establish varying connection priorities for specific timeslots, such as to mitigate the potential risk of a lower priority connection experiencing data transmission issues due to congestion.
void swc_connection_set_connection_slots_priority(swc_node_t *node, swc_connection_t *conn, uint8_t *slots_priority,
Note
The priority will be ignored on a reception connection.
Configure Acknowledgement
The SPARK wireless core allow the user to configure wheter or not there is acknowledgement on a target connection, which is enabled by default. This result in the transmitter expecting to receive an ACK frame in an Auto-Reply shortly after its transmission completes and the receiver will transmit an ACK frame in an Auto-Reply if the received frame destination address matches its local address or the broadcast address and the CRC checks.
Note that ACKs should be disabled on connections used for broadcasting since all receiving Nodes would transmit their respective ACK frame at the same time, and that would cause contention which is not desirable.
To configure the acknowledgement, use this API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_acknowledgement(swc_connection_t *conn, bool enabled, swc_error_t *err);
Configure Retransmissions
By default, when initializing a connection, the stop-and-wait automatic repeat request is considered to be in Guaranteed delivery mode, which mean that the Wireless Core will indefinitely try to retransmit frame that hasn’t been acknowledge.
The Wireless Core also allow user to configure a condition after which a frame is automatically dropped. The condition come in to form, a try conditions and/or a time conditions.
The try deadline parameters controls the maximum number of tries allowed before the frame is automatically dropped. For example, if try_count is set to 2, the Wireless Core, after the initial transmission fails, will attempt to retransmit the frame once (which is the second try) before the frame is discarded. If the try_count is set to 0, the frame will never be discarded.
The try deadline parameter controls the maximum amount of time (in increment of ticks) that a frame can sit in the transmission queue before it is dropped by the transmitting Node. The tick rate is set by the application depending of the tick rate of the swc_hal_t.get_tick function. For example, if time_deadline is set to 100, the Wireless Core will attempt to transmit the frame for 100 ticks before it is discarded. If the time_deadline is set to 0, the frame will never be discarded.
When both try_count and time_deadline are set to a non-zero value, the frame will be discarded when either limit is reached. See Stop and Wait for more details.
To configure that feature, use the following API call after the target connection has been initialized using swc_connection_init
void swc_connection_set_retransmission(swc_connection_t *conn, swc_node_t *node, bool enabled, uint32_t try_deadline,
Configure Clear Channel Assessment
For advance user wanting to customize the Clear Channel Assessment (CCA) beyond the scope of the available concurrency mode, the following API call can be used after the connection has been initialized using swc_connection_init:
void swc_connection_set_concurrency_cfg(const swc_connection_t *const conn, swc_connection_concurrency_cfg_t *cfg,
This fonction configuration structure will allow user to change a bunch of settings related to the CCA:
typedef struct swc_connection_concurrency_cfg { /*! Enable or disable the concurrency mechanism */ bool enabled; /*! Number of energy readings to do before the fail action is executed */ uint8_t try_count; /*! Amount of time between energy readings in increments of 48.8 ns (e.g. 10 is ~500 ns) */ uint16_t retry_time; /*! Action to do when the energy level sensed is still too high after the last energy sensing try */ swc_cca_fail_action_t fail_action; } swc_connection_concurrency_cfg_t;
swc_connection_concurrency_cfg.enabled
This parameter is used to enable the clear channel assessment (CCA) feature. If enabled, the energy level on the channel is sensed before attempting a transmission. If the energy level is considered too high for a successful transmission, the transmission will be delayed for a certain amount of time before the next attempt. After a certain number of unsuccessful attempts, a final action is done. See Clear Channel Assessment (CCA) for more details. This is one of the features enabling concurrency operations. See Concurrency for more details.
swc_connection_concurrency_cfg.try_count
This parameter defines the maximum number of transmission attempts before the configured fail action is executed. For example, if this is set to 2, the transceiver will sense the channel up to 2 times before transmitting. If both CCA checks fail, the Wireless Core will execute the fail action.
swc_connection_concurrency_cfg.retry_time
This parameter defines the amount of time to wait between CCA attempts. The retry time is specified in increments of 48.8 ns. For example, if a 25 us delay is desired, the value 512 (25 us / 48.8 ns) needs to be used.
swc_connection_concurrency_cfg.fail_action
This parameter defines the action to execute when the last CCA check fails. The action can be either to transmit anyway or to abort the transmission. If “transmit anyway” is selected and all CCA checks fail, the transmission will be forced after waiting an additional delay equal to the retry_time. Valid values are CCA_FAIL_ACTION_TX and CCA_FAIL_ACTION_ABORT_TX.
Configure Fallback
Fallback mode allows the Wireless Core to switch to an alternative output power and CCA try count configuration depending on the payload size provided by the application. See Fallback Mode for more details.
void swc_connection_set_fallback_cfg(swc_connection_t *conn, swc_connection_fallback_cfg_t *cfg, swc_error_t *err);
The fallback settings are as follows:
typedef struct swc_connection_fallback_cfg {
/*! Enable or disable the fallback mechanism */
bool enabled;
/*! Number of fallback modes */
uint8_t fallback_mode_count;
/*! Array of payload size fallback threshold. in descending order. Array size must be equal to
* fallback_mode_count
*/
uint8_t *thresholds;
/*! Array of number of CCA tries. Array size must be equal to fallback_mode_count */
uint8_t *cca_try_count;
} swc_connection_fallback_cfg_t;
enable
This parameter enables or disables the fallback mode on the connection.
fallback_mode_count
This parameter defines the number of fallback modes available. The minimum value is 1.
threshold
This is an array of size of the payload in bytes that triggers the fallback mode. For example, if sets to 20, every application payload of size 20 bytes or less will use the fallback power settings, while every payload of size larger than 20 bytes will use the regular power settings. The array must be sorted in descending order.
cca_try_count
This parameter defines an array of alternate number of swc_connection_concurrency_cfg.try_count to use while in fallback mode. For example, if this is set to 3 and swc_connection_concurrency_cfg.try_count is set to 2, then once fallback is triggered the transceiver will be able to sense up to 3 times instead of 2 before transmitting. the array size must be equal to the number of fallback modes. The order of the array must match the order of the threshold array.
swc_connection_add_fallback_channel
When the fallback mode is enabled, the Wireless Core will switch to an alternative channel configuration depending on the payload size provided by the application. The alternate channel configurations must be configured after the target connection has been initialized using swc_connection_init, and after the main channel configuration has been set using the following API call.
void swc_connection_add_fallback_channel(swc_connection_t *const conn, const swc_node_t *const node,
Wireless Status
This helper function can be used to obtain the status of the Wireless Core.
swc_status_t swc_get_status(void);
Callbacks
Callbacks are user implemented functions that can be registered on a specific connection. Callbacks will be automatically called by the Wireless Core when certain events occur and are optional. Available callbacks are described below.
TX Success
This callback triggers when a frame has been successfully transmitted on the connection. If ACKs are enabled, it triggers when the ACK frame is received. If ACKs are disabled, it triggers every time the frame is sent. At this point, the frame has been automatically removed from the connection transmission queue.
It is registered on a connection with:
void swc_connection_set_tx_success_callback(swc_connection_t *const conn, void (*cb)(void *conn), swc_error_t *err);
TX Fail
This callback triggers when a frame has not been successfully transmitted on the connection. If ACKs are enabled, it triggers if the ACK frame was expected and not received. If ACKs are disabled, it never triggers. The TX Fail callback is usually not used when ARQ is enabled as retransmissions are managed by the Wireless Core.
It is registered on a connection with:
void swc_connection_set_tx_fail_callback(swc_connection_t *const conn, void (*cb)(void *conn), swc_error_t *err);
TX Dropped
This callback triggers when the frame is automatically discarded by the Wireless Core because the configured ARQ deadline (time or number of retries) has expired. If ARQ is disabled, it never triggers.
Note
If both a TX Dropped and a TX Fail callback are registered on a Connection, both will trigger when a frame is dropped due to the maximum number of retries being reached. This is because the absence of an ACK frame will trigger both callbacks.
It is registered on a connection with:
void swc_connection_set_tx_dropped_callback(swc_connection_t *const conn, void (*cb)(void *conn), swc_error_t *err);
RX Success
This callback triggers when a frame has been successfully received. This means the destination address matches the Node local address or the broadcast address and the CRC checked. The frame is then ready to be retrieved by the application from the connection reception queue.
It is registered on a connection with:
void swc_connection_set_rx_success_callback(swc_connection_t *const conn, void (*cb)(void *conn), swc_error_t *err);
Event Callback
A configurable event callback is triggered when events occur on a connection. The event details can be retreived with the swc_get_event function. It is registered on a connection with:
void swc_connection_set_event_callback(swc_connection_t *const conn, void (*cb)(void *conn), swc_error_t *err);
Connect Event
Triggers when the link is successfully established between the sender and the receiver of the connection.
Disconnect Event
Triggers when the link is lost between the sender and the receiver of the connection.
Error Event
Triggers when an error occurs on the connection.
Low Power Callback
This callback triggers when the Wireless Core is ready to enter a lower power mode. This means that when received, the MCU can go into low power mode to save energy.
Note
A deeper low power mode will increase the time it takes to start servicing interrupts from the transceiver IRQ pin. Please refer to the datasheet of the MCUs used for details.
It is registered on a node with:
void swc_node_set_low_power_callback(const swc_node_t *const node, void (*cb)(void *node), swc_error_t *err);
Sending Data
Once the Wireless Core is fully initialized, the user can start sending data on TX connections with:
* when using the swc_connection_send method.
A call to this function will enqueue the payload into the connection’s transmission queue. At the next TX timeslot, the oldest payload in the queue will be encapsulated by the Wireless Core and transferred to the transceiver’s internal transmission buffer through SPI, ready to be sent over-the-air. Once the transmission is completed, depending on the connection configuration, callback functions will trigger.
Depending on what manages the payload memory (application vs Wireless Core), the method of sending data differs slightly. If the application wants to manage the memory allocation itself, it is suggested to set the connection’s queue_size to 1 to avoid unnecessary memory consumption by the Wireless Core.
For example, the following snippet of code shows that the application allocates memory for a 10-byte payload buffer. The buffer is then filled with data using a for loop and is finally sent through the tx_conn wireless connection.
#define PAYLOAD_SIZE 10
swc_error_t err;
uint8_t payload_buffer[PAYLOAD_SIZE];
for (uint8_t i = 0; i < PAYLOAD_SIZE; i++) {
payload_buffer[i] = i;
}
swc_connection_send(tx_conn, &payload_buffer, PAYLOAD_SIZE, &err);
Note that the content of the payload buffer should not be changed until the TX Success callback triggers, otherwise, data corruption could occur.
Now, if the user wants to use the Wireless Core allocated memory, a call to the following function must be done prior to calling the swc_connection_send() function in order to get a pointer to the payload memory allocated by the Wireless Core:
void swc_connection_allocate_payload_buffer(const swc_connection_t *const conn, uint8_t **const payload_buffer,
The size of the allocated space cannot be larger than the max_payload_size specified in the connection configuration.
The equivalent of the previous example in this case would look like this:
#define PAYLOAD_SIZE 10
swc_error_t err;
uint8_t *payload_buffer;
swc_connection_allocate_payload_buffer(tx_conn, &payload_buffer, PAYLOAD_SIZE, &err);
if (payload_buffer != NULL) {
for (uint8_t i = 0; i < PAYLOAD_SIZE; i++) {
payload_buffer[i] = i;
}
swc_connection_send(tx_conn, payload_buffer, PAYLOAD_SIZE, &err)
}
Note that in this example, payload_buffer is declared as a pointer and not an array, which means the application has not allocated memory for the payload content, but rather points to the memory allocated by the Wireless Core.
Receiving Data
Once the Wireless Core is fully initialized, the user can start receiving data on RX connections with:
uint16_t swc_connection_receive(const swc_connection_t *const conn, uint8_t **const payload_buffer, swc_error_t *err);
This function takes a double pointer to a payload_buffer as argument as the content of the payload_buffer pointer must be changed for the address of the buffer that contains the received payload.
Once the application has made a copy of the payload or has finished using it, a call to:
void swc_connection_receive_complete(const swc_connection_t *const conn, swc_error_t *err);
must be made in order the free the memory that the Wireless Core used to receive the payload. This function and swc_connection_receive_complete() are usually called in the RX Success callback as shown in the following example:
static uint8_t local_buffer[128];
void rx_success_callback(void *conn)
{
swc_error_t err;
swc_connection_t *rx_conn = conn;
uint8_t *payload = NULL;
uint8_t size;
size = swc_connection_receive(rx_conn, &payload, &err);
memcpy(local_buffer, payload, size);
swc_connection_receive_complete(rx_conn, &err);
}
Additionally, it is possible to read the size of the received bytes before reading them using:
uint16_t swc_connection_receive_get_payload_size(const swc_connection_t *const conn, swc_error_t *err);
Statistics
The Wireless Core provides connection-level statistics that the application can use to monitor the status of the payloads it sends and receives. The available statistics are as follows:
typedef struct swc_statistics {
/*! Increments when an acknowledge frame is received after sending a packet. */
uint32_t packet_sent_and_acked_count;
/*! Increments when an acknowledge frame is not received after sending a packet. */
uint32_t packet_sent_and_not_acked_count;
/*! Increments when there is nothing to send at the start of a TX timeslot. */
uint32_t no_packet_tranmission_count;
/*! Increments when a packet is dropped by the Wireless Core due to its timeout mechanism. */
uint32_t packet_dropped_count;
/*! Increments for every TX timeslot the connection goes through. */
uint32_t tx_timeslot_occurrence;
/*! Percentage of TX timeslots used for transmission over the total number of TX timeslots. */
float tx_used_capacity_pc;
/*! Increments when a packet is received and the CRC checks. */
uint32_t packet_successfully_received_count;
/*! Increment when nothing is received at the start of a RX timeslot. */
uint32_t no_packet_reception_count;
/*! Increments for every RX timeslot the connection goes through. */
uint32_t rx_timeslot_occurrence;
/*! Increments when a packet is received but is discarded because it is a
* duplicate of a previously received packet.
*/
uint32_t packet_duplicated_count;
/*! Increments when a packet is received but is discarded because the transceiver marked it as corrupted. */
uint32_t packet_rejected_count;
/*! Increments when a packet is received but is discarded because the Wireless Core reception queue is full. */
uint32_t packet_overrun_count;
/*! Increments when a ACK packet is received with data */
uint32_t packet_ack_data_received_count;
/*! Increments when a ACK packet is sent with data */
uint32_t packet_ack_data_send_count;
/*! Increments when a timeslot's Clear-Channel-Assessment passes and transmission occurs normally. */
uint32_t cca_pass_count;
/*! Increments when a timeslot's Clear-Channel-Assessment fails and aborts (or forces) transmission. */
uint32_t cca_fail_count;
/*! Increments when a single Clear-Channel-Assessment trial fails. */
uint32_t cca_try_fail_count;
/*! Average RSSI code. */
uint32_t rssi_avg;
/*! Average RNSI code. */
uint32_t rnsi_avg;
/*! Average link margin code. */
uint32_t link_margin_avg;
/*! Average RSSI raw code. */
uint32_t rssi_avg_raw;
/*! Average RNSI raw code. */
uint32_t rnsi_avg_raw;
/*! Number of bytes sent. */
uint32_t bytes_sent;
/*! Number of bytes received. */
uint32_t bytes_received;
/*! TX datarate in bits per seconds. */
uint32_t tx_data_rate_bps;
/*! RX datarate in bits per seconds. */
uint32_t rx_data_rate_bps;
/*! Tick value on statistics reset. */
uint32_t tick_on_reset;
/*! Tick value since last statistics reset. */
uint32_t tick_since_reset;
} swc_statistics_t;
To refresh the statistics, the following function must be called:
swc_statistics_t *swc_connection_update_stats(swc_connection_t *const conn);
This function also returns a pointer to the statistics for direct manipulation by the application. The following code snippet gives an example on how to access the packet_successfully_received_count counter:
uint32_t rx_good;
swc_statistics_t *stats;
stats = swc_connection_update_stats(conn);
rx_good = stats->packet_successfully_received_count
To reset the statistics, the user can simply call:
void swc_connection_reset_stats(swc_connection_t *const conn);
This will reset all the statistics counters to 0. Resetting the statistics just after the Node has finished synchronizing on the Coordinator is recommended as accumulated statistics prior to that point are mostly irrelevant.
Finally, a function that formats a string with all the available statistics is available:
int swc_connection_format_stats(const swc_connection_t *const conn, const swc_node_t *const node, char *const buffer,
This function detects if the connection is used for receiving or transmitting and will format only the relevant statistics. It also adds the connection’s name to the string in order to separate the statistics by connection. This is particularly useful on systems using many connections. Before calling swc_connection_format_stats(), the statistics must be updated with swc_connection_update_stats() as shown in the following example:
char stats_string[500];
swc_connection_update_stats(conn);
swc_connection_format_stats(conn, node, stats_string, sizeof(stats_string));
puts(stats_string);
Radio NVM
Each SPARK radio contains manufacturing information stored in its non-volatile memory (NVM). Part of the information can be extracted such as the serial number, the radio model and the radio version.
In order to have access to the NVM content, all radios must be initialized. Following the initialization process of Figure 51, all swc_node_add_radio() calls should have been made.
Formatted Output
To get a formatted string of the NVM content, the swc_format_radio_nvm function can be used as shown in the following example:
swc_error_t err;
char string[128];
swc_format_radio_nvm(string, sizeof(string), &err);
if (err == SWC_ERR_NONE) {
puts(string);
}
The same can be done with swc_format_radio2_nvm for a secondary radio.
Serial Number
To get the integer value of the radio’s serial number, the swc_node_get_radio_serial_number function can be used as shown in the following example:
swc_error_t err;
uint64_t serial_number;
serial_number = swc_node_get_radio_serial_number(&err);
if (err != SWC_ERR_NONE) {
while (1) {};
}
The same can be done with swc_node_get_radio2_serial_number for a secondary radio.
Product Model
To get the integer value of the radio’s product model, the swc_node_get_radio_product_model function can be used as shown in the following example:
swc_error_t err;
uint8_t product_model;
product_model = swc_node_get_radio_product_model(&err);
if (err != SWC_ERR_NONE) {
while (1) {};
}
The same can be done with swc_node_get_radio2_product_model for a secondary radio.
Product Version
To get the integer value of the radio’s product version, the swc_node_get_radio_product_version function can be used as shown in the following example:
swc_error_t err;
uint8_t product_version;
product_version = swc_node_get_radio_product_version(&err);
if (err != SWC_ERR_NONE) {
while (1) {};
}
The same can be done with swc_node_get_radio2_product_version for a secondary radio.
Low Power Mode
The Wireless Core provides functionality to indicate that Low Power mode can be enabled by the MCU. To do this, the user needs to call:
void swc_node_set_low_power_callback(const swc_node_t *const node, void (*cb)(void *node), swc_error_t *err);
Additionally, user can check the current low power status of the Wireless Core using the function below:
void swc_node_set_low_power_callback(const swc_node_t *const node, void (*cb)(void *node), swc_error_t *err);
Function swc_node_is_low_power_allowed() can be used to enter low power mode from the main application loop. If the user application supports other interrupts, then it can be used to check whether low power mode can be re-enabled.
References
sdk_spark_vx.y.z/
└── core/
└── wireless/
└── api/
├── swc_api.h
├── swc_error.h
├── swc_stats.h
└── swc_utils.h
File name |
Description |
|---|---|
swc_api.h |
The API itself. This header file must be included in the user’s application in order to use the Wireless Core. |
swc_error.h |
Wireless Core error codes. |
swc_stats.h |
Wireless Core statistics module. |
swc_utils.h |
Wireless Core utilities. |