Registering sensors or development boards using Protocol version 1

This topic provides a brief overview of how to register a sensor or development board using the Protocol version 1 (opens in a new tab). The following sample files outline the necessary functions for registering new sensors:

  • simple_protocol.c: This file includes the steps for defining the sensor configuration, initializing the protocol, and implementing the streaming protocol.
  • simple_main.c: This file contains the main function.

Refer to the Protocol version 1 (opens in a new tab) Bitbucket repository to know more about the protocol.

Step 1: Include the header files

Include all the header files as declared in simple_protocol.c.

Example including header files

#include <stdio.h>
#include "clock.h"
#include "config.h"
#include "protocol.h"

Step 2: Define sensor configuration

Example for defining microphone and accelerometer

static const char* CONFIG_MESSAGE =
        "{\r\n"
		"    \"device_name\": \"PSoC6\",\r\n"
		"    \"protocol_version\": 1,\r\n"
		"    \"heartbeat_timeout\": 5,\r\n"
		"    \"sensors\": [\r\n"
		"        {\r\n"
		"            \"channel\": 1,\r\n"
		"            \"type\": \"microphone\",\r\n"
		"            \"datatype\": \"s16\",\r\n"
		"            \"shape\": \[ 1024, 1 ],\r\n"
		"            \"rates\": [ 16000 ]\r\n"
		"        },\r\n"
		"        {\r\n"
		"            \"channel\": 2,\r\n"
		"            \"type\": \"accelerometer\",\r\n"
		"            \"datatype\": \"f32\",\r\n"
		"            \"shape\": \[ 1, 3 ],\r\n"
		"            \"rates\": [ 50,500 ]\r\n"
		"        }\r\n"
		"    ]\r\n"
		"}\r\n\0";"

The second step is to define the sensor configuration in the protocol. Begin by defining the following parameters:

  • device name: Write the name of the device name for easy identification. For instance, PSoC6.

  • heartbeat timeout: Set the duration in seconds after which the sensor stops data transmission data if no heartbeat is received.

  • channel: Set one or more channels for handling the incoming sensor data. Each sensor must be assigned a unique channel. You can set channel number from 1 to 9 for each sensor type. For instance, the device will receive audio data at channnel 1 and accelerometer data at channel 2.

  • sensor type: Write the name of the sensors in lowercase letters.

  • data type: Set the data type as "u8" "s8", "u16", "s16", "u32", "s32", "f32", "f64". All multi byte types are sent little endian.

  • shape: Set the format in which sensor data is transmitted to the device. For instance, the shape for microphone is set as [1024, 1], where 1024 indicates the amount of data sent in one packet, and 2 represents the stereo channel. Similarly, the shape for accelerometer is set to [1, 3], where 1 means one packet is sent at a time, and 3 corresponds to the X, Y, and Z axis.

  • rate: Set the range of valid sampling rates for data collection in Hz. For instance, the rate for microphone is set to [16000], indicating a sampling frequency of 16000 Hz for microphone data. For the accelerometer, the rate is set to [50, 500], meaning data can be collected at either 50 Hz or 500 Hz.

Step 3: Initializing the protocol

This function initializes the protocol and should be called once before using any other functions in this file. In the code snippet, the clock_init() function is called to initialize a clock used for sampling, this function is defined in clock.h.

Example Initializing the protocol function

void protocol_init()
{
	clock_init()
}

Step 4: Define protocol_repl Function

This function processes incoming characters, executes commands, and sends response messages within a read-eval-print loop. The function may block execution until the response transmission is complete.

