IRI Example Programs

The ITK includes a number of example programs for Windows, Linux, and OS X. These examples demonstrate many of the features of the ITK and Indy Reader Modules. Each example is complete and self contained, and can be compiled and run without any modification. These examples contrast with the Configuration Examples, which contain code snippets that demonstrate key aspects of numerous specific use cases of the Indy Modules.

The examples are listed below, starting with the basic IRI_Intro example, with all of the remaining examples following in alphabetical order.

Examples Directory Structure

Several example IRI programs (all IRI_*.c files) are provided with the release in the following locations:

ITK_C\Examples\ipj_util.c
ITK_C\Examples\ipj_util.h
ITK_C\Examples\IRI_Access.c
ITK_C\Examples\IRI_Antenna_Descriptors.c
ITK_C\Examples\IRI_Change_Baudrate.c
ITK_C\Examples\IRI_Empty.c
ITK_C\Examples\IRI_External_Antenna_Mux.c
ITK_C\Examples\IRI_GPIO.c
ITK_C\Examples\IRI_Intro.c
ITK_C\Examples\IRI_Loader.c
ITK_C\Examples\IRI_Multiple_Readers.c
ITK_C\Examples\IRI_Power_Management.c
ITK_C\Examples\IRI_Select.c
ITK_C\Examples\IRI_Test_CW_PRBS.c
ITK_C\Examples\Makefile
ITK_C\Examples\VS2005\Examples.sln
ITK_C\Examples\VS2005\README.txt
ITK_C\Examples\VS2005\stdbool.h
ITK_C\Examples\VS2005\stdint.h
ITK_C\Examples\VS2012\Examples.sln
ITK_C\Examples\VS2012\README.txt
ITK_C\Examples\VS2012\stdbool.h

The example programs are accompanied by example implementations of the platform specific code for a few platforms:

ITK_C\Library\platform_linux.c
ITK_C\Library\platform_osx.c
ITK_C\Library\platform_win32.c

These are documented below in the Platform Port Examples section.

Building, Running, and Debugging the Examples

Building and running the examples in Visual Studio in Windows

To build the examples in Visual Studio, open the one of the Examples.sln Visual Studio solutions and build it using the GUI.

To run the built examples in Windows using the command line, run the executable using the correct COM port as the argument, for example, type IRI_Intro COM1 .

Note

The correct COM port can easily be determined using the Indy Demo Tool GUI.

Debugging the examples in Visual Studio in Windows

To debug the examples in Visual Studio, perform the following steps:

  1. Right click on the desired example and select “Set as Startup Project”.
  2. Open the properties of the desired example project by right clicking the project and selecting “Properties”.
  3. Under “Configuration Properties”, select “Debugging”.
  4. In the “Command Arguments” field, enter the COM port that connects to your Indy device (e.g. COM1 ).
  5. Under “Configuration Properties”, expand “Linker” and select “Debugging”.
  6. Set the “Generate Debug Info” setting to “Yes (/DEBUG)”.
  7. Close the project configuration dialog.
  8. Press the “Local Windows Debugger” button, and debugging should begin.

Building and running the examples in the Linux command line

To build the examples from the Linux command line, type make in the \Examples\ directory

To run the examples in Linux in the console, run the output of the build using the /dev/ device as the argument, for example, type output/IRI_Intro /dev/ttyUSB0 .

IRI_Intro Example

The IRI_Intro example connects to an Indy Module and performs basic inventory for 1 second, printing read EPCs to the console or command line.

IRI_Intro - Source Code

IRI_Intro source code is provided in IRI_Intro.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This example illustrates the use of the basic inventory operation
   and to retrieve RS500 information. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 1000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;
    uint32_t value;
    ipj_key_info keyinfo;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /* Reader Info */
    printf("RS500 Info\n");
    error = ipj_get_value(&iri_device, E_IPJ_KEY_SERIAL_NUMBER, &value);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_get_value E_IPJ_KEY_SERIAL_NUMBER");
    printf("Serial Number      : %d\n", value);
    ipj_get_value(&iri_device, E_IPJ_KEY_BOOTSTRAP_VERSION, &value);
    printf("Bootstrap Version  : 0x%08X\n", value);
    ipj_get_value(&iri_device, E_IPJ_KEY_BOOTSTRAP_CRC, &value);
    printf("Bootstrap CRC      : 0x%08X\n", value);
    ipj_get_value(&iri_device, E_IPJ_KEY_APPLICATION_VERSION, &value);
    printf("Application Version: 0x%08X\n", value);
    ipj_get_value(&iri_device, E_IPJ_KEY_APPLICATION_CRC, &value);
    printf("Application CRC    : 0x%08X\n", value);
    ipj_get_value(&iri_device, E_IPJ_KEY_MICROPROCESSOR_ID, &value);
    printf("Microprocessor     : 0x%08X\n", value);
    ipj_get(&iri_device, E_IPJ_KEY_MICROPROCESSOR_ID, 0, 1, &value);
    printf("Microprocessor Id  : 0x%08X", value);
    ipj_get(&iri_device, E_IPJ_KEY_MICROPROCESSOR_ID, 0, 2, &value);
    printf("-0x%08X", value);
    ipj_get(&iri_device, E_IPJ_KEY_MICROPROCESSOR_ID, 0, 3, &value);
    printf("-0x%08X", value);
    printf("\n\n");

    IPJ_CLEAR_STRUCT(keyinfo);

    /* Verify that we can indeed write the ANTENNA_TX_POWER key */
    error = ipj_get_info(&iri_device, E_IPJ_KEY_ANTENNA_TX_POWER, &keyinfo);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_get_info E_IPJ_KEY_ANTENNA_TX_POWER");

    /* Check to make sure the key has either write, or read/write permissions */
    if (keyinfo.key_permissions == E_IPJ_KEY_PERMISSIONS_READ_ONLY)
    {
        printf("ERROR: Unable to set ANTENNA_TX_POWER KEY\n\n");
        return -1;
    }

    /* Configure transmit power */
    error = ipj_set_value(&iri_device, E_IPJ_KEY_ANTENNA_TX_POWER, 2300);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value E_IPJ_KEY_ANTENNA_TX_POWER");

    /* Start inventory */
    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return error;
}

IRI_Access Example

The IRI_Access example demonstrates how to use the Access tag operation to write a tag’s EPC.

This example can be easily modified to write user memory by modifying the values of the E_IPJ_KEY_WRITE_MEM_BANK and E_IPJ_KEY_WRITE_WORD_POINTER keys.

IRI_Access - Source Code

IRI_Access source code is provided in IRI_Access.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This example illustrates the use of the tag operations
   Write and Write EPC. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 250

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

