API Usage

The following sections describes each of the API modules. The functions are presented in a simplified form here as a quick reference; please see the RIIM SDK API Reference document included in the SDK for details. The RIIM SDK API Reference is distributed with the SDK, and is located at RIIM_SDK/docs/RIIM_API_Reference.html

Multicast

Multicast is supported for IPv6 transmissions not requiring responses. This means that you can use multicast for the functions UDP.send6 and CoAP.sendNoAck. In the RIIM wireless network, multicast act as a Broadcast, as the target group is “all nodes.” The following example shows how to send a UDP packet to all nodes in the network.

Multicast example code
const IPAddr Addr=UAPI_ADDR_ALL_RIIM_NODES;

UDP.send6(Addr, 12345, payload, payloadSize);

One-hop Multicast

RIIM supports multicast just to a node’s immediate neighbors as well. A multicast sent like this won’t be able to hop, and will only be responded to by nodes within reach of the sending node.

One-hop multicast example code
const IPAddr Addr=UAPI_ADDR_LINKLOCAL_NODES;

UDP.send6(Addr, 12345, payload, payloadSize);

RIIM_UAPI

This is basically an include file that includes everything you need to develop in ICI. It includes all User API definitions and needed standard C header files.

Simply put this include line on top of your source file:

#include "RIIM_UAPI.h"

API Descriptions

ADC

The ADC module lets you sample and convert the analog input of the module

RC18xx-IPM supports 2 ADC channels, called ADC0 and ADC1.

The following example shows an example usage where the ADC is initialized, read, and the value is converted to millivolts and printed on the console.

ADC example code
static uint32_t milliVolts;

void ADC_DemoFunc()
{
    milliVolts=0;

    // Set up interface
    ADC.init(ADC0, ADC_FIXED_REFERENCE, ADC_SAMPLING_DURATION_10_6_US);

    ADC.convertToMicroVolts(ADC0, &milliVolts);
    milliVolts /= 1000;

    // Print directly to console to show the latest values
    Util.printf("ADC sensor read: Voltage(mV): %i\n",milliVolts);

    return;
}

The following functions are part of the ADC module.

Function

Description

init

Initializes the ADC module input

convert

Convert input voltage to its raw ADC value

convertToMicroVolts

Convert input voltage to an microvolts

Clock

Note

The Clock API requires TSCH to work.

The Clock module provides ways to synchronize and distribute global time throughout the RIIM network. All the nodes part of a network are synchronized to within a few milliseconds of each other, enabling synchronous actions to take place across the RIIM network.

Note

For the border router, call to the Clock API can only be made > 100 ms after StartBorderRouter command

The Clock module provides two ways of representing time: Time of Day (ToD), and Epoch. ToD provides a 24 hour clock represented by hour, minute, second and millisecond. It can be used to do an action at a specific time during a day, and can be repetitive. Epoch provides an absolute time that’s always increasing. It’s represented in milliseconds, and can be used to measure absolute time or trigger an action at some specific time. It’s not repetitive.

Function

Description

getToD

Returns the ToD

setToD

Set the ToD

getEpoch

Returns the Epoch

setEpoch

Set the Epoch

getAbsoluteTime

Get absolute time

registerToDTimedAction

Register a ToD action

registerEpochTimedAction

Register an Epoch action

stopToDTimedAction

Stop a planned ToD action

stopEpochTimedAction

Stop a planned epoch action

sendClockToAllNodes

Send Epoch and ToD to all nodes

getClockFromBR

Retrieve the Epoch and ToD from the border router

getOffsets

Get the raw offset values for ToD and epoch

setOffsets

Set the raw offset values for ToD and epoch

getLastSynchronizeTimestamp

Get timestamp when the node last received a clock synchronization

Clock example code
EpochType epoch; // Set to zero in RIIM_SETUP()

