Customized SNICInterface

Fork of NySNICInterface by Ryo Iizuka

SNIC/SNIC_Core.cpp

Committer:
kishino
Date:
2014-07-15
Revision:
41:1c1b5ad4d491
Parent:
40:b6b10c22a121
Child:
43:d80bbb12ffe6

File content as of revision 41:1c1b5ad4d491:

/* Copyright (C) 2014 Murata Manufacturing Co.,Ltd., MIT License
 *  muRata, SWITCH SCIENCE Wi-FI module TypeYD SNIC-UART.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
 * and associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "mbed.h"
#include "SNIC_Core.h"
#include "SNIC_UartMsgUtil.h"
#include <string>

/** Wait signal ID of UART recv */
#define UART_DISPATCH_SIGNAL    0x00000002

#define UART_RECVBUF_SIZE       2048
#define UART_THREAD_STACK_SIZE  512
#define UART_FIXED_HEADER_SIZE    3
#define UART_FIXED_SIZE_IN_FRAME  6
#define UART_RECV_QUEUE_TIMEOUT   500

typedef struct
{
    tagMEMPOOL_BLOCK_T  *mem_p;
    unsigned int  size;
}tagUART_RECVBUF_T;

/*
    Define the global buffer using the area for Ethernet.
*/
unsigned char  gUART_TEMP_BUF[UART_RECVBUF_SIZE]                __attribute__((section("AHBSRAM1")));
unsigned char  gUART_COMMAND_BUF[UART_REQUEST_PAYLOAD_MAX]      __attribute__((section("AHBSRAM1")));
/** MemoryPool for payload of UART response */
MemoryPool<tagMEMPOOL_BLOCK_T, MEMPOOL_PAYLOAD_NUM>     mMemPoolPayload  __attribute__((section("AHBSRAM1")));
/** MemoryPool for UART receive */
MemoryPool<tagMEMPOOL_BLOCK_T, MEMPOOL_UART_RECV_NUM>   mMemPoolUartRecv __attribute__((section("AHBSRAM1")));
Queue<tagMEMPOOL_BLOCK_T, MEMPOOL_UART_RECV_NUM>        mUartRecvQueue;

tagMEMPOOL_BLOCK_T   *gUART_RCVBUF_p;
C_SNIC_Core *C_SNIC_Core::mInstance_p = NULL;

C_SNIC_Core *C_SNIC_Core::getInstance()
{
    if( mInstance_p == NULL )
    {
        mInstance_p    = new C_SNIC_Core();
    }
    return mInstance_p;
}

C_SNIC_Core::C_SNIC_Core()
{
    int i;
    
    mUartCommand_p = new C_SNIC_UartCommandManager();
    for( i = 0; i < MAX_SOCKET_ID+1; i++ )
    {
        mConnectInfo[i].recvbuf_p    = NULL;
        mConnectInfo[i].is_connected = false;
        
        mUdpRecvInfo[i].recvbuf_p    = NULL;
        mUdpRecvInfo[i].is_received  = false;
    }
    
    mUartRecvThread_p         = NULL;
    mUartRecvDispatchThread_p = NULL;
}

C_SNIC_Core::~C_SNIC_Core()
{
}

int C_SNIC_Core::resetModule( PinName reset )
{
    DigitalOut reset_pin( reset );

    reset_pin = 0;
    wait(0.1);
    reset_pin = 1;
    wait(0.1);
    
    return 0;
}

int C_SNIC_Core::initUart(PinName tx, PinName rx, int baud)
{
    mUartRequestSeq = 0;

    mUart_p = new RawSerial( tx, rx );
    mUart_p->baud( baud );
    mUart_p->format(8, SerialBase::None, 1);
     
    // Initialize uart
    gUART_RCVBUF_p = NULL;

    mUart_p->attach( C_SNIC_Core::uartRecvCallback );
    // Create UART recv dispatch thread
    mUartRecvDispatchThread_p = new Thread( C_SNIC_Core::uartRecvDispatchThread, NULL, osPriorityNormal, UART_THREAD_STACK_SIZE);
    if( mUartRecvDispatchThread_p == NULL )
    {
        DEBUG_PRINT("[C_SNIC_Core::initUart] thread create failed\r\n");
        return -1;
    }

    return 0;
}
unsigned int C_SNIC_Core::preparationSendCommand( unsigned char cmd_id, unsigned char cmd_sid
                                            , unsigned char *req_buf_p,    unsigned int req_buf_len
                                            , unsigned char *response_buf_p, unsigned char *command_p )
{
    unsigned int command_len = 0;
    
    // Make all command request
    command_len = C_SNIC_UartMsgUtil::makeRequest( cmd_id, req_buf_p, req_buf_len, command_p );

    // Set data for response
    mUartCommand_p->setCommandID( cmd_id );
    mUartCommand_p->setCommandSID( cmd_sid | 0x80 );
    mUartCommand_p->setResponseBuf( response_buf_p );
    
    return command_len;
}

