demo/uart_blaster/uart_blaster.c

See examples/demo/uart_blaster

/*
* ZentriOS SDK LICENSE AGREEMENT | Zentri.com, 2015.
*
* Use of source code and/or libraries contained in the ZentriOS SDK is
* subject to the Zentri Operating System SDK license agreement and
* applicable open source license agreements.
*
*/
/* Documentation for this app is available online.
* See https://docs.zentri.com/wifi/sdk/latest/examples/demo/uart-blaster
*/
#include "zos.h"
#include "common.h"
#define MAX_RX_IRQ_EVENTS 8
static struct
{
uart_blaster_settings_t *settings;
volatile zos_bool_t is_blasting;
char counter;
char *tx_buffer;
uint32_t tx_buffer_len;
} context;
static uint8_t rx_buffer[128];
/*************************************************************************************************/
void zn_app_init(void)
{
commands_init();
zn_event_enable_irq_events(MAX_RX_IRQ_EVENTS);
ZOS_NVM_GET_REF(context.settings);
}
/*************************************************************************************************/
void zn_app_deinit(void)
{
commands_deinit();
}
/*************************************************************************************************/
zos_bool_t zn_app_idle(void)
{
// return TRUE so the event loop idles
// it'll awake when the 'blast' command is received
return ZOS_TRUE;
}
/*************************************************************************************************
* This executes in the command thread. Issue an event so we can start/stop uart blasting data in the event thread.
*/
void toggle_uart_blasting(void)
{
// if we're not blasting, then issue an event to start blasting
if(!context.is_blasting)
{
zos_uart_config_t *uart_settings = &context.settings->uart;
const zos_uart_buffer_t buffer =
{
.buffer = rx_buffer,
.length = sizeof(rx_buffer)
};
context.is_blasting = ZOS_TRUE;
context.counter = 32;
zn_uart_configure(context.settings->uart_id, uart_settings, &buffer);
zn_uart_register_rx_callback(context.settings->uart_id, uart_rx_irq_callback);
zn_event_issue(uart_blast_event_handler, NULL, 0);
ZOS_LOG("Starting blasting:");
ZOS_LOG("\tUART #: %u", context.settings->uart_id);
ZOS_LOG("\tUART: baud=%u, flow=%u, stopbits=%u", uart_settings->baud_rate, (uart_settings->flow_control == UART_FLOW_CTS_RTS), uart_settings->stop_bits+1);
ZOS_LOG("\tPacket length: %d", context.settings->packet_length);
ZOS_LOG("\tPacket delay: %d", context.settings->packet_delay);
}
// de-register the event handler
else
{
context.is_blasting = ZOS_FALSE;
ZOS_LOG("Stopping blasting");
zn_event_unregister(uart_blast_event_handler, NULL);
zn_uart_register_rx_callback(context.settings->uart_id, NULL);
}
}
/*************************************************************************************************/
static void uart_blast_event_handler(void *arg)
{
// if we're not blasting then just return
if(!context.is_blasting)
{
return;
}
// if the tx len changed, then free the old buffer and update the length
if(context.tx_buffer_len != context.settings->packet_length)
{
if(context.tx_buffer != NULL)
{
zn_free(context.tx_buffer);
context.tx_buffer = NULL;
}
context.tx_buffer_len = context.settings->packet_length;
}
// alloc a tx buffer is we don't have one
if(context.tx_buffer == NULL)
{
if(zn_malloc((uint8_t**)&context.tx_buffer, context.tx_buffer_len) != ZOS_SUCCESS)
{
ZOS_LOG("Failed alloc tx buffer of size: %d", context.tx_buffer_len);
context.is_blasting = ZOS_FALSE;
zn_event_unregister(uart_blast_event_handler, NULL);
}
}
// populate the tx buffer
char *ptr = context.tx_buffer;
for(uint32_t remaining = context.tx_buffer_len; remaining > 0; --remaining, ++ptr)
{
*ptr = context.counter++;
// 32-126 are printable ASCII characters
if(context.counter >= 127)
{
context.counter = 32;
}
}
// transmit the packet
zn_uart_transmit_bytes(context.settings->uart_id, context.tx_buffer, context.tx_buffer_len);
// re-register handler to execute in packet_delay milliseconds
zn_event_register_timed(uart_blast_event_handler, NULL, context.settings->packet_delay, 0);
}
/*************************************************************************************************/
static void uart_rx_irq_callback(uint32_t c)
{
zn_event_issue(uart_rx_event_handler, NULL, EVENT_FLAGS1(FROM_IRQ));
}
/*************************************************************************************************/
static void uart_rx_event_handler(void *arg)
{
while(zn_uart_receive_bytes(context.settings->uart_id, rx_buffer, sizeof(rx_buffer)-1, ZOS_NO_WAIT) == ZOS_SUCCESS)
{
const uint32_t bytes_rx = zn_uart_get_bytes_received(context.settings->uart_id);
rx_buffer[bytes_rx] = 0;
ZOS_LOG("RX data: %s", rx_buffer);
}
}