<commit_before>#include "PointProcessor.h"
#include <Shiny.h>

namespace sensekit { namespace plugins { namespace xs {

    PointProcessor::PointProcessor(PluginServiceProxy& pluginService,
                   Sensor streamset,
                   StreamDescription& depthDesc,
                   PluginLogger& pluginLogger) :
       m_pluginService(pluginService),
       m_streamset(streamset),
       m_logger(pluginLogger),
       m_reader(streamset.create_reader())
    {
        PROFILE_FUNC();

        m_depthStream = m_reader.stream<DepthStream>(depthDesc.get_subtype());
        m_depthStream.start();

        m_reader.addListener(*this);
    }

    PointProcessor::~PointProcessor()
    {
        PROFILE_FUNC();

    }

    void PointProcessor::on_frame_ready(StreamReader& reader, Frame& frame)
    {
        PROFILE_FUNC();

        DepthFrame depthFrame = frame.get<DepthFrame>();

        create_point_stream_if_necessary(depthFrame);

        if (m_pointStream->has_connections())
        {
            update_pointframe_from_depth(depthFrame);
        }
    }

    void PointProcessor::create_point_stream_if_necessary(DepthFrame& depthFrame)
    {
        PROFILE_FUNC();

        if (m_pointStream != nullptr)
        {
            return;
        }
        //TODO check for changes in depthFrame width and height and update bin size
        m_logger.info("creating point stream");

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();
        m_pointStream = std::make_unique<PointStream>(m_pluginService, m_streamset, width, height);

        m_depthConversionCache = m_depthStream.depth_to_world_data();
    }

    void PointProcessor::update_pointframe_from_depth(DepthFrame& depthFrame)
    {
        PROFILE_FUNC();

        //use same frameIndex as source depth frame
        sensekit_frame_index_t frameIndex = depthFrame.frameIndex();

        sensekit_imageframe_wrapper_t* pointFrameWrapper = m_pointStream->begin_write(frameIndex);

        if (pointFrameWrapper != nullptr)
        {
            pointFrameWrapper->frame.frame = nullptr;
            pointFrameWrapper->frame.data = &pointFrameWrapper->frame_data[0];

            sensekit_image_metadata_t metadata;

            metadata.width = depthFrame.resolutionX();
            metadata.height = depthFrame.resolutionY();
            metadata.bytesPerPixel = sizeof(sensekit_vector3f_t);

            pointFrameWrapper->frame.metadata = metadata;

            Vector3f* p_points = reinterpret_cast<Vector3f*>(pointFrameWrapper->frame.data);
            calculate_point_frame(depthFrame, p_points);

            m_pointStream->end_write();
        }
    }

    void PointProcessor::calculate_point_frame(DepthFrame& depthFrame,
                                               Vector3f* p_points)
    {
        PROFILE_FUNC();

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();
        const int16_t* p_depth = depthFrame.data();

        const conversion_cache_t conversionData = m_depthConversionCache;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x, ++p_points, ++p_depth)
            {
                PROFILE_BEGIN(point_math);
                uint16_t depth = *p_depth;
                Vector3f& point = *p_points;

                float normalizedX = static_cast<float>(x) / conversionData.resolutionX - .5f;
                float normalizedY = .5f - static_cast<float>(y) / conversionData.resolutionY;

                point.x = normalizedX * depth * conversionData.xzFactor;
                point.y = normalizedY * depth * conversionData.yzFactor;
                point.z = depth;

                PROFILE_END();
            }
        }
    }

} } }
<commit_msg>Remove profile block from inner loop<commit_after>#include "PointProcessor.h"
#include <Shiny.h>

namespace sensekit { namespace plugins { namespace xs {

    PointProcessor::PointProcessor(PluginServiceProxy& pluginService,
                   Sensor streamset,
                   StreamDescription& depthDesc,
                   PluginLogger& pluginLogger) :
       m_pluginService(pluginService),
       m_streamset(streamset),
       m_logger(pluginLogger),
       m_reader(streamset.create_reader())
    {
        PROFILE_FUNC();

        m_depthStream = m_reader.stream<DepthStream>(depthDesc.get_subtype());
        m_depthStream.start();

        m_reader.addListener(*this);
    }

    PointProcessor::~PointProcessor()
    {
        PROFILE_FUNC();

    }

    void PointProcessor::on_frame_ready(StreamReader& reader, Frame& frame)
    {
        PROFILE_FUNC();

        DepthFrame depthFrame = frame.get<DepthFrame>();

        create_point_stream_if_necessary(depthFrame);

        if (m_pointStream->has_connections())
        {
            update_pointframe_from_depth(depthFrame);
        }
    }

    void PointProcessor::create_point_stream_if_necessary(DepthFrame& depthFrame)
    {
        PROFILE_FUNC();

        if (m_pointStream != nullptr)
        {
            return;
        }
        //TODO check for changes in depthFrame width and height and update bin size
        m_logger.info("creating point stream");

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();
        m_pointStream = std::make_unique<PointStream>(m_pluginService, m_streamset, width, height);

        m_depthConversionCache = m_depthStream.depth_to_world_data();
    }

    void PointProcessor::update_pointframe_from_depth(DepthFrame& depthFrame)
    {
        PROFILE_FUNC();

        //use same frameIndex as source depth frame
        sensekit_frame_index_t frameIndex = depthFrame.frameIndex();

        sensekit_imageframe_wrapper_t* pointFrameWrapper = m_pointStream->begin_write(frameIndex);

        if (pointFrameWrapper != nullptr)
        {
            pointFrameWrapper->frame.frame = nullptr;
            pointFrameWrapper->frame.data = &pointFrameWrapper->frame_data[0];

            sensekit_image_metadata_t metadata;

            metadata.width = depthFrame.resolutionX();
            metadata.height = depthFrame.resolutionY();
            metadata.bytesPerPixel = sizeof(sensekit_vector3f_t);

            pointFrameWrapper->frame.metadata = metadata;

            Vector3f* p_points = reinterpret_cast<Vector3f*>(pointFrameWrapper->frame.data);
            calculate_point_frame(depthFrame, p_points);

            m_pointStream->end_write();
        }
    }

    void PointProcessor::calculate_point_frame(DepthFrame& depthFrame,
                                               Vector3f* p_points)
    {
        PROFILE_FUNC();

        int width = depthFrame.resolutionX();
        int height = depthFrame.resolutionY();
        const int16_t* p_depth = depthFrame.data();

        const conversion_cache_t conversionData = m_depthConversionCache;

        for (int y = 0; y < height; ++y)
        {
            for (int x = 0; x < width; ++x, ++p_points, ++p_depth)
            {
                uint16_t depth = *p_depth;
                Vector3f& point = *p_points;

                float normalizedX = static_cast<float>(x) / conversionData.resolutionX - .5f;
                float normalizedY = .5f - static_cast<float>(y) / conversionData.resolutionY;

                point.x = normalizedX * depth * conversionData.xzFactor;
                point.y = normalizedY * depth * conversionData.yzFactor;
                point.z = depth;
            }
        }
    }

} } }
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// boost
#include <boost/python.hpp>

//mapnik
#include <mapnik/color.hpp>

using mapnik::color;

struct color_pickle_suite : boost::python::pickle_suite
{
    static boost::python::tuple
    getinitargs(const color& c)
    {
        using namespace boost::python;
        return boost::python::make_tuple(c.red(),c.green(),c.blue(),c.alpha());
    }
};

void export_color ()
{
    using namespace boost::python;
    class_<color>("Color", init<int,int,int,int>(
                      ( arg("r"), arg("g"), arg("b"), arg("a") ),
                      "Creates a new color from its RGB components\n"
                      "and an alpha value.\n"
                      "All values between 0 and 255.\n")
        )
        .def(init<int,int,int>(
                 ( arg("r"), arg("g"), arg("b") ),
                 "Creates a new color from its RGB components.\n"
                 "All values between 0 and 255.\n")
            )
        .def(init<std::string>(
                 ( arg("color_string") ),
                 "Creates a new color from its CSS string representation.\n"
                 "The string may be a CSS color name (e.g. 'blue')\n"
                 "or a hex color string (e.g. '#0000ff').\n")
            )
        .add_property("r",
                      &color::red,
                      &color::set_red,
                      "Gets or sets the red component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("g",
                      &color::green,
                      &color::set_green,
                      "Gets or sets the green component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("b",
                      &color::blue,
                      &color::set_blue,
                      "Gets or sets the blue component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("a",
                      &color::alpha,
                      &color::set_alpha,
                      "Gets or sets the alpha component.\n"
                      "The value is between 0 and 255.\n")
        .def(self == self)
        .def(self != self)
        .def_pickle(color_pickle_suite())
        .def("__str__",&color::to_string)
        .def("to_hex_string",&color::to_hex_string,
             "Returns the hexadecimal representation of this color.\n"
             "\n"
             "Example:\n"
             ">>> c = Color('blue')\n"
             ">>> c.to_hex_string()\n"
             "'#0000ff'\n")
        ;
}
<commit_msg>expose mapnik.Color.packed to get unsigned rgba value<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// boost
#include <boost/python.hpp>

//mapnik
#include <mapnik/color.hpp>

using mapnik::color;

struct color_pickle_suite : boost::python::pickle_suite
{
    static boost::python::tuple
    getinitargs(const color& c)
    {
        using namespace boost::python;
        return boost::python::make_tuple(c.red(),c.green(),c.blue(),c.alpha());
    }
};