static ipj_error write_epc(ipj_iri_device* iri_device, uint16_t* epc)
{
    unsigned int i;
    ipj_error error;
    ipj_key_value key_value[16];
    ipj_key_value key_value_2[16];
    uint32_t key_value_count = 0;
    ipj_key_list key_list;
    ipj_key_list key_list_2;
    uint32_t key_list_count = 0;

    printf("Setting EPC to: ");

    ipj_util_print_epc(epc, 6, false);

    /* Enable tag write */
    key_value_count = 5;

    IPJ_CLEAR_STRUCT(key_list);
    IPJ_CLEAR_STRUCT(key_value);

    key_value[0].key = E_IPJ_KEY_TAG_OPERATION_ENABLE;
    key_value[0].value = true;

    key_value[1].key = E_IPJ_KEY_TAG_OPERATION;
    key_value[1].value = E_IPJ_TAG_OPERATION_TYPE_WRITE;

    key_value[2].key = E_IPJ_KEY_WRITE_MEM_BANK;
    key_value[2].value = E_IPJ_MEM_BANK_EPC;

    key_value[3].key = E_IPJ_KEY_WRITE_WORD_POINTER;
    key_value[3].value = 1;

    key_value[4].key = E_IPJ_KEY_WRITE_WORD_COUNT;
    key_value[4].value = 7;

    key_list_count = 1;
    key_list.key = E_IPJ_KEY_WRITE_DATA;
    key_list.list_count = 7;

    key_list.list[0] = 0x3000;

    /* Set last two halfwords of EPC to random numbers*/
    for (i = 1; i < 7; i++)
    {
        key_list.list[i] = epc[i - 1];
    }

    error = ipj_bulk_set(
            iri_device,
            &key_value[0],
            key_value_count,
            &key_list,
            key_list_count);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_bulk_set");

    /* Copy over the keys for the sake of simplicity */
    memcpy(&key_value_2, &key_value, sizeof(key_value));
    memcpy(&key_list_2, &key_list, sizeof(key_list));

    /* Set the desired key list read length*/
    key_list_2.length = 7;

    error = ipj_bulk_get(
            iri_device,
            key_value_2,
            key_value_count,
            &key_list_2,
            key_list_count);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_bulk_get");

    printf("\n");
    printf("Get Key Value Pairs\n");
    for (i = 0; i < key_value_count; i++)
    {
        printf(
                "Key: 0x%03x Value: %10d Bank Index:%d Value Index:%d\n",
                key_value_2[i].key,
                key_value_2[i].value,
                key_value_2[i].bank_index,
                key_value_2[i].value_index);
    }
    printf("\n");

    printf("Key List\n");
    printf(
            "Key: 0x%03x\t\t     Bank Index:%d Value Index:%d\t",
            key_list_2.key,
            key_list_2.bank_index,
            key_list_2.value_index);

    printf("\n[ ");
    for (i = 0; i < key_list_2.list_count; i++)
    {
        printf("0x%04X ", key_list_2.list[i]);
    }
    printf("]\n\n");

    return E_IPJ_ERROR_SUCCESS;
}

static ipj_error write_epc_feature(ipj_iri_device* iri_device, uint16_t* epc)
{
    unsigned int i;
    ipj_error error;
    ipj_key_value key_value[16];
    uint32_t key_value_count = 0;
    ipj_key_list key_list;
    uint32_t key_list_count = 0;

    printf("Setting EPC to: ");

    ipj_util_print_epc(epc, 6, false);

    /* Enable tag write */
    key_value_count = 4;

    IPJ_CLEAR_STRUCT(key_value);
    IPJ_CLEAR_STRUCT(key_list);

    key_value[0].key = E_IPJ_KEY_TAG_OPERATION_ENABLE;
    key_value[0].value = true;

    key_value[1].key = E_IPJ_KEY_TAG_OPERATION;
    key_value[1].value = E_IPJ_TAG_OPERATION_TYPE_WRITE_EPC;

    key_value[2].key = E_IPJ_KEY_WRITE_EPC_LENGTH_CONTROL;
    key_value[2].value = E_IPJ_WRITE_EPC_LENGTH_CONTROL_AUTO;

    key_value[3].key = E_IPJ_KEY_WRITE_WORD_COUNT;
    key_value[3].value = 6;

    key_list_count = 1;
    key_list.key = E_IPJ_KEY_WRITE_DATA;
    key_list.list_count = 6;

    /* Set EPC to random numbers*/
    for (i = 0; i < 6; i++)
    {
        key_list.list[i] = epc[i];
    }

    error = ipj_bulk_set(
            iri_device,
            &key_value[0],
            key_value_count,
            &key_list,
            key_list_count);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_bulk_set");

    return E_IPJ_ERROR_SUCCESS;
}

/* Main */
int main(int argc, char* argv[])
{
    /* Holder for EPC */
    uint16_t epc[6] = { 0 };

    /* Define error code */
    ipj_error error;

    /* Set-Get and Bulk_Set-Get variables */
    uint32_t i = 0;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Seed random number generator */
    srand((unsigned int) time(NULL));

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /* Bulk_Set-Get example */
    /* Set a tag EPC */

    /* Generate 6 random numbers for EPC code */
    for (i = 0; i < 6; i++)
    {
        epc[i] = rand() % 0xffff;
    }

    /* Write EPC to tag */
    write_epc(&iri_device, epc);

    ipj_util_print_divider('*', 80);
    printf("EPC Write\n");
    ipj_util_print_divider('-', 80);

    /* Perform inventory to see results of EPC write */
    ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);

    /* Generate 6 random numbers for EPC code */
    for (i = 0; i < 6; i++)
    {
        epc[i] = rand() % 0xffff;
    }

    /* Write EPC to tag using WRITE_EPC feature */
    write_epc_feature(&iri_device, epc);

    ipj_util_print_divider('*', 80);
    printf("EPC Write Feature\n");
    ipj_util_print_divider('-', 80);

    /* Perform inventory to see results of EPC write */
    ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

IRI_Antenna_Descriptors Example

The IRI_Antenna_Descriptors example demonstrates how to use the Antenna Descriptors functionality of the modules, which allows physical or logical antennas to have their own unique key configurations, using the key E_IPJ_KEY_ANTENNA_DESCRIPTORS.

IRI_Antenna_Descriptors - Source Code

IRI_Antenna_Descriptors source code is provided in IRI_Antenna_Descriptors.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This file is used to demo the antenna descriptors feature, 
   using per antenna transmit power as an example. Each logical antenna has
   its own unique transmit power value, and these logical antennas can
   correspond to either physical antennas on the device, or antennas switched
   to using the external antenna mux feature. */

#define ANTENNA_SEQUENCE_OPTION_PHYSICAL 0
#define ANTENNA_SEQUENCE_OPTION_LOGICAL  1
#define NUM_ANTENNA_DESCRIPTORS          16
#define KVP_PER_ANTENNA_DESCRIPTOR       4

#define IPJ_EXAMPLE_DURATION_MS 10000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Each key-value pair consists of 32 bits to specify the key, bank index,
   and value index, followed by 32 bits that specify the value to be set. */
typedef struct
{
    uint16_t key;
    uint8_t bank_index;
    uint8_t value_index;

    uint32_t value;

} antenna_descriptor_kvp;

antenna_descriptor_kvp antenna_descriptors[NUM_ANTENNA_DESCRIPTORS][KVP_PER_ANTENNA_DESCRIPTOR] =
{
    /* Antenna Descriptor 1 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1000},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 2 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1100},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 3 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1200},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 4 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1300},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 5 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1400},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 6 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1500},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },
    
    /* Antenna Descriptor 7 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1600},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 8 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1700},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 9 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1800},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 10 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 1900},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 11 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2000},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 12 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2100},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 13 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2150},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 14 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2200},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },
    
    /* Antenna Descriptor 15 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2250},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },

    /* Antenna Descriptor 16 */
    {
        {E_IPJ_KEY_ANTENNA_PHYSICAL_PORT, 0, 0, 1},
        {E_IPJ_KEY_ANTENNA_TX_POWER, 0, 0, 2300},
        {0, 0, 0, 0},
        {0, 0, 0, 0}
    },
};

