/*
 * Copyright (c) 2007-2015 Freescale Semiconductor, Inc.
 * Copyright 2018-2020 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 * FreeMASTER Communication Driver - Example Application Code to be used
 * with MCUXpresso Peripheral Configuration tool. This code is similar to
 * general freemaster_example.c example application, but expects the
 * FreeMASTER to be configured by MCUXpresso ConfigTools and initialized
 * by code generated in peripherals.c.
 */

#include <string.h>
#include <stdio.h>

#include "peripherals.h"
#include "freemaster.h"
#include "freemaster_example.h"
#include "freemaster_democfg.h"

/****************************************************************************
 *
 * Default configuration of FreeMASTER demo
 *
 */

#ifndef FMSTR_GENERATED_CONFIGURATION
/* The FreeMASTER example application named "fmstr_any" demonstrates use of the generated configuration */
#warning This code should be used with FreeMASTER configuration generated by MCUXpresso Config Tools.
#endif

/* Demo application configuration. Enough ROM resources by default,
 * but not really large ROM by default (storing images and other active content) */
#ifndef FMSTR_DEMO_ENOUGH_ROM
#define FMSTR_DEMO_ENOUGH_ROM 1
#endif
#ifndef FMSTR_DEMO_LARGE_ROM
#define FMSTR_DEMO_LARGE_ROM 0
#endif

/* in LARGE_ROM is defined, then also enable ENOUGH_ROM option */
#if FMSTR_DEMO_LARGE_ROM && !(FMSTR_DEMO_ENOUGH_ROM)
#warning Probably wrong demo application settings
#undef FMSTR_DEMO_ENOUGH_ROM
#define FMSTR_DEMO_ENOUGH_ROM 1
#endif

/* Platform configuration for demo application */
#ifndef FMSTR_DEMO_SUPPORT_I64
#define FMSTR_DEMO_SUPPORT_I64 1 /* support for long long type */
#endif
#ifndef FMSTR_DEMO_SUPPORT_FLT
#define FMSTR_DEMO_SUPPORT_FLT 1 /* support for float type */
#endif
#ifndef FMSTR_DEMO_SUPPORT_DBL
#define FMSTR_DEMO_SUPPORT_DBL 1 /* support for double type */
#endif

/****************************************************************************
 *
 * Test variables, will be displayed in the FreeMASTER application
 *
 */

#define ARR_SIZE     10
#define ARR_SIZE_FLT 10
#define ARR_SIZE_DBL 10

volatile unsigned char var8;
volatile unsigned char var8rw;
volatile unsigned char var8inc = 1;
volatile unsigned short var16;
volatile unsigned short var16rw;
volatile unsigned short var16inc = 1;
volatile unsigned short var16prv;
volatile unsigned long var32;
volatile unsigned long var32rw;
volatile unsigned long var32inc = 100;

volatile unsigned char frac8;
volatile unsigned short frac16;
volatile unsigned long frac32;

volatile unsigned char ufrac8;
volatile unsigned short ufrac16;
volatile unsigned long ufrac32;

volatile unsigned char *var8ptr   = &var8;
volatile unsigned short *var16ptr = &var16;
volatile unsigned long *var32ptr  = &var32;

volatile unsigned short arr_size = ARR_SIZE;
volatile unsigned char arr8[ARR_SIZE];
volatile unsigned short arr16[ARR_SIZE];
volatile unsigned long arr32[ARR_SIZE];

#if FMSTR_DEMO_SUPPORT_I64
volatile unsigned long long var64;
volatile unsigned long long var64rw;
volatile unsigned long long var64inc = 10000;
volatile unsigned long long arr64[ARR_SIZE];
volatile unsigned long long frac64;
volatile unsigned long long ufrac64;
#endif

#if FMSTR_DEMO_SUPPORT_FLT
volatile float varFLT;
volatile float varFLTrw;
volatile float varFLTinc = 1.0;
volatile float arrFLT[ARR_SIZE_FLT];
volatile unsigned int arrFLT_size = ARR_SIZE_FLT;
#endif