Example protocol_repl

 void protocol_repl()
{
	/* Update clock */
	clock_update();
 
	/* Test clock */
	/* Uncomment if desired!
	static uint32_t last_t = 0;
	if (clock_get_ms() > last_t + 1000)
	{
		static char buffer[20];
		sprintf(buffer, "%lu\r\n", clock_get_ms());
		streaming_send(buffer, strlen(buffer));
		last_t += 1000;
	}
	*/
 
	/* Read and handle data if any bytes are available */
	size_t bytes_read = streaming_receive(receive_p, RECEIVE_BUFFER_SIZE - (receive_p - receive_buffer));
    if (bytes_read)
    {
    	/* Register receive time */
    	last_receive_time = clock_get_ms();
 
    	/* Echo incoming characters when not streaming data */
    	/* Uncomment if desired!
    	if (!subscribe_audio && !subscribe_imu)
    		streaming_send(receive_p, bytes_read);
    	*/
 
    	/* Advance receive pointer */
    	receive_p += bytes_read;
 
    	/* Check for \r\n at end */
    	if (receive_p >= receive_buffer + 2 && *(receive_p - 2) == '\r' && *(receive_p - 1) == '\n')
    	{
    		/* Remove \r\n */
            *(receive_p - 2) = 0;
 
            /* config? */
            if (strcmp(receive_buffer, "config?") == 0)
            {
            	subscribe_audio = subscribe_imu = false;
            	streaming_send(CONFIG_MESSAGE, strlen(CONFIG_MESSAGE));
            }
            /* subscribe,1,16000 */
            else if (strcmp(receive_buffer, "subscribe,1,16000") == 0)
            {
            	subscribe_audio = true;
            }
            /* unsubscribe,1 */
            else if (strcmp(receive_buffer, "unsubscribe,1") == 0)
            {
            	subscribe_audio = false;
            	streaming_send(OK_MESSAGE, strlen(OK_MESSAGE));
            }
            /* subscribe,2,50 */
            else if (strcmp(receive_buffer, "subscribe,2,50") == 0)
            {
            	subscribe_imu = true;
            }
            /* unsubscribe,2 */
            else if (strcmp(receive_buffer, "unsubscribe,2") == 0)
            {
            	subscribe_imu = false;
            	streaming_send(OK_MESSAGE, strlen(OK_MESSAGE));
            }
            /* unsubscribe */
            else if (strcmp(receive_buffer, "unsubscribe") == 0)
            {
            	subscribe_audio = subscribe_imu = false;
            	streaming_send(OK_MESSAGE, strlen(OK_MESSAGE));
            }
            /* empty command or heartbeat */
            else if (*receive_buffer == 0 || strcmp(receive_buffer, "heartbeat") == 0)
            {
            	/* Nothing to do except register receive time, which was done above */
            }
            else
            {
            	streaming_send(UNRECOGNIZED_COMMAND_MESSAGE, strlen(UNRECOGNIZED_COMMAND_MESSAGE));
            }
 
            /* Reset receive pointer; ready for new command */
    		receive_p = receive_buffer;
    	}
 
    	/* Check end of buffer */
    	if (receive_p == receive_buffer + RECEIVE_BUFFER_SIZE)
    	{
    		streaming_send(TOO_LONG_COMMAND_MESSAGE, strlen(TOO_LONG_COMMAND_MESSAGE));
    		receive_p = receive_buffer;
    	}
    }
 
    /* Check receive timeout: If no message for 5 seconds, stop streaming */
    if ((subscribe_audio || subscribe_imu) && clock_get_ms() - last_receive_time > HEARTBEAT_TIMEOUT_MS)
    {
    	subscribe_audio = subscribe_imu = false;
    }
}

Step 5: Define protocol_send Function

This function transmits a packet of data from the sensor to Studio. The function may block execution until the transmission is complete.

Parameters used in this function:

  • channel: Specifies the channel through which the packet will be sent
  • data: Pointer to the data to be transmitted
  • size: Number of bytes to be transmitted

Example Define protocol_send Function

void protocol_send(uint8_t channel, const uint8_t* data, size_t size)
{
	uint8_t header[2] = { 'B', '0' + channel };
    switch (channel)
    {
    case PROTOCOL_AUDIO_CHANNEL:
    	if (subscribe_audio)
    	{
    		streaming_send(header, 2);
    	    streaming_send(data, size);
    	    streaming_send(CRLF, 2);
    	}
    	break;
    case PROTOCOL_IMU_CHANNEL:
    	if (subscribe_imu)
    	{
    		streaming_send(header, 2);
    	    streaming_send(data, size);
    	    streaming_send(CRLF, 2);
    	}
    }
}

Refer to Flashing your custom firmware using ModusToolbox to know how to flash the custom firmware on your board using ModusToolbox™.

⚠️

For flashing information on boards other than Infineon boards, refer to your specific board documentation.