void export_color ()
{
    using namespace boost::python;
    class_<color>("Color", init<int,int,int,int>(
                      ( arg("r"), arg("g"), arg("b"), arg("a") ),
                      "Creates a new color from its RGB components\n"
                      "and an alpha value.\n"
                      "All values between 0 and 255.\n")
        )
        .def(init<int,int,int>(
                 ( arg("r"), arg("g"), arg("b") ),
                 "Creates a new color from its RGB components.\n"
                 "All values between 0 and 255.\n")
            )
        .def(init<std::string>(
                 ( arg("color_string") ),
                 "Creates a new color from its CSS string representation.\n"
                 "The string may be a CSS color name (e.g. 'blue')\n"
                 "or a hex color string (e.g. '#0000ff').\n")
            )
        .add_property("r",
                      &color::red,
                      &color::set_red,
                      "Gets or sets the red component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("g",
                      &color::green,
                      &color::set_green,
                      "Gets or sets the green component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("b",
                      &color::blue,
                      &color::set_blue,
                      "Gets or sets the blue component.\n"
                      "The value is between 0 and 255.\n")
        .add_property("a",
                      &color::alpha,
                      &color::set_alpha,
                      "Gets or sets the alpha component.\n"
                      "The value is between 0 and 255.\n")
        .def(self == self)
        .def(self != self)
        .def_pickle(color_pickle_suite())
        .def("__str__",&color::to_string)
        .def("packed",&color::rgba)
        .def("to_hex_string",&color::to_hex_string,
             "Returns the hexadecimal representation of this color.\n"
             "\n"
             "Example:\n"
             ">>> c = Color('blue')\n"
             ">>> c.to_hex_string()\n"
             "'#0000ff'\n")
        ;
}
<|endoftext|>


<commit_before>/* This file is part of python_mapnik (c++/python mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
 *
 * Mapnik 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 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.
 */

//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $

#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <mapnik.hpp>

using mapnik::Layer;
using mapnik::parameters;

struct layer_pickle_suite : boost::python::pickle_suite
{

    static boost::python::tuple
    getinitargs(const Layer& l)
    {
	using namespace boost::python;
        return boost::python::make_tuple(l.params());
    }
    static boost::python::tuple
    getstate(const Layer& l)
    {
	using namespace boost::python;

	std::vector<std::string> const& styles=l.styles();
	std::vector<std::string>::const_iterator itr=styles.begin();
	boost::python::list py_styles;

	while (itr!=styles.end())
	{
	    py_styles.append(*itr++);
	}

	return boost::python::make_tuple(l.getMinZoom(),
			  l.getMaxZoom(),
			  py_styles);
    }

    static void
    setstate (Layer& l, boost::python::tuple state)
    {
	using namespace boost::python;
	if (len(state) != 3)
	{
	    PyErr_SetObject(PyExc_ValueError,
			    ("expected 3-item tuple in call to __setstate__; got %s"
			     % state).ptr()
			    );
	    throw_error_already_set();
	}

	l.setMinZoom(extract<double>(state[0]));
	l.setMaxZoom(extract<double>(state[1]));

	boost::python::list styles=extract<boost::python::list>(state[2]);
	for (int i=0;i<len(styles);++i)
	{
	    l.add_style(extract<std::string>(styles[i]));
	}
    }
};

namespace
{
    //user-friendly wrapper that uses Python dictionary
    using namespace boost::python;
    Layer create_layer(const dict& d)
    {
	parameters params;
	boost::python::list keys=d.keys();
	for (int i=0;i<len(keys);++i)
	{
	    std::string key=extract<std::string>(keys[i]);
            std::string value=extract<std::string>(d[key]);
	    params[key] = value;
	}
	return Layer(params);
    }
}

void export_layer()
{
    using namespace boost::python;
    class_<std::vector<std::string> >("Styles")
    	.def(vector_indexing_suite<std::vector<std::string>,true >())
    	;

    class_<Layer>("Layer","A map layer.",no_init)
        .def("name",&Layer::name,return_value_policy<copy_const_reference>())
        .def("params",&Layer::params,return_value_policy<reference_existing_object>())
        .def("envelope",&Layer::envelope)
	.add_property("minzoom",&Layer::getMinZoom,&Layer::setMinZoom)
	.add_property("maxzoom",&Layer::getMaxZoom,&Layer::setMaxZoom)
	.add_property("styles",make_function
		      (&Layer::styles,return_value_policy<reference_existing_object>()))
        .def_pickle(layer_pickle_suite())
        ;
    def("Layer",&create_layer);
}
<commit_msg>Changed the layer constructor to use a more pythonic:<commit_after>/* This file is part of python_mapnik (c++/python mapping toolkit)
 * Copyright (C) 2005 Artem Pavlenko, Jean-Francois Doyon
 *
 * Mapnik 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 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.
 */

//$Id: mapnik_layer.cc 17 2005-03-08 23:58:43Z pavlenko $

#include <boost/python.hpp>
#include <boost/python/detail/api_placeholder.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include <mapnik.hpp>

using mapnik::Layer;
using mapnik::parameters;

struct layer_pickle_suite : boost::python::pickle_suite
{

    static boost::python::tuple
    getinitargs(const Layer& l)
    {
	using namespace boost::python;
        return boost::python::make_tuple(l.params());
    }
    static boost::python::tuple
    getstate(const Layer& l)
    {
	using namespace boost::python;

	std::vector<std::string> const& styles=l.styles();
	std::vector<std::string>::const_iterator itr=styles.begin();
	boost::python::list py_styles;

	while (itr!=styles.end())
	{
	    py_styles.append(*itr++);
	}

	return boost::python::make_tuple(l.getMinZoom(),
			  l.getMaxZoom(),
			  py_styles);
    }

    static void
    setstate (Layer& l, boost::python::tuple state)
    {
	using namespace boost::python;
	if (len(state) != 3)
	{
	    PyErr_SetObject(PyExc_ValueError,
			    ("expected 3-item tuple in call to __setstate__; got %s"
			     % state).ptr()
			    );
	    throw_error_already_set();
	}

	l.setMinZoom(extract<double>(state[0]));
	l.setMaxZoom(extract<double>(state[1]));

	boost::python::list styles=extract<boost::python::list>(state[2]);
	for (int i=0;i<len(styles);++i)
	{
	    l.add_style(extract<std::string>(styles[i]));
	}
    }
};

namespace
{
    using namespace boost::python;
    Layer create_layer(const char* name, const char* type, const char* file)
    {
	parameters params;
	params["name"] = name;
        params["type"] = type;
        params["file"] = file;
	return Layer(params);
    }
}

void export_layer()
{
    using namespace boost::python;
    class_<std::vector<std::string> >("Styles")
    	.def(vector_indexing_suite<std::vector<std::string>,true >())
    	;

    class_<Layer>("Layer","A map layer.",no_init)
        .def("name",&Layer::name,return_value_policy<copy_const_reference>())
        .def("params",&Layer::params,return_value_policy<reference_existing_object>())
        .def("envelope",&Layer::envelope)
	.add_property("minzoom",&Layer::getMinZoom,&Layer::setMinZoom)
	.add_property("maxzoom",&Layer::getMaxZoom,&Layer::setMaxZoom)
	.add_property("styles",make_function
		      (&Layer::styles,return_value_policy<reference_existing_object>()))
        .def_pickle(layer_pickle_suite())
        ;
    def("Layer",&create_layer);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/

#ifndef REALM_UTIL_EMULATED_ROBUST_MUTEX
#define REALM_UTIL_EMULATED_ROBUST_MUTEX

// Enable this only on platforms where it might be needed
// currently APPLE.
//#if REALM_PLATFORM_APPLE
#define REALM_ROBUST_MUTEX_EMULATION
//#endif

#include <realm/util/features.h>
#include <realm/util/thread.hpp>
#include <realm/util/file.hpp>

namespace realm {
namespace util {

// fwd decl to support friend decl below
class PlatformSpecificCondVar;

/// Emulation of a Robust Mutex.
/// A Robust Mutex is an interprocess mutex which will automatically
/// release any locks held by a process when it crashes. Contrary to
/// Posix robust mutexes, this robust mutex is not capable of informing
/// participants that they have been granted a lock after a crash of
/// the process holding it.

class EmulatedRobustMutex {
public:
    EmulatedRobustMutex();
    ~EmulatedRobustMutex() noexcept;

#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct SharedPart { };
#else
    using SharedPart = RobustMutex;
#endif

    class LockGuard {
    public:
        LockGuard(EmulatedRobustMutex& mutex) : m_mutex(mutex)
        {
            m_mutex.lock();
        }
        ~LockGuard()
        {
            m_mutex.unlock();
        }
    private:
        EmulatedRobustMutex& m_mutex;
    };

    /// You need to bind the emulation to a SharedPart in shared/mmapped memory.
    /// The SharedPart is assumed to have been initialized (possibly by another process)
    /// elsewhere.
    void set_shared_part(SharedPart& shared_part, std::string path, std::string mutex_name);

    /// Lock the mutex. If the mutex is already locked, wait for it to be unlocked.
    void lock();

    /// Unlock the mutex
    void unlock();

    /// Attempt to check if the mutex is valid (only relevant if not emulating)
    bool is_valid() noexcept;

//private:
#ifndef REALM_ROBUST_MUTEX_EMULATION
    SharedPart* m_shared_part = 0;
#else
    std::string m_filename;
    File m_file;
    Mutex m_local_mutex;
#endif
    friend class PlatformSpecificCondVar;
};

inline EmulatedRobustMutex::EmulatedRobustMutex()
{
}

inline EmulatedRobustMutex::~EmulatedRobustMutex() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    m_local_mutex.lock();
    m_file.close();
    m_local_mutex.unlock();
#endif
}

inline void EmulatedRobustMutex::set_shared_part(SharedPart& shared_part,
                                                 std::string path,
                                                 std::string mutex_name)
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    m_shared_part = &shared_part;
    static_cast<void>(path);
    static_cast<void>(mutex_name);
#else
    static_cast<void>(shared_part);
    if (m_file.is_attached()) {
        m_file.close();
    }
    m_filename = path + "_" + mutex_name + ".lck";
    m_local_mutex.lock();
    m_file.open(m_filename, File::mode_Write);
    m_local_mutex.unlock();
#endif
}

inline void EmulatedRobustMutex::lock()
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    m_shared_part->lock([](){});
#else
    m_local_mutex.lock();
    m_file.lock_exclusive();
#endif
}