#if FMSTR_DEMO_SUPPORT_DBL
volatile double varDBL;
volatile double varDBLrw;
volatile double varDBLinc = 1.0;
volatile double arrDBL[ARR_SIZE_DBL];
volatile unsigned int arrDBL_size = ARR_SIZE_DBL;
#endif

/* count received application commands, just for test purposes */
volatile unsigned char nAppCmdCounter;

/****************************************************************************
 *
 * Test structure types - demonstrates the "TSA" feature thanks to which the
 * FreeMASTER is able to load a variable and type information directly from
 * the embedded application.
 *
 */

typedef enum
{
    EXAMPLE_ENUM_FIRST_ENTRY,
    EXAMPLE_ENUM_SECOND_ENTRY,
    EXAMPLE_ENUM_THIRD_ENTRY,
} EXAMPLE_ENUM;

typedef enum
{
    SPEED_ZERO   = 0,
    SPEED_FAST   = 1,
    SPEED_NORMAL = 20,
    SPEED_SLOW   = 200,
} INCREMENT_SPEED;

typedef struct
{
    unsigned short aa;
    unsigned long bb[2];
    unsigned short cc;
    unsigned long dd[3];
    unsigned char ee;
    unsigned char ff[5];
} INNER_STRUCT;

typedef struct
{
    unsigned short a;
    unsigned long b;
    INNER_STRUCT inA[4];
    INNER_STRUCT inB;
} OUTER_STRUCT;

/****************************************************************************
 *
 * Test variables which make use of the user-defined data types. You are able
 * to display the variables including the member items in FreeMASTER.
 *
 */

volatile OUTER_STRUCT so1, so2;
volatile INNER_STRUCT si1, si2;
volatile EXAMPLE_ENUM varENUM;
volatile INCREMENT_SPEED varIncSpeed;

/****************************************************************************
 * Local prototypes
 */
FMSTR_APPCMD_RESULT my_appcmd_handler(FMSTR_APPCMD_CODE nAppcmd, FMSTR_APPCMD_PDATA pData, FMSTR_SIZE nDataLen);
void my_pipe_handler(FMSTR_HPIPE hpipe);
void my_pipe_math(FMSTR_HPIPE hpipe);

// clang-format off

/****************************************************************************
 *
 * With TSA enabled, the user describes the global and static variables using
 * so-called TSA tables. There can be any number of tables defined in
 * the project files. Each table does have the identifier which should be
 * unique across the project.
 *
 * Note that you can declare variables as Read-Only or Read-Write.
 * The FreeMASTER driver denies any write access to the Read-Only variables
 * when TSA_SAFETY is enabled.
 */

FMSTR_TSA_TABLE_BEGIN(first_table)
    FMSTR_TSA_RO_VAR(var8, FMSTR_TSA_UINT8)
    FMSTR_TSA_RW_VAR(arr8, FMSTR_TSA_UINT8)
    FMSTR_TSA_RW_VAR(var8rw, FMSTR_TSA_UINT8)
    FMSTR_TSA_RW_VAR(var8inc, FMSTR_TSA_UINT8)

    FMSTR_TSA_RO_VAR(var16, FMSTR_TSA_UINT16)
    FMSTR_TSA_RW_VAR(arr16, FMSTR_TSA_UINT16)
    FMSTR_TSA_RW_VAR(var16rw, FMSTR_TSA_UINT16)
    FMSTR_TSA_RW_VAR(var16inc, FMSTR_TSA_UINT16)

    FMSTR_TSA_RO_VAR(var32, FMSTR_TSA_UINT32)
    FMSTR_TSA_RW_VAR(arr32, FMSTR_TSA_UINT32)
    FMSTR_TSA_RW_VAR(var32rw, FMSTR_TSA_UINT32)
    FMSTR_TSA_RW_VAR(var32inc, FMSTR_TSA_UINT32)

    FMSTR_TSA_RO_VAR(var8ptr, FMSTR_TSA_POINTER)
    FMSTR_TSA_RO_VAR(var16ptr, FMSTR_TSA_POINTER)
    FMSTR_TSA_RO_VAR(var32ptr, FMSTR_TSA_POINTER)

    FMSTR_TSA_RW_VAR(frac8, FMSTR_TSA_FRAC_Q(0, 7))
    FMSTR_TSA_RW_VAR(frac16, FMSTR_TSA_FRAC_Q(3, 12))
    FMSTR_TSA_RW_VAR(frac32, FMSTR_TSA_FRAC_Q(12, 19))

    FMSTR_TSA_RW_VAR(ufrac8, FMSTR_TSA_UFRAC_UQ(1, 7))
    FMSTR_TSA_RW_VAR(ufrac16, FMSTR_TSA_UFRAC_UQ(4, 12))
    FMSTR_TSA_RW_VAR(ufrac32, FMSTR_TSA_UFRAC_UQ(13, 19))