ipj_error set_logical_antenna_sequence_option();
ipj_error set_antenna_descriptors();
uint32_t get_key_bank_index_value_index_encoding(uint16_t key, uint8_t bank_index, uint8_t value_index);
ipj_error set_antenna_sequence();


int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    error = set_antenna_sequence();
    IPJ_UTIL_RETURN_ON_ERROR(error, "set_antenna_sequence");

    error = set_logical_antenna_sequence_option();
    IPJ_UTIL_RETURN_ON_ERROR(error, "set_logical_antenna_sequence_option");

    error = set_antenna_descriptors();
    IPJ_UTIL_RETURN_ON_ERROR(error, "set_antenna_descriptors");

    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return error;
}

/* Setting the antenna sequence option to logical allows the antenna sequence
   key to be filled with logical antenna indexes, which do not have to
   correspond to physical antennas on the device. */
ipj_error set_logical_antenna_sequence_option()
{
    return ipj_set_value(
        &iri_device,
        E_IPJ_KEY_ANTENNA_SEQUENCE_OPTION,
        ANTENNA_SEQUENCE_OPTION_LOGICAL
    );
}

/* The antenna descriptor key consists of 16 banks of
   four key-value pairs. Each key value pair can be used
   to set the value of one other key when the associated
   antenna is to be switched to. */
ipj_error set_antenna_descriptors()
{
    ipj_error error;
    ipj_key_value key_value[16];
    unsigned int  key_value_count = 0;
    ipj_key_list  key_list;
    unsigned int  key_list_count = 1;
    unsigned int  i, j;

    memset(&key_value, 0, sizeof(key_value));
    memset(&key_list, 0, sizeof(key_list));

    key_list.has_key = true;
    key_list.key = E_IPJ_KEY_ANTENNA_DESCRIPTORS;

    key_list.list_count = 2 * KVP_PER_ANTENNA_DESCRIPTOR;

    key_list.has_bank_index = true;

    for(i = 0; i < NUM_ANTENNA_DESCRIPTORS; ++i)
    {
        key_list.bank_index = i;

        for(j = 0; j < KVP_PER_ANTENNA_DESCRIPTOR; ++j)
        {
            antenna_descriptor_kvp *kvp = &(antenna_descriptors[i][j]);

            key_list.list[(2*j)] = get_key_bank_index_value_index_encoding(
                kvp->key,
                kvp->bank_index,
                kvp->value_index
            );

            key_list.list[(2*j) + 1] = kvp->value;
        }

        error = ipj_bulk_set(&iri_device, &key_value[0], key_value_count, &key_list, key_list_count);

        if(error != E_IPJ_ERROR_SUCCESS)
        {
            break;
        }
    }

    return error;
}

/* Returns a 32 bit integer that contains the information specifying the key,
   bank index, and value index to set the value of. */
uint32_t get_key_bank_index_value_index_encoding(uint16_t key, uint8_t bank_index, uint8_t value_index)
{
    uint32_t result = key | ((bank_index & 0xff) << 16) | ((value_index & 0xff) << 24);

    return result;
}

ipj_error set_antenna_sequence()
{
    ipj_error error;
    ipj_key_value key_value[16];
    unsigned int  key_value_count = 0;
    ipj_key_list  key_list;
    unsigned int  key_list_count = 1;
    unsigned int  i;

    memset(&key_value, 0, sizeof(key_value));
    memset(&key_list, 0, sizeof(key_list));

    key_list_count = 1;
    key_list.key = E_IPJ_KEY_ANTENNA_SEQUENCE;
    key_list.list_count = NUM_ANTENNA_DESCRIPTORS;

    for(i = 0; i < key_list.list_count; ++i)
    {
        key_list.list[i] = i + 1;
    }

    error = ipj_bulk_set(&iri_device, &key_value[0], key_value_count, &key_list, key_list_count);

    return error;
}

IRI_Change_Baudrate Example

The IRI_Change_Baudrate example demonstrates how to change the baud rate of UART communication with an Indy Module.

IRI_Change_Baudrate - Source Code

IRI_Change_Baudrate source code is provided in IRI_Change_Baudrate.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This example illustrates the use of the change baud rate feature. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 250

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error;

    /* IRI Connection parameters */
    ipj_connection_params connection_params;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    printf("Setting Baud to 57600 and performing inventory\n");

    connection_params.serial.baudrate = E_IPJ_BAUD_RATE_BR57600;
    /* Change Baud rate to 57600 bps */
    error = ipj_modify_connection(
            &iri_device,
            E_IPJ_CONNECTION_TYPE_SERIAL,
            &connection_params);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_modify_connection");

    /* Perform inventory to test results of baud rate change */
    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

IRI_Empty Example

The IRI_Empty example is an empty program including the IRI library that can be used as the basis for a program communicating with an Indy Module.

IRI_Empty - Source Code

IRI_Empty source code is provided in IRI_Empty.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This file is place holder template to begin a new IRI application. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 1000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");


    /* YOUR CODE HERE */


    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return error;
}

IRI_External_Antenna_Mux Example

The IRI_External_Antenna_Mux example demonstrates how to use the External Antenna Mux functionality of the modules, which allows multiple antennas to be connected to a single antenna port by controlling an external antenna mux (RF switch) using the module GPIOs. This is configured specifically using the keys E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_ENABLE, E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_PHYSICAL_PORT, E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_NUM_ANTENNAS, and E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_DELAY_MICROSECONDS.

IRI_External_Antenna_Mux - Source Code

IRI_External_Antenna_Mux source code is provided in IRI_External_Antenna_Mux.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This file is used to demo the external antenna mux feature.
   The four GPIO pins are redirected to being used by the reader firmware
   to switch antennas using an external RF switch. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 2000

#define NUM_EXTERNAL_MUX_ANTENNAS 16

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

ipj_error enable_external_antenna_mux();
ipj_error disable_external_antenna_mux();

ipj_error config_external_antenna_mux(
    unsigned int num_antennas,
    unsigned int physical_port,
    unsigned int delay_microseconds
);

ipj_error set_antenna_sequence();

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    error = set_antenna_sequence();
    IPJ_UTIL_RETURN_ON_ERROR(error, "set_antenna_sequence");

    error = config_external_antenna_mux(NUM_EXTERNAL_MUX_ANTENNAS, 1, 0);
    IPJ_UTIL_RETURN_ON_ERROR(error, "config_external_antenna_mux");

    error = enable_external_antenna_mux();
    IPJ_UTIL_RETURN_ON_ERROR(error, "enable_external_antenna_mux");

    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return error;
}

ipj_error enable_external_antenna_mux()
{
    return ipj_set_value(
        &iri_device,
        E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_ENABLE,
        true
    );
}

ipj_error disable_external_antenna_mux()
{
    return ipj_set_value(
        &iri_device,
        E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_ENABLE,
        false
    );
}