inline void EmulatedRobustMutex::unlock()
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    m_shared_part->unlock();
#else
    m_file.unlock();
    m_local_mutex.unlock();
#endif
}

inline bool EmulatedRobustMutex::is_valid() noexcept
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    return m_shared_part->is_valid();
#else
    return true;
#endif
}

} // namespace util
} // namespace realm

#endif // #ifndef REALM_UTIL_EMULATED_ROBUST_MUTEX
<commit_msg>added is_robust_on_this_platform()<commit_after>/*************************************************************************
 *
 * REALM CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2015] Realm Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Realm Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Realm Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Realm Incorporated.
 *
 **************************************************************************/

#ifndef REALM_UTIL_EMULATED_ROBUST_MUTEX
#define REALM_UTIL_EMULATED_ROBUST_MUTEX

// Enable this only on platforms where it might be needed
// currently APPLE.
//#if REALM_PLATFORM_APPLE
#define REALM_ROBUST_MUTEX_EMULATION
//#endif

#include <realm/util/features.h>
#include <realm/util/thread.hpp>
#include <realm/util/file.hpp>

namespace realm {
namespace util {

// fwd decl to support friend decl below
class PlatformSpecificCondVar;

/// Emulation of a Robust Mutex.
/// A Robust Mutex is an interprocess mutex which will automatically
/// release any locks held by a process when it crashes. Contrary to
/// Posix robust mutexes, this robust mutex is not capable of informing
/// participants that they have been granted a lock after a crash of
/// the process holding it.

class EmulatedRobustMutex {
public:
    EmulatedRobustMutex();
    ~EmulatedRobustMutex() noexcept;

#ifdef REALM_ROBUST_MUTEX_EMULATION
    struct SharedPart { };
#else
    using SharedPart = RobustMutex;
#endif

    class LockGuard {
    public:
        LockGuard(EmulatedRobustMutex& mutex) : m_mutex(mutex)
        {
            m_mutex.lock();
        }
        ~LockGuard()
        {
            m_mutex.unlock();
        }
    private:
        EmulatedRobustMutex& m_mutex;
    };

    /// You need to bind the emulation to a SharedPart in shared/mmapped memory.
    /// The SharedPart is assumed to have been initialized (possibly by another process)
    /// elsewhere.
    void set_shared_part(SharedPart& shared_part, std::string path, std::string mutex_name);

    /// Lock the mutex. If the mutex is already locked, wait for it to be unlocked.
    void lock();

    /// Unlock the mutex
    void unlock();

    /// Attempt to check if the mutex is valid (only relevant if not emulating)
    bool is_valid() noexcept;

    static bool is_robust_on_this_platform()
    {
#ifdef REALM_ROBUST_MUTEX_EMULATION
        return true;  // we're faking it!
#else
        return RobustMutex::is_robust_on_this_platform();
#endif
    }
//private:
#ifndef REALM_ROBUST_MUTEX_EMULATION
    SharedPart* m_shared_part = 0;
#else
    std::string m_filename;
    File m_file;
    Mutex m_local_mutex;
#endif
    friend class PlatformSpecificCondVar;
};

inline EmulatedRobustMutex::EmulatedRobustMutex()
{
}

inline EmulatedRobustMutex::~EmulatedRobustMutex() noexcept
{
#ifdef REALM_ROBUST_MUTEX_EMULATION
    m_local_mutex.lock();
    m_file.close();
    m_local_mutex.unlock();
#endif
}

inline void EmulatedRobustMutex::set_shared_part(SharedPart& shared_part,
                                                 std::string path,
                                                 std::string mutex_name)
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    m_shared_part = &shared_part;
    static_cast<void>(path);
    static_cast<void>(mutex_name);
#else
    static_cast<void>(shared_part);
    if (m_file.is_attached()) {
        m_file.close();
    }
    m_filename = path + "_" + mutex_name + ".lck";
    m_local_mutex.lock();
    m_file.open(m_filename, File::mode_Write);
    m_local_mutex.unlock();
#endif
}

inline void EmulatedRobustMutex::lock()
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    m_shared_part->lock([](){});
#else
    m_local_mutex.lock();
    m_file.lock_exclusive();
#endif
}

inline void EmulatedRobustMutex::unlock()
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    m_shared_part->unlock();
#else
    m_file.unlock();
    m_local_mutex.unlock();
#endif
}

inline bool EmulatedRobustMutex::is_valid() noexcept
{
#ifndef REALM_ROBUST_MUTEX_EMULATION
    REALM_ASSERT(m_shared_part);
    return m_shared_part->is_valid();
#else
    return true;
#endif
}

} // namespace util
} // namespace realm

#endif // #ifndef REALM_UTIL_EMULATED_ROBUST_MUTEX
<|endoftext|>


<commit_before>/*! \brief Very simple HTTP server. Everything's done for you.
 *
 * It just serves static pages.
 */
#include <x0/http/HttpServer.h>
#include <x0/http/HttpRequest.h>
#include <x0/io/BufferSource.h>
#include <iostream>
#include <fstream>
#include <memory>
#include <ev++.h>

class MyServer {
private:
    struct ev_loop* loop_;
    ev::sig sigterm_;
    std::unique_ptr<x0::HttpServer> http_;

public:
    MyServer() :
        loop_(ev_default_loop()),
        sigterm_(loop_),
        http_()
    {
    }

    ~MyServer()
    {
        if (sigterm_.is_active()) {
            ev_ref(loop_);
            sigterm_.stop();
        }
    }

    bool requestHandler(x0::HttpRequest* r)
    {
        x0::Buffer body;
        body.push_back("Hello, World\n");

        r->status = x0::HttpStatus::Ok;
        r->responseHeaders.push_back("Content-Type", "text/plain");
        r->write<x0::BufferSource>(body);
        r->finish();

        return true;
    }

    int run()
    {
        std::clog << "Initializing ..." << std::endl;
        sigterm_.set<MyServer, &MyServer::terminate_handler>(this);
        sigterm_.start(SIGTERM);
        ev_unref(loop_);

        http_.reset(new x0::HttpServer(loop_));
        http_->requestHandler = std::bind(&MyServer::requestHandler, this, std::placeholders::_1);
        http_->setupListener("0.0.0.0", 3000);

        std::clog << "Running ..." << std::endl;
        int rv = http_->run();

        std::clog << "Quitting ..." << std::endl;
        return rv;
    }

private:
    void terminate_handler(ev::sig& sig, int)
    {
        std::clog << "Terminate signal received ..." << std::endl;

        ev_ref(loop_);
        sig.stop();

        http_->stop();
    }
};

int main(int argc, const char *argv[])
{
    MyServer s;
    return s.run();
}
<commit_msg>[examples] app1: also abort on SIGINT<commit_after>/*! \brief Very simple HTTP server. Everything's done for you.
 *
 * It just serves static pages.
 */
#include <x0/http/HttpServer.h>
#include <x0/http/HttpRequest.h>
#include <x0/io/BufferSource.h>
#include <iostream>
#include <fstream>
#include <memory>
#include <ev++.h>

class MyServer {
private:
    struct ev_loop* loop_;
    ev::sig sigterm_;
    ev::sig sigint_;
    std::unique_ptr<x0::HttpServer> http_;

public:
    MyServer() :
        loop_(ev_default_loop()),
        sigterm_(loop_),
        sigint_(loop_),
        http_()
    {
    }

    ~MyServer()
    {
        if (sigterm_.is_active()) {
            ev_ref(loop_);
            sigterm_.stop();
        }

        if (sigint_.is_active()) {
            ev_ref(loop_);
            sigint_.stop();
        }
    }

    bool requestHandler(x0::HttpRequest* r)
    {
        x0::Buffer body;
        body.push_back("Hello, World\n");

        r->status = x0::HttpStatus::Ok;
        r->responseHeaders.push_back("Content-Type", "text/plain");
        r->write<x0::BufferSource>(body);
        r->finish();

        return true;
    }