#if FMSTR_DEMO_SUPPORT_I64
    FMSTR_TSA_RO_VAR(var64, FMSTR_TSA_UINT64)
    FMSTR_TSA_RW_VAR(arr64, FMSTR_TSA_UINT64)
    FMSTR_TSA_RW_VAR(var64rw, FMSTR_TSA_UINT64)
    FMSTR_TSA_RW_VAR(var64inc, FMSTR_TSA_UINT64)
    FMSTR_TSA_RW_VAR(frac64, FMSTR_TSA_FRAC_Q(8, 55))
    FMSTR_TSA_RW_VAR(ufrac64, FMSTR_TSA_UFRAC_UQ(9, 55))
#endif

#if FMSTR_DEMO_SUPPORT_FLT
    FMSTR_TSA_RO_VAR(varFLT, FMSTR_TSA_FLOAT)
    FMSTR_TSA_RW_VAR(varFLTrw, FMSTR_TSA_FLOAT)
    FMSTR_TSA_RW_VAR(arrFLT, FMSTR_TSA_FLOAT)
    FMSTR_TSA_RW_VAR(varFLTinc, FMSTR_TSA_FLOAT)
    FMSTR_TSA_RO_VAR(arrFLT_size, FMSTR_TSA_UINT32)
#endif

#if FMSTR_DEMO_SUPPORT_DBL
    FMSTR_TSA_RO_VAR(varDBL, FMSTR_TSA_DOUBLE)
    FMSTR_TSA_RW_VAR(arrDBL, FMSTR_TSA_DOUBLE)
    FMSTR_TSA_RW_VAR(varDBLrw, FMSTR_TSA_DOUBLE)
    FMSTR_TSA_RW_VAR(varDBLinc, FMSTR_TSA_DOUBLE)
    FMSTR_TSA_RO_VAR(arrDBL_size, FMSTR_TSA_UINT32)