int C_SNIC_Core::sendUart( unsigned int len, unsigned char *data )
{
    int ret = 0;
    mUartMutex.lock();
    for( int i = 0; i < len; i++ )
    {
        // Write to UART
        ret = mUart_p->putc( data[i] );
        if( ret == -1 )
        {
            break;
        }
    }
    mUartMutex.unlock();

    return ret;
}

tagMEMPOOL_BLOCK_T *C_SNIC_Core::allocCmdBuf()
{
    // Get buffer from MemoryPool
    return mMemPoolPayload.alloc();
}

void C_SNIC_Core::freeCmdBuf( tagMEMPOOL_BLOCK_T *buf_p )
{
    mMemPoolPayload.free( buf_p );
}

tagMEMPOOL_BLOCK_T *C_SNIC_Core::allocUartRcvBuf()
{
    // Get buffer from MemoryPool
    return mMemPoolUartRecv.alloc();
}

void C_SNIC_Core::freeUartRecvBuf( tagMEMPOOL_BLOCK_T *buf_p )
{
    mMemPoolUartRecv.free( buf_p );
}

C_SNIC_Core::tagCONNECT_INFO_T  *C_SNIC_Core::getConnectInfo( int socket_id )
{
    if( (socket_id < 0) || (socket_id > MAX_SOCKET_ID) )
    {
        return NULL;
    }
    return &mConnectInfo[socket_id];
}

C_SNIC_Core::tagUDP_RECVINFO_T  *C_SNIC_Core::getUdpRecvInfo( int socket_id )
{
    if( (socket_id < 0) || (socket_id > MAX_SOCKET_ID) )
    {
        return NULL;
    }
    return &mUdpRecvInfo[socket_id];
}

C_SNIC_UartCommandManager *C_SNIC_Core::getUartCommand()
{
    return mUartCommand_p;
}

unsigned char *C_SNIC_Core::getCommandBuf()
{
    return gUART_COMMAND_BUF;
}

void C_SNIC_Core::uartRecvCallback( void )
{
    C_SNIC_Core *instance_p = C_SNIC_Core::getInstance();
    if( instance_p != NULL )
    {
        int  recvdata = 0;

        // Check received data from UART.
        while( instance_p->mUart_p->readable() )
        {
            // Receive data from UART.
            recvdata = instance_p->mUart_p->getc();

            // Check UART receiving buffer
            if( gUART_RCVBUF_p != NULL )
            {
                gUART_RCVBUF_p->buf[ gUART_RCVBUF_p->size ] = (unsigned char)recvdata;
                gUART_RCVBUF_p->size++;
                
                if( gUART_RCVBUF_p->size == UART_FIXED_HEADER_SIZE )
                {
                    // get demand size
                    unsigned short  payload_len = ( ( (gUART_RCVBUF_p->buf[1] & ~0x80) & 0xff) | ( ( (gUART_RCVBUF_p->buf[2] & ~0xC0) << 7) & 0xff80) );
                    gUART_RCVBUF_p->demand_size = payload_len + UART_FIXED_SIZE_IN_FRAME;
                    if( gUART_RCVBUF_p->demand_size > MEMPOOL_BLOCK_SIZE )
                    {
                        gUART_RCVBUF_p->demand_size = MEMPOOL_BLOCK_SIZE;
                    }
                }

                if( gUART_RCVBUF_p->demand_size > 0 )
                {
                    // Check size of received data.
                    if( gUART_RCVBUF_p->size >= gUART_RCVBUF_p->demand_size )
                    {
                        // Add queue 
                        mUartRecvQueue.put( gUART_RCVBUF_p );
                        
                        gUART_RCVBUF_p = NULL;
                    
                        // set signal for dispatch thread
                        instance_p->mUartRecvDispatchThread_p->signal_set( UART_DISPATCH_SIGNAL );
                    }
                }

            }
            else
            {
                // Check  received data is SOM.
                if( recvdata == UART_CMD_SOM )
                {
                    gUART_RCVBUF_p = instance_p->allocUartRcvBuf();
                    gUART_RCVBUF_p->size = 0;
                    gUART_RCVBUF_p->demand_size = 0;
                    // get buffer for Uart receive
                    gUART_RCVBUF_p->buf[ 0 ] = (unsigned char)recvdata;
                    
                    gUART_RCVBUF_p->size++;
                }
            }
        }
    }
}