    int run()
    {
        std::clog << "Initializing ..." << std::endl;

        sigterm_.set<MyServer, &MyServer::terminateHandler>(this);
        sigterm_.start(SIGTERM);
        ev_unref(loop_);

        sigint_.set<MyServer, &MyServer::terminateHandler>(this);
        sigint_.start(SIGINT);
        ev_unref(loop_);

        http_.reset(new x0::HttpServer(loop_));
        http_->requestHandler = std::bind(&MyServer::requestHandler, this, std::placeholders::_1);
        http_->setupListener("0.0.0.0", 3000);

        std::clog << "Listening on http://0.0.0.0:3000 ..." << std::endl;
        int rv = http_->run();

        std::clog << "Quitting ..." << std::endl;
        return rv;
    }

private:
    void terminateHandler(ev::sig& sig, int)
    {
        std::clog << "Signal (" << sig.signum << ") received. Terminating." << std::endl;

        ev_ref(loop_);
        sig.stop();

        http_->stop();
    }
};

int main(int argc, const char *argv[])
{
    MyServer s;
    return s.run();
}
<|endoftext|>


<commit_before>//                       MFEM Example 3 - Parallel Version
//
// Compile with: make ex3p
//
// Sample runs:  mpirun -np 4 ex3p -m ../data/star.mesh
//               mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/beam-tet.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh -o 2 -pa
//               mpirun -np 4 ex3p -m ../data/escher.mesh
//               mpirun -np 4 ex3p -m ../data/escher.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/fichera.mesh
//               mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
//               mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
//               mpirun -np 4 ex3p -m ../data/square-disc-nurbs.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex-nurbs.mesh
//               mpirun -np 4 ex3p -m ../data/amr-quad.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/amr-hex.mesh
//               mpirun -np 4 ex3p -m ../data/star-surf.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/mobius-strip.mesh -o 2 -f 0.1
//               mpirun -np 4 ex3p -m ../data/klein-bottle.mesh -o 2 -f 0.1
//
// Device sample runs:
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d cuda
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d raja-cuda
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d raja-omp
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh -pa -d cuda
//
// Description:  This example code solves a simple electromagnetic diffusion
//               problem corresponding to the second order definite Maxwell
//               equation curl curl E + E = f with boundary condition
//               E x n = <given tangential field>. Here, we use a given exact
//               solution E and compute the corresponding r.h.s. f.
//               We discretize with Nedelec finite elements in 2D or 3D.
//
//               The example demonstrates the use of H(curl) finite element
//               spaces with the curl-curl and the (vector finite element) mass
//               bilinear form, as well as the computation of discretization
//               error when the exact solution is known. Static condensation is
//               also illustrated.
//
//               We recommend viewing examples 1-2 before viewing this example.

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
int dim;

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../data/beam-tet.mesh";
   int order = 1;
   bool static_cond = false;
   bool pa = false;
   const char *device_config = "cpu";
   bool visualization = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree).");
   args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
                  " solution.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
                  "--no-partial-assembly", "Enable Partial Assembly.");
   args.AddOption(&device_config, "-d", "--device",
                  "Device configuration string, see Device::Configure().");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }
   kappa = freq * M_PI;

   // 3. Enable hardware devices such as GPUs, and programming models such as
   //    CUDA, OCCA, RAJA and OpenMP based on command line options.
   Device device(device_config);
   if (myid == 0) { device.Print(); }

   // 4. Read the (serial) mesh from the given mesh file on all processors.  We
   //    can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
   //    and volume meshes with the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   dim = mesh->Dimension();
   int sdim = mesh->SpaceDimension();

   // 5. Refine the serial mesh on all processors to increase the resolution. In
   //    this example we do 'ref_levels' of uniform refinement. We choose
   //    'ref_levels' to be the largest number that gives a final mesh with no
   //    more than 1,000 elements.
   {
      int ref_levels = (int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
   //    this mesh further in parallel to increase the resolution. Once the
   //    parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
   //    meshes need to be reoriented before we can define high-order Nedelec
   //    spaces on them.
   ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
   delete mesh;
   {
      int par_ref_levels = 2;
      for (int l = 0; l < par_ref_levels; l++)
      {
         pmesh->UniformRefinement();
      }
   }
   pmesh->ReorientTetMesh();

   // 7. Define a parallel finite element space on the parallel mesh. Here we
   //    use the Nedelec finite elements of the specified order.
   FiniteElementCollection *fec = new ND_FECollection(order, dim);
   ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
   HYPRE_Int size = fespace->GlobalTrueVSize();
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   // 8. Determine the list of true (i.e. parallel conforming) essential
   //    boundary dofs. In this example, the boundary conditions are defined
   //    by marking all the boundary attributes from the mesh as essential
   //    (Dirichlet) and converting them to a list of true dofs.
   Array<int> ess_tdof_list;
   if (pmesh->bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh->bdr_attributes.Max());
      ess_bdr = 1;
      fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 9. Set up the parallel linear form b(.) which corresponds to the
   //    right-hand side of the FEM linear system, which in this case is
   //    (f,phi_i) where f is given by the function f_exact and phi_i are the
   //    basis functions in the finite element fespace.
   VectorFunctionCoefficient f(sdim, f_exact);
   ParLinearForm *b = new ParLinearForm(fespace);
   b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
   b->Assemble();

   // 10. Define the solution vector x as a parallel finite element grid function
   //     corresponding to fespace. Initialize x by projecting the exact
   //     solution. Note that only values from the boundary edges will be used
   //     when eliminating the non-homogeneous boundary condition to modify the
   //     r.h.s. vector b.
   ParGridFunction x(fespace);
   VectorFunctionCoefficient E(sdim, E_exact);
   x.ProjectCoefficient(E);

   // 11. Set up the parallel bilinear form corresponding to the EM diffusion
   //     operator curl muinv curl + sigma I, by adding the curl-curl and the
   //     mass domain integrators.
   Coefficient *muinv = new ConstantCoefficient(1.0);
   Coefficient *sigma = new ConstantCoefficient(1.0);
   ParBilinearForm *a = new ParBilinearForm(fespace);
   if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
   a->AddDomainIntegrator(new CurlCurlIntegrator(*muinv));
   a->AddDomainIntegrator(new VectorFEMassIntegrator(*sigma));

   // 12. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a->EnableStaticCondensation(); }
   a->Assemble();

   OperatorPtr A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);

   // 13. Solve the system AX=B using PCG with the AMS preconditioner from hypre
   //     (in the full assembly case) or CG with Jacobi preconditioner (in the
   //     partial assembly case).

   if (pa) // Jacobi preconditioning in partial assembly mode
   {
      OperatorJacobiSmoother Jacobi(*a, ess_tdof_list);

      CGSolver cg(MPI_COMM_WORLD);
      cg.SetRelTol(1e-12);
      cg.SetMaxIter(1000);
      cg.SetPrintLevel(1);
      cg.SetOperator(*A);
      cg.SetPreconditioner(Jacobi);
      cg.Mult(B, X);
   }
   else
   {
      if (myid == 0)
      {
         cout << "Size of linear system: "
              << A.As<HypreParMatrix>()->GetGlobalNumRows() << endl;
      }

      ParFiniteElementSpace *prec_fespace =
         (a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
      HypreAMS ams(*A.As<HypreParMatrix>(), prec_fespace);
      HyprePCG pcg(*A.As<HypreParMatrix>());
      pcg.SetTol(1e-12);
      pcg.SetMaxIter(500);
      pcg.SetPrintLevel(2);
      pcg.SetPreconditioner(ams);
      pcg.Mult(B, X);
   }

   // 14. Recover the parallel grid function corresponding to X. This is the
   //     local finite element solution on each processor.
   a->RecoverFEMSolution(X, *b, x);

   // 15. Compute and print the L^2 norm of the error.
   {
      double err = x.ComputeL2Error(E);
      if (myid == 0)
      {
         cout << "\n|| E_h - E ||_{L^2} = " << err << '\n' << endl;
      }
   }

   // 16. Save the refined mesh and the solution in parallel. This output can
   //     be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
   {
      ostringstream mesh_name, sol_name;
      mesh_name << "mesh." << setfill('0') << setw(6) << myid;
      sol_name << "sol." << setfill('0') << setw(6) << myid;

      ofstream mesh_ofs(mesh_name.str().c_str());
      mesh_ofs.precision(8);
      pmesh->Print(mesh_ofs);

      ofstream sol_ofs(sol_name.str().c_str());
      sol_ofs.precision(8);
      x.Save(sol_ofs);
   }

   // 17. Send the solution by socket to a GLVis server.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock << "parallel " << num_procs << " " << myid << "\n";
      sol_sock.precision(8);
      sol_sock << "solution\n" << *pmesh << x << flush;
   }

   // 18. Free the used memory.
   delete a;
   delete sigma;
   delete muinv;
   delete b;
   delete fespace;
   delete fec;
   delete pmesh;

   MPI_Finalize();

   return 0;
}

void E_exact(const Vector &x, Vector &E)
{
   if (dim == 3)
   {
      E(0) = sin(kappa * x(1));
      E(1) = sin(kappa * x(2));
      E(2) = sin(kappa * x(0));
   }
   else
   {
      E(0) = sin(kappa * x(1));
      E(1) = sin(kappa * x(0));
      if (x.Size() == 3) { E(2) = 0.0; }
   }
}