#endif

    FMSTR_TSA_RO_VAR(arr_size, FMSTR_TSA_UINT16)

    FMSTR_TSA_RO_VAR(nAppCmdCounter, FMSTR_TSA_UINT8)

    FMSTR_TSA_RW_VAR(so1, FMSTR_TSA_USERTYPE(OUTER_STRUCT))
    FMSTR_TSA_RW_VAR(si1, FMSTR_TSA_USERTYPE(INNER_STRUCT))
    FMSTR_TSA_RW_VAR(varENUM, FMSTR_TSA_USERTYPE(EXAMPLE_ENUM))
    FMSTR_TSA_RW_VAR(varIncSpeed, FMSTR_TSA_USERTYPE(INCREMENT_SPEED))

    FMSTR_TSA_STRUCT(OUTER_STRUCT)
    FMSTR_TSA_MEMBER(OUTER_STRUCT, a, FMSTR_TSA_UINT16)
    FMSTR_TSA_MEMBER(OUTER_STRUCT, b, FMSTR_TSA_UINT32)
    FMSTR_TSA_MEMBER(OUTER_STRUCT, inA, FMSTR_TSA_USERTYPE(INNER_STRUCT))
    FMSTR_TSA_MEMBER(OUTER_STRUCT, inB, FMSTR_TSA_USERTYPE(INNER_STRUCT))

    FMSTR_TSA_STRUCT(INNER_STRUCT)
    FMSTR_TSA_MEMBER(INNER_STRUCT, aa, FMSTR_TSA_UINT16)
    FMSTR_TSA_MEMBER(INNER_STRUCT, bb, FMSTR_TSA_UINT32)
    FMSTR_TSA_MEMBER(INNER_STRUCT, cc, FMSTR_TSA_SINT16)
    FMSTR_TSA_MEMBER(INNER_STRUCT, dd, FMSTR_TSA_SINT32)
    FMSTR_TSA_MEMBER(INNER_STRUCT, ee, FMSTR_TSA_UINT8)
    FMSTR_TSA_MEMBER(INNER_STRUCT, ff, FMSTR_TSA_SINT8)

    FMSTR_TSA_ENUM(EXAMPLE_ENUM)
    FMSTR_TSA_CONST(EXAMPLE_ENUM_FIRST_ENTRY)
    FMSTR_TSA_CONST(EXAMPLE_ENUM_SECOND_ENTRY)
    FMSTR_TSA_CONST(EXAMPLE_ENUM_THIRD_ENTRY)

    FMSTR_TSA_ENUM(INCREMENT_SPEED)
    FMSTR_TSA_CONST(SPEED_ZERO)
    FMSTR_TSA_CONST(SPEED_FAST)
    FMSTR_TSA_CONST(SPEED_NORMAL)
    FMSTR_TSA_CONST(SPEED_SLOW)

FMSTR_TSA_TABLE_END()

/****************************************************************************
 *
 * This is an example of another TSA table. Typically, you put one table
 * to each .c file where your global or static variables are instantiated.
 */

FMSTR_TSA_TABLE_BEGIN(next_table)
    FMSTR_TSA_RO_VAR(so2, FMSTR_TSA_USERTYPE(OUTER_STRUCT))
    FMSTR_TSA_RO_VAR(si2, FMSTR_TSA_USERTYPE(INNER_STRUCT))
FMSTR_TSA_TABLE_END()

/****************************************************************************
 *
 * Another TSA table with specific information about in-memory files,
 * project files and related web-links. This feature requires FreeMASTER
 * version 2.0 or later running on the PC Host to make use of this "Active Content"
 */

/* Uncomment this macro to add link to your project file accessible online */
//#define PROJECT_WEB_LINK "http://customwebsite.com/path/file.pmp"

/* In-memory text "files" which are going to be accessible in FreeMASTER browser */
#if FMSTR_USE_TSA && FMSTR_DEMO_ENOUGH_ROM
static const char readme_txt[] =
    "This is a sample text file stored in target device memory and "
    "retrieved over the FreeMASTER protocol.\n"
    "Press the back button to return to previous page.";
static const char one_txt[] =
    "This is sample file named 'one.txt'\n"
    "Press the back button to return to previous page.";
static const char two_txt[] =
    "This is sample file named 'two.txt'\n"
    "Press the back button to return to previous page.";
static const char three_txt[] =
    "This is sample file named 'three.txt'\n"
    "Press the back button to return to previous page.";
#endif

/* Data files generated with bin2h utility are put here as C arrays.
 * Get all files if enough ROM memory is available, otherwise get
 * only the basic index.html file. */
#if FMSTR_DEMO_LARGE_ROM
#include "example_data.h"
#elif FMSTR_DEMO_ENOUGH_ROM
#include "data_html_index.h"
#endif

FMSTR_TSA_TABLE_BEGIN(files_and_links)

#if FMSTR_DEMO_ENOUGH_ROM
    /* text files in the default / root folder */
    FMSTR_TSA_MEMFILE("index.htm", index_htm, sizeof(index_htm))
    FMSTR_TSA_MEMFILE("readme.txt", readme_txt, sizeof(readme_txt))
    /* text files in dedicated folder */
    FMSTR_TSA_DIRECTORY("/text_files")
    FMSTR_TSA_MEMFILE("one.txt", one_txt, sizeof(one_txt))
    FMSTR_TSA_MEMFILE("two.txt", two_txt, sizeof(two_txt))
    /* text file in separate folder which is directly specified */
    FMSTR_TSA_MEMFILE("/other/three.txt", three_txt, sizeof(three_txt))
    /* links to be visible in FreeMASTER GUI */
    FMSTR_TSA_HREF("Board's Built-in Welcome Page", "/index.htm")
