// $Id: MELRandom.cpp,v 1.2 2002/10/12 09:11:53 fukasawa Exp $

//=============================================================================
/**
 *  @file    MELRandom.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-2002 BEE Co.,Ltd. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

#define BEE_BUILD_DLL

#include "MELDeviceServer.h"
#include "MELMemory.h"
#if !defined(PLC_SHARED_MEMORY)
#include "Mdfunc.h"
#endif
#include "ace/Mem_Map.h"
#include "ace/Log_Msg.h"

//------------------------------------------------------------------------------
//
// Dummy functions of MELSEC
//
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Random read data from bus driver
//------------------------------------------------------------------------------
int RandomRead(long path, short stnum, short devp[], short bufp[], short bufsize)
{
    int result = MEL_NORMAL;
#if defined(PLC_SHARED_MEMORY)
    int blockq = devp[0] & 0xFFFF;
    u_short * curptr = (u_short *)&devp[1];
    u_short * curbufp = (u_short *)bufp;
    size_t    byteq;
    size_t    restsize = (size_t)bufsize;
    for (int i = 0; i < blockq; i++)
    {
        int devtype = *(curptr + 0);
        u_int addr = *(curptr + 1);
        u_int size = *(curptr + 2);
        PLCDevice * pmem = MELDeviceServer::instance()->get(devtype);

        byteq = (pmem->isBit()) ? ((size + 15) / 16) * 2 : size * 2;
        if (byteq > restsize)
        {
            // Area overflow
            break;
        }

        pmem->read(addr, size, curbufp);          // ***

        curptr += 3;
        curbufp += (byteq / 2);
        restsize -= byteq;
    }

#else
    MELDeviceServer * melsvr = MELDeviceServer::instance();
#if 1
    char * bytebufp = (char *)bufp;
    for (int d = 0; d < *devp; d++)
    {
        u_int p = d * 3;
        short devtype = *(devp + p + 1);
        u_short dsize = *(devp + p + 3);
        u_int byteq;
        PLCDevice * pmem = MELDeviceServer::instance()->get(devtype);
        if (devtype >= MELDEV_ZR || pmem == NULL)
        {
            byteq = dsize * 2;
        }
        else
        {
            byteq = (pmem->isBit()) ? (dsize + 7) / 8 : dsize * 2;
        }
        short bsize = byteq;
        if (devtype != MELDEV_ZR)   // Skip top 3 blocks in ZR 
        {
            result = mdReceive(melsvr->getPath(), melsvr->getStationNum(),
                               devtype, *(devp + p + 2), &bsize, bytebufp);
        }
        bytebufp += byteq;
    }
#else
    // OBSOLETE:
    // result = mdRandR(melsvr->getPath(), melsvr->getStationNum(),
    //                 devp, bufp, bufsize);
#endif
#endif
    return result;
}

//------------------------------------------------------------------------------
// Random write data to bus driver
//------------------------------------------------------------------------------
int RandomWrite(short * devp, unsigned short * bufp, unsigned short bufsize)
{
    int result = MEL_NORMAL;
#if defined(PLC_SHARED_MEMORY)
    int blockq = devp[0] & 0xFFFF;
    u_short * curptr = (u_short *)&devp[1];
    u_short * curbufp = (u_short *)bufp;
    size_t    byteq;
    size_t    restsize = (size_t)bufsize;
    for (int i = 0; i < blockq; i++)
    {
        int devtype = *(curptr + 0);
        u_int addr = *(curptr + 1);
        u_int size = *(curptr + 2);
        PLCDevice * pmem = MELDeviceManager::instance()->get(devtype);

        byteq = (pmem->isBit()) ? ((size + 15) / 16) * 2 : size * 2;
        if (byteq > restsize)
        {
            // Area overflow
            break;
        }

        pmem->write(addr, size, curbufp);          // ***

        curptr += 3;
        curbufp += (byteq / 2);
        restsize -= byteq;
    }


#else
    MELDeviceServer * melsvr = MELDeviceServer::instance();
    result = mdRandW(melsvr->getPath(), melsvr->getStationNum(), devp, bufp, bufsize);
#endif
    return result;
}