void f_exact(const Vector &x, Vector &f)
{
   if (dim == 3)
   {
      f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
      f(1) = (1. + kappa * kappa) * sin(kappa * x(2));
      f(2) = (1. + kappa * kappa) * sin(kappa * x(0));
   }
   else
   {
      f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
      f(1) = (1. + kappa * kappa) * sin(kappa * x(0));
      if (x.Size() == 3) { f(2) = 0.0; }
   }
}
<commit_msg>Add device w/o partial assembly runs<commit_after>//                       MFEM Example 3 - Parallel Version
//
// Compile with: make ex3p
//
// Sample runs:  mpirun -np 4 ex3p -m ../data/star.mesh
//               mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/beam-tet.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh -o 2 -pa
//               mpirun -np 4 ex3p -m ../data/escher.mesh
//               mpirun -np 4 ex3p -m ../data/escher.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/fichera.mesh
//               mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
//               mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
//               mpirun -np 4 ex3p -m ../data/square-disc-nurbs.mesh
//               mpirun -np 4 ex3p -m ../data/beam-hex-nurbs.mesh
//               mpirun -np 4 ex3p -m ../data/amr-quad.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/amr-hex.mesh
//               mpirun -np 4 ex3p -m ../data/star-surf.mesh -o 2
//               mpirun -np 4 ex3p -m ../data/mobius-strip.mesh -o 2 -f 0.1
//               mpirun -np 4 ex3p -m ../data/klein-bottle.mesh -o 2 -f 0.1
//
// Device sample runs:
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d cuda
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d raja-cuda
//               mpirun -np 4 ex3p -m ../data/star.mesh -pa -d raja-omp
//               mpirun -np 4 ex3p -m ../data/beam-hex.mesh -pa -d cuda
//
// Device w/o partial assembly runs:
//               mpirun -np 1 ex3p -m ../data/star.mesh -no-pa -d cpu
//               mpirun -np 1 ex3p -m ../data/star.mesh -no-pa -d debug
//
// Description:  This example code solves a simple electromagnetic diffusion
//               problem corresponding to the second order definite Maxwell
//               equation curl curl E + E = f with boundary condition
//               E x n = <given tangential field>. Here, we use a given exact
//               solution E and compute the corresponding r.h.s. f.
//               We discretize with Nedelec finite elements in 2D or 3D.
//
//               The example demonstrates the use of H(curl) finite element
//               spaces with the curl-curl and the (vector finite element) mass
//               bilinear form, as well as the computation of discretization
//               error when the exact solution is known. Static condensation is
//               also illustrated.
//
//               We recommend viewing examples 1-2 before viewing this example.

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
int dim;

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../data/beam-tet.mesh";
   int order = 1;
   bool static_cond = false;
   bool pa = false;
   const char *device_config = "cpu";
   bool visualization = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree).");
   args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
                  " solution.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
                  "--no-partial-assembly", "Enable Partial Assembly.");
   args.AddOption(&device_config, "-d", "--device",
                  "Device configuration string, see Device::Configure().");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }
   kappa = freq * M_PI;

   // 3. Enable hardware devices such as GPUs, and programming models such as
   //    CUDA, OCCA, RAJA and OpenMP based on command line options.
   Device device(device_config);
   if (myid == 0) { device.Print(); }

   // 4. Read the (serial) mesh from the given mesh file on all processors.  We
   //    can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
   //    and volume meshes with the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   dim = mesh->Dimension();
   int sdim = mesh->SpaceDimension();

   // 5. Refine the serial mesh on all processors to increase the resolution. In
   //    this example we do 'ref_levels' of uniform refinement. We choose
   //    'ref_levels' to be the largest number that gives a final mesh with no
   //    more than 1,000 elements.
   {
      int ref_levels = (int)floor(log(1000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
   //    this mesh further in parallel to increase the resolution. Once the
   //    parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
   //    meshes need to be reoriented before we can define high-order Nedelec
   //    spaces on them.
   ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
   delete mesh;
   {
      int par_ref_levels = 2;
      for (int l = 0; l < par_ref_levels; l++)
      {
         pmesh->UniformRefinement();
      }
   }
   pmesh->ReorientTetMesh();

   // 7. Define a parallel finite element space on the parallel mesh. Here we
   //    use the Nedelec finite elements of the specified order.
   FiniteElementCollection *fec = new ND_FECollection(order, dim);
   ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
   HYPRE_Int size = fespace->GlobalTrueVSize();
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   // 8. Determine the list of true (i.e. parallel conforming) essential
   //    boundary dofs. In this example, the boundary conditions are defined
   //    by marking all the boundary attributes from the mesh as essential
   //    (Dirichlet) and converting them to a list of true dofs.
   Array<int> ess_tdof_list;
   if (pmesh->bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh->bdr_attributes.Max());
      ess_bdr = 1;
      fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 9. Set up the parallel linear form b(.) which corresponds to the
   //    right-hand side of the FEM linear system, which in this case is
   //    (f,phi_i) where f is given by the function f_exact and phi_i are the
   //    basis functions in the finite element fespace.
   VectorFunctionCoefficient f(sdim, f_exact);
   ParLinearForm *b = new ParLinearForm(fespace);
   b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
   b->Assemble();

   // 10. Define the solution vector x as a parallel finite element grid function
   //     corresponding to fespace. Initialize x by projecting the exact
   //     solution. Note that only values from the boundary edges will be used
   //     when eliminating the non-homogeneous boundary condition to modify the
   //     r.h.s. vector b.
   ParGridFunction x(fespace);
   VectorFunctionCoefficient E(sdim, E_exact);
   x.ProjectCoefficient(E);

   // 11. Set up the parallel bilinear form corresponding to the EM diffusion
   //     operator curl muinv curl + sigma I, by adding the curl-curl and the
   //     mass domain integrators.
   Coefficient *muinv = new ConstantCoefficient(1.0);
   Coefficient *sigma = new ConstantCoefficient(1.0);
   ParBilinearForm *a = new ParBilinearForm(fespace);
   if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
   a->AddDomainIntegrator(new CurlCurlIntegrator(*muinv));
   a->AddDomainIntegrator(new VectorFEMassIntegrator(*sigma));

   // 12. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a->EnableStaticCondensation(); }
   a->Assemble();

   OperatorPtr A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);

   // 13. Solve the system AX=B using PCG with the AMS preconditioner from hypre
   //     (in the full assembly case) or CG with Jacobi preconditioner (in the
   //     partial assembly case).

   if (pa) // Jacobi preconditioning in partial assembly mode
   {
      OperatorJacobiSmoother Jacobi(*a, ess_tdof_list);

      CGSolver cg(MPI_COMM_WORLD);
      cg.SetRelTol(1e-12);
      cg.SetMaxIter(1000);
      cg.SetPrintLevel(1);
      cg.SetOperator(*A);
      cg.SetPreconditioner(Jacobi);
      cg.Mult(B, X);
   }
   else
   {
      if (myid == 0)
      {
         cout << "Size of linear system: "
              << A.As<HypreParMatrix>()->GetGlobalNumRows() << endl;
      }

      ParFiniteElementSpace *prec_fespace =
         (a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
      HypreAMS ams(*A.As<HypreParMatrix>(), prec_fespace);
      HyprePCG pcg(*A.As<HypreParMatrix>());
      pcg.SetTol(1e-12);
      pcg.SetMaxIter(500);
      pcg.SetPrintLevel(2);
      pcg.SetPreconditioner(ams);
      pcg.Mult(B, X);
   }

   // 14. Recover the parallel grid function corresponding to X. This is the
   //     local finite element solution on each processor.
   a->RecoverFEMSolution(X, *b, x);

   // 15. Compute and print the L^2 norm of the error.
   {
      double err = x.ComputeL2Error(E);
      if (myid == 0)
      {
         cout << "\n|| E_h - E ||_{L^2} = " << err << '\n' << endl;
      }
   }

   // 16. Save the refined mesh and the solution in parallel. This output can
   //     be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
   {
      ostringstream mesh_name, sol_name;
      mesh_name << "mesh." << setfill('0') << setw(6) << myid;
      sol_name << "sol." << setfill('0') << setw(6) << myid;

      ofstream mesh_ofs(mesh_name.str().c_str());
      mesh_ofs.precision(8);
      pmesh->Print(mesh_ofs);

      ofstream sol_ofs(sol_name.str().c_str());
      sol_ofs.precision(8);
      x.Save(sol_ofs);
   }

   // 17. Send the solution by socket to a GLVis server.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock << "parallel " << num_procs << " " << myid << "\n";
      sol_sock.precision(8);
      sol_sock << "solution\n" << *pmesh << x << flush;
   }

   // 18. Free the used memory.
   delete a;
   delete sigma;
   delete muinv;
   delete b;
   delete fespace;
   delete fec;
   delete pmesh;

   MPI_Finalize();

   return 0;
}

void E_exact(const Vector &x, Vector &E)
{
   if (dim == 3)
   {
      E(0) = sin(kappa * x(1));
      E(1) = sin(kappa * x(2));
      E(2) = sin(kappa * x(0));
   }
   else
   {
      E(0) = sin(kappa * x(1));
      E(1) = sin(kappa * x(0));
      if (x.Size() == 3) { E(2) = 0.0; }
   }
}

void f_exact(const Vector &x, Vector &f)
{
   if (dim == 3)
   {
      f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
      f(1) = (1. + kappa * kappa) * sin(kappa * x(2));
      f(2) = (1. + kappa * kappa) * sin(kappa * x(0));
   }
   else
   {
      f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
      f(1) = (1. + kappa * kappa) * sin(kappa * x(0));
      if (x.Size() == 3) { f(2) = 0.0; }
   }
}
<|endoftext|>


<commit_before>// @(#)root/cintex:$Name:  $:$Id: CINTEnumBuilder.cxx,v 1.4 2005/11/17 14:12:33 roiser Exp $
// Author: Pere Mato 2005

// Copyright CERN, CH-1211 Geneva 23, 2004-2005, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#include "Reflex/Reflex.h"
#include "Reflex/Tools.h"
#include "Cintex/Cintex.h"
#include "CINTdefs.h"
#include "CINTScopeBuilder.h"
#include "CINTClassBuilder.h"
#include "CINTEnumBuilder.h"
#include "Api.h"

#include <sstream>

using namespace ROOT::Reflex;
using namespace std;

namespace ROOT { namespace Cintex {

  void CINTEnumBuilder::Setup(const Type& e) {
    if ( e.IsEnum() )  {
      string name = e.Name(SCOPED);
      int tagnum = ::G__defined_tagname(name.c_str(), 2);
      if( -1 != tagnum ) return;

      if ( Cintex::Debug() )  {
        cout << "Building enum " << name << endl;
      }

      Scope scope = e.DeclaringScope();
      CINTScopeBuilder::Setup( scope );

      G__linked_taginfo taginfo;
      taginfo.tagnum  = -1;
      taginfo.tagtype = 'e';
      taginfo.tagname = name.c_str();
      G__get_linked_tagnum(&taginfo);
      tagnum = taginfo.tagnum;
      ::G__tagtable_setup( tagnum, sizeof(int), -1, 0,(char*)NULL, NULL, NULL);

      //--- setup enum values -------
      int isstatic;
      if ( scope.IsTopScope() ) {
        isstatic = -1;
        /* Setting up global variables */
        ::G__resetplocal();
      }
      else {
        string sname = scope.Name(SCOPED);
        int stagnum = ::G__defined_tagname(sname.c_str(), 2);
        isstatic = -2;
        if( -1 == stagnum ) return;
        ::G__tag_memvar_setup(stagnum);
      }
      for ( size_t i = 0; i < e.DataMemberSize(); i++ ) {
        stringstream s;
        s << e.DataMemberAt(i).Name() << "=" << (int)e.DataMemberAt(i).Offset();

        string item = s.str();
        if ( Cintex::Debug() ) cout << "  item " << i << " " << item  <<endl;
        ::G__memvar_setup((void*)G__PVOID, 'i', 0, 1, tagnum, -1, isstatic, 1, item.c_str(), 0, (char*)NULL);
      }
      if ( scope.IsTopScope() ) {
        ::G__resetglobalenv();
      }
      else {
        ::G__tag_memvar_reset();
      }

    }
  }
}}
<commit_msg>We introduce a special enum $CPP_MACROS which contains information needed by CINT to run properly. This solution will work for reflex dictionaries generated with the cint parser, not for gccxml generated ones. To also make gccxml dictionaries work we can either remove this fix or try to adapt gccxml to also get macro values (if this is possible)<commit_after>// @(#)root/cintex:$Name:  $:$Id: CINTEnumBuilder.cxx,v 1.5 2005/12/12 09:12:27 roiser Exp $
// Author: Pere Mato 2005

// Copyright CERN, CH-1211 Geneva 23, 2004-2005, All rights reserved.
//
// Permission to use, copy, modify, and distribute this software for any
// purpose is hereby granted without fee, provided that this copyright and
// permissions notice appear in all copies and derivatives.
//
// This software is provided "as is" without express or implied warranty.

#include "Reflex/Reflex.h"
#include "Reflex/Tools.h"
#include "Cintex/Cintex.h"
#include "CINTdefs.h"
#include "CINTScopeBuilder.h"
#include "CINTClassBuilder.h"
#include "CINTEnumBuilder.h"
#include "Api.h"

#include <sstream>

using namespace ROOT::Reflex;
using namespace std;

namespace ROOT { namespace Cintex {

  void CINTEnumBuilder::Setup(const Type& e) {
    if ( e.IsEnum() )  {
      string name = e.Name(SCOPED);
      int tagnum = ::G__defined_tagname(name.c_str(), 2);
      if( -1 != tagnum ) return;

      if ( Cintex::Debug() )  {
        cout << "Building enum " << name << endl;
      }

      Scope scope = e.DeclaringScope();
      CINTScopeBuilder::Setup( scope );
      bool isCPPMacroEnum = name == "$CPP_MACROS";

      if (!isCPPMacroEnum) {
         G__linked_taginfo taginfo;
         taginfo.tagnum  = -1;
         taginfo.tagtype = 'e';
         taginfo.tagname = name.c_str();
         G__get_linked_tagnum(&taginfo);
         tagnum = taginfo.tagnum;
         ::G__tagtable_setup( tagnum, sizeof(int), -1, 0,(char*)NULL, NULL, NULL);
      }

      //--- setup enum values -------
      int isstatic;
      if ( scope.IsTopScope() ) {
        isstatic = -1;
        /* Setting up global variables */
        ::G__resetplocal();
      }
      else {
        string sname = scope.Name(SCOPED);
        int stagnum = ::G__defined_tagname(sname.c_str(), 2);
        isstatic = -2;
        if( -1 == stagnum ) return;
        ::G__tag_memvar_setup(stagnum);
      }
      for ( size_t i = 0; i < e.DataMemberSize(); i++ ) {
        stringstream s;
        s << e.DataMemberAt(i).Name();
        if ( isCPPMacroEnum ) s << "=" << (const char*)e.DataMemberAt(i).Offset();
        else                  s << (int)e.DataMemberAt(i).Offset();

        string item = s.str();
        if ( Cintex::Debug() ) cout << "  item " << i << " " << item  <<endl;
        if ( isCPPMacroEnum )
          ::G__memvar_setup((void*)G__PVOID, 'p', 0, 0, -1, -1, -1, 1, item.c_str(), 1, (char*)NULL);
        else
          ::G__memvar_setup((void*)G__PVOID, 'i', 0, 1, tagnum, -1, isstatic, 1, item.c_str(), 0, (char*)NULL);
      }
      if ( scope.IsTopScope() ) {
        ::G__resetglobalenv();
      }
      else {
        ::G__tag_memvar_reset();
      }

    }
  }
}}
<|endoftext|>


<commit_before>#include "WProgram.h"
#include "HardwareSerial.h"

#include "serial_comm_helper.hpp"

#include "DataPacketStructs.hpp"
#include "ArduinoCmds.hpp"
#include "packet_handle.hpp"
#include "wheel_encoders.hpp"
#include "current_sensors.hpp"
#include "motorPWM.hpp"
#include "analogjoystick.hpp"

#include "common_defines.hpp"

//#include "profile.hpp"
extern "C" void __cxa_pure_virtual()
{
	for(;;)
	{

	}
}
#if 0
void HCF()
{
	pinMode(13, OUTPUT);
	for(;;)
	{
		digitalWrite(13, LOW);
		Serial.println("HCF: LOW");
		delay(1000);
		digitalWrite(13, HIGH);
		Serial.println("HCF: HIGH");
		delay(1000);
	}
}
#endif
int main()
{
	init();
	Serial.begin(SERIAL_BAUD);

	unsigned long tx_num = 0;
	unsigned long rx_num = 0;
	bool analogJoyOn = false;
	unsigned long lastsettime = 0;
	//setup
	//pinMode(leftCurrentADCPin, INPUT);
	//pinMode(rightCurrentADCPin, INPUT);

	pinMode(leftSpeedPin, OUTPUT);
	pinMode(rightDirectionPin, OUTPUT);
	pinMode(leftDirectionPin, OUTPUT);
	pinMode(rightSpeedPin, OUTPUT);
	setPWMFreq();
	setRightMotorDutyCycle(MC_MOTOR_FORWARD, 0);
	setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 0);

	pinMode(rightDisablePin, OUTPUT);
	pinMode(leftDisablePin, OUTPUT);
	digitalWrite(rightDisablePin, LOW);
	digitalWrite(leftDisablePin, LOW);

	pinMode(LIGHT_PIN_LB, OUTPUT);
	digitalWrite(LIGHT_PIN_LB, HIGH);

	setupJoystick();
	//end setup

	//test
#if 0
	for(;;)
{
		setRightMotorDutyCycle(MC_MOTOR_REVERSE, 200);
		//setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 200);
		setLeftMotorDutyCycle(MC_MOTOR_REVERSE, 20);
		for(;;)
		{
			delay(50);
		}
}
#endif
	//test

	//arduinoProfile aP(13, 12);

	//aP.print("startup\n\r");
	unsigned long joystickpollt0 = millis();
	for(;;)
	{

		if((millis() - lastsettime) > 2e3)
		{
			if(!analogJoyOn)
			{
				setRightMotorDutyCycle(MC_MOTOR_FORWARD, 0);
				setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 0);
			}
		}

		if(digitalRead(joystickEnable) == LOW)
		{
			analogJoyOn = true;
			//Serial.println("joy on");
			if((millis() - joystickpollt0) > 10)
			{
				//Serial.println("joy set");

				int x,y;
				getJoystickReading(&x, &y);

				//Serial.print("x: ");
				//Serial.print(x, DEC);
				//Serial.print("\ty: ");
				//Serial.println(y, DEC);
				joystickSetMotors();
				joystickpollt0 = millis();
			}
		}
		else
		{
			analogJoyOn = false;
		}

		if(!(Serial.available() > 1))
		{
			continue;
		}

		header_t header;
		byte* indata = NULL;
		//byte indata[20];
		//memset(indata, 0, 20);
		if(!serialReadBytesTimeout(PACKET_HEADER_SIZE, (byte*)&header))
		{
			continue;
		}

		if(header.size > 0)
		{
			indata = (byte*)malloc(header.size);
			if(!serialReadBytesTimeout(header.size, indata))
			{
				free(indata);
				indata = NULL;
				/*
				for(;;)
				{
					Serial.print("header.size: ");
					Serial.println(header.size, DEC);

					Serial.print("sizeof(header): ");
					Serial.println(sizeof(header_t), DEC);

					byte* dptr = (byte*)&header;
					for(size_t i = 0; i < sizeof(header_t); i++)
					{
						Serial.print("i[");
						Serial.print(i);
						Serial.print("]: ");
						Serial.println(dptr[i], DEC);
					}
					delay(1000);
				}
				*/
				//HCF();
				continue;
			}
		}

		//Serial.println("Header cmd: ");
		//Serial.println(header.cmd, DEC);
		//continue;
		//aP.profileStartSec();
		switch(header.cmd)
		{
			case ARDUINO_RESET:
			{
				//Serial.println("Reset");
				break;
			}
			case ARDUINO_SET_CLOCK:
			{
				//Serial.println("Set Clock");
				break;
			}
			case ARDUINO_GET_ID:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);

				headerOut.packetnum = tx_num;
				headerOut.cmd = ARDUINO_GET_ID;
				headerOut.size = 1;
				//char msg = OSMC_IF_BOARD;
				//char msg = OSMC_IF_FOR_BOARD;
				char msg = OSMC_IF_AFT_BOARD;

				//serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				Serial.write((uint8_t*)&headerOut, PACKET_HEADER_SIZE);
				Serial.print(msg);
				//savePacket(headerOut, (unsigned char*)&msg);
				tx_num++;
				break;
			}
			case MC_GET_ENCODER_TICK:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_ENCODER_TICK;

				reply_dtick_t msg = getEncoderStatus();
				headerOut.size = sizeof(reply_dtick_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&msg, headerOut.size);
				tx_num++;
				break;
			}
			case MC_GET_RL_CURR_VAL:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_RL_CURR_VAL;

				current_reply_t msg = getBothCurrentADCVal();
				headerOut.size = sizeof(current_reply_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&msg, headerOut.size);
				tx_num++;
				break;
			}
 			case MC_SET_RL_DUTY_CYCLE:
			{
				//Serial.println("Set R Speed");
				speed_set_t dcp;

				memcpy(&dcp, indata, sizeof(speed_set_t));

				//if the analog joystick is enabled, accept the serial command and resp success, but do not take the input
				if(!analogJoyOn)
				{
					setRightMotorDutyCycle(dcp.rightDir, dcp.sr);
					setLeftMotorDutyCycle(dcp.leftDir, dcp.sl);
				}

				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_SET_RL_DUTY_CYCLE;
				headerOut.size = 0;

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				tx_num++;

				lastsettime = millis();
				break;
			}
			case MC_GET_JOYSTICK:
			{
				joystick_reply_t data;
				getJoystickReading(&(data.joy_x), &(data.joy_y));

				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_JOYSTICK;
				headerOut.size = sizeof(joystick_reply_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&data, headerOut.size);
				tx_num++;
				break;
			}
			case MC_SET_LIGHT:
			{
				switch(indata[0])
				{
					case MC_LIGHT_STEADY:
					{
						digitalWrite(LIGHT_PIN_LB, HIGH);
						break;
					}
					case MC_LIGHT_PULSING:
					{
						digitalWrite(LIGHT_PIN_LB, LOW);
						break;
					}
				}
			}
			case ARDUINO_HALT_CATCH_FIRE:
			default:
			{
				//HCF();
				break;
			}
		}//end switch

		if(header.size > 0)
		{
			free(indata);
			indata = NULL;
		}
		//aP.profileEndSec("Switch/Case");
	}//end for

	return 0;
}//end main

