The ITK-C host library is designed to be run in embedded systems. Embedded systems cover a wide range of platforms and, as such, have a wide variety of system resources available. In some memory constrained applications the system ROM and RAM requirements of the ITK-C may prove to be too great.
To address these applications, the ITK-LT-C has been designed with a subset of the IRI API and features. The result is a small host library with a reduced RAM and ROM footprint with reader functionality that can enable many applications.
For more details on the differences between the ITK-C and ITK-LT-C, see the ITK Differences section of the FAQ.
Important
ITK-LT-C should only be used if the the standard ITK-C can not be used due to host memory constraints. The ITK-C is extensible and enables future advanced features.
As a general rule all documentation for the ITK-C applies to ITK-LT-C. The differences are detailed in the sections below.
The following table lists verified ITK-LT-C host platforms and corresponding library sizes.
Notes:
If you have questions please submit a support ticket at support.impinj.com .
Library | Build Machine | Target Platform | Target Architecture | Target Processor | Toolchain | Optimizations | Library Contents | Size (Bytes) |
---|---|---|---|---|---|---|---|---|
ITK-LT-C | Windows 7 + Cygwin | Windows | 32-bit | x86 | GCC 4.5.3 | For size (-Os) | iri_lt.o | 1,412 |
ITK-LT-C | CentOS 6.5 | Linux | 32-bit | x86 | GCC 4.4.7 | For size (-Os) | iri_lt.o | 1,248 |
ITK-LT-C | Apple Mac 10.9.2 | OSX | 32-bit | x86 | GCC (Apple LLVM 5.1 - Clang 503.0.40) | For size (-Os) | iri_lt.o | 1,362 |
ITK-LT-C | Windows 7 + GCC ARM Embedded for Windows | STM32F0DISCOVERY Board | 32-bit | ARM Cortex-M0 (STM32F051) | GCC ARM Embedded 4.8.3 | For size (-Os) | iri_lt.o | 1,016 |
ITK-LT-C | Windows 7 + Code Composer Studio 6 | MSP430FG4618/F2013 Experimenter’s Board | 16-bit | TI MSP430 (MSP430FG4618) | TI Compiler 4.3.1 | Level 4, for size | iri_lt.obj | 1,508 |
ITK-LT-C | Windows 7 + AtmelStudio 6.1 | AVR XMEGA-A1 Xplained | 8-bit | Atmel AVR (ATxmega128A1) | AVR/GNU C Compiler 4.7.3 | For size (-Os) | iri_lt.o | 2,229 |
Source code is provided for the ITK-LT-C library and example applications. This will enable users to port the IRI library as needed and to get a jump start on writing code for their own specific applications.
ITK_LT_C\Library\config.h
ITK_LT_C\Library\iri_lt.c
ITK_LT_C\Library\iri_lt.h
ITK_LT_C\Library\platform.h
ITK_LT_C\Library\platform_empty.c
ITK_LT_C\Library\platform_linux.c
ITK_LT_C\Library\platform_osx.c
ITK_LT_C\Library\platform_win32.c
ITK_LT_C\Library\PORTING.txt
ITK_LT_C\Library\version.h
ITK_LT_C\Examples\ipj_util_lt.c
ITK_LT_C\Examples\ipj_util_lt.h
ITK_LT_C\Examples\IRI_LT_Access.c
ITK_LT_C\Examples\IRI_LT_Empty.c
ITK_LT_C\Examples\IRI_LT_GPIO.c
ITK_LT_C\Examples\IRI_LT_Intro.c
ITK_LT_C\Examples\IRI_LT_Loader.c
ITK_LT_C\Examples\IRI_LT_Multiple_Readers.c
ITK_LT_C\Examples\IRI_LT_Power_Management.c
ITK_LT_C\Examples\IRI_LT_RxOnly.c
ITK_LT_C\Examples\IRI_LT_Select.c
ITK_LT_C\Examples\IRI_LT_Test_CW_PRBS.c
ITK_LT_C\Examples\Makefile
The lists below provide links to all ITK-C API calls that are supported in ITK-LT-C.
Device Management:
Operational Commands:
This API is disabled by default in order to keep the ITK-LT-C library size to a minimum.
It can be enabled via an ENABLE_FW_UPDATES compile time switch in config.h, at the cost of an increased library size.
See the IRI_LT_Loader example program for details on how to use this API to update firmware on the device.
The lists below provide links to all ITK-C API calls that are not supported in ITK-LT-C.
Device Management:
Operational Commands:
In addition to API limitations, there is also no individual Response or Report timestamping. The Tag Operation Report however still has a configurable timestamp field.
The sections below provide further explanations on a few specific API limitations.
The Platform Interface remains identical to ITK-C, however without the dynamic handler registration provided by ipj_register_handler the platform function names must be exactly as defined in Platform.h.
This is already the case for the provided platform_*.c files, so if they are used then no modification is needed.
Note
In addition to platform handlers, there is also an externed function defined in iri_lt.h for ipj_report_handler which needs to be implemented in user code. This allows users to trim down the report handler to only what is needed for a specific application. An example of ipj_report_handler can be found in ipj_util_lt.c.
This function enabled dynamically changing the baudrate of the device on the fly. That is not possible with ITK-LT-C, however Stored Settings and the Indy Demo Tool can be used to configure a non-default baudrate which can then be passed into ipj_connect. In this way the ITK-LT-C can support alternate baudrates.
This function enabled dynamically suppressing set responses. This is not possible with ITK-LT-C, however a compile time switch has been provided in config.h to SUPPRESS_SET_RESPONSES. If this switch is enabled then any Set command will not send a response, thereby cutting down on the IRI traffic over the wire.
The risk with this option is to miss some possible errors that could occur with the command. Therefore it is recommended that SUPPRESS_SET_RESPONSES be disabled during development and only enabled when the host application is ready for production.
Reports are defined differently in ITK-LT-C. All of them are simple c structs with each parameter defined as a fixed width uint32_t.
The exception to this rule is the Tag Operation Report, which is encoded as a series of simple field blocks separated by a 32-bit header (16-bits FIELD_ID and 16-bits FIELD_LENGTH). This allows users to trim down the report handler to only what is needed for a specific application. The desired report fields can be enabled or disabled through E_IPJ_KEY_REPORT_CONTROL_TAG.
Source code for both report types is provided below.
Here is the definition of the report structs and the Tag Operation Report field IDs from iri_lt.h:
// *****************************************************************************
{%- for r in reports%}
{{r}}
{%-endfor%}
// *****************************************************************************
// IRI API - LT Defines
// *****************************************************************************
{{flex_reports}}
Here are some macros for helping decode the Tag Operation Report:
/* Report Decoding */
#define REPORT_FIELD_ID(x) ((x >> 16) & 0xFFFF)
#define REPORT_FIELD_LENGTH(x) (x & 0xFFFF)
#define ROUNDED_COUNT_32(x) (((x + sizeof(uint32_t) - 1) & 0xFFFFFFFC) / sizeof(uint32_t))
Here are example report decoders, including the Tag Operation Report, as defined in ipj_util_lt.c:
ipj_error ipj_util_tag_operation_report_handler(
ipj_iri_device* iri_device,
uint32_t report_count_32,
uint32_t* tag_operation_report)
{
uint32_t index = 0;
while (index < report_count_32)
{
uint32_t field_header = tag_operation_report[index++];
switch (REPORT_FIELD_ID(field_header))
{
case E_IPJ_TAG_OPERATION_REPORT_ERROR:
{
IPJ_UTIL_PRINT_ERROR(tag_operation_report[index], "tag_operation_report");
break;
}
case E_IPJ_TAG_OPERATION_REPORT_PC:
{
printf("PC: %04X\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_XPC:
{
printf("XPC: %04X\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_CRC:
{
printf("CRC: %04X\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_RSSI:
{
printf("RSSI: %d\n", (int)tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_PHASE:
{
printf("PHASE: %d\n", (int)tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_CHANNEL:
{
printf("CHANNEL: %d\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_ANTENNA:
{
printf("ANTENNA: %d\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_TAG_OPERATION_TYPE:
{
printf("Tag operation: ");
switch (tag_operation_report[index])
{
case E_IPJ_TAG_OPERATION_TYPE_READ:
{
printf("READ\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_WRITE:
{
printf("WRITE\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_LOCK:
{
printf("LOCK\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_KILL:
{
printf("KILL\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_BLOCKPERMALOCK:
{
printf("BLOCK PERMALOCK\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_WRITE_EPC:
{
printf("WRITE EPC\n");
break;
}
case E_IPJ_TAG_OPERATION_TYPE_QT:
{
printf("QT\n");
break;
}
default:
{
printf("TYPE=%d\n", tag_operation_report[index]);
}
}
break;
}
case E_IPJ_TAG_OPERATION_REPORT_RETRIES:
{
printf("RETRIES: %d\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_DIAGNOSTIC:
{
printf("DIAGNOSTIC: %X\n", tag_operation_report[index]);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_TIMESTAMP:
{
printf(
"TIMESTAMP: %I64d\n",
(uint64_t) tag_operation_report[index]
| ((uint64_t) (tag_operation_report[index + 1]) << 32));
break;
}
case E_IPJ_TAG_OPERATION_REPORT_EPC:
{
printf("EPC: ");
ipj_util_print_epc(
(uint16_t*) &tag_operation_report[index],
REPORT_FIELD_LENGTH(field_header) / sizeof(uint16_t),
true);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_TID:
{
printf("TID: ");
/* Reuse the print epc method */
ipj_util_print_epc(
(uint16_t*) &tag_operation_report[index],
REPORT_FIELD_LENGTH(field_header) / sizeof(uint16_t),
true);
break;
}
case E_IPJ_TAG_OPERATION_REPORT_TAG_OPERATION_DATA:
{
printf("Report contains data: %d bytes\n", REPORT_FIELD_LENGTH(field_header));
/* Reuse the print epc method */
ipj_util_print_epc(
(uint16_t*) &tag_operation_report[index],
REPORT_FIELD_LENGTH(field_header) / sizeof(uint16_t),
true);
break;
}
}
index += ROUNDED_COUNT_32(REPORT_FIELD_LENGTH(field_header));
}
ipj_util_print_divider('-', 80);
return E_IPJ_ERROR_SUCCESS;
}
/* Stop report handler processes asynchronous reports */
ipj_error ipj_util_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;
}
/* GPIO handler processes asynchronous GPIO event reports */
ipj_error ipj_util_gpio_report_handler(
ipj_iri_device* iri_device,
ipj_gpio_report* gpio_report)
{
unsigned int i;
for (i = 0; i < 40; i++)
printf("*");
printf("\n%s: GPIO Report\n", (char*) iri_device->reader_identifier);
printf("GPIO Modes: ");
for (i = 1; i < ARRAY_SIZE(gpio_report->gpio_modes); i++)
{
switch (gpio_report->gpio_modes[i])
{
case E_IPJ_GPIO_MODE_DISABLED:
{
printf("D ");
break;
}
case E_IPJ_GPIO_MODE_INPUT:
{
printf("I ");
break;
}
case E_IPJ_GPIO_MODE_OUTPUT:
{
printf("O ");
break;
}
case E_IPJ_GPIO_MODE_OUTPUT_PULSE:
{
printf("OP ");
break;
}
case E_IPJ_GPIO_MODE_INPUT_ACTION:
{
printf("IA ");
break;
}
case E_IPJ_GPIO_MODE_OUTPUT_ACTION:
{
printf("OA ");
break;
}
case E_IPJ_GPIO_MODE_OUTPUT_PULSE_ACTION:
{
printf("OPA");
break;
}
}
if (i < ARRAY_SIZE(gpio_report->gpio_modes) - 1)
printf("|");
}
printf("\nGPIO States: ");
for (i = 1; i < ARRAY_SIZE(gpio_report->gpio_states); i++)
{
switch (gpio_report->gpio_states[i])
{
case E_IPJ_GPIO_STATE_LO:
case E_IPJ_GPIO_STATE_FLOAT:
{
printf("0 ");
break;
}
case E_IPJ_GPIO_STATE_HI:
{
printf("1 ");
break;
}
}
if (i < ARRAY_SIZE(gpio_report->gpio_states) - 1)
printf("|");
}
printf("\n");
for (i = 0; i < 40; i++)
printf("*");
printf("\n");
return E_IPJ_ERROR_SUCCESS;
}
ipj_error ipj_util_error_report_handler(
ipj_iri_device* iri_device,
ipj_error_report* error_report)
{
printf("Error Report\n");
printf("Error: 0x%X, %d\n", error_report->error, error_report->error);
printf("Param1: 0x%X, %d\n", error_report->param1, error_report->param1);
printf("Param2: 0x%X, %d\n", error_report->param2, error_report->param2);
printf("Param3: 0x%X, %d\n", error_report->param3, error_report->param3);
printf("Param4: 0x%X, %d\n", error_report->param4, error_report->param4);
return E_IPJ_ERROR_SUCCESS;
}
ipj_error ipj_util_status_report_handler(
ipj_iri_device* iri_device,
ipj_status_report* status_report)
{
uint32_t i;
printf("Status Report\n");
printf("status_flag: 0x%X, %d\n", status_report->status_flag, status_report->status_flag);
printf("status_1: 0x%X, %d\n", status_report->status_1, status_report->status_1);
printf("status_2: 0x%X, %d\n", status_report->status_2, status_report->status_2);
printf("status_3: 0x%X, %d\n", status_report->status_3, status_report->status_3);
printf("Additional Data:\n");
for (i = 0; i < ARRAY_SIZE(status_report->data); i++)
{
printf("[%d] 0x%X, %d\n", i, status_report->data[i], status_report->data[i]);
}
return E_IPJ_ERROR_SUCCESS;
}
ipj_error ipj_util_test_report_handler(
ipj_iri_device* iri_device,
ipj_test_report* test_report)
{
uint32_t i;
if (test_report->error != E_IPJ_ERROR_SUCCESS)
{
IPJ_UTIL_PRINT_ERROR(test_report->error, "test");
}
printf("\n*** %s Test Report ***\n", (char*) iri_device->reader_identifier);
printf("Test ID: %d\n", test_report->test_id);
printf("Test Results (optional):\n");
printf("Result 1: 0x%X, %d\n", test_report->result_1, test_report->result_1);
printf("Result 2: 0x%X, %d\n", test_report->result_2, test_report->result_2);
printf("Result 3: 0x%X, %d\n", test_report->result_3, test_report->result_3);
printf("Additional Data:\n");
for (i = 0; i < ARRAY_SIZE(test_report->data); i++)
{
printf("[%d] 0x%X, %d\n", i, test_report->data[i], test_report->data[i]);
}
return E_IPJ_ERROR_SUCCESS;
}