#endif

#if FMSTR_DEMO_LARGE_ROM
    /* image files in dedicated folder */
    FMSTR_TSA_DIRECTORY("/images")
    FMSTR_TSA_MEMFILE("file.png", file_png, sizeof(file_png))
    FMSTR_TSA_MEMFILE("logo.png", logo_png, sizeof(logo_png))
    FMSTR_TSA_MEMFILE("fmstrlogo.png", fmstrlogo_png, sizeof(fmstrlogo_png))
    /* project files in root */
    FMSTR_TSA_MEMFILE("/demo.pmp.zip", demo_pmp, sizeof(demo_pmp))
    /* projects to be made available in FreeMASTER */
    FMSTR_TSA_PROJECT("FreeMASTER Demonstration Project (embedded in device)", "/demo.pmp.zip")
#endif /* FMSTR_DEMO_ENOUGH_ROM */

/* project file stored online */
#ifdef PROJECT_WEB_LINK
    FMSTR_TSA_PROJECT("Full FreeMASTER Project (online)", PROJECT_WEB_LINK)
#endif

    /* additional web links to be shown in FreeMASTER GUI */
    FMSTR_TSA_HREF("NXP Web Site", "http://www.nxp.com")
    FMSTR_TSA_HREF("MCUXpresso SDK Home Page","http://www.nxp.com/mcuxpresso/sdk")
    FMSTR_TSA_HREF("FreeMASTER Home Page", "http://www.nxp.com/freemaster")
FMSTR_TSA_TABLE_END()

// clang-format on

/****************************************************************************
 *
 * This list describes all TSA tables which should be exported to the
 * FreeMASTER application.
 */

FMSTR_TSA_TABLE_LIST_BEGIN()
FMSTR_TSA_TABLE(first_table)
FMSTR_TSA_TABLE(next_table)
FMSTR_TSA_TABLE(files_and_links)
FMSTR_TSA_TABLE_LIST_END()

/****************************************************************************
 *
 * This function is registered as an application command handler (see the
 * initialization code below. It gets automatically invoked when the
 * FreeMASTER PC Host tool sends appropriate application command.
 *
 */

FMSTR_APPCMD_RESULT my_appcmd_handler(FMSTR_APPCMD_CODE nAppcmd, FMSTR_APPCMD_PDATA pData, FMSTR_SIZE nDataLen)
{
    // the return value is used as the application command result code
    return 0x10;
}

/****************************************************************************
 *
 * This function is registered as a pipe communication handler (see the
 * initialization code generated by MCUX Config Tools in peripherals.c).
 *
 * The function gets automatically invoked when the FreeMASTER PC Host tool
 * services the open pipe. This handler is called any time the pipe receives
 * data to be processed or when PC probes if pipe has anything to transmit.
 *
 */

void my_pipe_handler(FMSTR_HPIPE hpipe)
{
    static const char *names[10] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

    static char buff[4];
    char *n;
    char c;

    /* This simple handler translates the digits into number names.
     * Other characters are just echoed back.  */
    while (FMSTR_PipeRead(hpipe, (FMSTR_ADDR)buff, 1, 0))
    {
        c = buff[0];

        if (c >= '0' && c <= '9')
        {
            /* echo a number name */
            n = (char *)names[c - '0'];
            FMSTR_PipeWrite(hpipe, (FMSTR_ADDR)n, FMSTR_StrLen(n), 0);
        }
        else
        {
            /* echo non-number character */
            FMSTR_PipeWrite(hpipe, (FMSTR_ADDR)buff, 1, 0);
        }
    }
}