<commit_msg>Changed what board main.cc flahses the board<commit_after>#include "WProgram.h"
#include "HardwareSerial.h"

#include "serial_comm_helper.hpp"

#include "DataPacketStructs.hpp"
#include "ArduinoCmds.hpp"
#include "packet_handle.hpp"
#include "wheel_encoders.hpp"
#include "current_sensors.hpp"
#include "motorPWM.hpp"
#include "analogjoystick.hpp"

#include "common_defines.hpp"

//#include "profile.hpp"
extern "C" void __cxa_pure_virtual()
{
	for(;;)
	{

	}
}
#if 0
void HCF()
{
	pinMode(13, OUTPUT);
	for(;;)
	{
		digitalWrite(13, LOW);
		Serial.println("HCF: LOW");
		delay(1000);
		digitalWrite(13, HIGH);
		Serial.println("HCF: HIGH");
		delay(1000);
	}
}
#endif
int main()
{
	init();
	Serial.begin(SERIAL_BAUD);

	unsigned long tx_num = 0;
	unsigned long rx_num = 0;
	bool analogJoyOn = false;
	unsigned long lastsettime = 0;
	//setup
	//pinMode(leftCurrentADCPin, INPUT);
	//pinMode(rightCurrentADCPin, INPUT);

	pinMode(leftSpeedPin, OUTPUT);
	pinMode(rightDirectionPin, OUTPUT);
	pinMode(leftDirectionPin, OUTPUT);
	pinMode(rightSpeedPin, OUTPUT);
	setPWMFreq();
	setRightMotorDutyCycle(MC_MOTOR_FORWARD, 0);
	setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 0);

	pinMode(rightDisablePin, OUTPUT);
	pinMode(leftDisablePin, OUTPUT);
	digitalWrite(rightDisablePin, LOW);
	digitalWrite(leftDisablePin, LOW);

	pinMode(LIGHT_PIN_LB, OUTPUT);
	digitalWrite(LIGHT_PIN_LB, HIGH);

	setupJoystick();
	//end setup

	//test