void C_SNIC_Core::uartRecvDispatchThread (void const *args_p)
{
    C_SNIC_Core               *instance_p   = C_SNIC_Core::getInstance();
    C_SNIC_UartCommandManager *uartCmdMgr_p = instance_p->getUartCommand();
    
    tagMEMPOOL_BLOCK_T  *uartRecvBuf_p;
    osEvent      evt;
    
    for(;;)
    {
        // wait
        Thread::signal_wait( UART_DISPATCH_SIGNAL );

        // Get scanresults from queue
        evt = mUartRecvQueue.get(UART_RECV_QUEUE_TIMEOUT);
        if (evt.status == osEventMessage)
        {
            do
            {
                uartRecvBuf_p = (tagMEMPOOL_BLOCK_T *)evt.value.p;

#if 0   /* for Debug */
                {
                    int i;
                    for(i=0;i<uartRecvBuf_p->size;i++)
                    {
                        DEBUG_PRINT("%02x", uartRecvBuf_p->buf[i]);
                    }
                    DEBUG_PRINT("\r\n");
                }
#endif
                unsigned char command_id;
                // Get payload from received data from UART.
                int payload_len = C_SNIC_UartMsgUtil::getResponsePayload( uartRecvBuf_p->size, uartRecvBuf_p->buf
                                                        , &command_id, gUART_TEMP_BUF );
                // Check receive a TCP packet
                if( (command_id == UART_CMD_ID_SNIC) && (gUART_TEMP_BUF[0] == UART_CMD_SID_SNIC_CONNECTION_RECV_IND) )
                {
                    // Packet buffering
                    uartCmdMgr_p->bufferredPacket( gUART_TEMP_BUF, payload_len );
                }
                // Check connected from TCP client
                else if( (command_id == UART_CMD_ID_SNIC) && (gUART_TEMP_BUF[0] == UART_CMD_SID_SNIC_TCP_CLIENT_SOCKET_IND) )
                {
                    // Connected from TCP client
                    uartCmdMgr_p->connectedTCPClient( gUART_TEMP_BUF, payload_len );
                }
                // Check receive UDP packet
                else if( (command_id == UART_CMD_ID_SNIC) && (gUART_TEMP_BUF[0] == UART_CMD_SID_SNIC_UDP_RECV_IND) )
                {
                    // UDP packet buffering
                    uartCmdMgr_p->bufferredUDPPacket( gUART_TEMP_BUF, payload_len );
                }
                // Check scan results indication 
                else if( (command_id == UART_CMD_ID_WIFI) && (gUART_TEMP_BUF[0] == UART_CMD_SID_WIFI_SCAN_RESULT_IND) )
                {
                    // Scan result indicate
                    uartCmdMgr_p->scanResultIndicate( gUART_TEMP_BUF, payload_len );
                }
                // Checks in the command which is waiting.
                else if( uartCmdMgr_p->isWaitingCommand(command_id, gUART_TEMP_BUF) )
                {
                    // Get buffer for payload data
                    unsigned char *payload_buf_p = uartCmdMgr_p->getResponseBuf();
                    if( payload_buf_p != NULL )
                    {
                        memcpy( payload_buf_p, gUART_TEMP_BUF, payload_len );
                        uartCmdMgr_p->setResponseBuf( NULL );
                    }
                    // Set status
                    uartCmdMgr_p->setCommandStatus( gUART_TEMP_BUF[2] );
                    // Set signal for command response wait.
                    uartCmdMgr_p->signal();
                }
                else
                {
                    DEBUG_PRINT(" The received data is not expected.\r\n");
                }
                
                // 
                instance_p->freeUartRecvBuf( uartRecvBuf_p );
                
                evt = mUartRecvQueue.get(500);
            } while( evt.status == osEventMessage );
        }
    }
}