/****************************************************************************
 *
 * Example of more useful pipe handler function which performs multiplication
 * operation on two input long integers, returning one long integer.
 *
 */

void my_pipe_math(FMSTR_HPIPE hpipe)
{
    unsigned long result;
    unsigned long buff[2];

    /* we want to receive both operands at once (we do not want to do any caching here).
     * The 'granularity' argument can be used for this purpose. */
    while (FMSTR_PipeRead(hpipe, (FMSTR_ADDR)&buff, 8, 8) == 8)
    {
        result = buff[0] * buff[1];

        /* Note: Thanks to granularity argument, we can be sure that the
         * data are sent as a whole (if there is a space in the transmit buffer)
         * or not sent at all. */
        FMSTR_PipeWrite(hpipe, (FMSTR_ADDR)&result, 4, 4);
    }
}

/* Pipe welcome strings put to pipe as soon as application starts. */
static char *sz_pipe1_hello = "Hello from embedded application! Pipe 1.\n";
static char *sz_pipe2_hello = "Kind regards from from embedded application! Pipe 2.\n";
static char *sz_pipe_other  = "Send me numbers 0-9 and I will echo it back to you on the same pipe.\n";

/*******************************************************************************************
 *
 * General initialization of FreeMASTER example is made here. Note that communication driver,
 * FreeMASTER protocol driver and its features has already been initialized by a code generated
 * by MCUXpresso Peripheral Config Tool in peripherals.c and freemaster_cfg.h files.
 *
 * Run the MCUXpresso Config Tools (v8 or later) to open the FreeMASTER configuration
 * and edit it graphically. The tool can also be used to re-generate the code
 * after any change is made.
 *
 * See more details and the generated initialization code in BOARD_InitPeripherals() function.
 */

void FMSTR_Example_Init(void)
{
    int i;

    var8     = 0;
    var8rw   = 0;
    var8inc  = 1;
    var16    = 0;
    var16rw  = 0;
    var16inc = 1;
    var32    = 0;
    var32rw  = 0;
    var32inc = 100;

    frac8   = 0;
    frac16  = 0;
    frac32  = 0;
    ufrac8  = 0;
    ufrac16 = 0;
    ufrac32 = 0;

    arr_size = ARR_SIZE;
    
#if FMSTR_DEMO_SUPPORT_I64
    var64    = 0;
    var64rw  = 0;
    var64inc = 10000;
    frac64   = 0;
    ufrac64  = 0;
#endif

#if FMSTR_DEMO_SUPPORT_FLT
    varFLT    = 0;
    varFLTrw  = 0;
    varFLTinc = 1.0;
    arrFLT_size = ARR_SIZE_FLT;    
#endif

#if FMSTR_DEMO_SUPPORT_DBL
    varDBL    = 0;
    varDBLrw  = 0;
    varDBLinc = 1.0;
    arrDBL_size = ARR_SIZE_DBL;
#endif

    varENUM     = EXAMPLE_ENUM_SECOND_ENTRY;
    varIncSpeed = SPEED_NORMAL;

    for (i = 0; i < ARR_SIZE; i++)
    {
        arr8[i]  = (unsigned char)i;
        arr16[i] = (unsigned short)i * 10;
        arr32[i] = (unsigned long)i * 100;
#if FMSTR_DEMO_SUPPORT_I64
        arr64[i] = (unsigned long long)i * 1000;
#endif
    }

#if FMSTR_DEMO_SUPPORT_FLT
    for (i = 0; i < ARR_SIZE_FLT; i++)
        arrFLT[i] = ((float)i) / 10;
#endif

#if FMSTR_DEMO_SUPPORT_DBL
    for (i = 0; i < ARR_SIZE_DBL; i++)
        arrDBL[i] = ((double)i) / 10;
#endif

        /* When application commands are enabled, register the handler callback */
#if FMSTR_USE_APPCMD && FMSTR_MAX_APPCMD_CALLS
    FMSTR_RegisterAppCmdCall(10, my_appcmd_handler);
#endif

    /* When dynamic TSA tables are enabled, add an example entry here. You can use
       dynamic TSA entries to describe variables which do not have addresses known
       in compile-time, so they cannot be put to static TSA tables. */
#if FMSTR_USE_TSA && FMSTR_USE_TSA_DYNAMIC
    FMSTR_TsaAddVar("var16prv", FMSTR_TSA_UINT16, (void *)&var16prv, sizeof(var16prv), FMSTR_TSA_INFO_RW_VAR);
#endif

#if FMSTR_USE_PIPES
    /* The pipes are created/open in generated initialization code in peripherals.c already.
       Here we send the initial welcome text to the pipes, so it is received by the
       FreeMASTER tool as soon as it opens the pipe. */
    if (FreeMASTER_Pipe_handle_1)
    {
        FMSTR_PipeWrite(FreeMASTER_Pipe_handle_1, (FMSTR_ADDR)sz_pipe1_hello, FMSTR_StrLen(sz_pipe1_hello), 0);
        FMSTR_PipeWrite(FreeMASTER_Pipe_handle_1, (FMSTR_ADDR)sz_pipe_other, FMSTR_StrLen(sz_pipe_other), 0);
    }

    /* Second pipe at port 2 */
    if (FreeMASTER_Pipe_handle_2)
    {
        FMSTR_PipeWrite(FreeMASTER_Pipe_handle_2, (FMSTR_ADDR)sz_pipe2_hello, FMSTR_StrLen(sz_pipe2_hello), 0);
        FMSTR_PipeWrite(FreeMASTER_Pipe_handle_2, (FMSTR_ADDR)sz_pipe_other, FMSTR_StrLen(sz_pipe_other), 0);
    }

    /* Note: Third pipe is a binary one, performing the mathematical operations. No welcome data put there. */
#endif
}