#if 0
	for(;;)
{
		setRightMotorDutyCycle(MC_MOTOR_REVERSE, 200);
		//setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 200);
		setLeftMotorDutyCycle(MC_MOTOR_REVERSE, 20);
		for(;;)
		{
			delay(50);
		}
}
#endif
	//test

	//arduinoProfile aP(13, 12);

	//aP.print("startup\n\r");
	unsigned long joystickpollt0 = millis();
	for(;;)
	{

		if((millis() - lastsettime) > 2e3)
		{
			if(!analogJoyOn)
			{
				setRightMotorDutyCycle(MC_MOTOR_FORWARD, 0);
				setLeftMotorDutyCycle(MC_MOTOR_FORWARD, 0);
			}
		}

		if(digitalRead(joystickEnable) == LOW)
		{
			analogJoyOn = true;
			//Serial.println("joy on");
			if((millis() - joystickpollt0) > 10)
			{
				//Serial.println("joy set");

				int x,y;
				getJoystickReading(&x, &y);

				//Serial.print("x: ");
				//Serial.print(x, DEC);
				//Serial.print("\ty: ");
				//Serial.println(y, DEC);
				joystickSetMotors();
				joystickpollt0 = millis();
			}
		}
		else
		{
			analogJoyOn = false;
		}

		if(!(Serial.available() > 1))
		{
			continue;
		}

		header_t header;
		byte* indata = NULL;
		//byte indata[20];
		//memset(indata, 0, 20);
		if(!serialReadBytesTimeout(PACKET_HEADER_SIZE, (byte*)&header))
		{
			continue;
		}

		if(header.size > 0)
		{
			indata = (byte*)malloc(header.size);
			if(!serialReadBytesTimeout(header.size, indata))
			{
				free(indata);
				indata = NULL;
				/*
				for(;;)
				{
					Serial.print("header.size: ");
					Serial.println(header.size, DEC);

					Serial.print("sizeof(header): ");
					Serial.println(sizeof(header_t), DEC);

					byte* dptr = (byte*)&header;
					for(size_t i = 0; i < sizeof(header_t); i++)
					{
						Serial.print("i[");
						Serial.print(i);
						Serial.print("]: ");
						Serial.println(dptr[i], DEC);
					}
					delay(1000);
				}
				*/
				//HCF();
				continue;
			}
		}

		//Serial.println("Header cmd: ");
		//Serial.println(header.cmd, DEC);
		//continue;
		//aP.profileStartSec();
		switch(header.cmd)
		{
			case ARDUINO_RESET:
			{
				//Serial.println("Reset");
				break;
			}
			case ARDUINO_SET_CLOCK:
			{
				//Serial.println("Set Clock");
				break;
			}
			case ARDUINO_GET_ID:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);

				headerOut.packetnum = tx_num;
				headerOut.cmd = ARDUINO_GET_ID;
				headerOut.size = 1;
				//char msg = OSMC_IF_BOARD;
				//char msg = OSMC_IF_FOR_BOARD;
				char msg = OSMC_IF_AFT_BOARD;

				//serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				Serial.write((uint8_t*)&headerOut, PACKET_HEADER_SIZE);
				Serial.print(msg);
				//savePacket(headerOut, (unsigned char*)&msg);
				tx_num++;
				break;
			}
			case MC_GET_ENCODER_TICK:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_ENCODER_TICK;

				reply_dtick_t msg = getEncoderStatus();
				headerOut.size = sizeof(reply_dtick_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&msg, headerOut.size);
				tx_num++;
				break;
			}
			case MC_GET_RL_CURR_VAL:
			{
				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_RL_CURR_VAL;

				current_reply_t msg = getBothCurrentADCVal();
				headerOut.size = sizeof(current_reply_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&msg, headerOut.size);
				tx_num++;
				break;
			}
 			case MC_SET_RL_DUTY_CYCLE:
			{
				//Serial.println("Set R Speed");
				speed_set_t dcp;

				memcpy(&dcp, indata, sizeof(speed_set_t));

				//if the analog joystick is enabled, accept the serial command and resp success, but do not take the input
				if(!analogJoyOn)
				{
					setRightMotorDutyCycle(dcp.rightDir, dcp.sr);
					setLeftMotorDutyCycle(dcp.leftDir, dcp.sl);
				}

				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_SET_RL_DUTY_CYCLE;
				headerOut.size = 0;

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				tx_num++;

				lastsettime = millis();
				break;
			}
			case MC_GET_JOYSTICK:
			{
				joystick_reply_t data;
				getJoystickReading(&(data.joy_x), &(data.joy_y));

				header_t headerOut;
				genTimestamp(&headerOut.timestamp_sec, &headerOut.timestamp_usec);
				headerOut.packetnum = tx_num;
				headerOut.cmd = MC_GET_JOYSTICK;
				headerOut.size = sizeof(joystick_reply_t);

				serialPrintBytes(&headerOut, PACKET_HEADER_SIZE);
				serialPrintBytes(&data, headerOut.size);
				tx_num++;
				break;
			}
			case MC_SET_LIGHT:
			{
				switch(indata[0])
				{
					case MC_LIGHT_STEADY:
					{
						digitalWrite(LIGHT_PIN_LB, HIGH);
						break;
					}
					case MC_LIGHT_PULSING:
					{
						digitalWrite(LIGHT_PIN_LB, LOW);
						break;
					}
				}
			}
			case ARDUINO_HALT_CATCH_FIRE:
			default:
			{
				//HCF();
				break;
			}
		}//end switch

		if(header.size > 0)
		{
			free(indata);
			indata = NULL;
		}
		//aP.profileEndSec("Switch/Case");
	}//end for

	return 0;
}//end main