ipj_error config_external_antenna_mux(
    unsigned int num_antennas,
    unsigned int physical_port,
    unsigned int delay_microseconds
)
{
    ipj_error error;

    error = ipj_set_value(&iri_device, E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_NUM_ANTENNAS, num_antennas);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_NUM_ANTENNAS");

    error = ipj_set_value(&iri_device, E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_PHYSICAL_PORT, physical_port);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value EXTERNAL_ANTENNA_MUX_PHYSICAL_PORT");

    error = ipj_set_value(&iri_device, E_IPJ_KEY_EXTERNAL_ANTENNA_MUX_DELAY_MICROSECONDS, delay_microseconds);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value EXTERNAL_ANTENNA_MUX_DELAY_MICROSECONDS");

    return error;
}

ipj_error set_antenna_sequence()
{
    ipj_error error;
    ipj_key_value key_value[16];
    unsigned int  key_value_count = 0;
    ipj_key_list  key_list;
    unsigned int  key_list_count = 1;
    unsigned int  i;

    memset(&key_value, 0, sizeof(key_value));
    memset(&key_list, 0, sizeof(key_list));

    key_list_count = 1;
    key_list.key = E_IPJ_KEY_ANTENNA_SEQUENCE;
    key_list.list_count = NUM_EXTERNAL_MUX_ANTENNAS;

    for(i = 0; i < key_list.list_count; ++i)
    {
        key_list.list[i] = i + 1;
    }

    error = ipj_bulk_set(&iri_device, &key_value[0], key_value_count, &key_list, key_list_count);

    return error;
}

IRI_GPIO Example

The IRI_GPIO example demonstrates how to use Indy Modules’ GPIOs as inputs and outputs, including triggering inventories.

IRI_GPIO - Source Code

IRI_GPIO source code is provided in IRI_GPIO.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/

/* NOTE: For this example, you will need to jumper GPIO0 to GPIO1 */
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"
#include "platform.h"

/* PURPOSE: This example illustrates the use GPIOs to initiate an inventory
   operation.  It also has an example of how to override the stop_handler
   versus using the default handler. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 5000

/* Declare local report handlers */
static ipj_error report_handler(
        ipj_iri_device* iri_device,
        ipj_report_id report_id,
        void* report);

static ipj_error stop_report_handler(
        ipj_iri_device* iri_device,
        ipj_stop_report* ipj_stop_report);

static uint32_t ipj_stopped_flag;

static struct ipj_handler event_handlers[] =
{
    { E_IPJ_HANDLER_TYPE_REPORT, &report_handler }
};

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

ipj_error register_handlers(ipj_iri_device* iri_device)
{
    ipj_error error;
    unsigned int i;
    for (i = 0; i < (sizeof(event_handlers) / sizeof(event_handlers[0])); i++)
    {
        error = ipj_register_handler(
                iri_device,
                event_handlers[i].type,
                event_handlers[i].handler);
        if (error)
        {
            return error;
        }
    }
    return E_IPJ_ERROR_SUCCESS;
}

static ipj_error perform_gpio_triggered_inventory(
        ipj_iri_device* iri_device,
        uint32_t timeout_ms)
{
    uint32_t end_time_ms;
    ipj_error error;
    ipj_key_value key_value[16];
    uint32_t key_value_count = 0;

    IPJ_CLEAR_STRUCT(key_value);

    /* GPIO 1 as output resting low*/
    key_value[0].key = E_IPJ_KEY_GPIO_MODE;
    key_value[0].value = E_IPJ_GPIO_MODE_OUTPUT;
    key_value[0].bank_index = 1;
    key_value_count++;

    key_value[1].key = E_IPJ_KEY_GPIO_STATE;
    key_value[1].value = E_IPJ_GPIO_STATE_LO;
    key_value[1].bank_index = 1;
    key_value_count++;

    /* GPIO2 as floating input with attached actions */
    key_value[2].key = E_IPJ_KEY_GPIO_MODE;
    key_value[2].value = E_IPJ_GPIO_MODE_INPUT_ACTION;
    key_value[2].bank_index = 2;
    key_value_count++;

    key_value[3].key = E_IPJ_KEY_GPIO_STATE;
    key_value[3].value = E_IPJ_GPIO_STATE_FLOAT;
    key_value[3].bank_index = 2;
    key_value_count++;

    key_value[4].key = E_IPJ_KEY_GPIO_HI_ACTION;
    key_value[4].value = E_IPJ_GPI_ACTION_START_INVENTORY;
    key_value[4].bank_index = 2;
    key_value_count++;

    key_value[5].key = E_IPJ_KEY_GPIO_LO_ACTION;
    key_value[5].value = E_IPJ_GPI_ACTION_STOP_INVENTORY;
    key_value[5].bank_index = 2;
    key_value_count++;

    /* Set the keys */
    error = ipj_bulk_set(iri_device, &key_value[0], key_value_count, NULL, 0);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_bulk_set");

    /* start the GPIO set up */
    error = ipj_start(iri_device, E_IPJ_ACTION_GPIO);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_start E_IPJ_ACTION_GPIO");

    /* set GPIO1 high */
    error = ipj_set(iri_device, E_IPJ_KEY_GPIO_STATE, 1, 0, E_IPJ_GPIO_STATE_HI);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set E_IPJ_KEY_GPIO_STATE");

    /* Set example end time */
    end_time_ms = platform_timestamp_ms_handler() + timeout_ms;

    /*  Perform receive until end time reached */
    while (platform_timestamp_ms_handler() < end_time_ms)
    {
        /* Call ipj_receive to process tag reports  */
        error = ipj_receive(iri_device);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_receive");
    }

    /* Set GPIO1 Low  & Stop inventory  */
    error = ipj_set(iri_device, E_IPJ_KEY_GPIO_STATE, 1, 0, E_IPJ_GPIO_STATE_LO);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set E_IPJ_KEY_GPIO_STATE");

    error = ipj_stop(iri_device, E_IPJ_ACTION_GPIO);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_stop E_IPJ_ACTION_GPIO");

    /* Set stop end time */
    end_time_ms = platform_timestamp_ms_handler() + timeout_ms;

    /*  Collect the last few tags and look for the stop report */
    while (!ipj_stopped_flag && platform_timestamp_ms_handler() < end_time_ms)
    {
        /* Call ipj_receive to process tag reports  */
        error = ipj_receive(iri_device);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_receive");
    }
    return E_IPJ_ERROR_SUCCESS;
}

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error;

    uint32_t end_message_ms;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /*
     * Override the report handler so the local stop_handler can be called and
     * stop perform_gpio_triggered_inventory
     */
    register_handlers(&iri_device);

    /* Display a message to the user for ~5 seconds */
    end_message_ms = platform_timestamp_ms_handler() + 5000;
    printf("Please jump GPIO1 to GPIO2 for this demonstration\n");
    while (platform_timestamp_ms_handler() < end_message_ms)
    {
        /* Do nothing */
    }

    /* Start inventory */
    error = perform_gpio_triggered_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "perform_gpio_triggered_inventory");

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