// Epoch callback
void epochCallback(void)
{
    EpochType thisEpoch;
    Clock.getEpoch(&thisEpoch);
    Util.printf("Epoch callback at : %i" , (int32_t)thisEpoch);

    // Set next callback to be in 5 seconds
    epoch=epoch+5000;
    Clock.registerEpochTimedAction(&epoch, epochCallback);
    Util.printf(" - New set to : %i\n" , (int32_t)epoch);

    return;
}

CoAP

The CoAP module lets you start and run a CoAP server and lets you transmit CoAP messages to and from a server. If the server is at the border router or on a mesh router is up to the implementor. The CoAP resources on the server side need to be registered along with a callback function (ResourceHandler). This function is called every time the module receives a CoAP request for the resource. The ResourceHandler have as input a pointer to the response that will be sent upon returning from the callback. This response can be filled in during the callback, if a value is intended returned in the response. The generateResponse() function is a support function to fill the response with boundry checked data.

The client need to connectToServer to allow communication with the server. It also need to register a callback function to handle respones form the server. It can be an empty reponse to a PUT-command or a response with value related to a GET command Then the client can issue CoAP requests when it want and wait for responses.

The CoAP protocol include automatically retries in case of no reponse. The retries are after 20 second and then it times out after slightly over 1 minute.

sequenceDiagram participant Client participant Server Server->>Server: CoAP.registerResource(ResourceHandler) Client->>Client: CoAP.connectToServer(Server) Client->>Client: CoAP.registerResponseHandler(RespHandler) Client->>Client: CoAP.send() Client->>Server: "CoAP REQUEST" Server->>Server: ResourceHandler() Server->>Client: "RESPONSE" Client->>Client: RespHandler()

The following example demonstrates how you initialize the CoAP module, set up a response handler and a resource access handler. When this node receives a PUT, POST, GET or DELETE CoAP message, it will call the CoAP_Handler routine. 5 CoAP resources can be registered, and CoAP.registerResource will return an error if more recsorces are requested.

CoAP example code
static const uint8_t Resource_Name[]="data";

static void CoAP_Handler(RequestType type, uint8_t *payload, uint8_t payloadSize, uint8_t *response, uint8_t *responseSize)
{
    // In this example we only print the payload directly to the UART
    Debug.printPayload(payload, payloadSize);
    Util.printf("\n"); // Add a newline for readability in console
    return;
}

void ResponseHandler(const uint8_t *payload, uint8_t payload_size)
{
    Util.printf("# Got CoAP Response. Doing nothing with it.\n");
    return;
}

RIIM_SETUP()
{
    Network.startBorderRouter(NULL, NULL, NULL, NULL);

    // Setup coap resource
    CoAP.init(ResponseHandler);
    CoAP.registerResource(Resource_Name,0,CoAP_Handler);

    return UAPI_OK;
}

The following functions are part of the CoAP module.

Function

Description

Init

Initializes the CoAP module

connectToServer4

Connect to a CoAP server using IPv4. This must be done before accessing it.

connectToServer6

Connect to a CoAP server using IPv6. This must be done before accessing it.

setKey

Set DTLS key

setIdentity

Set DTLS Identity

registerResponseHandler

Register a handler to be executed when a CoAP response arrives

registerResource

Register a new resource that will be accessible on the node

generateResponse

Generate a response message and send it back to the caller

send

Send a GET, PUT, POST or DELETE message to a CoAP server

sendNoAck

Send a GET, PUT, POST or DELETE message to a CoAP server, but don’t ask for a CoAP response

disconnectFromServer

Disconnect from the CoAP server

Note: CoAP packets will be retransmitted several times if they’re lost on the way to their destination. Each retransmission with an increased timeout. The total time might be in the order of minutes, and hence the CoAP queue can easily fill up. It’s therefore important to wait for the CoAP response before sending new CoAP packets.

Debug

The Debug module contains useful functions for debugging.

The following example shows how you can dump the configuration of the node by calling Debug.printSetup().