<|endoftext|>


<commit_before>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../AppleII/Target.hpp"
#include "../Oric/Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"

#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"

namespace {

Analyser::Static::Target *AppleTarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::AppleII::Target;
	auto *const target = new Target;

	if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) {
		target->disk_controller = Target::DiskController::ThirteenSector;
	} else {
		target->disk_controller = Target::DiskController::SixteenSector;
	}

	return target;
}

Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *) {
	using Target = Analyser::Static::Oric::Target;
	auto *const target = new Target;
	target->rom = Target::ROM::Pravetz;
	target->disk_interface = Target::DiskInterface::Pravetz;
	target->loading_command = "CALL 800\n";
	return target;
}

}

Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
	// This analyser can comprehend disks only.
	if(media.disks.empty()) return {};

	// Grab track 0, sector 0: the boot sector.
	const auto track_zero = media.disks.front()->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
	const auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
		Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));

	const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr;
	for(const auto &pair: sector_map) {
		if(!pair.second.address.sector) {
			sector_zero = &pair.second;
			break;
		}
	}

	// If there's no boot sector then if there are also no sectors at all,
	// decline to nominate a machine. Otherwise go with an Apple as the default.
	TargetList targets;
	if(!sector_zero) {
		if(sector_map.empty()) {
			return targets;
		} else {
			targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(nullptr)));
			targets.back()->media = media;
			return targets;
		}
	}

	// If the boot sector looks like it's intended for the Oric, create an Oric.
	// Otherwise go with the Apple II.

	const auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});

	bool did_read_shift_register = false;
	bool is_oric = false;

	// Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there,
	// so the probability of such a loop is infinitesimal.
	for(const auto &instruction: disassembly.instructions_by_address) {
		// Is this a read of the shift register?
		if(
			(
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY)
			) &&
			instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute &&
			instruction.second.address == 0x031c) {
			did_read_shift_register = true;
			continue;
		}

		if(did_read_shift_register) {
			if(
				instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL &&
				instruction.second.address == 0xfb) {
				is_oric = true;
				break;
			}

			did_read_shift_register = false;
		}
	}

	// Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is.
	for(const auto address: disassembly.outward_calls) {
		is_oric |= address >= 0x320 && address < 0x400;
	}

	if(is_oric) {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(OricTarget(sector_zero)));
	} else {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleTarget(sector_zero)));
	}
	targets.back()->media = media;
	return targets;
}
<commit_msg>Adds a route for 'DiskII' images to the IIgs.<commit_after>//
//  StaticAnalyser.cpp
//  Clock Signal
//
//  Created by Thomas Harte on 03/05/2018.
//  Copyright 2018 Thomas Harte. All rights reserved.
//

#include "StaticAnalyser.hpp"

#include "../AppleII/Target.hpp"
#include "../AppleIIgs/Target.hpp"
#include "../Oric/Target.hpp"
#include "../Disassembler/6502.hpp"
#include "../Disassembler/AddressMapper.hpp"

#include "../../../Storage/Disk/Track/TrackSerialiser.hpp"
#include "../../../Storage/Disk/Encodings/AppleGCR/SegmentParser.hpp"

namespace {

Analyser::Static::Target *AppleIITarget(const Storage::Encodings::AppleGCR::Sector *sector_zero) {
	using Target = Analyser::Static::AppleII::Target;
	auto *const target = new Target;

	if(sector_zero && sector_zero->encoding == Storage::Encodings::AppleGCR::Sector::Encoding::FiveAndThree) {
		target->disk_controller = Target::DiskController::ThirteenSector;
	} else {
		target->disk_controller = Target::DiskController::SixteenSector;
	}

	return target;
}

Analyser::Static::Target *AppleIIgsTarget() {
	return new Analyser::Static::AppleIIgs::Target();
}

Analyser::Static::Target *OricTarget(const Storage::Encodings::AppleGCR::Sector *) {
	using Target = Analyser::Static::Oric::Target;
	auto *const target = new Target;
	target->rom = Target::ROM::Pravetz;
	target->disk_interface = Target::DiskInterface::Pravetz;
	target->loading_command = "CALL 800\n";
	return target;
}

}

Analyser::Static::TargetList Analyser::Static::DiskII::GetTargets(const Media &media, const std::string &, TargetPlatform::IntType) {
	// This analyser can comprehend disks only.
	if(media.disks.empty()) return {};

	auto &disk = media.disks.front();
	TargetList targets;

	// If the disk image is too large for a 5.25" disk, map this to the IIgs.
	if(disk->get_maximum_head_position() > Storage::Disk::HeadPosition(40)) {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleIIgsTarget()));
		targets.back()->media = media;
		return targets;
	}

	// Grab track 0, sector 0: the boot sector.
	const auto track_zero = disk->get_track_at_position(Storage::Disk::Track::Address(0, Storage::Disk::HeadPosition(0)));
	const auto sector_map = Storage::Encodings::AppleGCR::sectors_from_segment(
		Storage::Disk::track_serialisation(*track_zero, Storage::Time(1, 50000)));

	const Storage::Encodings::AppleGCR::Sector *sector_zero = nullptr;
	for(const auto &pair: sector_map) {
		if(!pair.second.address.sector) {
			sector_zero = &pair.second;
			break;
		}
	}

	// If there's no boot sector then if there are also no sectors at all,
	// decline to nominate a machine. Otherwise go with an Apple as the default.
	if(!sector_zero) {
		if(sector_map.empty()) {
			return targets;
		} else {
			targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleIITarget(nullptr)));
			targets.back()->media = media;
			return targets;
		}
	}

	// If the boot sector looks like it's intended for the Oric, create an Oric.
	// Otherwise go with the Apple II.

	const auto disassembly = Analyser::Static::MOS6502::Disassemble(sector_zero->data, Analyser::Static::Disassembler::OffsetMapper(0xb800), {0xb800});

	bool did_read_shift_register = false;
	bool is_oric = false;

	// Look for a tight BPL loop reading the Oric's shift register address of 0x31c. The Apple II just has RAM there,
	// so the probability of such a loop is infinitesimal.
	for(const auto &instruction: disassembly.instructions_by_address) {
		// Is this a read of the shift register?
		if(
			(
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDA) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDX) ||
				(instruction.second.operation == Analyser::Static::MOS6502::Instruction::LDY)
			) &&
			instruction.second.addressing_mode == Analyser::Static::MOS6502::Instruction::Absolute &&
			instruction.second.address == 0x031c) {
			did_read_shift_register = true;
			continue;
		}

		if(did_read_shift_register) {
			if(
				instruction.second.operation == Analyser::Static::MOS6502::Instruction::BPL &&
				instruction.second.address == 0xfb) {
				is_oric = true;
				break;
			}

			did_read_shift_register = false;
		}
	}

	// Check also for calls into the 0x3xx page above 0x320, as that's where the Oric's boot ROM is.
	for(const auto address: disassembly.outward_calls) {
		is_oric |= address >= 0x320 && address < 0x400;
	}

	if(is_oric) {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(OricTarget(sector_zero)));
	} else {
		targets.push_back(std::unique_ptr<Analyser::Static::Target>(AppleIITarget(sector_zero)));
	}
	targets.back()->media = media;
	return targets;
}
<|endoftext|>