WizziLab / modem_ref_v5_3_217

Dependents:   modem_ref_helper_for_v5_3_217

src/wc_deserializer.cpp

Committer:
Jeej
Date:
2018-09-26
Revision:
36:ac99535c4843
Parent:
19:701d5669f2e9

File content as of revision 36:ac99535c4843:

/// @copyright
/// ========================================================================={{{
/// Copyright (c) 2013-2016 WizziLab                                           /
/// All rights reserved                                                        /
/// =========================================================================}}}
/// @endcopyright

//  =======================================================================
/// @file       wc_deserializer.c
/// @brief      Exemple of WizziCom serial transport layer parser.
///             Can be used as entry-point/scheduler for modem_ref
//  =======================================================================
#include "modem_ref.h"
#include "WizziDebug.h"

// Depending on Host needs/capacities, choose variable-size buffer allocation style
#if 1 // static buffer alloc
    #define MAX_RX_BUFFER_SIZE              (256)
    #define GET_BUFFER(_s)                  rxbuf
    #define FREE_BUFFER(_b)
    static u8 rxbuf[MAX_RX_BUFFER_SIZE];
#else // Dynamic alloc
    #define GET_BUFFER(_s)                  MALLOC(_s);
    #define FREE_BUFFER(_b)                 FREE(_b);
#endif

enum { S_SYNC0, S_SYNC1, S_SIZE, S_SEQU, S_FLOWID, S_DATA };

//======================================================================
// wc_deserializer
//----------------------------------------------------------------------
/// @brief  Parse serial flow character-wise and extract packets from
///         WizziCom serial transport layer (WC).
///         It calls modem_input on complete payloads.
/// @param  c           : received character.
/// @param  init        : 0 when parsing, 1 to init/reinit parser.
/// @return flowid of successfuly parsed packet, 0 otherwise.
/// @note   This function must be called on every received character on
///         modem serial link
/// @note   This function should not be directly called from (serial)
///         ISR as it is the entry point for all driver/callback execution.
/// @note   If WC deserialization is performed by other means, and that
///         full packets are available, one should do direct calls to
///         modem_input
//======================================================================
public uint8_t wc_deserializer(uint8_t c, u8 init)
{
    static u8 state;
    static u8 rx_ptr;
    static u8 rx_size;
    static u8 rx_sequ;
    static u8 rx_flowid;
    static u8* rx_data;

    if (init)
    {
        state = S_SYNC0;
        rx_sequ = 255;
    }

    //PRINT("%02X %d %02X %d %d\r\n", c, state, rx_flowid, rx_sequ, rx_size);
    //vTaskDelay(10);

    // WC Packet decap'
    switch(state)
    {
        case S_SYNC0:
            state   = (c == WC_SYNC_BYTE_0)?S_SYNC1:S_SYNC0;
            rx_ptr  = 0;
            rx_size = 0;
            rx_data = (u8*)NULL;
            rx_flowid = WC_FLOW_ID_NONE;
            return WC_FLOW_ID_NONE;
        case S_SYNC1:
            state = (c == WC_SYNC_BYTE_1)?S_SIZE:
                    (c == WC_SYNC_BYTE_0)?S_SYNC1:S_SYNC0;
            return WC_FLOW_ID_NONE;
        case S_SIZE:
            state       = S_SEQU;
            rx_size     = (u8)c;
            if (rx_size)
                        {
                            rx_data = GET_BUFFER(rx_size);
                        }
            return WC_FLOW_ID_NONE;
        case S_SEQU:
            state       = S_FLOWID;
            int missed = c - rx_sequ - 1;
            if (missed)
            {
                PRINT("Missed %d packets!\r\n", missed);
            }
            rx_sequ     = (u8)c;
            return WC_FLOW_ID_NONE;
        case S_FLOWID:
            state       = (rx_size!=0)?S_DATA:S_SYNC0;
            rx_flowid   = (u8)c;
            break;
        case S_DATA:
            state       = (rx_ptr >= rx_size)?S_SYNC0:S_DATA;
            if (rx_data)
            {
                rx_data[rx_ptr++] = (u8)c;
            }
            break;
        default:
            break;
    }

    if ((rx_size == rx_ptr) && (WC_FLOW_ID_NONE != rx_flowid))
    {
        // Full packet
        state = S_SYNC0;
        //PRINT("--> (0x%02X) %3d %d\r\n", rx_flowid, rx_sequ, rx_size);
        modem_input(rx_flowid, rx_data, rx_size);
        if (rx_data) { FREE_BUFFER(rx_data); }
        return rx_flowid;
    }
    else
    {
        return WC_FLOW_ID_NONE;
    }
}