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. .. code-block:: c :caption: 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. .. code-block:: c :caption: 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: .. code-block:: c #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. .. code-block:: c :caption: 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 =========================================== ================================================== .. code-block:: c :caption: 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. .. mermaid:: 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. .. code-block:: c :caption: 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(). .. code-block:: c :caption: 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 .. code-block:: c :caption: 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’. .. code-block:: c :caption: 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. .. code-block:: c :caption: 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: .. code-block:: c :caption: 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. .. code-block:: c :caption: Node example code static void DemoFunc() { NodeInfo info; Node.getNodeInfo(&info); Util.printf("HW Revision is %i\n", NodeInfo.Hardware_Rev); return; } .. code-block:: c :caption: 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: .. code-block:: c :caption: 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: .. code-block:: c :caption: 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. .. code-block:: c :caption: 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. .. code-block:: c :caption: 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) .. code-block:: c :caption: 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 =========================================== ==================================================