Sample Applications

These sample applications are included with the SDK. Modules are in custom/module and projects are in custom/project. Once you have built a project, find the ROM and other project files in xPico200/work.


Custom Data

The custom_data module demonstrates how to define and access custom configurables, how to embed files in a module, and how to overlay files using embedded files.

Build it from project customDataDemo.

When this project is loaded onto the xPico200 device, a new Custom Data tab appears in Web Manager. Click the tab to go to the Custom Device Configuration page. Bring up the trouble log on a line to watch what is happening. Change Name, Rank, and Serial Number, click Submit, and observe the changes on the trouble Log.

Function Details

The following is an overview of the functions used in the custom_data module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream and write the data to the buffer and ltrx_xml_emit_value() to emit the XML value onto the buffer.

static bool getItem(
    const char *desiredItemName,
    char *buffer,
    size_t size
) {...}

Find the desired custom item and write it to the buffer. Use snprintf() to write up to size bytes to str under the control of a format string.

static void customConfigMonitorThread(void *opaque) {...}

Find any new config values and print them out to the trouble log.


BLE Explorer

The ble_explorer module provides utilities to inspect and communicate with BLE devices. This module operates only on the CLI; it does not have a Web Manager interface, and has the look and feel of a *nix commmand-line program.

ble_explorer can scan and display nearby devices as well as scan and display BLE advertisements.

It also offers GATT client functionality for discovering GATT services, as well as connecting to BLE central devices (GATT servers) and reading and writing to attributes available via those devices.

Build it from project bleExplorer.

Status Actions

The ble_explorer module provides a command line interface driven by status actions. Navigate to the status/BLE Explorer CLI level to use these actions:

scan

Initiates a hi-duty scan for nearby devices.

Note that it is recommended to enable Background Scanning in the Bluetooth configuration for this application.

show devices

Shows nearby devices discovered from the background scan or the scan action.

watch ads [-d duration] [-a [-e] bdaddr1;bdaddr2;...]] [-s [-e] scanevent1;[scanevent2;...]]

Displays BLE advertisements.

Options:

-d duration : Specifies duration to display advertisements. Defaults to 5 seconds.
-a [-e] bdaddr1;bdaddr2;... : Optionally filter by specified Bluetooth device address(es). If the [-e] option follows the -a, the addresses will filtered out (excluded).
-s [-e] scanevent1;scanevent2;...: Optionally filter by specified scan event(s). If the [-e] option follows the -s, the scan events will be filtered out (excluded). Scan events can be specified by numeric value or name. They are as follows:

CONNECTABLE_ADVERTISEMENT (0)
CONNECTABLE_DIRECTED_ADVERTISEMENT (1)
SCANNABLE_ADVERTISEMENT (2)
NON_CONNECTABLE_ADVERTISEMENT (3)
SCAN_RESPONSE (4)

The status/BLE Explorer level contains a sub-level called gatt client. Navigate to the status/BLE Explorer/gatt client CLI level to use the following actions:

connect [-a "random"] [-t "bredr"] <device_address>

Establish a GATT client connection to the device specified by the Bluetooth Device Address. A GATT client may also be referred to as a BLE Central device; the peer device may be referred to as a BLE Peripheral. By default, the Connect command assumes that the Device Address is a public address. To connect to a device with a random BLE address, use the option "-a random".

Also by default, the Connect command will use the BLE transport. If the peer devices requires it, the connection can be made over the BR/EDR (Basic Rate / Enhanced Data Rate), using the "-t bredr" option.

If successful, the Connect command will return a Connection Id, which is required for any additional operations against a connected device.

disconnect <connection_id>

Tear down a GATT client connection to a BLE Peripheral. The Connection Id parameter is the id returned from the Connect command.

services [-u uuid] <connection_id>

Discover and list the services provided by a connected BLE Peripheral device.

An optional BLE service UUID may be provided. If omitted, the Services command will discover all available GATT Services.

Service discovery returns the service UUID as well as the handle range associated with that service. It is these handles which are the basis for discovery of service characteristics and descriptors.

characteristics [-s start_handle] [-e end_handle] <connection_id>

Discover and list the service characteristics identified by a specified handle range. By default, the handle range is the maximum possible value range: 0x001 to 0xFFFF. The start and end handles may be independently specified with the "-s start_handle" and "-e end_handle" options, respectively.