/* Report handler processes asynchronous reports */
static ipj_error report_handler(
        ipj_iri_device* iri_device,
        ipj_report_id report_id,
        void* report)
{
    ipj_error error = E_IPJ_ERROR_SUCCESS;
    /* Case statement for each report type */
    switch (report_id)
    {
        case E_IPJ_REPORT_ID_TAG_OPERATION_REPORT:
            error = ipj_util_tag_operation_report_handler(
                    iri_device,
                    (ipj_tag_operation_report*) report);
            break;
        case E_IPJ_REPORT_ID_STOP_REPORT:
            error = stop_report_handler(iri_device, (ipj_stop_report*) report);
            break;
        case E_IPJ_REPORT_ID_GPIO_REPORT:
            error = ipj_util_gpio_report_handler(
                    iri_device,
                    (ipj_gpio_report*) report);
            break;
        default:
            printf(
                    "%s: REPORT ID: %d NOT HANDLED\n",
                    (char*) iri_device->reader_identifier,
                    report_id);
            error = E_IPJ_ERROR_GENERAL_ERROR;
            break;
    }
    return error;
}

/* Stop report handler processes asynchronous reports */
static ipj_error stop_report_handler(
        ipj_iri_device* iri_device,
        ipj_stop_report* ipj_stop_report)
{
    if (ipj_stop_report->error == E_IPJ_ERROR_SUCCESS)
    {
        /* Print reader identifier */
        printf("%s: STOPPED\n", (char*) iri_device->reader_identifier);

        /* Set the stopped flag, the stop report does not have any fields that
         * need to be checked */
        ipj_stopped_flag = 1;
    }
    else
    {
        IPJ_UTIL_PRINT_ERROR(ipj_stop_report->error,"stop_report");
    }
    return ipj_stop_report->error;
}

IRI_Loader Example

The IRI_Loader example demonstrates how to load a firmware image into an Indy Module using the IRI host library.

IRI_Loader - Source Code

IRI_Loader source code is provided in IRI_Loader.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#if defined(__GNUC__)
    #include <unistd.h>
#else
    #include <io.h>
#endif
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This example illustrates the use of the image loader to download
   firmware to the device. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 1000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error;

    /* Storage buffer for device read */
    uint8_t file_buf[300];
    FILE* image_file_handle;

    int chunk_size;

    /* connection parameters */
    ipj_connection_params params;

    /* High speed flag */
    bool high_speed = false;

    if ((argc < 3) || (argc > 4))
    {
        printf("\n\nUsage:"
                "\n\tIRI_Loader.exe COMx <image_location> [-s] \n"
                "where: \n"
                "\tx is a COM port number\n"
                "\t<image_location> is an absolute path\n"
                "\t-s for high speed 921600 baud update (optional)\n");
        return -1;
    }

    /* Determine if we're in high speed mode or not */
    if ((argc == 4) && (strcmp(argv[3], "-s") == 0))
    {
        high_speed = true;
    }

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /* Put the device in bootloader mode */
    error = ipj_reset(&iri_device, E_IPJ_RESET_TYPE_TO_BOOTLOADER);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_reset E_IPJ_RESET_TYPE_TO_BOOTLOADER");

    if (high_speed)
    {
        /* Speed up the upgrade process */

        /* Perform a modify connection command to bring the device
         * and host up to 921600 baud */
        params.serial.baudrate = E_IPJ_BAUD_RATE_BR921600;
        params.serial.parity = E_IPJ_PARITY_PNONE;

        error = ipj_modify_connection(&iri_device,
        E_IPJ_CONNECTION_TYPE_SERIAL, &params);
        if (error)
        {
            printf("Unable to change baud rate");
            return -1;
        }
    }

#if defined(__GNUC__)
    image_file_handle = fopen(argv[2], "rb");
#else
    fopen_s(&image_file_handle, argv[2], "rb");
#endif

    if (image_file_handle == NULL)
    {
        printf("Unable to open image file\n");
        return -1;
    }

    /* Get the image chunk size.  This is stored in the first 32 bits
     * of the upgrade image */
    if (fread(file_buf, 4, 1, image_file_handle) == 0)
    {
        printf("Unable to determine chunk size\n");
        return -1;
    }

    chunk_size = (file_buf[0] & 0xff) | (file_buf[1] << 8) | (file_buf[2] << 16)
            | (file_buf[3] << 24);

    printf("Image chunk size: %d\n", chunk_size);
    printf(
            "(%d bytes header | %d bytes payload | 2 bytes CRC)\n",
            12,
            (chunk_size - 2) - 12);

    if (chunk_size < 22 || chunk_size > 270)
    {
        printf("Invalid chunk size\n");
        return -1;
    }

    /* For each chunk in the image file, write it to the RS500 */
    while (fread(file_buf, chunk_size, 1, image_file_handle) > 0)
    {
        error = ipj_flash_handle_loader_block(&iri_device, chunk_size, file_buf);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_flash_handle_loader_block");
    }

    printf("Image load complete\n");

    if (high_speed)
    {
        /* Return to our previous baud rate */
        params.serial.baudrate = E_IPJ_BAUD_RATE_BR115200;
        error = ipj_modify_connection(&iri_device,
        E_IPJ_CONNECTION_TYPE_SERIAL, &params);
        if (error)
        {
            printf("Unable to change baud rate");
            return -1;
        }
    }

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

IRI_Multiple_Readers Example

The IRI_Multiple_Readers example connects to multiple Indy Modules and performs basic inventory using both.

IRI_Multiple_Readers - Source Code

IRI_Multiple_Readers source code is provided in IRI_Multiple_Readers.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"
#include "platform.h"

/* PURPOSE: This example illustrates the use of multiple readers from one
   application. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 1000
#define MAX_READERS 5

/* Declare local report handlers */
static ipj_error report_handler(
        ipj_iri_device* iri_device,
        ipj_report_id report_id,
        void* report);

static ipj_error stop_report_handler(
        ipj_iri_device* iri_device,
        ipj_stop_report* ipj_stop_report);

/* Allocate memory for iri device */
static ipj_iri_device iri_devices[MAX_READERS];

static uint32_t ipj_stopped_flags[MAX_READERS];

static struct ipj_handler event_handlers[] =
{
    { E_IPJ_HANDLER_TYPE_REPORT, &report_handler }
};

static ipj_error register_handlers(ipj_iri_device* iri_device)
{
    ipj_error error;
    unsigned int i;
    for (i = 0; i < (sizeof(event_handlers) / sizeof(event_handlers[0])); i++)
    {
        error = ipj_register_handler(
                iri_device,
                event_handlers[i].type,
                event_handlers[i].handler);
        if (error)
        {
            return error;
        }
    }
    return E_IPJ_ERROR_SUCCESS;
}