/****************************************************************************
 *
 * Poll function of the FreeMASTER example, called periodically from the
 * main application. We increment the variables so the change can be monitored
 * in Variable Watch or graphs displayed in the FreeMASTER tool.
 *
 */

void FMSTR_Example_Poll(void)
{
    static unsigned short div;
    unsigned short nAppCmdCode;
    int i;

    /* scope variables, increment once a while */
    if (varIncSpeed && ++div > varIncSpeed)
    {
        var8 += var8inc;
        var16 += var16inc;
        var32 += var32inc;

#if FMSTR_DEMO_SUPPORT_I64
        var64 += var64inc;
#endif
#if FMSTR_DEMO_SUPPORT_FLT
        varFLT = varFLT + varFLTinc;
        for (i = 0; i < arrFLT_size; i++)
            arrFLT[i]++;
#endif
#if FMSTR_DEMO_SUPPORT_DBL
        varDBL = varDBL + varDBLinc;
        for (i = 0; i < arrDBL_size; i++)
            arrDBL[i]++;
#endif

        div = 0;
    }

    /* the application commands not registered with callback handlers
       can be detected and processed using the API calls below */

    /* first, check if a new command has been received */
    nAppCmdCode = FMSTR_GetAppCmd();

    /* when a new command arrives, the nAppCmdCode contains the application
       command code. In other case, the "NOCMD" special value is returned */
    if (nAppCmdCode != FMSTR_APPCMDRESULT_NOCMD)
    {
        nAppCmdCounter++;

        /* each command may have different processing and different
           result code. The command processing is finished by
           calling FMSTR_AppCmdAck() with the result code value */
        switch (nAppCmdCode)
        {
            case 1:
                FMSTR_AppCmdAck(1);
                break;
            case 2:
                FMSTR_AppCmdAck(0xcd);
                break;
            default:
                FMSTR_AppCmdAck(0);
                break;
        }
    }

    /* This call should rather be placed in the timer interrupt or anywhere
       where the recorder sampling should occur. */
    FMSTR_Recorder(0);

    /* In this example we call both recorders here in the main loop. In real project
        each recorder will be called from different place. */
    FMSTR_Recorder(1);

    /* The FreeMASTER poll call must be called in the main application loop
       to handle the communication interface and protocol. */
    FMSTR_Poll();
}