For example, to discover the handle range for a specific service, first use the Services command to obtain the handle range for that service. Then use the Characteristics command to list the services characteristics in that handle range. Service characteristic discovery returns the characteristic UUID, the handle and value handle, and the properties for that characteristic. The characteristic properties identify what kind of I/O may be performed against that characteristic.

descriptors [-s start_handle] [-e end_handle] <connection_id>

Discover and list characteristic descriptors identified by a specified handle range. Characteristic descriptor discovery returns the descriptor UUID and the descriptor handle.

mtu <connection_id> <mtu>

Sets the Maximum Transmission Unit size for communication with the connected peer device. By default, the BLE MTU is 23 bytes. It may be increased, depending on the capabilities of the peer device, up to 512 bytes.

read handle [-b buffer_size] [-o offset] <connection_id> <handle>

Reads an attribute value by the specified handle.

Options:

-b buffer_size : Specifies the buffer size to be used for receiving the attribute value. Defaults to 64 bytes. The buffer size specified with this option is separate from the MTU. You generally want to set this buffer size to at least the same size as the current MTU.

-o offset: Specifies an optional offset from which to read the attribute value.

write  [-r | -p [-o offset]] <connection_id> <handle> [-n] <data>
          [-c | -e] <connection_id>`

Writes the specified value to an attribute. There are several different write operations:

-r: Specifies a write with no response. From the application perspective, this option will not make a noticeable difference. However, it must match the attribute properties. Only an attribute with the property "WRITE_NR" (found in the display for the "characteristics" command) can service this operation.

-p : Specifies a write prepare operation. Depending on the attribute implementation on the peer device, several write prepare operations may be called before the write(s) are executed (see the -e option). The write prepare operation supports specifying an offset for the write with the -o option. If specified for any other write operation, the offset is ignored.

-c : Specifes that any previous write prepare operations (which have not been executed) be cancelled.

-e : Specifies that any previous write prepare operations be executed.

Without the -r, -p, -c, or -e option specified, a "normal" write operation is executed, where the write operation is called and a response is expected before the operation will return to the application.

By default, the data written to the attribute is text. That can be changed with the -n option. If the -n precedes the data, it is interpreted as a numeric value. This is currently limited to a 32-bit signed integer value.

Notification [-s start_handle] [-e end_handle] <on | off | listen>

Turns BLE GATT notification handling on or off, or listens for notifications and displays notification data.

Sub-commands:

on : Registers the notification handler. Once the handler is registered, received notifications are either logged to the TLOG, or if the listen sub-command is active, displayed on the CLI.

off : Unregisters the notification handler.

listen : Displays received notifications.

Indication [-s start_handle] [-e end_handle] <on | off | listen>

Turns BLE GATT indication handling on or off, or listens for notifications and displays notification data. Note that because indications involve a response, unlike notifications, if the indication handler is not registered before indications are enabled on the GATT server (BLE Peripheral), you may see errors on the GATT server.

Sub-commands:

on : Registers the indication handler. Once the handler is registered, received indications are either logged to the TLOG, or if the listen sub-command is active, displayed on the CLI.

off : Unregisters the indication handler.

listen : Displays received indications.

show

Shows the connection state for all possible GATT client connections. Note that this command shows the actual GATT connection status available from the Bluetooth module.


BLE GATT Server Demo

The ble_gatt_server_demo module is the most basic Bluetooth Low Energy (BLE) demo application. It creates a connection that demonstrates reading and writing data and demonstrates GATT database usage and device configuration. The ble_gatt_server_demo makes use of the API function ltrx_gatt_register_server().

ble_gatt_server_demo requires the use of LightBlue found on the Google Play and Apple App Stores. This app can be used to connect to the xPico2x0 device using Bluetooth. Use the TLOG to confirm the transmission of data. The default Bluetooth SSID is "BLE Gatt Demo".

Build it from project bleGattServerDemo.

Function Details

static void bgsd_thread(void *arg)

Waits for Bluetooth to enter the running state, then registers the server defined by the struct ltrx_gatt_server.

static void bgsd_connection(uint16_t connection_id, bool connected)

Called when a GATT client (BLE Central device) connects to the server.

static int bgsd_attribute_read(
    uint16_t handle,
    uint16_t offset,
    uint8_t *datap,
    uint16_t *lengthp
)

Called when the connected client issues a request to read attributes.

static int bgsd_attribute_write(
    uint16_t handle,
    uint16_t offset,
    uint8_t *datap,
    uint16_t length
)

Called when the connected client issues a request to write attributes. If the attribute handle is that of the Client Characteristic Configuration Descriptor, indications are turned on or off depending on the value written.

static int bgsd_attribute_confirmation(uint16_t handle)

Called when the connected client issues an indication confirmation.


BLE Test Server

The ble_test_server is primarily aimed at testing the various GATT client capabilities found in the ble_explorer example application. It offers three attributes:

  • One with read and write properties
  • One with read and write-with-no-response properties
  • One with read and notification and indication properties

The ble_test_server is written specifically to serve the capabilities encapsulated in the ble_explorer module, but can be used as the basis of a more complete server than that provided by the basic server in the ble_gatt_server_demo application. ble_test_server provides status actions to configure and control the server. These status actions can be invoked from the CLI, or, while it does not provide a Web Manager interface, the Web API.

Build it from project bleTestServer.

Status Actions

mode <write back | data logging>

Sets the operating mode to either “write back” or “data logging”. The “write back” mode is the default.

The operating mode simply specifies how read and write data is provided and handled. In “write back” mode, the attribute values are initially empty. It must be written to before it can be read, and the value(s) read from the attributes will simply be what has been previously written to it.

In data logging mode, the attribute values are initialized with simple repeating incrementing byte values, starting from 0x00 through 0xFF. Data written to the attribute are written to the TLOG, while the read values are not changed. Similarly, all values read from the attribute are also logged.

start

Starts the BLE Test Server if it is not already running.

stop

Stops the BLE Test Server.

Function Details

bool bts_start(void)

Called by the status action “start”, this function waits for Bluetooth to enter the running state, then starts the server thread bts_thread() and registers the server with ltrx_gatt_register_server().

bool bts_stop(void)

Called by the status action “stop”, this function signals the thread bts_thread() to exit, then unregisters the server with ltrx_gatt_unregister_server().

static void bts_thread(void *arg)

The server thread waits, in 10 second increments, for a write request to be processed which requires a response. If the response is required, it is issued in the thread with ltrx_gatt_send_response().

If a response is not issued, the current notification and indication state values are checked. If configured (via a client write request to the Client Characteristic Configuration Descriptor), a notification and indication are dispatched to the connected client.

static void bts_connection(uint16_t connection_id, bool connected)

Called when a GATT client (BLE Central device) connects or disconnects.

static int bts_attribute_mtu(uint16_t size)

Called when a connected client issues a request to configure the MTU.

static int bts_attribute_read(
      uint16_t handle,
      uint16_t offset,
      uint8_t *datap,
      uint16_t *lengthp
)

Called when a connected client issues a request to read an attribute.

static int bts_attribute_write_prepare(
      uint16_t handle,
      uint16_t offset,
      uint8_t *datap,
      uint16_t length
)

Called when a connected client issues a write prepare request for an attribute.

static int bts_attribute_write_execute(bool proceed)

Called when a connected client issues a write execute request for an attribute.

static int bts_attribute_write(
      uint16_t handle,
      uint16_t offset,
      uint8_t *datap,
      uint16_t length
)

Called when a connected client issues a write request for an attribute. If the attribute handle is that for the Client Characteristic Configuration Descriptor, indications or notifications will be started or stopped, depending on the value written.

static int bts_attribute_confirmation(uint16_t handle)

Called when a connected client issues an indication confirmation request.


XML Access

The xml_access module demonstrates how to read device status and configuration values via XML.

Build it from project xmlAccessDemo.

Function Details

The following is an overview of the functions used in the xml_access module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream to buffer and ltrx_xml_emit_value() to emit an XML value onto the buffer.

static void xmlAccessThread(void *opaque) {...}

Use ltrx_ip_address_state() to check if the IP interfaces are up, and while there is no connection, use ltrx_thread_sleep() to pause the thread. While there is a connection, get firmware version, MAC address, current WLAN0 IP address, and configured dynamic power mode and print related information to the trouble log, and then pause the thread.


Secure Tunnel

The secure_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TLS out on the line. It sends data received on the line out via TLS when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for a TLS connection on both the AP0 and WLAN0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TLS. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Note

You must add TLS Credential called secure_tunnel. Log in to Web Manager and click TLS Credentials. For more information, see Creating a TLS Credential in the xPico 200 Series User Guide.

https://docs.lantronix.com/products/xpico-200/ug/1.6.0.0/cli-ref/#config-tls-credential-level

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project secureTunnelDemo.

Function Details

The following is an overview of the functions used in the secure_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, send the data and then use ltrx_tcp_socket_close() to close the socket and then close the connection.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

Use ltrx_network_lookup_network_protocol() to get the protocol structure for "TLS".

If REMOTE_ADDRESS is defined and there is no socket open for the thread, use ltrx_tcp_listener_begin() to initialize the listener and start listening.

If REMOTE_ADDRESS is defined and there is a socket open for the thread, use ltrx_output_stream_write_line() to print "Connected" with a new line.

If REMOTE_ADDRESS is not defined and there is no socket open and no listener in use, use ltrx_tcp_listener_begin() to initialize listener and begin listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

If REMOTE_ADDRESS is not defined and there is a listener in use, use ltrx_tcp_listener_end() to stop listening.

Close the socket with ltrx_tcp_socket_close().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

If a thread is already running, print message to the trouble log. Otherwise, use ltrx_thread_create() to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


Programmatic Scan

The programmatic_scan module demonstrates how to run a CLI command from your program and capture its output for program use.

Build it from project programmaticScanDemo.

Function Details

The following is an overview of the functions used in the programmatic_scan module.

static void processScanResults(
    const char *ssid,
    uint8_t *bssid,
    uint8_t channel,
    int rssi,
    const char *securitySuite
) {...}

Print debug information to trouble log.

static void parseScanLine(const char *scanLine) {...}

Read formatted input from a string and send to processScanResults().

static bool writeData(
    struct output_stream *outStream,
    const char *data, size_t length
) {...}

Write the data to the scan line and then yield control to other threads using ltrx_thread_yield().

static bool writeNewline(struct output_stream *outStream) {...}

Determine if the scan is completed, and if so, write the new line. Then, yield control to other threads using ltrx_thread_yield().

static bool flushData(struct output_stream *outStream) {...}

Flush data from the output stream.

static bool outputClose(struct output_stream *outStream) {...}

Close the output stream.

static void programmaticScanThread(void *opaque) {...}

Use ltrx_ip_address_state() to see if the IP interface is up. If not, use ltrx_thread_sleep() to pause the thread for 1000 ms to allow time for WLAN0 to come up.

Use ltrx_input_stream_init_from_const_char() to construct input stream from const character, and when up, send "Starting scan." message to trouble log.

Use ltrx_cli_command_loop() to enter command line interface.

Closes the input stream with ltrx_input_stream_close() and pause the thread with ltrx_thread_sleep().


Configurable Pins

The config_pin module implements an output role, which can be assigned to any configurable pin (CP).

Build it from project configurablePinDemo.

Use either Web Manager or Command Line Interface to set up configuration in group configurable pin manager (CPM). Under Roles, find your role of Blinker. Assign it a CP of your choice and set State to Enabled.

Tip

If using the evaluation board, you must jumper your selected configurable pin on J2 to an external LED (and current limiting resistor) -- if some other role is enabled using your selected CP, this will fail. Observe the blinking with an LED or scope connected to your selected CP.

Function Details

The following is an overview of the functions used in the config_pin module.

static void blinkerThread(void *opaque) {...}

Look up role index using ltrx_cp_role_index_get() and print the role name and roll index to trouble log. While there is a thread, use ltrx_cp_write() to write to a configurable pin and then pause the thread with ltrx_thread_sleep().

void config_pin_module_startup(void) {...}

Notice use of the macro STACK_SIZE_GREEN_FROM_MAX_OBSERVED_STACK_USED when calling ltrx_thread_create() in the startup function. It was originally built with 2000 bytes of stack. Then the module was built and run. The actual stack was observed either via the Web Manager or the Command Line Interface under Diagnostics Threads. Find the Blinker thread, and the Stack used is shown. That value was plugged into the macro in the sample code.


UDP Tunnel

The udp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via UDP out on the line. It sends data received on the line out via UDP when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for UDP packets on interface WLAN0 addressed to the LOCAL_PORT 10001. When the first packet is received, it sends Connected to the line. Subsequently, it listens to the line for data to send out via UDP. #define REMOTE_ADDRESS may be AP0 or WLAN0 to operate in this listening mode.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the interface is established and resolves the name or address, it sends Connected to the line.

Build it from project udpTunnelDemo.

Function Details

The following is an overview of the functions used in the udp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If the length of the received data is greater than zero, use ltrx_output_stream_write_binary() to write the binary data to the buffer.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, there is no socket open, and ltrx_udp_socket_open_with_options() to open a socket returns false (failed), wait and try again. Otherwise, call networkReadAndSerialWrite() and then, if ltrx_udp_socket_is_active() returns true, and the thread is not connected, use ltrx_output_stream_write_line() to write "" and a new line, follwed by "Connected" and a new line. If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


TCP Tunnel

The tcp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TCP out on the line. It sends data received on the line out via TCP when it receives Enter or fills its 80 character buffer.

As delivered in the SDK, the module listens for a TCP connection on both the AP0 and WLAN0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TCP. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project tcpTunnelDemo.

For connecting out, fill in REMOTE_ADDRESS with either an IP address or a host name. For listening, comment out the definition of REMOTE_ADDRESS. The REMOTE_PORT is only used if "connecting out" according to REMOTE_ADDRESS.

#define REMOTE_ADDRESS "remote_host_goes_here"

Function Details

The following is an overview of the functions used in the tcp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "" ending with a new line and then "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, REMOTE_ADDRESS is defined, and there is no socket, use ltrx_tcp_connect() to connect. If there is a socket, print "Connected".

While the thread is running, REMOTE_ADDRESS is not defined, and there is no socket and no listener, use ltrx_tcp_listener_begin() to initialize a listener and start listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Otherwise, pause the thread for 100ms with ltrx_thread_sleep().


Power Down

The power_down module demonstrates how an application program can place restrictions on when the device powers down.

Build it from project powerDownDemo.

Function Details

The following is an overview of the functions used in the power_down module.

static void powerDownThread(void *opaque) {...}

Use ltrx_ip_address_state() to check if the IP interfaces are up, and while there is no connection, use ltrx_thread_sleep() to pause the thread for 100 ms to give WLAN0 time to come up.

When there is a connection, use ltrx_power_level_application_request_full_power() to request full power until further notice, then use ltrx_timemark() to get a time mark.

Use ltrx_elapsed_time_current_ms() to find the time since the time mark. If the elapsed time is less than the duration specified in s_timeBetweenWorkStartInMilliseconds, calculate the difference between the elapsed time and remaining time. If the difference is greater that 1000 ms, print a message indicating the permitted shutdown time to the trouble log and then permit shutdown for specified time duration using ltrx_power_level_application_permit_shutdown().

Pause the thread with ltrx_thread_sleep() and yeild control using ltrx_thread_yield().


SPI Log

The spi_log module implements a rudimentary serial peripheral interface (SPI) protocol. When this protocol is chosen by a SPI, it logs whatever it receives on the SPI.

To run it you will need to select protocol Log under SPI Configuration.

Also, you will need to enable the SPI configurable pins (CPs): Under CPM Roles Configuration, enable the SPI group of CPs.

Tip

If using the evaluation board, you may place a jumper between J2 pins CP3 and CP4 to effect a loopback of your SPI data. Note that the SPI group of CPs is ganged, so when you enable one, you enable them all. Also note that all the other CPM Roles referring to any of the SPI CPs must be disabled.

Build it from project spiLogDemo.

Function Details

The following is an overview of the functions used in the power_down module.

static void spiLoop(struct thread_info *ti) {...}

While the thread is running, use ltrx_spi_transfer() to transfer data and then confirm "Sent" in the trouble log. Then use ltrx_thread_sleep() to pause the thread for 5000 ms.

static void spiThread(void *opaque) {...}

Wheile the thread is running and calling ltrx_spi_open() to open a serial peripheral interface returns false (failed), wait 1000 ms and try again. Print start message to trouble log and call spiLoop().

Relinquish the SPI using ltrx_spi_close().

bool StartSpiLog(uint16_t zeroBasedIndex) {...}

If a thread is already running, print message to the trouble log. Otherwise, use ltrx_thread_create() to create a thread and start it.

void StopSpiLog(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, change wasRunning to true, Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, pause the thread with ltrx_thread_sleep().