static ipj_error perform_inventory(int num_readers, uint32_t timeout_ms)
{
    uint32_t end_time_ms;
    ipj_error error;
    int i;
    bool all_stopped_flag = false;

    for (i = 0; i < num_readers; i++)
    {
        ipj_stopped_flags[i] = 0x00;
        error = ipj_start(&iri_devices[i], E_IPJ_ACTION_INVENTORY);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_start E_IPJ_ACTION_INVENTORY");
    }

    /* Set example end time */
    end_time_ms = platform_timestamp_ms_handler() + timeout_ms;

    /*  Perform receive until end time reached */
    while (platform_timestamp_ms_handler() < end_time_ms)
    {
        for (i = 0; i < num_readers; i++)
        {
            /* Call ipj_receive to process tag reports  */
            error = ipj_receive(&iri_devices[i]);
            IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_receive");
        }
    }

    for (i = 0; i < num_readers; i++)
    {
        /* Stop inventory  */
        error = ipj_stop(&iri_devices[i], E_IPJ_ACTION_INVENTORY);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_stop");
    }

    /* Set stop end time */
    end_time_ms = platform_timestamp_ms_handler() + timeout_ms;

    while (!all_stopped_flag && platform_timestamp_ms_handler() < end_time_ms)
    {
        for (i = 0; i < num_readers; i++)
        {
            /*  Collect the last few tags and look for the stop report */
            if (!ipj_stopped_flags[i])
            {
                /* Call ipj_receive to process tag reports  */
                error = ipj_receive(&iri_devices[i]);
                IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_receive");
            }
            all_stopped_flag &= ipj_stopped_flags[i];
        }
    }
    return E_IPJ_ERROR_SUCCESS;
}

/* Main */
int main(int argc, char* argv[])
{
    /* Loop placeholder */
    int i;

    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    if (argc < 2)
    {
        printf(
                "\n\nUsage:\t%s COMx COMy...COMz \n\nwhere x/y/z is a COM port number (Maximum 5 readers)\n\n",
                argv[0]);
        return -1;
    }

    /* Loop through all of the devices we've supplied and set them up */
    for (i = 0; i < argc - 1; i++)
    {
        /* Common example setup */
        error = ipj_util_setup(&iri_devices[i], argv[1 + i]);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

        /*
         * Override the report handler so the local stop_handler can be called
         */
        register_handlers(&iri_devices[i]);
    }

    /* Start and run inventory with all devices for the specified
     * duration */
    error = perform_inventory(argc - 1, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "perform_inventory");

    /* Loop through and disconnect/deinit each iri_device */
    for (i = 0; i < argc - 1; i++)
    {
        /* Common example cleanup */
        error = ipj_util_cleanup(&iri_devices[i]);
        IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");
    }
    return error;
}

/* Report handler processes asynchronous reports */
static ipj_error report_handler(
        ipj_iri_device* iri_device,
        ipj_report_id report_id,
        void* report)
{
    ipj_error error = E_IPJ_ERROR_SUCCESS;
    /* Case statement for each report type */
    switch (report_id)
    {
        case E_IPJ_REPORT_ID_TAG_OPERATION_REPORT:
            error = ipj_util_tag_operation_report_handler(
                    iri_device,
                    (ipj_tag_operation_report*) report);
            break;
        case E_IPJ_REPORT_ID_STOP_REPORT:
            error = stop_report_handler(iri_device, (ipj_stop_report*) report);
            break;
        case E_IPJ_REPORT_ID_GPIO_REPORT:
            error = ipj_util_gpio_report_handler(
                    iri_device,
                    (ipj_gpio_report*) report);
            break;
        default:
            printf(
                    "%s: REPORT ID: %d NOT HANDLED\n",
                    (char*) iri_device->reader_identifier,
                    report_id);
            error = E_IPJ_ERROR_GENERAL_ERROR;
            break;
    }
    return error;
}

/* Tag report handler processes asynchronous reports */
static ipj_error stop_report_handler(
        ipj_iri_device* iri_device,
        ipj_stop_report* ipj_stop_report)
{
    int i;
    if (ipj_stop_report->error == E_IPJ_ERROR_SUCCESS)
    {
        /* Print reader identifier */
        printf("%s: STOPPED\n", (char*) iri_device->reader_identifier);

        /* Set the stopped flag, the stop report does not have any fields that
         * need to be checked */
        for (i = 0; i < MAX_READERS; i++)
        {
            if (&iri_devices[i] == iri_device)
            {
                ipj_stopped_flags[i] = 1;
            }
        }
    }
    else
    {
        printf("IPJ_STOP Error. Error Code:%x\n\n", ipj_stop_report->error);
    }
    return ipj_stop_report->error;
}

IRI_Power_Management Example

The IRI_Power_Management example demonstrates changing Indy Module power modes using the IRI host library.

IRI_Power_Management - Source Code

IRI_Power_Management source code is provided in IRI_Power_Management.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"
#include "platform.h"

/* PURPOSE: This example illustrates the use of the power management modes. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 1000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

static ipj_error sleep_ms(uint32_t sleep_time_ms)
{
    uint32_t end_time_ms = platform_timestamp_ms_handler() + sleep_time_ms;
    printf("Sleeping for %d milliseconds\n", sleep_time_ms);

    while (platform_timestamp_ms_handler() < end_time_ms)
        ;
    return E_IPJ_ERROR_SUCCESS;
}

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error = E_IPJ_ERROR_SUCCESS;
    uint32_t val = 0;
    int retries = 10;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /* Configure transmit power */
    error = ipj_set_value(&iri_device, E_IPJ_KEY_ANTENNA_TX_POWER, 2300);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value E_IPJ_KEY_ANTENNA_TX_POWER");

    /* Start inventory */
    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    /* Put the device into standby mode */
    error = ipj_start(&iri_device, E_IPJ_ACTION_STANDBY);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_start E_IPJ_ACTION_STANDBY");

    /* Sleep for 5 seconds */
    sleep_ms(5000);

    printf("Attempting to wake RS500\n");

    /* Set the receive timeout MS to a lower number (100ms) */
    error = ipj_set_receive_timeout_ms(&iri_device, 100);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_receive_timeout_ms");

    /* Spin on IPJ_GET_VALUE (any key will do) until the device responds */
    do
    {
        error = ipj_get_value(&iri_device, E_IPJ_KEY_ANTENNA_TX_POWER, &val);
    } while (error && retries--);
    IPJ_UTIL_RETURN_ON_ERROR(error, "Wake RS500");

    printf("Successfully woke RS500\n");
    printf("Performing Inventory to check for full functionality\n");

    /* Reset the timeout to it's default value */
    error = ipj_set_receive_timeout_ms(&iri_device, IPJ_DEFAULT_RECEIVE_TIMEOUT_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_receive_timeout_ms");

    /* Perform second inventory */
    error = ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_perform_inventory");

    printf("Inventory Successful, putting device into sleep mode\n");
    error = ipj_start(&iri_device, E_IPJ_ACTION_SLEEP);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_start E_IPJ_ACTION_SLEEP");

    printf("Successfully put device into sleep.  To wake:\n");
    printf("Jump WKUP to VCC -or- press the reset button\n");

    /* Disconnect IRI device & close serial port */
    error = ipj_disconnect(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_disconnect");

    /* Deinitialize IRI device */
    error = ipj_deinitialize_iri_device(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_deinitialize_iri_device");

    return error;
}

IRI_Select Example

The IRI_Select example demonstrates how to use the Select tag operation to inventory only tags with a certain TID.

This example can be easily modified to select based on EPC as well by changing the E_IPJ_KEY_SELECT_MEM_BANK and E_IPJ_KEY_SELECT_POINTER keys.

IRI_Select - Source Code

IRI_Select source code is provided in IRI_Select.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"

/* PURPOSE: This example illustrates the use of Gen2 Select operation. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 250

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* This select command will cause only tags with a TID starting with
 * 0xe280 to set their select flags  */
static ipj_error setup_select_1(ipj_iri_device* iri_device)
{
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_ENABLE, 0, 0, true);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_TARGET, 0, 0,
    E_IPJ_SELECT_TARGET_SL_FLAG);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_ACTION, 0, 0,
    E_IPJ_SELECT_ACTION_ASLINVA_DSLINVB);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MEM_BANK, 0, 0,
    E_IPJ_MEM_BANK_TID);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_POINTER, 0, 0, 0x0);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MASK_LENGTH, 0, 0, 16);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MASK_VALUE, 0, 0, 0xE280);

    return error;
}