Debug example code
RIIM_SETUP()
{
    Network.startBorderRouter(NULL, NULL, NULL, NULL);

    // Print out the configuration
    Debug.printSetup();

    return UAPI_OK;
}

The following functions are part of the Debug module.

Function

Description

printPayload

Dump the payload to the UART

printSetup

Print the current node setup on the UART

printIPAddr

Nicely print IPAddr

radioTest

Test the radio in CW or MW mode.

getResetReason

Return the reset code for last module reset

Note

For the radioTest function:

  1. This command is locking, meaning that the module needs to be externally reset after its called.

  2. This command can’t be called in RIIM_SETUP(), but must be executed in a callback

Ethernet

The Ethernet module is used to interface the Ethernet system. The Ethernet MAC is by default set by using the EUI64 / IEEE address of the module, which is unique to each module.

The following example shows how to read the MAC address

Ethernet example code
RIIM_SETUP()
{
    // Set Ethernet MAC address
    uint8_t Mac[6];
    Ethernet. getMACAddress(Mac);

    return UAPI_OK;
}

Function

Description

Init

Initialize the GPIO module

getMACAddress

Read the Ethernet MAC address

GPIO

The GPIO module is used to control the GPIOs. By default all GPIOs are tri-state inputs with no pullup or pulldown.

All GPIOs also include PWM controllers capable of working autonomously.

Note

PWM could impact current consumption

The following example shows how to configure GPIO 9 as output and setting it to logical ‘1’.

GPIO example code
RIIM_SETUP()
{
    // Set up GPIO 9
    GPIO.setDirection(GPIO_9, OUTPUT);
    GPIO.setValue(GPIO_9, HIGH);

    return UAPI_OK;
}

The following functions are part of the GPIO module.

Function

Description

Init

Initialize the GPIO module

setDirection

Set the GPIO direction to input or output

setPull

Set pullup, pulldown or no pull on an input pin

setHandler

Register a handler to be called when a specific transition happen on a GPIO

setValue

Set the value on an output GPIO to logical 0 or 1

toggle

Invert the output value on an GPIO

getValue

Read the value of a GPIO pin

startPWM

Start PWM output

stopPWM

Stop PWM output

I2C

The I2C module has functions needed for interfacing the I2C bus. It always operates as master, and support clock stretching. It supports two speeds: 100KHz and 400KHz.

The following example demonstrates how the module is initialized and an example transmission towards a Sensirion SHT35 Temperature/Humidity sensor.

I2C example code
static void ReadSensor()
{
    static uint8_t wbuf[2];
    static uint8_t rbuf[10];

    // The command 0x2C0D starts a Medium repeatibility measuring
    // with clock stretching enabled. See Sensirion SHT35 datasheet.
    wbuf[0]=0x2C;
    wbuf[1]=0x0D;

    I2C.transfer(0x44,wbuf,2,rbuf, 7);

    .......

}

RIIM_SETUP()
{
    // Set up interface towards the SHT35-sensor
    I2C.init(I2C_400KHZ);

    .........

    return UAPI_OK;
}

The following functions are part of the I2C module.

Function

Description

init

Initializes the I2C driver with the chosen Speed

transfer

Transfers data both to and from the slave at bus address SlaveAddress. Data is first written on bus, then read

read

Perform only read on the I2C bus

write

Perform only write on the I2C bus

close

Closes the I2C interface

Network

The Network module has the functions needed for network operations. Before the node can join any network, it must be started by a call to either startBorderRouter, startMeshRouter or startLeaf. Some functions will only have effect depending on the RIIM variant (single channel or TSCH) used.

Note

The UART API can’t be used if SLIP is used, as SLIP uses the UART to transfer data

The following example shows how to start a node as a Router:

Network example code
RIIM_SETUP()
{
    // Simply start as a router node. Nothing more is needed.
    Network.startMeshRouter();

    return UAPI_OK;
}

The following functions are part of the Network module.

Function

SC

TSCH

Description

startBorderRouter

