Skip to content
Snippets Groups Projects
SilecsBlock.cpp 5.60 KiB
/*
Copyright (c) 2017 European Organization for Nuclear Research (CERN).
All rights reserved. This program and the accompanying materials
are made available under the terms of the GNU Public License v3.0
which accompanies this distribution, and is available at
http://www.gnu.org/licenses/gpl.html

Contributors:
    .European Organization for Nuclear Research    (CERN) - initial API and implementation
    .GSI Helmholtzzentrum für Schwerionenforschung (GSI)  - features and bugfixes
*/


#include <silecs-communication/interface/core/SilecsService.h>
#include <silecs-communication/interface/utility/XMLParser.h>
#include <silecs-communication/interface/equipment/SilecsPLC.h>
#include <silecs-communication/interface/equipment/SilecsBlock.h>
#include <silecs-communication/interface/equipment/SilecsRegister.h>
#include <silecs-communication/interface/core/SilecsAction.h>
#include <silecs-communication/interface/utility/SilecsException.h>
#include <silecs-communication/interface/utility/SilecsLog.h>
#include <silecs-communication/interface/utility/StringUtilities.h>

namespace Silecs
{

Block::Block(const ElementXML& blockNode, Connection& plcConnection) :
            plcConnection_(plcConnection),
            configuration_(false)
{
    name_ = blockNode.getAttribute("name");;
    if(blockNode.getName() == "Configuration-Block")
        configuration_ = true;

    StringUtilities::fromString(size_, blockNode.getAttribute("size"));
    StringUtilities::fromString(memSize_, blockNode.getAttribute("mem-size"));
    StringUtilities::fromString(address_, blockNode.getAttribute("address"));
    if (blockNode.hasAttribute("ioType")) // only IO-Blocks have this attribute
        accessArea_ = Block::whichAccessArea(blockNode.getAttribute("ioType"));
    else
        accessArea_ = AccessArea::Memory;

    resetCustomAttributes(); //by default custom-size of the block is the maximum size

    accessType_ = whichAccessType(blockNode.getName());
}

Block::~Block()
{
    if (DEBUG & Log::topics_)
        LOG(ALLOC) << "Block (delete): " << name_;
}

AccessType Block::whichAccessType(const std::string& type)
{
    if (type == "Acquisition-Block")
        return AccessType::Acquisition;
    else if (type == "Command-Block")
        return AccessType::Command;
    else if (type == "Configuration-Block")
        return AccessType::Setting;
    else if (type == "Setting-Block")
        return AccessType::Setting;
    else if (type == "Setting-IO-Block")
        return AccessType::Setting;
    else if (type == "Acquisition-IO-Block")
        return AccessType::Acquisition;
    else if (type == "Command-IO-Block")
        return AccessType::Command;
    else
        throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_TYPE, type);
}

std::string Block::whichAccessType(AccessType type)
{
    switch (type)
    {
        case AccessType::Command:
            return "WRITE-ONLY";
        case AccessType::Acquisition:
            return "READ-ONLY";
        case AccessType::Setting:
            return "READ-WRITE";
        default:
            throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_TYPE, StringUtilities::toString(static_cast<int>(type)));
    }
}

AccessArea Block::whichAccessArea(std::string area)
{
    StringUtilities::toLower(area);
    if (area == "memory")
        return AccessArea::Memory;
    else if (area == "digital-io")
        return AccessArea::Digital;
    else if (area == "analog-io")
        return AccessArea::Analog;
    else
        throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_AREA, area);
}

std::string Block::whichAccessArea(AccessArea area)
{
    switch (area)
    {
        case AccessArea::Memory:
            return "MEMORY";
        case AccessArea::Digital:
            return "DIGITAL-IO";
        case AccessArea::Analog:
            return "ANALOG-IO";
        default:
            throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_ACCESS_AREA, StringUtilities::toString(static_cast<int>(area)));
    }
}

void Block::setCustomAttributes(const unsigned long customAddress, const unsigned long customOffset, const unsigned long customSize)
{
    //user wants to limit the size of data to be sent/receive - check that it is lower than design allocation size
    if (customSize > memSize_)
        throw SilecsException(__FILE__, __LINE__, PARAM_EXCEEDED_BLOCK_SIZE, StringUtilities::toString(memSize_));

    customAddress_ = customAddress;
    customOffset_ = customOffset;
    customSize_ = customSize;
    customAttributes_ = true;
    LOG(DEBUG) << "Set custom attributes of block: " << name_ << ", memSize: " << memSize_ << ", customSize: " << customSize << ", customAddress: " << customAddress << ", customOffset: " << customOffset;
}

void Block::resetCustomAttributes()
{
    customAttributes_ = false;
    LOG(DEBUG) << "Reset custom attributes of block: " << name_;
}

void Block::importRegisters(void* pBuffer, timeval ts)
{
    for (auto& reg : registers_)
    {
        if (reg->getFormat() == String)
        {
            reg->importString(pBuffer, ts);
        }
        else
        {
            reg->importValue(pBuffer, ts);
        }
    }
}

void Block::exportRegisters(void* pBuffer)
{
    for (auto& reg : registers_)
    {
        if (reg->getFormat() == String)
        {
            reg->exportString(pBuffer);
        }
        else
        {
            reg->exportValue(pBuffer);
        }
    }
}

void Block::copyInToOut()
{
    for (auto& reg : registers_)
    {
        if (reg->isReadable() && reg->isWritable())
        {
            reg->copyValue();
        }
    }
}

const std::vector<std::unique_ptr<Register>>& Block::getRegisters() const
{
    return registers_;
}

} // namespace