/* This select command will cause only tags with 1 at bit 19
 to maintain their select flag, else their SL flag will de-assert.
 This causes and AND effect with the first select.
 The 2 selects combined will select Monza4/5 tags*/
static ipj_error setup_select_2(ipj_iri_device* iri_device)
{
    ipj_error error = E_IPJ_ERROR_SUCCESS;

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_ENABLE, 1, 0, true);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_TARGET, 1, 0,
    E_IPJ_SELECT_TARGET_SL_FLAG);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_ACTION, 1, 0,
    E_IPJ_SELECT_ACTION_NOTHING_DSLINVB);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MEM_BANK, 1, 0,
    E_IPJ_MEM_BANK_TID);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_POINTER, 1, 0, 19);

    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MASK_LENGTH, 1, 0, 1);

    /* Note: When the mod of the length is less than 16, the MSBs
     of the mask are used.  So for 1 bit length, the msb of the
     mask (bit 15) is the mask and the LSBs are ignored. */
    error |= ipj_set(iri_device,
    E_IPJ_KEY_SELECT_MASK_VALUE, 1, 0, 0x8000);

    return error;
}

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    printf("Sending Select Command for Monza4/5 tags (TID = 0xE280.1xxx)\n");
    /* Send Select Command */
    error = setup_select_1(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "setup_select_1");

    error = setup_select_2(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "setup_select_2");

    /*
     * NOTE: In this example, we target the SL flag, hence setting it
     * here.  Your Select use case may or may not require this.
     * Please refer to the GEN2 spec for details
     */
    error = ipj_set_value(&iri_device, E_IPJ_KEY_INVENTORY_SELECT_FLAG, E_IPJ_INVENTORY_SELECT_FLAG_SL);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value E_IPJ_KEY_INVENTORY_SELECT_FLAG");

    error = ipj_set_value(&iri_device, E_IPJ_KEY_TAG_OPERATION, 0);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_set_value E_IPJ_KEY_TAG_OPERATION");

    /* Perform inventory to see results of EPC write */
    ipj_util_perform_inventory(&iri_device, IPJ_EXAMPLE_DURATION_MS);

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

IRI_Test_CW_PRBS Example

The IRI_Test_CW_PRBS example demonstrates how to use some of the IRI host library test commands, such as CW (Continuous Wave) and PRBS (Pseudo-Random Bit Sequence).

IRI_Test_CW_PRBS - Source Code

IRI_Test_CW_PRBS source code is provided in IRI_Test_CW_PRBS.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/
#include <stdio.h>
#include <string.h>
#include "ipj_util.h"
#include "iri.h"
#include "platform.h"

/* PURPOSE: This example illustrates the use of the test commands to control
   the CW (Continuous Wave) and PRBS (Pseudo-Random Bit Sequence) functions. */

/* Parameters */
#define IPJ_EXAMPLE_DURATION_MS 10000

/* Allocate memory for iri device */
static ipj_iri_device iri_device = { 0 };

/* Main */
int main(int argc, char* argv[])
{
    /* Define error code */
    ipj_error error;

    IPJ_UTIL_CHECK_USER_INPUT_FOR_COM_PORT_RETURN_ON_ERROR()

    /* Common example setup */
    error = ipj_util_setup(&iri_device, argv[1]);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_setup");

    /* Set frequency to 912.25 MHz (specified in kHz)*/
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_SET_FREQUENCY, 912250, 0, 0, 0);

    /* Enable CW */
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_CW_CONTROL, 1, 0, 0, 0);

    /* Leave CW on for 1 second */
    platform_sleep_ms_handler(1000);

    /* Disable CW */
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_CW_CONTROL, 0, 0, 0, 0);

    /* Set frequency to 912.75 MHz (specified in kHz)*/
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_SET_FREQUENCY, 912750, 0, 0, 0);

    /* Enable PRBS */
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_PRBS_CONTROL, 1, 0, 0, 0);

    /* Leave PRBS on for 1 second */
    platform_sleep_ms_handler(1000);

    /* Disable PRBS */
    ipj_util_test_command(&iri_device, E_IPJ_TEST_ID_PRBS_CONTROL, 0, 0, 0, 0);

    /* Common example cleanup */
    error = ipj_util_cleanup(&iri_device);
    IPJ_UTIL_RETURN_ON_ERROR(error, "ipj_util_cleanup");

    return 0;
}

Platform Port Examples

The platform source code is common between all of the examples, although it differs for each host platform.

Platform source code is provided in the platform_*.c files.

For example, here is platform_win32.c :

/*
 *****************************************************************************
 * Copyright 2016-2017 Impinj, Inc.                                          *
 *                                                                           *
 * Licensed under the Apache License, Version 2.0 (the "License");           *
 * you may not use this file except in compliance with the License.          *
 * You may obtain a copy of the License at                                   *
 *                                                                           *
 * http://www.apache.org/licenses/LICENSE-2.0                                *
 *                                                                           *
 * Unless required by applicable law or agreed to in writing, software       *
 * distributed under the License is distributed on an "AS IS" BASIS,         *
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 * See the License for the specific language governing permissions and       *
 * limitations under the License.                                            *
 *****************************************************************************/

#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include "platform.h"
#include "iri.h"