x

x

Start the node as a Border Router.

startMeshRouter

x

x

Start the node as a Mesh Router.

startLeaf

x

x

Start the node as a Leaf.

getBorderRouterAddress

x

x

Returns the address of the Border Router

getParentRSSI

x

x

Get the RSSI value of parent

getNeighbors

x

x

The a list of all neighbors, including RSSI

getNetworkState

x

x

Get the state of the network

radio_On

x

Turn radio on

radio_Off

x

Turn radio off

join

x

x

(Re)-join a network

leave

Deprecated. don’t use.

setFreqBand

x

x

Set the frequency band.

setPanId

x

x

Set the PAN ID of the node

getPanId

x

x

Get the PAN ID of the node

getAddress

x

x

Get the IP (v6) address of the node

getAddress4

x

X

Get the IPv4 address of the node

getNetworkLinks

x

x

Retrieves a list of links between nodes

setTxPower

x

x

Set the output transmission power

getNodeType

x

x

Return the type of node we’re configured as

setChannel

x

Set the RF channel to use

isPartOfNetwork

x

x

Check if a gived IP address is part of the network

setNWKey

x

x

Set the network (LLSEC) key

setRobustnessFactor

x

x

Set the node’s robustness factor

setTschMaxBrodcastRate

x

Set the maximum network broadcast period

getNodeCount

x

x

Get the number of nodes in the network

startSlip

x

x

Start the SLIP interface

setTSCHMode

Deprecated.

setTSCHParameters

x

Deprecated. Use Use Node.SetCurrentConfiguration instead.

reConnect

x

x

Reconnect to (possibly another) network

autoupdateTSCHParameters

x

Enable/disable automatic update of TSCH parameters

stop

x

x

Stops all RF traffic and disjoins any network

Node

The Node module contains functions for reading/writing node information and settings.

Node example code
static void DemoFunc()
{
    NodeInfo info;
    Node.getNodeInfo(&info);
    Util.printf("HW Revision is %i\n", NodeInfo.Hardware_Rev);

    return;
}
Example setting MPL parameters
RIIM_SETUP()
{
    RIIMConfig_t Configuration;
    Node.GetCurrentConfiguration(&Configuration);
    Configuration.MPLParameters.MPL_Control_Message_IMin=128;   // Should be power-of-two
    Configuration.MPLParameters.MPL_Control_Message_IMax=2048;  // Should be power-of-two
    Configuration.MPLParameters.MPL_Control_Message_K=1;
    Configuration.MPLParameters.MPL_Data_Message_IMin=128;      // Should be power-of-two
    Configuration.MPLParameters.MPL_Data_Message_IMax=4096;     // Should be power-of-two
    Configuration.MPLParameters.MPL_Data_Message_K=3;
    Node.SetCurrentConfiguration(&Configuration);

    return UAPI_OK;
}

The following functions are part of the Node module:

Function

Description

getNodeInfo

Return info about the node: Hardware ID+Revision, Platform ID+Version

GetDefaultConfiguration

Get the default configuration (Factory settings)

GetCurrentConfiguration

Get the current (in-use) configuration

SetCurrentConfiguration

Set the current (in-use) configuration

SPI

The SPI module has all the functions needed for accessing the SPI bus. For chip select control, the user must use a GPIO. For all data transfer and initialization, the SPI module can be used. In the example below, usage of both GPIO and SPI is demonstrated. Only 4-wire SPI is supported

The following example shows how to set up SPI and access the ST LIS3DE accelerometer:

SPI example code
RIIM_SETUP()
{
    // Set up GPIO. We must use one GPIO for SPI chip select
    GPIO.setDirection(GPIO_3, OUTPUT);
    GPIO.setValue(GPIO_3, HIGH);

    // Set up interface towards the LIS3DE-sensor
    SPI.init(4000000,SPI_POL_0_PHA_0);

    // Setup accelerometer to update every second
    uint8_t wbuf[2];
    wbuf[0]=0x20; // 0 (write), 0(don't increment), 0x20 (register address)
    wbuf[1]=0x17; // 1 Hz, enable X,Y and Z axes

    GPIO.setValue(GPIO_3, LOW);
    SPI.transfer(2, wbuf, NULL);
    GPIO.setValue(GPIO_3, HIGH);

    return UAPI_OK;
}