/* PLATFORM_OPEN_PORT_HANDLER */
uint32_t platform_open_port_handler(IPJ_READER_CONTEXT* reader_context,
                                    IPJ_READER_IDENTIFIER reader_identifier,
                                    ipj_connection_type connection_type,
                                    ipj_connection_params* params)
{
    HANDLE h_port;
    DCB dcb;
    COMMTIMEOUTS commtimeouts;

    uint32_t result;
    char port_name[30];

    /* we currently only support serial */
    (void)connection_type;

    /* Map reader_identifier to COM port name */
#if defined(__GNUC__)
    strcpy(port_name, "\\\\.\\");
    strcat(port_name, (char*)reader_identifier);
#else /* Visual Studio/Intel/etc */
    strcpy_s(port_name, sizeof(port_name), "\\\\.\\");
    strcat_s(port_name, sizeof(port_name), (char*)reader_identifier);
#endif

    /* Open serial port */
    h_port = CreateFileA(port_name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    /* Return error if invalid handle */
    if ((h_port == INVALID_HANDLE_VALUE))
    {
        return 0;
    }

    /* Get default serial port parameters */
    dcb.DCBlength = sizeof(dcb);
    result = GetCommState(h_port, &dcb);

    /* Return error if unsuccessful getting serial port parameters */
    if (!result)
    {
        return 0;
    }

    /* Modify serial port parameters */
    if(!params)
    {
        return 0;
    }
    else
    {
        dcb.BaudRate = params->serial.baudrate;
        switch(params->serial.parity)
        {
            case E_IPJ_PARITY_PODD:
            {
                dcb.Parity = ODDPARITY;
                break;
            }
            case E_IPJ_PARITY_PEVEN:
            {
                dcb.Parity = EVENPARITY;
                break;
            }
            default: /* Fall through */
            case E_IPJ_PARITY_PNONE:
            {
                dcb.Parity = NOPARITY;
                break;
            }
        }
    }
    dcb.ByteSize = 8;
    dcb.StopBits = ONESTOPBIT;
    dcb.fParity  = false;
    dcb.fOutX    = false;
    dcb.fInX     = false;
    dcb.fNull    = false;
    dcb.fDtrControl = DTR_CONTROL_ENABLE;
    dcb.fRtsControl = RTS_CONTROL_ENABLE;

    /* Set serial port parameters */
    result = SetCommState(h_port, &dcb);

    /* Return error if unsuccessful setting serial port parameters */
    if (!result)
    {
        return 0;
    }

    /* Get timeout values */
    result = GetCommTimeouts(h_port, &commtimeouts);

    // Return error if unsuccessful getting serial port timeout parameters */
    if (!result)
    {
        return 0;
    }

    /* Modify timeout values */
    commtimeouts.ReadIntervalTimeout         = 0;
    commtimeouts.ReadTotalTimeoutConstant    = PLATOFRM_DEFAULT_READ_TIMEOUT_MS;
    commtimeouts.ReadTotalTimeoutMultiplier  = 0;
    commtimeouts.WriteTotalTimeoutConstant   = PLATFORM_DEFAULT_WRITE_TIMEOUT_MS;
    commtimeouts.WriteTotalTimeoutMultiplier = 0;

    /* Set timeout values */
    result = SetCommTimeouts(h_port, &commtimeouts);

    if(!result)
    {
        return 0;
    }

    /* Assign serial port handle to reader context */
    *reader_context = (IPJ_READER_CONTEXT)h_port;
    return 1;
}

/* PLATFORM_CLOSE_PORT_HANDLER */
uint32_t platform_close_port_handler(IPJ_READER_CONTEXT reader_context)
{
    uint32_t result;

    /* Close reader handle */
    result = CloseHandle((HANDLE)reader_context);

    if(!result)
    {
        return 0;
    }

    return 1;
}

/*
 * PLATFORM_TRANSMIT_HANDLER
 *
 * Return: 1: Success, 0:Fail
 */
uint32_t platform_transmit_handler(IPJ_READER_CONTEXT reader_context, uint8_t* message_buffer, uint16_t  buffer_size,
                                   uint16_t* number_bytes_transmitted)
{
    uint32_t result;
    DWORD dw_bytes_written = 0;

    /* Write serial port */
    result = WriteFile((HANDLE)reader_context, message_buffer, buffer_size, &dw_bytes_written, NULL);
    if (!result)
    {
        /* Fail */
        return 0;
    }
    else
    {
        /* Success */
        /* Assign number of bytes transmitted */
        *number_bytes_transmitted = (uint16_t)dw_bytes_written;
        return 1;
    }
}

/* PLATFORM_RECEIVE_HANDLER */
uint32_t platform_receive_handler(IPJ_READER_CONTEXT reader_context, uint8_t* message_buffer, uint16_t buffer_size,
                                  uint16_t* number_bytes_received, uint16_t timeout_ms)
{
    uint32_t result;
    DWORD dw_bytes_received = 0;
    COMMTIMEOUTS commtimeouts;

    /* Get timeout values */
    result = GetCommTimeouts((HANDLE)reader_context, &commtimeouts);

    /* Return error if unsuccessful getting serial port timeout parameters */
    if (!result)
    {
        return 0;
    }

    /* Modify timeout values */
    if (timeout_ms == 0)
    {
        commtimeouts.ReadIntervalTimeout = MAXDWORD;
        commtimeouts.ReadTotalTimeoutConstant = 1;
    }
    else
    {
        commtimeouts.ReadIntervalTimeout = timeout_ms;
        commtimeouts.ReadTotalTimeoutConstant = 1;
    }

    /* Set timeout values */
    result = SetCommTimeouts((HANDLE)reader_context, &commtimeouts);

    /* Return if error if unsuccessful setting timeout parameters */
    if(!result)
    {
        return 0;
    }

    /* Read serial port */
    result = ReadFile((HANDLE)reader_context, message_buffer, buffer_size, &dw_bytes_received, NULL);
    if (result)
    {
        /* Assign bytes received */
        *number_bytes_received = (uint16_t)dw_bytes_received;
         return 1;
    }
    else
    {
        return 0;
    }
}

/* PLATFORM_TIMESTAMP_HANDLER */
uint32_t platform_timestamp_ms_handler()
{
    DWORD timestamp_ms = timeGetTime();

    return (uint32_t)timestamp_ms;
}

void platform_sleep_ms_handler(uint32_t milliseconds)
{
    Sleep(milliseconds);
}

uint32_t platform_flush_port_handler(IPJ_READER_CONTEXT reader_context)
{
    int result;

    result = PurgeComm((HANDLE)reader_context, PURGE_RXCLEAR | PURGE_TXCLEAR);

    return result == 0 ? 1 : 0;
}

uint32_t platform_reset_pin_handler(IPJ_READER_CONTEXT reader_context,
                                    bool enable)
{
    int action = enable ? SETDTR : CLRDTR;
    int result = EscapeCommFunction((HANDLE)reader_context, action);
    return result == 0 ? 1 : 0;
}

uint32_t platform_wakeup_pin_handler(IPJ_READER_CONTEXT reader_context,
                                     bool enable)
{
    int action = enable ? SETRTS : CLRRTS;
    int result = EscapeCommFunction((HANDLE)reader_context, action);
    return result == 0 ? 1 : 0;
}


uint32_t platform_modify_connection_handler(IPJ_READER_CONTEXT reader_context,
                                            ipj_connection_type connection_type,
                                            ipj_connection_params* params)
{
    DCB dcb;
    int result;

    switch(connection_type)
    {
        /* For all serial operations */
        case E_IPJ_CONNECTION_TYPE_SERIAL:
        {
            /* Get serial port parameters */
            result = GetCommState((HANDLE)reader_context, &dcb);
            if (!result)
            {
                return 1;
            }
            /* Set the new baudrate */
            dcb.BaudRate = (DWORD)params->serial.baudrate;

            switch(params->serial.parity)
            {
                case E_IPJ_PARITY_PODD:
                {
                    dcb.Parity = ODDPARITY;
                    break;
                }
                case E_IPJ_PARITY_PEVEN:
                {
                    dcb.Parity = EVENPARITY;
                    break;
                }
                default: /* Fall through */
                case E_IPJ_PARITY_PNONE:
                {
                    dcb.Parity = NOPARITY;
                    break;
                }
            }

            result = SetCommState((HANDLE)reader_context, &dcb);
            if (!result)
            {
                return 1;
            }
            return 0;
        }
        default:
        {
            return 0;
        }
    }
}