The following functions are part of the SPI module:

Function

Description

init

Initialize the SPI module

transfer

Transfer bytes over the SPI bus

Timer

The Timer module enables the user to create various timers. The timers will call a function when they’re triggered, and can be configured as periodic or one-shot, started and stopped.

The following example creates a periodic timer that calls the function ReadSensor every 10 seconds:

Timer example code
static const uint32_t TimerPeriod=10000;
static uint8_t Sensor_timer_handler;

static void ReadSensor()
{
    Util.printf("Reading sensors....\n");

    return;
}

RIIM_SETUP()
{
    // Create timer that sends the CoAP PUT message
    Sensor_timer_handler=Timer.create(PERIODIC, TimerPeriod, ReadSensor);
    Timer.start(Sensor_timer_handler);

    return UAPI_OK;
}

Function

Description

create

Create a new timer

start

Start the timer

stop

Stop the timer

isActive

Check if the timer is active

config

(Re)-configure a timer

UART

Note

The UART API can’t be used if SLIP is used, as SLIP uses the UART to transfer data

The UART module controls the UART port. The uart can be configured with respect to baudrate, parity, number of databits and number of stopbits.

UART example code
static void TxCallback(uint8_t len)
{
    Util.printf("Sent %i bytes\n", len);

    return;
}

static void DemoFunc()
{
    const uint8_t buffer="Test";

    UART.init(115200, UART_PARITY_NONE, UART_DATA_8_BITS, UART_STOP_1_BIT);
    UART.startTransmit(buffer, sizeof(buffer), TXCallback);

    return;
}

Function

Description

Init

Initialize the UART module

startReceive

Start reception

cancelReceive

Stop reception

startTransmit

Start transmission of a buffer of bytes

isTXActive

Returns true if UART TX is active

isRXActive

Returns true if UART RX is active

enableRXTX

Enables RXTX functionality on CTS pin. Compatible with RS485

startReceive_Adv

Advanced version of startReceive

wakeOnUART

Enable or disable wake-on-uart

UDP

The UDP module controls the sending and reception of UDP packets. It has functions for receiving and sending over IPv6 or IPv4.

UART example code
void udpCallback(IPAddr src_ipAddr, uint8_t *payload, uint8_t payloadSize)
{
    int i;

    Util.printf("Msg from ");
    for(i=0;i<16;i++){
        Util.printf("%.02x" , src_ipAddr.byte[i]);
    }
    Util.printf(" : %.*s\n" , payloadSize, payload);
    UDP.send6(src_ipAddr, 12345, payload, payloadSize);
}

RIIM_SETUP()
{
    .....
    UDP.setup(udpCallback,12345);
    .....
}

Function

Description

send4

Send a UDP packet to an IPv4 address. Typically to the internet

send6

Send a UDP packet to an IPv6 address. Typically inside the RIIM wireless network

setup

Setup a handler for reception of UDP packets

Util

The Util module contains useful helper functions. The module provides common C library functions for the ICI user application to use: printf, sprintf, snprinf. It also provides a random generator.

The following example shows how to print something on the console (UART)

Util example code
static void DemoFunc()
{
    Util.printf("Reading sensors....\n");

    return;
}

Function

Description

printf

Standard C-library printf

sprintf

Standard C-library sprintf

snprintf

Standard C-library snprintf

getRand

Get a random number

reset

Reset the module

getTemperature

Get module temperature

strlen

Return string length

strcmp

Standard C-library strcmp

strncmp

Standard C-library strncmp

getVoltage

Get voltage on the supply pin of the module