<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2019.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Execution/Exceptions.h"
#include "../../Foundation/IO/Network/HTTP/ClientErrorException.h"
#include "../../Foundation/IO/Network/HTTP/Headers.h"

#include "Router.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Memory;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebServer;

using IO::Network::HTTP::ClientErrorException;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1

/*
 ********************************************************************************
 ************************* WebServer::Router::Rep_ ******************************
 ********************************************************************************
 */

struct Router::Rep_ : Interceptor::_IRep {
    Rep_ (const Sequence<Route>& routes)
        : fRoutes_ (routes)
    {
    }
    virtual void HandleFault ([[maybe_unused]] Message* m, [[maybe_unused]] const exception_ptr& e) noexcept override
    {
    }
    virtual void HandleMessage (Message* m) override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx{L"Router::Rep_::HandleMessage", L"(...method=%s,url=%s)", m->GetRequestHTTPMethod ().c_str (), Characters::ToString (m->GetRequestURL ()).c_str ()};
#endif
        Sequence<String>         matches;
        optional<RequestHandler> handler = Lookup_ (*m->PeekRequest (), &matches);
        if (handler) {
            (*handler) (m, matches);
        }
        else {
            if (optional<Set<String>> o = GetAllowedMethodsForRequest_ (*m->PeekRequest ())) {
                // From 10.4.6 405 Method Not Allowed
                //      The method specified in the Request-Line is not allowed for the resource identified by the Request-URI.
                //      The response MUST include an Allow header containing a list of valid methods for the requested resource.
                Assert (not o->empty ());
                StringBuilder res;
                o->Apply ([&res] (const String& i) { if (not res.empty ()) { res += L", "; } res += i; });
                m->PeekResponse ()->AddHeader (IO::Network::HTTP::HeaderName::kAllow, res.str ());
                Execution::Throw (ClientErrorException (IO::Network::HTTP::StatusCodes::kMethodNotAllowed));
            }
            else {
                DbgTrace (L"Router 404: (...url=%s)", Characters::ToString (m->GetRequestURL ()).c_str ());
                Execution::Throw (ClientErrorException (IO::Network::HTTP::StatusCodes::kNotFound));
            }
        }
    }
    optional<RequestHandler> Lookup_ (const Request& request, Sequence<String>* matches) const
    {
        String method = request.GetHTTPMethod ();
        URI    url    = request.GetURL ();

        String hostRelPath;
        try {
            hostRelPath = url.GetAbsPath<String> ().SubString (1); // According to https://tools.ietf.org/html/rfc2616#section-5.1.2 - the URI must be abs_path
        }
        catch (...) {
            Execution::Throw (ClientErrorException (IO::Network::HTTP::StatusCodes::kBadRequest, L"request URI requires an absolute path"sv));
        }

        // We interpret routes as matching against a relative path from the root
        for (Route r : fRoutes_) {
            if (r.fVerbMatch_ and not method.Match (*r.fVerbMatch_)) {
                continue;
            }
            if (matches == nullptr) {
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_)) {
                    continue;
                }
            }
            else {
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_, matches)) {
                    continue;
                }
            }
            if (r.fRequestMatch_ and not(*r.fRequestMatch_) (request)) {
                continue;
            }
            return r.fHandler_;
        }
        return nullopt;
    }
    optional<Set<String>> GetAllowedMethodsForRequest_ (const Request& request) const
    {
        URI                      url         = request.GetURL ();
        String                   hostRelPath = url.GetPath ();
        static const Set<String> kMethods2Try_{L"GET"sv, L"PUT"sv, L"OPTIONS"sv, L"DELETE"sv, L"POST"sv};
        Set<String>              methods;
        for (String method : kMethods2Try_) {
            for (Route r : fRoutes_) {
                if (r.fVerbMatch_ and not method.Match (*r.fVerbMatch_)) {
                    continue;
                }
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_)) {
                    continue;
                }
                if (r.fRequestMatch_ and not(*r.fRequestMatch_) (request)) {
                    continue;
                }
                methods.Add (method);
            }
        }
        return methods.empty () ? optional<Set<String>>{} : optional<Set<String>>{methods};
    }

    const Sequence<Route> fRoutes_; // no need for synchronization cuz constant - just set on construction
};

/*
 ********************************************************************************
 *************************** WebServer::Router **********************************
 ********************************************************************************
 */
Router::Router (const Sequence<Route>& routes)
    : inherited (make_shared<Rep_> (routes))
{
}

optional<RequestHandler> Router::Lookup (const Request& request) const
{
    return _GetRep<Rep_> ().Lookup_ (request, nullptr);
}
<commit_msg>minor cleanups to WebServer Router code, and fixed one regression - due to GetPath/GetAbsPath change - / in name - with getting allowed methods for path<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2019.  All rights reserved
 */
#include "../StroikaPreComp.h"

#include "../../Foundation/Characters/String_Constant.h"
#include "../../Foundation/Characters/ToString.h"
#include "../../Foundation/Execution/Exceptions.h"
#include "../../Foundation/IO/Network/HTTP/ClientErrorException.h"
#include "../../Foundation/IO/Network/HTTP/Headers.h"
#include "../../Foundation/IO/Network/HTTP/Methods.h"

#include "Router.h"

using namespace Stroika::Foundation;
using namespace Stroika::Foundation::Characters;
using namespace Stroika::Foundation::Containers;
using namespace Stroika::Foundation::Memory;
using namespace Stroika::Foundation::IO::Network;

using namespace Stroika::Frameworks;
using namespace Stroika::Frameworks::WebServer;

using HTTP::ClientErrorException;

// Comment this in to turn on aggressive noisy DbgTrace in this module
//#define USE_NOISY_TRACE_IN_THIS_MODULE_ 1

/*
 ********************************************************************************
 ************************* WebServer::Router::Rep_ ******************************
 ********************************************************************************
 */

struct Router::Rep_ : Interceptor::_IRep {
    Rep_ (const Sequence<Route>& routes)
        : fRoutes_ (routes)
    {
    }
    virtual void HandleFault ([[maybe_unused]] Message* m, [[maybe_unused]] const exception_ptr& e) noexcept override
    {
    }
    virtual void HandleMessage (Message* m) override
    {
#if USE_NOISY_TRACE_IN_THIS_MODULE_
        Debug::TraceContextBumper ctx{L"Router::Rep_::HandleMessage", L"(...method=%s,url=%s)", m->GetRequestHTTPMethod ().c_str (), Characters::ToString (m->GetRequestURL ()).c_str ()};
#endif
        Sequence<String>         matches;
        optional<RequestHandler> handler = Lookup_ (*m->PeekRequest (), &matches);
        if (handler) {
            (*handler) (m, matches);
        }
        else {
            if (optional<Set<String>> o = GetAllowedMethodsForRequest_ (*m->PeekRequest ())) {
                // From 10.4.6 405 Method Not Allowed
                //      The method specified in the Request-Line is not allowed for the resource identified by the Request-URI.
                //      The response MUST include an Allow header containing a list of valid methods for the requested resource.
                Assert (not o->empty ());
                StringBuilder res;
                o->Apply ([&res] (const String& i) { if (not res.empty ()) { res += L", "; } res += i; });
                m->PeekResponse ()->AddHeader (HTTP::HeaderName::kAllow, res.str ());
                Execution::Throw (ClientErrorException (HTTP::StatusCodes::kMethodNotAllowed));
            }
            else {
                DbgTrace (L"Router 404: (...url=%s)", Characters::ToString (m->GetRequestURL ()).c_str ());
                Execution::Throw (ClientErrorException (HTTP::StatusCodes::kNotFound));
            }
        }
    }
    optional<RequestHandler> Lookup_ (const Request& request, Sequence<String>* matches) const
    {
        String method = request.GetHTTPMethod ();
        URI    url    = request.GetURL ();

        String hostRelPath;
        try {
            hostRelPath = url.GetAbsPath<String> ().SubString (1); // According to https://tools.ietf.org/html/rfc2616#section-5.1.2 - the URI must be abs_path
        }
        catch (...) {
            Execution::Throw (ClientErrorException (HTTP::StatusCodes::kBadRequest, L"request URI requires an absolute path"sv));
        }

        // We interpret routes as matching against a relative path from the root
        for (Route r : fRoutes_) {
            if (r.fVerbMatch_ and not method.Match (*r.fVerbMatch_)) {
                continue;
            }
            if (matches == nullptr) {
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_)) {
                    continue;
                }
            }
            else {
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_, matches)) {
                    continue;
                }
            }
            if (r.fRequestMatch_ and not(*r.fRequestMatch_) (request)) {
                continue;
            }
            return r.fHandler_;
        }
        return nullopt;
    }
    optional<Set<String>> GetAllowedMethodsForRequest_ (const Request& request) const
    {
        URI    url = request.GetURL ();
        String hostRelPath;
        try {
            hostRelPath = url.GetAbsPath<String> ().SubString (1); // According to https://tools.ietf.org/html/rfc2616#section-5.1.2 - the URI must be abs_path
        }
        catch (...) {
            return nullopt;
        }
        static const Set<String> kMethods2Try_{HTTP::Methods::kGet, HTTP::Methods::kPut, HTTP::Methods::kOptions, HTTP::Methods::kDelete, HTTP::Methods::kPost};
        Set<String>              methods;
        for (String method : kMethods2Try_) {
            for (Route r : fRoutes_) {
                if (r.fVerbMatch_ and not method.Match (*r.fVerbMatch_)) {
                    continue;
                }
                if (r.fPathMatch_ and not hostRelPath.Match (*r.fPathMatch_)) {
                    continue;
                }
                if (r.fRequestMatch_ and not(*r.fRequestMatch_) (request)) {
                    continue;
                }
                methods.Add (method);
            }
        }
        return methods.empty () ? nullopt : optional<Set<String>>{methods};
    }

    const Sequence<Route> fRoutes_; // no need for synchronization cuz constant - just set on construction
};

/*
 ********************************************************************************
 *************************** WebServer::Router **********************************
 ********************************************************************************
 */
Router::Router (const Sequence<Route>& routes)
    : inherited (make_shared<Rep_> (routes))
{
}

optional<RequestHandler> Router::Lookup (const Request& request) const
{
    return _GetRep<Rep_> ().Lookup_ (request, nullptr);
}
<|endoftext|>


<commit_before>#include "gum/Statistics.h"
#include "gum/StatFPS.h"
#include "gum/StatTag.h"
#include "gum/GUM_GTxt.h"
#include "gum/SymbolPool.h"
#include "gum/Image.h"

#include <logger.h>
#include <glp_loop.h>
#include <ps_3d.h>
#include <sprite2/pre_defined.h>
#include S2_MAT_HEADER
#include <sprite2/StatDrawCall.h>
#include <sprite2/StatPingPong.h>
#include <sprite2/StatTopNodes.h>
#include <sprite2/StatSymDraw.h>
#include <sprite2/StatSymCount.h>
#include <sprite2/StatSprCount.h>
#include <sprite2/S2_Sprite.h>
#include <sprite2/S2_Actor.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Statistics.h>
#include <shaderlab/StatDrawCall.h>

#include <string>

#include <time.h>

namespace gum
{

SINGLETON_DEFINITION(Statistics);

static const float FPS_SMOOTHING = 0.99f;

Statistics::Statistics()
	: m_flags(0)
	, m_tpf(0)
	, m_tpf_smooth(0)
	, m_no_stat_begin(0)
	, m_no_stat_tot(0)
	, m_opt_enable(false)
{
	memset(&m_mem, 0, sizeof(m_mem));
}

void Statistics::EnableGraph(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_GRAPH;
	} else {
		m_flags &= ~FLAG_PRINT_GRAPH;
	}
}

void Statistics::EnableConsole(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_CONSOLE;
	} else {
		m_flags &= ~FLAG_PRINT_CONSOLE;
	}
}

void Statistics::EnableFile(bool enable)
{
	if (enable == IsFileEnable()) {
		return;
	}

	if (enable)
	{
		m_flags |= FLAG_PRINT_FILE;

#ifdef __ANDROID__
		m_fout.open("/sdcard/lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#else
		m_fout.open("lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#endif // __ANDROID__
	}
	else
	{
		m_flags &= ~FLAG_PRINT_FILE;

		m_fout.close();
	}
}

bool Statistics::IsGraphEnable() const
{
	return (m_flags & FLAG_PRINT_GRAPH) != 0;
}

bool Statistics::IsConsoleEnable() const
{
	return (m_flags & FLAG_PRINT_CONSOLE) != 0;
}

bool Statistics::IsFileEnable() const
{
	return (m_flags & FLAG_PRINT_FILE) != 0;
}

void Statistics::Update()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = glp_get_dt();
	m_tpf_smooth = (m_tpf_smooth * FPS_SMOOTHING) + m_tpf * (1.0f - FPS_SMOOTHING);
}

void Statistics::Print()
{
	StatTag::Instance()->PrintScreen();

	if (m_flags == 0) {
		return;
	}

	if (m_flags & FLAG_PRINT_GRAPH) {
		PrintScreen();
	}
	if (m_flags & FLAG_PRINT_CONSOLE) {
		PrintConsole();
	}
	if (m_flags & FLAG_PRINT_FILE) {
		PrintFile();
	}
}

void Statistics::Reset()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = 0;

	sl::Statistics::Instance()->Reset();
	sl::StatDrawCall::Instance()->Reset();

	s2::StatDrawCall::Instance()->Reset();
	s2::StatPingPong::Instance()->Reset();
	s2::StatTopNodes::Instance()->Reset();
	s2::StatSymDraw::Instance()->Reset();
}

void Statistics::Flush()
{
	StatTag::Instance()->Flush();
}

void Statistics::NoStatBegin()
{
	m_no_stat_begin = glp_get_time();
}

void Statistics::NoStatEnd()
{
	m_no_stat_tot = (glp_get_time() - m_no_stat_begin);
}

void Statistics::OptEnable(bool enable)
{
	m_opt_enable = enable;
}

void Statistics::SetMem(float tot, float lua)
{
	m_mem.tot = tot;
	m_mem.lua = lua;
}

void Statistics::PrintScreen() const
{
	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->SetShader(sl::SPRITE2);

	static char buf[512];

	const int w = 960;
	const int top = 280;

	S2_MAT mt;
	mt.Translate(0, top);

	sprintf(buf, "OPT: %s, emitter: %d", m_opt_enable ? "open" : "closed", p3d_emitter_count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "FPS: %.1f, ms: %.1f, ex:%.1f", 1000.0f / m_tpf, m_tpf_smooth, m_no_stat_tot / 1000.0f);
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "MEM: tot %.1f, tex %.1f, lua %.1f", m_mem.tot, m_mem.tex, m_mem.lua);
	GTxt::Instance()->Draw(mt, buf, w);

	static std::string buf_str;
	buf_str.reserve(512);

	mt.Translate(0, -30);
	sl::Statistics::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatDrawCall::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -40);
	s2::StatPingPong::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -50);
	sprintf(buf, "COUNT: sym %d, spr %d, actor %d, img %d",
		SymbolPool::Instance()->Count(),
		s2::Sprite::GetAllSprCount(),
		s2::Actor::GetAllActorCount(),
		ImageMgr::Instance()->Count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	s2::StatSymCount::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatSprCount::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(450, -100);
	s2::StatTopNodes::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

// 	mt.Translate(450, 180);
// 	s2::StatSymbol::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

// 	mt.Translate(0, -230);
// 	sl::StatDrawCall::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

	mgr->FlushShader();
}

void Statistics::PrintConsole() const
{
	static const int PRINT_COUNT = 30;
	static int count = 0;
	++count;
	if (count == PRINT_COUNT)
	{
		count = 0;
		sl::Statistics* stat = sl::Statistics::Instance();
		int dc = stat->GetDrawCall();
		int count = stat->GetVertices();
		float fps_curr = StatFPS::Instance()->GetFPSCurr();
		float curr_cost = 0;
		if (fps_curr != 0) {
			curr_cost = 1000.0f / fps_curr;
		}
		LOGI("fps %.1f, cost %.1f, dc %d, vertices %d, cost avg %.1f\n",
			1000.0f / m_tpf_smooth, m_tpf_smooth, dc, count, curr_cost);
	}
}

void Statistics::PrintFile() const
{
	sl::Statistics* sl_stat = sl::Statistics::Instance();

	static char buf[512];
	sprintf(buf, "timestamp %lu, cost %.1f, vertices %d, dc %d\n",
		time(NULL), m_tpf_smooth, sl_stat->GetVertices(), sl_stat->GetDrawCall());
	m_fout << buf;

// 	static std::string buf_str;
// 	buf_str.reserve(1024);
// 	s2::StatTopNodes::Instance()->Print(buf_str);
// 	m_fout << buf_str;

	static const int FLUSH_COUNT = 100;
	static int count = 0;
	++count;
	if (count == FLUSH_COUNT) {
		count = 0;
		m_fout.flush();
	}
}

}<commit_msg>[FIXED] stat reset<commit_after>#include "gum/Statistics.h"
#include "gum/StatFPS.h"
#include "gum/StatTag.h"
#include "gum/GUM_GTxt.h"
#include "gum/SymbolPool.h"
#include "gum/Image.h"

#include <logger.h>
#include <glp_loop.h>
#include <ps_3d.h>
#include <sprite2/pre_defined.h>
#include S2_MAT_HEADER
#include <sprite2/StatDrawCall.h>
#include <sprite2/StatPingPong.h>
#include <sprite2/StatTopNodes.h>
#include <sprite2/StatSymDraw.h>
#include <sprite2/StatSymCount.h>
#include <sprite2/StatSprCount.h>
#include <sprite2/S2_Sprite.h>
#include <sprite2/S2_Actor.h>
#include <shaderlab/ShaderMgr.h>
#include <shaderlab/Statistics.h>
#include <shaderlab/StatDrawCall.h>

#include <string>

#include <time.h>

namespace gum
{

SINGLETON_DEFINITION(Statistics);

static const float FPS_SMOOTHING = 0.99f;

Statistics::Statistics()
	: m_flags(0)
	, m_tpf(0)
	, m_tpf_smooth(0)
	, m_no_stat_begin(0)
	, m_no_stat_tot(0)
	, m_opt_enable(false)
{
	memset(&m_mem, 0, sizeof(m_mem));
}

void Statistics::EnableGraph(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_GRAPH;
	} else {
		m_flags &= ~FLAG_PRINT_GRAPH;
	}
}

void Statistics::EnableConsole(bool enable)
{
	if (enable) {
		m_flags |= FLAG_PRINT_CONSOLE;
	} else {
		m_flags &= ~FLAG_PRINT_CONSOLE;
	}
}

void Statistics::EnableFile(bool enable)
{
	if (enable == IsFileEnable()) {
		return;
	}

	if (enable)
	{
		m_flags |= FLAG_PRINT_FILE;

#ifdef __ANDROID__
		m_fout.open("/sdcard/lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#else
		m_fout.open("lr_stat.bin", std::ofstream::out | std::ofstream::binary);
#endif // __ANDROID__
	}
	else
	{
		m_flags &= ~FLAG_PRINT_FILE;

		m_fout.close();
	}
}

bool Statistics::IsGraphEnable() const
{
	return (m_flags & FLAG_PRINT_GRAPH) != 0;
}

bool Statistics::IsConsoleEnable() const
{
	return (m_flags & FLAG_PRINT_CONSOLE) != 0;
}

bool Statistics::IsFileEnable() const
{
	return (m_flags & FLAG_PRINT_FILE) != 0;
}

void Statistics::Update()
{
	if (m_flags == 0) {
		return;
	}

	m_tpf = glp_get_dt();
	m_tpf_smooth = (m_tpf_smooth * FPS_SMOOTHING) + m_tpf * (1.0f - FPS_SMOOTHING);
}

void Statistics::Print()
{
	StatTag::Instance()->PrintScreen();

	if (m_flags == 0) {
		return;
	}

	if (m_flags & FLAG_PRINT_GRAPH) {
		PrintScreen();
	}
	if (m_flags & FLAG_PRINT_CONSOLE) {
		PrintConsole();
	}
	if (m_flags & FLAG_PRINT_FILE) {
		PrintFile();
	}
}

void Statistics::Reset()
{
	m_tpf = 0;

	sl::Statistics::Instance()->Reset();
	sl::StatDrawCall::Instance()->Reset();

	s2::StatDrawCall::Instance()->Reset();
	s2::StatPingPong::Instance()->Reset();
	s2::StatTopNodes::Instance()->Reset();
	s2::StatSymDraw::Instance()->Reset();
}

void Statistics::Flush()
{
	StatTag::Instance()->Flush();
}

void Statistics::NoStatBegin()
{
	m_no_stat_begin = glp_get_time();
}

void Statistics::NoStatEnd()
{
	m_no_stat_tot = (glp_get_time() - m_no_stat_begin);
}

void Statistics::OptEnable(bool enable)
{
	m_opt_enable = enable;
}

void Statistics::SetMem(float tot, float lua)
{
	m_mem.tot = tot;
	m_mem.lua = lua;
}

void Statistics::PrintScreen() const
{
	sl::ShaderMgr* mgr = sl::ShaderMgr::Instance();
	mgr->SetShader(sl::SPRITE2);

	static char buf[512];

	const int w = 960;
	const int top = 280;

	S2_MAT mt;
	mt.Translate(0, top);

	sprintf(buf, "OPT: %s, emitter: %d", m_opt_enable ? "open" : "closed", p3d_emitter_count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "FPS: %.1f, ms: %.1f, ex:%.1f", 1000.0f / m_tpf, m_tpf_smooth, m_no_stat_tot / 1000.0f);
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	sprintf(buf, "MEM: tot %.1f, tex %.1f, lua %.1f", m_mem.tot, m_mem.tex, m_mem.lua);
	GTxt::Instance()->Draw(mt, buf, w);

	static std::string buf_str;
	buf_str.reserve(512);

	mt.Translate(0, -30);
	sl::Statistics::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatDrawCall::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -40);
	s2::StatPingPong::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -50);
	sprintf(buf, "COUNT: sym %d, spr %d, actor %d, img %d",
		SymbolPool::Instance()->Count(),
		s2::Sprite::GetAllSprCount(),
		s2::Actor::GetAllActorCount(),
		ImageMgr::Instance()->Count());
	GTxt::Instance()->Draw(mt, buf, w);

	mt.Translate(0, -30);
	s2::StatSymCount::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(0, -30);
	s2::StatSprCount::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

	mt.Translate(450, -100);
	s2::StatTopNodes::Instance()->Print(buf_str);
	GTxt::Instance()->Draw(mt, buf_str, w);
	buf_str.clear();

// 	mt.Translate(450, 180);
// 	s2::StatSymbol::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

// 	mt.Translate(0, -230);
// 	sl::StatDrawCall::Instance()->Print(buf_str);
// 	GTxt::Instance()->Draw(mt, buf_str, w);
// 	buf_str.clear();

	mgr->FlushShader();
}

void Statistics::PrintConsole() const
{
	static const int PRINT_COUNT = 30;
	static int count = 0;
	++count;
	if (count == PRINT_COUNT)
	{
		count = 0;
		sl::Statistics* stat = sl::Statistics::Instance();
		int dc = stat->GetDrawCall();
		int count = stat->GetVertices();
		float fps_curr = StatFPS::Instance()->GetFPSCurr();
		float curr_cost = 0;
		if (fps_curr != 0) {
			curr_cost = 1000.0f / fps_curr;
		}
		LOGI("fps %.1f, cost %.1f, dc %d, vertices %d, cost avg %.1f\n",
			1000.0f / m_tpf_smooth, m_tpf_smooth, dc, count, curr_cost);
	}
}

void Statistics::PrintFile() const
{
	sl::Statistics* sl_stat = sl::Statistics::Instance();

	static char buf[512];
	sprintf(buf, "timestamp %lu, cost %.1f, vertices %d, dc %d\n",
		time(NULL), m_tpf_smooth, sl_stat->GetVertices(), sl_stat->GetDrawCall());
	m_fout << buf;

// 	static std::string buf_str;
// 	buf_str.reserve(1024);
// 	s2::StatTopNodes::Instance()->Print(buf_str);
// 	m_fout << buf_str;

	static const int FLUSH_COUNT = 100;
	static int count = 0;
	++count;
	if (count == FLUSH_COUNT) {
		count = 0;
		m_fout.flush();
	}
}

}<|endoftext|>


<commit_before>#include <sstream>

#include <sys/time.h>

#include "marshal.h"

using namespace std;

namespace rpc {

#ifdef PKT_SAMPLING
int _pkt_sample_in[PKT_SAMPLE_SIZE];
int _pkt_sample_out[PKT_SAMPLE_SIZE];

void _pkt_sampling_report() {
    static size_t ratelimit_counter = 0;
    static int last_report_tm = 0;
    if (ratelimit_counter++ % 1024 == 0) {
        struct timeval now;
        gettimeofday(&now, NULL);
        if (now.tv_sec - last_report_tm >= 1) {
            {
                ostringstream ostr;
                for (int i = 0; i < PKT_SAMPLE_SIZE; i++) {
                    ostr << " " << _pkt_sample_in[i];
                }
                Log::info("PKT_SAMPLE_IN: %s", ostr.str().c_str());
            }
            {
                ostringstream ostr;
                for (int i = 0; i < PKT_SAMPLE_SIZE; i++) {
                    ostr << " " << _pkt_sample_out[i];
                }
                Log::info("PKT_SAMPLE_OUT:%s", ostr.str().c_str());
            }
            last_report_tm = now.tv_sec;
        }
    }
}

#endif // PKT_SAMPLING

/**
 * 8kb minimum chunk size.
 * NOTE: this value directly affects how many read/write syscall will be issued.
 */
const int Chunk::min_size = 8192;

Marshal1::Bookmark* Marshal1::set_bookmark(int size) {
    verify(write_counter_ == 0);

    // invariant: head of chunk list is not fully read (otherwise it's a waste of memory)
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    Bookmark* bmark = new Bookmark();
    bmark->size_ = size;
    bmark->ptr_ = new char*[bmark->size_];

    for (int i = 0; i < bmark->size_; i++) {
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            chunk_.push_back(new Chunk);
        }
        bmark->ptr_[i] = chunk_.back()->set_bookmark();
    }

    return bmark;
}

void Marshal1::write_bookmark(Bookmark* bmark, const void* ptr) {
    char* pc = (char *) ptr;
    verify(bmark != NULL && bmark->ptr_ != NULL && bmark->size_ >= 0);
    for (int i = 0; i < bmark->size_; i++) {
        *(bmark->ptr_[i]) = pc[i];
    }
}

int Marshal1::write(const void* p, int n) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    if (chunk_.empty() || chunk_.back()->fully_written()) {
        chunk_.push_back(new Chunk(p, n));
    } else {
        int n_write = chunk_.back()->write(p, n);

        // otherwise the above fully_written() will return true
        assert(n_write > 0);

        if (n_write < n) {
            const char* pc = (const char *) p;
            chunk_.push_back(new Chunk(pc + n_write, n - n_write));
        }
    }

    write_counter_ += n;
    return n;
}

int Marshal1::read(void* p, int n) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    char* pc = (char *) p;
    int n_read = 0;
    while (!chunk_.empty() && n_read < n) {
        int r = chunk_.front()->read(pc + n_read, n - n_read);
        if (chunk_.front()->fully_read()) {
            // remove fully read chunks, avoid unnecessary mem usage
            delete chunk_.front();
            chunk_.pop_front();
        }
        if (r == 0) {
            // currently there's no content for us to read, so stop.
            break;
        }
        n_read += r;
    }

    verify(n_read <= n);
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_read;
}

int Marshal1::peek(void* p, int n) const {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    char* pc = (char *) p;
    int n_peek = 0;

    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        int r = (*it)->peek(pc + n_peek, n - n_peek);
        if (r == 0) {
            // no more data to peek, so stop
            break;
        }
        n_peek += r;
        if (n_peek == n) {
            // read enough data, so stop
            break;
        }
    }

    assert(n_peek <= n);
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_peek;
}

int Marshal1::write_to_fd(int fd, const io_ratelimit& rate) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    if (rate.min_size > 0 || rate.interval > 0) {
        // rpc batching, check if should wait till next batch
        bool should_wait = true;
        if (rate.min_size > 0 && content_size_gt(rate.min_size)) {
            should_wait = false;
        }

        if (rate.interval > 0) {
            struct timeval tm;
            gettimeofday(&tm, NULL);
            double now = tm.tv_sec + tm.tv_usec / 1000.0 / 1000.0;
            if (should_wait && now - last_write_fd_tm_ > rate.interval) {
                should_wait = false;
            }
            if (should_wait == false) {
                last_write_fd_tm_ = now;
            }
        }

        if (should_wait) {
            return 0;
        }
    }

    int n_write = 0;
    while (!chunk_.empty()) {
        int r = chunk_.front()->write_to_fd(fd);
        if (chunk_.front()->fully_read()) {
            // remove useless chunks when they are fully read
            delete chunk_.front();
            chunk_.pop_front();
        }
        if (r <= 0) {
            break;
        }
        n_write += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_write;
}

int Marshal1::read_from_marshal(Marshal1& m, int n /* =? */) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());
    assert(m.chunk_.empty() || !m.chunk_.front()->fully_read());

    int n_read = 0;
    while (n_read < n) {
        if (m.chunk_.empty()) {
            // nothing more to read
            break;
        }
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            int head_size = m.chunk_.front()->content_size();
            if (head_size < n - n_read) {

                // speed up: directly transfer chunk pointer, avoid memory copying
                chunk_.push_back(m.chunk_.front());
                m.chunk_.pop_front();
                n_read += head_size;

                // skip read_from_chunk operations
                continue;

            } else {
                chunk_.push_back(new Chunk);
            }
        }
        int r = chunk_.back()->read_from_chunk(*m.chunk_.front(), n - n_read);

        if (m.chunk_.front()->fully_read()) {
            // remove useless chunks when they are fully read
            delete m.chunk_.front();
            m.chunk_.pop_front();
        }
        if (r == 0) {
            // no more data to read
            break;
        }
        n_read += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());
    assert(m.chunk_.empty() || !m.chunk_.front()->fully_read());

    return n_read;
}

int Marshal1::read_from_fd(int fd) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    int n_read = 0;
    for (;;) {
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            chunk_.push_back(new Chunk);
        }
        int r = chunk_.back()->read_from_fd(fd);
        if (r <= 0) {
            break;
        }
        n_read += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_read;
}

bool Marshal1::content_size_gt(int size) const {

    int size_visited = 0;
    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        size_visited += (*it)->content_size();
        if (size_visited > size) {
            return true;
        }
    }

    return size_visited > size;
}

size_t Marshal1::content_size() const {
    size_t size = 0;
    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        size += (*it)->content_size();
    }
    return size;
}

}
<commit_msg>FastMarshal::content_size and ~FastMarshal<commit_after>#include <sstream>

#include <sys/time.h>

#include "marshal.h"

using namespace std;

namespace rpc {

#ifdef PKT_SAMPLING
int _pkt_sample_in[PKT_SAMPLE_SIZE];
int _pkt_sample_out[PKT_SAMPLE_SIZE];

void _pkt_sampling_report() {
    static size_t ratelimit_counter = 0;
    static int last_report_tm = 0;
    if (ratelimit_counter++ % 1024 == 0) {
        struct timeval now;
        gettimeofday(&now, NULL);
        if (now.tv_sec - last_report_tm >= 1) {
            {
                ostringstream ostr;
                for (int i = 0; i < PKT_SAMPLE_SIZE; i++) {
                    ostr << " " << _pkt_sample_in[i];
                }
                Log::info("PKT_SAMPLE_IN: %s", ostr.str().c_str());
            }
            {
                ostringstream ostr;
                for (int i = 0; i < PKT_SAMPLE_SIZE; i++) {
                    ostr << " " << _pkt_sample_out[i];
                }
                Log::info("PKT_SAMPLE_OUT:%s", ostr.str().c_str());
            }
            last_report_tm = now.tv_sec;
        }
    }
}

#endif // PKT_SAMPLING

FastMarshal::~FastMarshal() {
    chunk* chnk = head_;
    while (chnk != nullptr) {
        chunk* next = chnk->next;
        delete chnk;
        chnk = next;
    }
}

bool FastMarshal::content_size_gt(size_t n) const {
    assert(tail_ == nullptr || tail_->next == nullptr);

    size_t sz = 0;
    chunk* chnk = head_;
    while (chnk != nullptr) {
        sz += chnk->content_size();
        if (sz > n) {
            return true;
        }
        chnk = chnk->next;
    }
    return sz > n;
}

size_t FastMarshal::content_size() const {
    assert(tail_ == nullptr || tail_->next == nullptr);

    size_t sz = 0;
    chunk* chnk = head_;
    while (chnk != nullptr) {
        sz += chnk->content_size();
        chnk = chnk->next;
    }
    return sz;
}

/**
 * 8kb minimum chunk size.
 * NOTE: this value directly affects how many read/write syscall will be issued.
 */
const int Chunk::min_size = 8192;

Marshal1::Bookmark* Marshal1::set_bookmark(int size) {
    verify(write_counter_ == 0);

    // invariant: head of chunk list is not fully read (otherwise it's a waste of memory)
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    Bookmark* bmark = new Bookmark();
    bmark->size_ = size;
    bmark->ptr_ = new char*[bmark->size_];

    for (int i = 0; i < bmark->size_; i++) {
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            chunk_.push_back(new Chunk);
        }
        bmark->ptr_[i] = chunk_.back()->set_bookmark();
    }

    return bmark;
}

void Marshal1::write_bookmark(Bookmark* bmark, const void* ptr) {
    char* pc = (char *) ptr;
    verify(bmark != NULL && bmark->ptr_ != NULL && bmark->size_ >= 0);
    for (int i = 0; i < bmark->size_; i++) {
        *(bmark->ptr_[i]) = pc[i];
    }
}

int Marshal1::write(const void* p, int n) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    if (chunk_.empty() || chunk_.back()->fully_written()) {
        chunk_.push_back(new Chunk(p, n));
    } else {
        int n_write = chunk_.back()->write(p, n);

        // otherwise the above fully_written() will return true
        assert(n_write > 0);

        if (n_write < n) {
            const char* pc = (const char *) p;
            chunk_.push_back(new Chunk(pc + n_write, n - n_write));
        }
    }

    write_counter_ += n;
    return n;
}

int Marshal1::read(void* p, int n) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    char* pc = (char *) p;
    int n_read = 0;
    while (!chunk_.empty() && n_read < n) {
        int r = chunk_.front()->read(pc + n_read, n - n_read);
        if (chunk_.front()->fully_read()) {
            // remove fully read chunks, avoid unnecessary mem usage
            delete chunk_.front();
            chunk_.pop_front();
        }
        if (r == 0) {
            // currently there's no content for us to read, so stop.
            break;
        }
        n_read += r;
    }

    verify(n_read <= n);
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_read;
}

int Marshal1::peek(void* p, int n) const {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    char* pc = (char *) p;
    int n_peek = 0;

    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        int r = (*it)->peek(pc + n_peek, n - n_peek);
        if (r == 0) {
            // no more data to peek, so stop
            break;
        }
        n_peek += r;
        if (n_peek == n) {
            // read enough data, so stop
            break;
        }
    }

    assert(n_peek <= n);
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_peek;
}

int Marshal1::write_to_fd(int fd, const io_ratelimit& rate) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    if (rate.min_size > 0 || rate.interval > 0) {
        // rpc batching, check if should wait till next batch
        bool should_wait = true;
        if (rate.min_size > 0 && content_size_gt(rate.min_size)) {
            should_wait = false;
        }

        if (rate.interval > 0) {
            struct timeval tm;
            gettimeofday(&tm, NULL);
            double now = tm.tv_sec + tm.tv_usec / 1000.0 / 1000.0;
            if (should_wait && now - last_write_fd_tm_ > rate.interval) {
                should_wait = false;
            }
            if (should_wait == false) {
                last_write_fd_tm_ = now;
            }
        }

        if (should_wait) {
            return 0;
        }
    }

    int n_write = 0;
    while (!chunk_.empty()) {
        int r = chunk_.front()->write_to_fd(fd);
        if (chunk_.front()->fully_read()) {
            // remove useless chunks when they are fully read
            delete chunk_.front();
            chunk_.pop_front();
        }
        if (r <= 0) {
            break;
        }
        n_write += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_write;
}

int Marshal1::read_from_marshal(Marshal1& m, int n /* =? */) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());
    assert(m.chunk_.empty() || !m.chunk_.front()->fully_read());

    int n_read = 0;
    while (n_read < n) {
        if (m.chunk_.empty()) {
            // nothing more to read
            break;
        }
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            int head_size = m.chunk_.front()->content_size();
            if (head_size < n - n_read) {

                // speed up: directly transfer chunk pointer, avoid memory copying
                chunk_.push_back(m.chunk_.front());
                m.chunk_.pop_front();
                n_read += head_size;

                // skip read_from_chunk operations
                continue;

            } else {
                chunk_.push_back(new Chunk);
            }
        }
        int r = chunk_.back()->read_from_chunk(*m.chunk_.front(), n - n_read);

        if (m.chunk_.front()->fully_read()) {
            // remove useless chunks when they are fully read
            delete m.chunk_.front();
            m.chunk_.pop_front();
        }
        if (r == 0) {
            // no more data to read
            break;
        }
        n_read += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());
    assert(m.chunk_.empty() || !m.chunk_.front()->fully_read());

    return n_read;
}

int Marshal1::read_from_fd(int fd) {
    assert(chunk_.empty() || !chunk_.front()->fully_read());

    int n_read = 0;
    for (;;) {
        if (chunk_.empty() || chunk_.back()->fully_written()) {
            chunk_.push_back(new Chunk);
        }
        int r = chunk_.back()->read_from_fd(fd);
        if (r <= 0) {
            break;
        }
        n_read += r;
    }

    assert(chunk_.empty() || !chunk_.front()->fully_read());

    return n_read;
}

bool Marshal1::content_size_gt(int size) const {

    int size_visited = 0;
    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        size_visited += (*it)->content_size();
        if (size_visited > size) {
            return true;
        }
    }

    return size_visited > size;
}

size_t Marshal1::content_size() const {
    size_t size = 0;
    for (list<Chunk*>::const_iterator it = chunk_.begin(); it != chunk_.end(); ++it) {
        size += (*it)->content_size();
    }
    return size;
}

}
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetParamBankTest
#include <boost/test/unit_test.hpp>

#define private public
#include "../../JPetParamBank/JPetParamBank.h"
#include <TFile.h>

BOOST_AUTO_TEST_SUITE(ParamBankTS)

BOOST_AUTO_TEST_CASE(DefaultConstructorTest)
{
  JPetParamBank bank;
  BOOST_REQUIRE(bank.getScintillatorsSize() == 0);
  BOOST_REQUIRE(bank.getPMsSize() == 0);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 0);
  BOOST_REQUIRE(bank.getFEBsSize() == 0);
  BOOST_REQUIRE(bank.getTRBsSize() == 0);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 0);

  BOOST_REQUIRE(bank.getScintillators().GetEntries() == 0);
  BOOST_REQUIRE(bank.getPMs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getPMCalibs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getFEBs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getTRBs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getTOMBChannels().GetEntries() == 0);
}

BOOST_AUTO_TEST_CASE(AddingDummyElementsTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);
  float epsilon = 0.0001f;

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getScintillatorsSize() == 1);
  BOOST_REQUIRE(bank.getPMsSize() == 1);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);
  BOOST_REQUIRE(bank.getFEBsSize() == 1);
  BOOST_REQUIRE(bank.getTRBsSize() == 1);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 1);

  BOOST_REQUIRE(bank.getScintillators().GetEntries() == 1);
  BOOST_REQUIRE(bank.getPMs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getPMCalibs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getFEBs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getTRBs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getTOMBChannels().GetEntries() == 1);

  BOOST_REQUIRE(bank.getScintillator(0).getID() == 111);
  BOOST_CHECK_CLOSE(bank.getScintillator(0).getAttenLen(), 8.f, epsilon);
  struct JPetScin::ScinDimensions scin_dimensions(2.f, 4.f, 8.f);
  scin_dimensions = bank.getScintillator(0).getScinSize();
  BOOST_CHECK_CLOSE(scin_dimensions.fLength, 2.f, epsilon);
  BOOST_CHECK_CLOSE(scin_dimensions.fHeight, 4.f, epsilon);
  BOOST_CHECK_CLOSE(scin_dimensions.fWidth, 8.f, epsilon);

  BOOST_REQUIRE(bank.getPM(0).getSide() == JPetPM::SideB);
  BOOST_REQUIRE(bank.getPM(0).getID() == 222);
  BOOST_REQUIRE(bank.getPM(0).getHVset() == 32);
  BOOST_REQUIRE(bank.getPM(0).getHVopt() == 64);
  BOOST_CHECK_CLOSE(bank.getPM(0).getHVgain(JPetPM::kFirst), 16.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPM(0).getHVgain(JPetPM::kSecond), 32.f, epsilon);
  std::pair<float, float> HVgain = bank.getPM(0).getHVgain();
  BOOST_CHECK_CLOSE(HVgain.first, 16.f, epsilon);
  BOOST_CHECK_CLOSE(HVgain.second, 32.f, epsilon);

  BOOST_REQUIRE(bank.getPMCalib(0).GetId() == 256);
  BOOST_REQUIRE(bank.getPMCalib(0).GetNamePM() == "JPetPMCalibTest");
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetOpthv(), 2.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetC2e_1(), 4.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetC2e_2(), 8.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetGainalpha(), 16.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetGainbeta(), 32.f, epsilon);
  BOOST_REQUIRE(bank.getPMCalib(0).GetPMCalibAssignment().id == 128);
  BOOST_REQUIRE(bank.getPMCalib(0).GetPMCalibAssignment().photomultiplier_id == 512);

  BOOST_REQUIRE(bank.getFEB(0).getID() == 1);
  BOOST_REQUIRE(bank.getFEB(0).isActive() == true);
  BOOST_REQUIRE(bank.getFEB(0).status() == "testStatus");
  BOOST_REQUIRE(bank.getFEB(0).description() == "descr");
  BOOST_REQUIRE(bank.getFEB(0).version() == 1);

  BOOST_REQUIRE(bank.getTRB(0).getID() == 333);
  BOOST_REQUIRE(bank.getTRB(0).getType() == 64);
  BOOST_REQUIRE(bank.getTRB(0).getChannel() == 128);

  BOOST_REQUIRE(bank.getTOMBChannel(0).getChannel() == 32u);
}

BOOST_AUTO_TEST_CASE(clearAllContainersTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getScintillatorsSize() == 1);
  BOOST_REQUIRE(bank.getPMsSize() == 1);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);
  BOOST_REQUIRE(bank.getFEBsSize() == 1);
  BOOST_REQUIRE(bank.getTRBsSize() == 1);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 1);

  bank.clear();

  BOOST_REQUIRE(bank.getScintillatorsSize() == 0);
  BOOST_REQUIRE(bank.getPMsSize() == 0);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 0);
  BOOST_REQUIRE(bank.getFEBsSize() == 0);
  BOOST_REQUIRE(bank.getTRBsSize() == 0);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 0);
}

BOOST_AUTO_TEST_CASE(getSizeTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getSize(JPetParamBank::kScintillator) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kPM) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kPMCalib) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kFEB) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kTRB) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kTOMBChannel) == 1);

}

BOOST_AUTO_TEST_CASE( saving_reading_file )
{
  JPetParamBank bank;
  JPetScin scint1(1, 0, 0, 0, 0);
  JPetScin scint2(2, 0, 0, 0, 0);
  JPetPM pm1;
  JPetPM pm2;
  JPetPM pm3;
  JPetPM pm4;
  pm1.setID(1);
  pm2.setID(2);
  pm3.setID(3);
  pm4.setID(4);
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  pm1.setTRefScin(scint1);
  pm2.setTRefScin(scint1);
  pm3.setTRefScin(scint2);
  pm4.setTRefScin(scint2);

  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb;
  bank.addPM(pm1);
  bank.addPM(pm2);
  bank.addPM(pm3);
  bank.addPM(pm4);
  bank.addPMCalib(pmCalib);
  bank.addScintillator(scint1);
  bank.addScintillator(scint2);
  bank.addTRB(trb);
  bank.addFEB(feb);
  for (int i = 0; i < 100; i++) {
    JPetTOMBChannel channel(i);
    bank.addTOMBChannel(channel);
  }

  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);

  TFile file("test.root", "UPDATE");
  file.cd();
  file.WriteObject(&bank, "ParamBank");
  file.Close();
  bank.clear();

  TFile file2("test.root", "READ");
  JPetParamBank* pBank = static_cast<JPetParamBank*>(file2.Get("ParamBank"));
  JPetParamBank& bank2 = *pBank;

  BOOST_REQUIRE(bank2.getScintillatorsSize() == 2);
  BOOST_REQUIRE(bank2.getPMsSize() == 4);
  BOOST_REQUIRE(bank2.getPMCalibsSize() == 0); // TODO ERROR - should be 1
  BOOST_REQUIRE(bank2.getFEBsSize() == 1);
  BOOST_REQUIRE(bank2.getTRBsSize() == 1);

  BOOST_REQUIRE(bank2.getScintillators().GetEntries() == 2);
  BOOST_REQUIRE(bank2.getPMs().GetEntries() == 4);
  BOOST_REQUIRE(bank2.getPMCalibs().GetEntries() == 0); // TODO ERROR - should be 1
  BOOST_REQUIRE(bank2.getFEBs().GetEntries() == 1);
  BOOST_REQUIRE(bank2.getTRBs().GetEntries() == 1);

  // BOOST_REQUIRE(bank2.getPMCalib(0).GetId() == 256); // TODO ERROR

  BOOST_REQUIRE(bank2.getFEB(0).getID() == 1);
  BOOST_REQUIRE(bank2.getFEB(0).isActive());
  BOOST_REQUIRE(bank2.getFEB(0).status() == "testStatus");
  BOOST_REQUIRE(bank2.getFEB(0).description() == "descr");
  BOOST_REQUIRE(bank2.getFEB(0).version() == 1);

  BOOST_REQUIRE(bank2.getPM(0).getScin().getID() == 1);
  BOOST_REQUIRE(bank2.getPM(1).getScin().getID() == 1);
  BOOST_REQUIRE(bank2.getPM(2).getScin().getID() == 2);
  BOOST_REQUIRE(bank2.getPM(3).getScin().getID() == 2);
  BOOST_REQUIRE(bank2.getScintillator(0).getID() == 1);
  BOOST_REQUIRE(bank2.getScintillator(1).getID() == 2);

  file2.Close();
}

BOOST_AUTO_TEST_SUITE_END()

<commit_msg>fixed JPetParamBankTests<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE JPetParamBankTest
#include <boost/test/unit_test.hpp>

#define private public
#include "../../JPetParamBank/JPetParamBank.h"
#include <TFile.h>

BOOST_AUTO_TEST_SUITE(ParamBankTS)

BOOST_AUTO_TEST_CASE(DefaultConstructorTest)
{
  JPetParamBank bank;
  BOOST_REQUIRE(bank.getScintillatorsSize() == 0);
  BOOST_REQUIRE(bank.getPMsSize() == 0);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 0);
  BOOST_REQUIRE(bank.getFEBsSize() == 0);
  BOOST_REQUIRE(bank.getTRBsSize() == 0);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 0);

  BOOST_REQUIRE(bank.getScintillators().GetEntries() == 0);
  BOOST_REQUIRE(bank.getPMs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getPMCalibs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getFEBs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getTRBs().GetEntries() == 0);
  BOOST_REQUIRE(bank.getTOMBChannels().GetEntries() == 0);
}

BOOST_AUTO_TEST_CASE(AddingDummyElementsTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);
  float epsilon = 0.0001f;

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getScintillatorsSize() == 1);
  BOOST_REQUIRE(bank.getPMsSize() == 1);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);
  BOOST_REQUIRE(bank.getFEBsSize() == 1);
  BOOST_REQUIRE(bank.getTRBsSize() == 1);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 1);

  BOOST_REQUIRE(bank.getScintillators().GetEntries() == 1);
  BOOST_REQUIRE(bank.getPMs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getPMCalibs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getFEBs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getTRBs().GetEntries() == 1);
  BOOST_REQUIRE(bank.getTOMBChannels().GetEntries() == 1);

  BOOST_REQUIRE(bank.getScintillator(0).getID() == 111);
  BOOST_CHECK_CLOSE(bank.getScintillator(0).getAttenLen(), 8.f, epsilon);
  struct JPetScin::ScinDimensions scin_dimensions(2.f, 4.f, 8.f);
  scin_dimensions = bank.getScintillator(0).getScinSize();
  BOOST_CHECK_CLOSE(scin_dimensions.fLength, 2.f, epsilon);
  BOOST_CHECK_CLOSE(scin_dimensions.fHeight, 4.f, epsilon);
  BOOST_CHECK_CLOSE(scin_dimensions.fWidth, 8.f, epsilon);

  BOOST_REQUIRE(bank.getPM(0).getSide() == JPetPM::SideB);
  BOOST_REQUIRE(bank.getPM(0).getID() == 222);
  BOOST_REQUIRE(bank.getPM(0).getHVset() == 32);
  BOOST_REQUIRE(bank.getPM(0).getHVopt() == 64);
  BOOST_CHECK_CLOSE(bank.getPM(0).getHVgain(JPetPM::kFirst), 16.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPM(0).getHVgain(JPetPM::kSecond), 32.f, epsilon);
  std::pair<float, float> HVgain = bank.getPM(0).getHVgain();
  BOOST_CHECK_CLOSE(HVgain.first, 16.f, epsilon);
  BOOST_CHECK_CLOSE(HVgain.second, 32.f, epsilon);

  BOOST_REQUIRE(bank.getPMCalib(0).GetId() == 256);
  BOOST_REQUIRE(bank.getPMCalib(0).GetNamePM() == "JPetPMCalibTest");
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetOpthv(), 2.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetC2e_1(), 4.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetC2e_2(), 8.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetGainalpha(), 16.f, epsilon);
  BOOST_CHECK_CLOSE(bank.getPMCalib(0).GetGainbeta(), 32.f, epsilon);
  BOOST_REQUIRE(bank.getPMCalib(0).GetPMCalibAssignment().id == 128);
  BOOST_REQUIRE(bank.getPMCalib(0).GetPMCalibAssignment().photomultiplier_id == 512);

  BOOST_REQUIRE(bank.getFEB(0).getID() == 1);
  BOOST_REQUIRE(bank.getFEB(0).isActive() == true);
  BOOST_REQUIRE(bank.getFEB(0).status() == "testStatus");
  BOOST_REQUIRE(bank.getFEB(0).description() == "descr");
  BOOST_REQUIRE(bank.getFEB(0).version() == 1);

  BOOST_REQUIRE(bank.getTRB(0).getID() == 333);
  BOOST_REQUIRE(bank.getTRB(0).getType() == 64);
  BOOST_REQUIRE(bank.getTRB(0).getChannel() == 128);

  BOOST_REQUIRE(bank.getTOMBChannel(0).getChannel() == 32u);
}

BOOST_AUTO_TEST_CASE(clearAllContainersTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getScintillatorsSize() == 1);
  BOOST_REQUIRE(bank.getPMsSize() == 1);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);
  BOOST_REQUIRE(bank.getFEBsSize() == 1);
  BOOST_REQUIRE(bank.getTRBsSize() == 1);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 1);

  bank.clear();

  BOOST_REQUIRE(bank.getScintillatorsSize() == 0);
  BOOST_REQUIRE(bank.getPMsSize() == 0);
  BOOST_REQUIRE(bank.getPMCalibsSize() == 0);
  BOOST_REQUIRE(bank.getFEBsSize() == 0);
  BOOST_REQUIRE(bank.getTRBsSize() == 0);
  BOOST_REQUIRE(bank.getTOMBChannelsSize() == 0);
}

BOOST_AUTO_TEST_CASE(getSizeTest)
{
  JPetParamBank bank;
  JPetScin scint(111, 8.f, 2.f, 4.f, 8.f);
  JPetPM pm(JPetPM::SideB, 222, 32, 64, std::make_pair(16.f, 32.f));
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb(333, 64, 128);
  JPetTOMBChannel TOMBChannel(32u);

  bank.addScintillator(scint);
  bank.addPM(pm);
  bank.addPMCalib(pmCalib);
  bank.addFEB(feb);
  bank.addTRB(trb);
  bank.addTOMBChannel(TOMBChannel);

  BOOST_REQUIRE(bank.getSize(JPetParamBank::kScintillator) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kPM) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kPMCalib) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kFEB) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kTRB) == 1);
  BOOST_REQUIRE(bank.getSize(JPetParamBank::kTOMBChannel) == 1);

}

BOOST_AUTO_TEST_CASE( saving_reading_file )
{
  JPetParamBank bank;
  JPetScin scint1(1, 0, 0, 0, 0);
  JPetScin scint2(2, 0, 0, 0, 0);
  JPetPM pm1;
  JPetPM pm2;
  JPetPM pm3;
  JPetPM pm4;
  pm1.setID(1);
  pm2.setID(2);
  pm3.setID(3);
  pm4.setID(4);
  JPetPMCalib pmCalib(256, "JPetPMCalibTest", 2.f, 4.f, 8.f, 16.f, 32.f, 128, 512);
  pm1.setScin(scint1);
  pm2.setScin(scint1);
  pm3.setScin(scint2);
  pm4.setScin(scint2);

  JPetFEB feb(1, true, "testStatus", "descr", 1, 1);
  JPetTRB trb;
  bank.addPM(pm1);
  bank.addPM(pm2);
  bank.addPM(pm3);
  bank.addPM(pm4);
  bank.addPMCalib(pmCalib);
  bank.addScintillator(scint1);
  bank.addScintillator(scint2);
  bank.addTRB(trb);
  bank.addFEB(feb);
  for (int i = 0; i < 100; i++) {
    JPetTOMBChannel channel(i);
    bank.addTOMBChannel(channel);
  }

  BOOST_REQUIRE(bank.getPMCalibsSize() == 1);

  TFile file("test.root", "UPDATE");
  file.cd();
  file.WriteObject(&bank, "ParamBank");
  file.Close();
  bank.clear();

  TFile file2("test.root", "READ");
  JPetParamBank* pBank = static_cast<JPetParamBank*>(file2.Get("ParamBank"));
  JPetParamBank& bank2 = *pBank;

  BOOST_REQUIRE(bank2.getScintillatorsSize() == 2);
  BOOST_REQUIRE(bank2.getPMsSize() == 4);
  BOOST_REQUIRE(bank2.getPMCalibsSize() == 0); // TODO ERROR - should be 1
  BOOST_REQUIRE(bank2.getFEBsSize() == 1);
  BOOST_REQUIRE(bank2.getTRBsSize() == 1);

  BOOST_REQUIRE(bank2.getScintillators().GetEntries() == 2);
  BOOST_REQUIRE(bank2.getPMs().GetEntries() == 4);
  BOOST_REQUIRE(bank2.getPMCalibs().GetEntries() == 0); // TODO ERROR - should be 1
  BOOST_REQUIRE(bank2.getFEBs().GetEntries() == 1);
  BOOST_REQUIRE(bank2.getTRBs().GetEntries() == 1);

  // BOOST_REQUIRE(bank2.getPMCalib(0).GetId() == 256); // TODO ERROR

  BOOST_REQUIRE(bank2.getFEB(0).getID() == 1);
  BOOST_REQUIRE(bank2.getFEB(0).isActive());
  BOOST_REQUIRE(bank2.getFEB(0).status() == "testStatus");
  BOOST_REQUIRE(bank2.getFEB(0).description() == "descr");
  BOOST_REQUIRE(bank2.getFEB(0).version() == 1);

  BOOST_REQUIRE(bank2.getPM(0).getScin().getID() == 1);
  BOOST_REQUIRE(bank2.getPM(1).getScin().getID() == 1);
  BOOST_REQUIRE(bank2.getPM(2).getScin().getID() == 2);
  BOOST_REQUIRE(bank2.getPM(3).getScin().getID() == 2);
  BOOST_REQUIRE(bank2.getScintillator(0).getID() == 1);
  BOOST_REQUIRE(bank2.getScintillator(1).getID() == 2);

  file2.Close();
}

BOOST_AUTO_TEST_SUITE_END()

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <ncurses.h>
#include <csignal>
#include <cstdlib>

#include "signals.hh"

extern "C" {
static void myexit(int i) {
    endwin();
    SIG_DFL(i);
}
}

namespace vick {

void setup_signal_handling() {
    signal(SIGABRT, myexit);
    signal(SIGFPE, myexit);
    signal(SIGILL, myexit);
    signal(SIGINT, myexit);
    signal(SIGSEGV, myexit);
    signal(SIGTERM, myexit);
}
}
<commit_msg>Use `*.h` headers rather than `c*`<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <ncurses.h>
#include <signal.h>
#include <stdlib.h>

#include "signals.hh"

extern "C" {
static void myexit(int i) {
    endwin();
    SIG_DFL(i);
}
}

namespace vick {

void setup_signal_handling() {
    signal(SIGABRT, myexit);
    signal(SIGFPE, myexit);
    signal(SIGILL, myexit);
    signal(SIGINT, myexit);
    signal(SIGSEGV, myexit);
    signal(SIGTERM, myexit);
}
}
<|endoftext|>


<commit_before>//=====================================================================//
/*! @file
    @brief  RX65N ダイレクト・デジタル・シンセサイザ @n
			マイコン内臓１２ビットＤ／Ａ変換を使って、波形を生成するガジェット
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2019 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#define CASH_KFONT

#include "common/renesas.hpp"
#include "common/cmt_io.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/sci_i2c_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"
#include "common/spi_io2.hpp"
#include "ff13c/mmc_io.hpp"
#include "common/tpu_io.hpp"
#include "common/qspi_io.hpp"
#include "graphics/font8x16.hpp"
#include "graphics/graphics.hpp"
#include "graphics/filer.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"

#include "chip/FT5206.hpp"

namespace {

	typedef device::PORT<device::PORT7, device::bitpos::B0> LED;

	typedef device::system_io<12000000> SYSTEM_IO;

	typedef device::cmt_io<device::CMT0, utils::null_task> CMT;
	CMT			cmt_;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<device::SCI9, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	// カード電源制御は使わないので、「device::NULL_PORT」を指定する。
//	typedef device::PORT<device::PORT6, device::bitpos::B4> SDC_POWER;
	typedef device::NULL_PORT SDC_POWER;

#ifdef SDHI_IF
	// RX65N Envision Kit の SDHI ポートは、候補３になっている
	typedef fatfs::sdhi_io<device::SDHI, SDC_POWER, device::port_map::option::THIRD> SDHI;
	SDHI		sdh_;
#else
	// Soft SDC 用　SPI 定義（SPI）
	typedef device::PORT<device::PORT2, device::bitpos::B2> MISO;  // DAT0
	typedef device::PORT<device::PORT2, device::bitpos::B0> MOSI;  // CMD
	typedef device::PORT<device::PORT2, device::bitpos::B1> SPCK;  // CLK

	typedef device::spi_io2<MISO, MOSI, SPCK> SPI;  ///< Soft SPI 定義

	SPI			spi_;

	typedef device::PORT<device::PORT1, device::bitpos::B7> SDC_SELECT;  // DAT3 カード選択信号
	typedef device::PORT<device::PORT2, device::bitpos::B5> SDC_DETECT;  // CD   カード検出

	typedef fatfs::mmc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> MMC;   // ハードウェアー定義

	MMC			sdh_(spi_, 20000000);
#endif

	typedef device::PORT<device::PORT6, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B6> LCD_LIGHT;
	static const int16_t LCD_X = 480;
	static const int16_t LCD_Y = 272;
	static void* LCD_ORG = reinterpret_cast<void*>(0x00000100);
	static const auto PIXT = graphics::pixel::TYPE::RGB565;
	typedef device::glcdc_io<device::GLCDC, LCD_X, LCD_Y, PIXT> GLCDC_IO;
	GLCDC_IO	glcdc_io_(nullptr, LCD_ORG);

	typedef graphics::font8x16 AFONT;
	AFONT		afont_;
#ifdef CASH_KFONT
	typedef graphics::kfont<16, 16, 64> KFONT;
#else
	typedef graphics::kfont<16, 16> KFONT;
#endif
	KFONT		kfont_;
	typedef graphics::font<AFONT, KFONT> FONT;
	FONT		font_(afont_, kfont_);

//	typedef device::drw2d_mgr<GLCDC_IO, FONT> RENDER;
	typedef graphics::render<GLCDC_IO, FONT> RENDER;
	RENDER		render_(glcdc_io_, font_);

	// FT5206, SCI6 簡易 I2C 定義
	typedef device::PORT<device::PORT0, device::bitpos::B7> FT5206_RESET;
	typedef utils::fixed_fifo<uint8_t, 64> RB6;
	typedef utils::fixed_fifo<uint8_t, 64> SB6;
	typedef device::sci_i2c_io<device::SCI6, RB6, SB6,
		device::port_map::option::FIRST_I2C> FT5206_I2C;

	FT5206_I2C	ft5206_i2c_;
	typedef chip::FT5206<FT5206_I2C> FT5206;
	FT5206		ft5206_(ft5206_i2c_);

	utils::command<256> cmd_;

	void update_led_()
	{
		static uint8_t n = 0;
		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}
	}

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}

		uint8_t cmdn = cmd_.get_words();
		if(cmdn >= 1) {
			bool f = false;
			if(cmd_.cmp_word(0, "dir")) {  // dir [xxx]
				if(sdh_.get_mount()) {
					if(cmdn >= 2) {
						char tmp[128];
						cmd_.get_word(1, tmp, sizeof(tmp));
						utils::file_io::dir(tmp);
					} else {
						utils::file_io::dir("");
					}
				}
				f = true;
			} else if(cmd_.cmp_word(0, "cd")) {  // cd [xxx]
				if(sdh_.get_mount()) {
					if(cmdn >= 2) {
						char tmp[128];
						cmd_.get_word(1, tmp, sizeof(tmp));
						utils::file_io::cd(tmp);
					} else {
						utils::file_io::cd("/");
					}
				}
				f = true;
			} else if(cmd_.cmp_word(0, "pwd")) { // pwd
				char tmp[FF_MAX_LFN + 1];
				if(!utils::file_io::pwd(tmp, sizeof(tmp))) {
					utils::format("%s\n") % tmp;
				}
				f = true;
			} else if(cmd_.cmp_word(0, "help")) {
				utils::format("    dir [path]\n");
				utils::format("    cd [path]\n");
				utils::format("    pwd\n");
				f = true;
			}
			if(!f) {
				char tmp[128];
				if(cmd_.get_word(0, tmp, sizeof(tmp))) {
					utils::format("Command error: '%s'\n") % tmp;
				}
			}
		}
	}
}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdh_.disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdh_.disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdh_.disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		time_t t = 0;
///		rtc_.get_time(t);
		return utils::str::get_fattime(t);
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		static const uint8_t sci_level = 2;
		sci_.start(115200, sci_level);
	}

	{  // SD カード・クラスの初期化
		sdh_.start();
	}

	utils::format("RTK5RX65N Start for Direct Digital Synthsyzer\n");
	cmd_.set_prompt("# ");

	{  // GLCDC の初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_io_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_io_.control(GLCDC_IO::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			}
		} else {
			utils::format("GLCDC Fail\n");
		}
	}

	{  // FT5206 touch screen controller
		FT5206::reset<FT5206_RESET>();
		uint8_t intr_lvl = 1;
		if(!ft5206_i2c_.start(FT5206_I2C::SPEED::STANDARD, intr_lvl)) {
			utils::format("FT5206 I2C Start Fail...\n");
		}
		if(!ft5206_.start()) {
			utils::format("FT5206 Start Fail...\n");
		}
	}

	LED::DIR = 1;

	// タッチパネルの安定待ち

	while(1) {
		render_.sync_frame();

		ft5206_.update();

		sdh_.service();

		command_();

		update_led_();
	}
}
<commit_msg>Update: clean up shell class<commit_after>//=====================================================================//
/*! @file
    @brief  RX65N ダイレクト・デジタル・シンセサイザ @n
			マイコン内臓１２ビットＤ／Ａ変換を使って、波形を生成するガジェット
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2019 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#define CASH_KFONT

#include "common/renesas.hpp"
#include "common/cmt_io.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
#include "common/sci_i2c_io.hpp"
#include "common/format.hpp"
#include "common/command.hpp"
#include "common/shell.hpp"
#include "common/spi_io2.hpp"
#include "common/tpu_io.hpp"
#include "common/qspi_io.hpp"
#include "graphics/font8x16.hpp"
#include "graphics/graphics.hpp"
#include "graphics/filer.hpp"
#include "graphics/kfont.hpp"
#include "graphics/font.hpp"

#include "chip/FT5206.hpp"

namespace {

	typedef device::PORT<device::PORT7, device::bitpos::B0> LED;

	typedef device::system_io<12000000> SYSTEM_IO;

	typedef device::cmt_io<device::CMT0, utils::null_task> CMT;
	CMT			cmt_;

	typedef utils::fixed_fifo<char, 512>  RECV_BUFF;
	typedef utils::fixed_fifo<char, 1024> SEND_BUFF;
	typedef device::sci_io<device::SCI9, RECV_BUFF, SEND_BUFF> SCI;
	SCI			sci_;

	// カード電源制御は使わないので、「device::NULL_PORT」を指定する。
//	typedef device::PORT<device::PORT6, device::bitpos::B4> SDC_POWER;
	typedef device::NULL_PORT SDC_POWER;

#ifdef SDHI_IF
	// RX65N Envision Kit の SDHI ポートは、候補３になっている
	typedef fatfs::sdhi_io<device::SDHI, SDC_POWER, device::port_map::option::THIRD> SDHI;
	SDHI		sdh_;
#else
	// Soft SDC 用　SPI 定義（SPI）
	typedef device::PORT<device::PORT2, device::bitpos::B2> MISO;  // DAT0
	typedef device::PORT<device::PORT2, device::bitpos::B0> MOSI;  // CMD
	typedef device::PORT<device::PORT2, device::bitpos::B1> SPCK;  // CLK

	typedef device::spi_io2<MISO, MOSI, SPCK> SPI;  ///< Soft SPI 定義

	SPI			spi_;

	typedef device::PORT<device::PORT1, device::bitpos::B7> SDC_SELECT;  // DAT3 カード選択信号
	typedef device::PORT<device::PORT2, device::bitpos::B5> SDC_DETECT;  // CD   カード検出

	typedef fatfs::mmc_io<SPI, SDC_SELECT, SDC_POWER, SDC_DETECT> MMC;   // ハードウェアー定義

	MMC			sdh_(spi_, 20000000);
#endif

	typedef device::PORT<device::PORT6, device::bitpos::B3> LCD_DISP;
	typedef device::PORT<device::PORT6, device::bitpos::B6> LCD_LIGHT;
	static const int16_t LCD_X = 480;
	static const int16_t LCD_Y = 272;
	static void* LCD_ORG = reinterpret_cast<void*>(0x00000100);
	static const auto PIXT = graphics::pixel::TYPE::RGB565;
	typedef device::glcdc_io<device::GLCDC, LCD_X, LCD_Y, PIXT> GLCDC_IO;
	GLCDC_IO	glcdc_io_(nullptr, LCD_ORG);

	typedef graphics::font8x16 AFONT;
	AFONT		afont_;
#ifdef CASH_KFONT
	typedef graphics::kfont<16, 16, 64> KFONT;
#else
	typedef graphics::kfont<16, 16> KFONT;
#endif
	KFONT		kfont_;
	typedef graphics::font<AFONT, KFONT> FONT;
	FONT		font_(afont_, kfont_);

//	typedef device::drw2d_mgr<GLCDC_IO, FONT> RENDER;
	typedef graphics::render<GLCDC_IO, FONT> RENDER;
	RENDER		render_(glcdc_io_, font_);

	// FT5206, SCI6 簡易 I2C 定義
	typedef device::PORT<device::PORT0, device::bitpos::B7> FT5206_RESET;
	typedef utils::fixed_fifo<uint8_t, 64> RB6;
	typedef utils::fixed_fifo<uint8_t, 64> SB6;
	typedef device::sci_i2c_io<device::SCI6, RB6, SB6,
		device::port_map::option::FIRST_I2C> FT5206_I2C;

	FT5206_I2C	ft5206_i2c_;
	typedef chip::FT5206<FT5206_I2C> FT5206;
	FT5206		ft5206_(ft5206_i2c_);

	typedef utils::command<256> CMD;
	CMD			cmd_;
	typedef utils::shell<CMD> SHELL;
	SHELL		shell_(cmd_);

	void update_led_()
	{
		static uint8_t n = 0;
		++n;
		if(n >= 30) {
			n = 0;
		}
		if(n < 10) {
			LED::P = 0;
		} else {
			LED::P = 1;
		}
	}

	void command_()
	{
		if(!cmd_.service()) {
			return;
		}
		if(shell_.analize()) {
			return;
		}
		if(cmd_.cmp_word(0, "help")) {
			shell_.help();
		} else {
			utils::format("Command error: '%s'\n") % cmd_.get_command();
		}
	}
}

extern "C" {

	void sci_putch(char ch)
	{
		sci_.putch(ch);
	}

	void sci_puts(const char* str)
	{
		sci_.puts(str);
	}

	char sci_getch(void)
	{
		return sci_.getch();
	}

	uint16_t sci_length()
	{
		return sci_.recv_length();
	}

	DSTATUS disk_initialize(BYTE drv) {
		return sdh_.disk_initialize(drv);
	}

	DSTATUS disk_status(BYTE drv) {
		return sdh_.disk_status(drv);
	}

	DRESULT disk_read(BYTE drv, BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_read(drv, buff, sector, count);
	}

	DRESULT disk_write(BYTE drv, const BYTE* buff, DWORD sector, UINT count) {
		return sdh_.disk_write(drv, buff, sector, count);
	}

	DRESULT disk_ioctl(BYTE drv, BYTE ctrl, void* buff) {
		return sdh_.disk_ioctl(drv, ctrl, buff);
	}

	DWORD get_fattime(void) {
		time_t t = 0;
///		rtc_.get_time(t);
		return utils::str::get_fattime(t);
	}
}

int main(int argc, char** argv);

int main(int argc, char** argv)
{
	SYSTEM_IO::setup_system_clock();

	{  // SCI 設定
		static const uint8_t sci_level = 2;
		sci_.start(115200, sci_level);
	}

	{  // SD カード・クラスの初期化
		sdh_.start();
	}

	utils::format("RTK5RX65N Start for Direct Digital Synthsyzer\n");
	cmd_.set_prompt("# ");

	{  // GLCDC の初期化
		LCD_DISP::DIR  = 1;
		LCD_LIGHT::DIR = 1;
		LCD_DISP::P  = 0;  // DISP Disable
		LCD_LIGHT::P = 0;  // BackLight Disable (No PWM)
		if(glcdc_io_.start()) {
			utils::format("Start GLCDC\n");
			LCD_DISP::P  = 1;  // DISP Enable
			LCD_LIGHT::P = 1;  // BackLight Enable (No PWM)
			if(!glcdc_io_.control(GLCDC_IO::CONTROL_CMD::START_DISPLAY)) {
				utils::format("GLCDC ctrl fail...\n");
			}
		} else {
			utils::format("GLCDC Fail\n");
		}
	}

	{  // FT5206 touch screen controller
		FT5206::reset<FT5206_RESET>();
		uint8_t intr_lvl = 1;
		if(!ft5206_i2c_.start(FT5206_I2C::SPEED::STANDARD, intr_lvl)) {
			utils::format("FT5206 I2C Start Fail...\n");
		}
		if(!ft5206_.start()) {
			utils::format("FT5206 Start Fail...\n");
		}
	}

	LED::DIR = 1;

	// タッチパネルの安定待ち

	while(1) {
		render_.sync_frame();

		ft5206_.update();

		sdh_.service();

		command_();

		update_led_();
	}
}
<|endoftext|>


<commit_before>#include "RenderCameraSystem.hpp"

#include <Components/CameraComponent.hpp>
#include <Components/SpotLight.hh>
#include <Components/DirectionalLightComponent.hh>
#include <Components/Light.hh>

#include <Core/Engine.hh>
#include <Core/AScene.hh>

#include <glm/gtc/matrix_transform.hpp>

#include <BFC/BFCLinkTracker.hpp>
#include <BFC/BFCBlockManagerFactory.hpp>
#include <BFC/BFCCullableObject.hpp>

#include <Graphic/DRBCameraDrawableList.hpp>
#include <Graphic/BFCCullableTypes.hpp>

#include <Threads/ThreadManager.hpp>
#include <Threads/RenderThread.hpp>
#include <Threads/MainThread.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>

#include "Utils/Frustum.hh"

namespace AGE
{
	RenderCameraSystem::RenderCameraSystem(AScene *scene) :
		System(std::move(scene)),
		_cameras(std::move(scene)),
		_spotLights(std::move(scene)),
		_directionnalLights(std::move(scene)),
		_pointLights(std::move(scene))
	{
		_name = "Camera system";
	}

	bool RenderCameraSystem::initialize()
	{
		_cameras.requireComponent<CameraComponent>();
		_spotLights.requireComponent<SpotLightComponent>();
		_directionnalLights.requireComponent<DirectionalLightComponent>();
		_pointLights.requireComponent<PointLightComponent>();
		return (true);
	}

	void RenderCameraSystem::updateBegin(float time)
	{

	}

	void RenderCameraSystem::mainUpdate(float time)
	{
		_scene->getBfcLinkTracker()->reset();

		// check if the render thread does not already have stuff to draw
		if (GetMainThread()->isRenderFrame() == false)
		{
			return;
		}

		std::list<std::shared_ptr<DRBSpotLightDrawableList>> spotLightList;
		std::list<std::shared_ptr<DRBData>> pointLightList;

		for (auto spotEntity : _spotLights.getCollection())
		{
			auto spot = spotEntity->getComponent<SpotLightComponent>();
			auto spotDrawableList = std::make_shared<DRBSpotLightDrawableList>();
			spotDrawableList->spotLight = spot->getCullableHandle().getPtr()->getDatas();

			// WARNINNNNNNNNNNNG
			// Le calcul n'est pas bon !!!!
			// Paul, fais le STP, merci
			Frustum spotlightFrustum;
			spotlightFrustum.setMatrix(glm::perspective(spot->getCutOff() / 2.0f, spot->getExponent(), 0.1f, 1000.0f)* glm::inverse(spotEntity->getLink().getGlobalTransform()));
			glm::vec4 a = spotEntity->getLink().getGlobalTransform() * glm::vec4(-1, -1, 0, 1);
			glm::vec4 b = spotEntity->getLink().getGlobalTransform() * glm::vec4(-1, 1, 0, 1);
			glm::vec4 c = spotEntity->getLink().getGlobalTransform() * glm::vec4(1, 1, 0, 1);
			glm::vec4 d = spotEntity->getLink().getGlobalTransform() * glm::vec4(1, -1, 0, 1);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DQuad>(glm::vec3(a), glm::vec3(b), glm::vec3(c), glm::vec3(d));

			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullableMesh, spotDrawableList->meshs, spotlightFrustum);
			spotLightList.push_back(spotDrawableList);
		}
		for (auto pointLightEntity : _pointLights.getCollection())
		{
			auto point = pointLightEntity->getComponent<PointLightComponent>();

			pointLightList.push_back(point->getCullableHandle().getPtr()->getDatas());
		}

		for (auto cameraEntity : _cameras.getCollection())
		{
			Frustum cameraFrustum;
			auto camera = cameraEntity->getComponent<CameraComponent>();

			auto cameraList = std::make_shared<DRBCameraDrawableList>();
			cameraList->cameraInfos.data = camera->getData();
			cameraList->cameraInfos.view = glm::inverse(cameraEntity->getLink().getGlobalTransform());

			cameraFrustum.setMatrix(camera->getProjection() * cameraList->cameraInfos.view);

			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullableMesh, cameraList->meshs, cameraFrustum);
			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullablePointLight, cameraList->pointLights, cameraFrustum);
			cameraList->spotLights = spotLightList;
			cameraList->pointLights = pointLightList;
			AGE::GetRenderThread()->getQueue()->emplaceCommand<AGE::DRBCameraDrawableListCommand>(cameraList);
		}
	}

	void RenderCameraSystem::updateEnd(float time)
	{
	}
}<commit_msg>spotlight frustum in debug<commit_after>#include "RenderCameraSystem.hpp"

#include <Components/CameraComponent.hpp>
#include <Components/SpotLight.hh>
#include <Components/DirectionalLightComponent.hh>
#include <Components/Light.hh>

#include <Core/Engine.hh>
#include <Core/AScene.hh>

#include <glm/gtc/matrix_transform.hpp>

#include <BFC/BFCLinkTracker.hpp>
#include <BFC/BFCBlockManagerFactory.hpp>
#include <BFC/BFCCullableObject.hpp>

#include <Graphic/DRBCameraDrawableList.hpp>
#include <Graphic/BFCCullableTypes.hpp>

#include <Threads/ThreadManager.hpp>
#include <Threads/RenderThread.hpp>
#include <Threads/MainThread.hpp>
#include <Threads/Commands/ToRenderCommands.hpp>

#include "Utils/Frustum.hh"

namespace AGE
{
	RenderCameraSystem::RenderCameraSystem(AScene *scene) :
		System(std::move(scene)),
		_cameras(std::move(scene)),
		_spotLights(std::move(scene)),
		_directionnalLights(std::move(scene)),
		_pointLights(std::move(scene))
	{
		_name = "Camera system";
	}

	bool RenderCameraSystem::initialize()
	{
		_cameras.requireComponent<CameraComponent>();
		_spotLights.requireComponent<SpotLightComponent>();
		_directionnalLights.requireComponent<DirectionalLightComponent>();
		_pointLights.requireComponent<PointLightComponent>();
		return (true);
	}

	void RenderCameraSystem::updateBegin(float time)
	{

	}

	void RenderCameraSystem::mainUpdate(float time)
	{
		_scene->getBfcLinkTracker()->reset();

		// check if the render thread does not already have stuff to draw
		if (GetMainThread()->isRenderFrame() == false)
		{
			return;
		}

		std::list<std::shared_ptr<DRBSpotLightDrawableList>> spotLightList;
		std::list<std::shared_ptr<DRBData>> pointLightList;

		for (auto spotEntity : _spotLights.getCollection())
		{
			auto spot = spotEntity->getComponent<SpotLightComponent>();
			auto spotDrawableList = std::make_shared<DRBSpotLightDrawableList>();
			spotDrawableList->spotLight = spot->getCullableHandle().getPtr()->getDatas();

			float spotFov = glm::max(0.001f, (1.0f - spot->getCutOff()) * 180.0f);
			glm::mat4 spotViewProj = glm::perspective(spotFov, 1.0f, 0.1f, 1000.0f) * glm::inverse(spotEntity->getLink().getGlobalTransform());

			Frustum spotlightFrustum;
			spotlightFrustum.setMatrix(spotViewProj);

			// Draw spotlight frustum debug:
			glm::vec4 worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, -1, 1.0f);
			glm::vec3 aNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, -1, 1.0f);
			glm::vec3 bNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, -1, 1.0f);
			glm::vec3 cNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, -1, 1.0f);
			glm::vec3 dNear = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, -1, 1, 1.0f);
			glm::vec3 aFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(-1, 1, 1, 1.0f);
			glm::vec3 bFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, 1, 1, 1.0f);
			glm::vec3 cFar = glm::vec3(worldPos / worldPos.w);
			worldPos = glm::inverse(spotViewProj) * glm::vec4(1, -1, 1, 1.0f);
			glm::vec3 dFar = glm::vec3(worldPos / worldPos.w);

			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DQuad>(aNear, bNear, cNear, dNear);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DQuad>(aFar, bFar, cFar, dFar);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DLine>(aNear, aFar);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DLine>(bNear, bFar);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DLine>(cNear, cFar);
			AGE::GetRenderThread()->getQueue()->emplaceCommand<Commands::ToRender::Draw3DLine>(dNear, dFar);

			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullableMesh, spotDrawableList->meshs, spotlightFrustum);
			spotLightList.push_back(spotDrawableList);
		}
		for (auto pointLightEntity : _pointLights.getCollection())
		{
			auto point = pointLightEntity->getComponent<PointLightComponent>();

			pointLightList.push_back(point->getCullableHandle().getPtr()->getDatas());
		}

		for (auto cameraEntity : _cameras.getCollection())
		{
			Frustum cameraFrustum;
			auto camera = cameraEntity->getComponent<CameraComponent>();

			auto cameraList = std::make_shared<DRBCameraDrawableList>();
			cameraList->cameraInfos.data = camera->getData();
			cameraList->cameraInfos.view = glm::inverse(cameraEntity->getLink().getGlobalTransform());

			cameraFrustum.setMatrix(camera->getProjection() * cameraList->cameraInfos.view);

			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullableMesh, cameraList->meshs, cameraFrustum);
			_scene->getBfcBlockManagerFactory()->cullOnChannel(BFCCullableType::CullablePointLight, cameraList->pointLights, cameraFrustum);
			cameraList->spotLights = spotLightList;
			cameraList->pointLights = pointLightList;
			AGE::GetRenderThread()->getQueue()->emplaceCommand<AGE::DRBCameraDrawableListCommand>(cameraList);
		}
	}

	void RenderCameraSystem::updateEnd(float time)
	{
	}
}<|endoftext|>


<commit_before>/*
 * Copyright 2012 BrewPi/Elco Jacobs.
 *
 * This file is part of BrewPi.
 *
 * BrewPi 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 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi 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 BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "RotaryEncoder.h"

#include "Pins.h"
#include "util/atomic.h"
#include <limits.h>
#include "Ticks.h"
#include "Display.h"
#include "FastDigitalPin.h"
#include "Brewpi.h"

RotaryEncoder rotaryEncoder;

#if rotarySwitchPin != 7
	#error Review interrupt vectors when not using pin 7 for menu push
#endif
#if rotaryAPin != 8
	#error Review interrupt vectors when not using pin 8 for menu right
#endif
#if rotaryBPin != 9
	#error Review interrupt vectors when not using pin 9 for menu left
#endif

#if ENABLE_ROTARY_ENCODER

#if defined(USBCON)
// Arduino Leonardo
ISR(INT6_vect){
	rotaryEncoder.setPushed();
}

ISR(PCINT0_vect){
	//todo rotaryEncoder.rotationHandler();
	static bool prevPinA = 0;
	static bool prevPinB = 0;

	bool currPinA = bitRead(PINB,4);
	bool currPinB = bitRead(PINB,5);
	if(currPinA != prevPinA){
		rotaryEncoder.pinAHandler(currPinA);
	}
	if(currPinB != prevPinB){
		rotaryEncoder.pinBHandler(currPinB);
	}
	prevPinA = currPinA;
	prevPinB = currPinB;
}
#else
// Arduino UNO or older
ISR(PCINT2_vect){
	if(!bitRead(PIND,7)){
		// high to low transition
		rotaryEncoder.setPushed();
	}
}

ISR(PCINT0_vect){
	//todo rotaryEncoder.rotationHandler();
	static bool prevPinA = 0;
	static bool prevPinB = 0;

	bool currPinA = bitRead(PINB,0);
	bool currPinB = bitRead(PINB,1);
	if(currPinA != prevPinA){
		rotaryEncoder.pinAHandler(currPinA);
	}
	if(currPinB != prevPinB){
		rotaryEncoder.pinBHandler(currPinB);
	}
	prevPinA = currPinA;
	prevPinB = currPinB;
}

#endif

#endif

void RotaryEncoder::setPushed(void){
	pushFlag = true;
	display.resetBacklightTimer();
}

void RotaryEncoder::pinAHandler(bool pinState){
	if(ticks.micros() - pinATime < ROTARY_THRESHOLD){
		return;
	}
	pinAHistory = pinASignal;
	pinASignal = pinState;
	if ( pinAHistory==pinASignal ){
		return; // not a transition
	}
	pinATime = ticks.micros();
	if ( pinASignal == pinBSignal ){
		steps++;
	}
	else{
		steps--;
	}
	// loop around at edges
	if(steps > maximum){
		steps = minimum;
	}
	if(steps < minimum){
		steps = maximum;
	}
	display.resetBacklightTimer();
}

void RotaryEncoder::pinBHandler(bool pinState){
	if (ticks.micros() - pinBTime < ROTARY_THRESHOLD ){
		return;
	}
	pinBHistory = pinBSignal;
	pinBSignal = pinState;
	if ( pinBHistory==pinBSignal ){
		return; // not a transition
	}
	pinBTime = ticks.micros();
}

void RotaryEncoder::init(void){
	maximum = INT_MAX;
	minimum = INT_MIN;
	prevRead = 0;
	steps = 0;
	pushFlag = 0;
	pinASignal = 1;
	pinBSignal = 1;
	pinAHistory = 1;
	pinBHistory = 1;
	pinATime = 0;
	pinBTime = 0;

	#if(USE_INTERNAL_PULL_UP_RESISTORS)
	fastPinMode(rotaryAPin, INPUT_PULLUP);
	fastPinMode(rotaryBPin, INPUT_PULLUP);
	fastPinMode(rotarySwitchPin, INPUT_PULLUP);
	#else
	fastPinMode(rotaryAPin, INPUT);
	fastPinMode(rotaryBPin, INPUT);
	fastPinMode(rotarySwitchPin, INPUT);
	#endif

	pinAHandler(true); // call functions ones here for proper initialization
	pinBHandler(true);

#if ENABLE_ROTARY_ENCODER
	#if defined(USBCON) // Arduino Leonardo
		// falling edge interrupt for switch on INT6
		EICRB |= (1<<ISC61) | (0<<ISC60);
		// enable interrupt for INT6
		EIMSK |= (1<<INT6);
		// enable pin change interrupts
		PCICR |= (1<<PCIE0);
		// enable pin change interrupt on Arduino pin 8 and 9
		PCMSK0 |= (1<<PCINT5) | (1<<PCINT4);
	#else // Arduino UNO
		// enable PCINT0 (PCINT0 and PCINT1 pin) and PCINT2 vector (PCINT23 pin)
		PCICR |= (1<<PCIE2) | (1<<PCIE0);
		// enable mask bits for PCINT0 and PCINT1
		PCMSK0 |= (1<<PCINT0) | (1<<PCINT1);
		// enable mask bit for PCINT23
		PCMSK2 |= (1<<PCINT23);
	#endif
#endif
}

void RotaryEncoder::setRange(int start, int minVal, int maxVal){
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
		// this part cannot be interrupted
		// Multiply by two to convert to half steps
		steps = start;
		minimum = minVal;
		maximum = maxVal; // +1 to make sure that one step is still two half steps at overflow
		prevRead = start;
	}
}

bool RotaryEncoder::changed(void){
	// returns one if the value changed since the last call of changed.
	static int prevValue = 0;
	if(read() != prevValue){
		prevValue = read();
		return 1;
	}
	if(pushFlag == true){
		return 1;
	}
	return 0;
}

int RotaryEncoder::read(void){
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
		prevRead = steps;
		return prevRead;
	}
	return 0;
}
<commit_msg>First step of rotary encoder  was in wrong direction after reset, this fixes it.<commit_after>/*
 * Copyright 2012 BrewPi/Elco Jacobs.
 *
 * This file is part of BrewPi.
 *
 * BrewPi 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 3 of the License, or
 * (at your option) any later version.
 *
 * BrewPi 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 BrewPi.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "Brewpi.h"
#include "RotaryEncoder.h"

#include "Pins.h"
#include "util/atomic.h"
#include <limits.h>
#include "Ticks.h"
#include "Display.h"
#include "FastDigitalPin.h"
#include "Brewpi.h"

RotaryEncoder rotaryEncoder;

#if rotarySwitchPin != 7
	#error Review interrupt vectors when not using pin 7 for menu push
#endif
#if rotaryAPin != 8
	#error Review interrupt vectors when not using pin 8 for menu right
#endif
#if rotaryBPin != 9
	#error Review interrupt vectors when not using pin 9 for menu left
#endif

#if ENABLE_ROTARY_ENCODER

#if defined(USBCON)
// Arduino Leonardo
ISR(INT6_vect){
	rotaryEncoder.setPushed();
}

ISR(PCINT0_vect){
	//todo rotaryEncoder.rotationHandler();
	static bool prevPinA = 1;
	static bool prevPinB = 1;

	bool currPinA = bitRead(PINB,4);
	bool currPinB = bitRead(PINB,5);
	if(currPinA != prevPinA){
		rotaryEncoder.pinAHandler(currPinA);
	}
	if(currPinB != prevPinB){
		rotaryEncoder.pinBHandler(currPinB);
	}
	prevPinA = currPinA;
	prevPinB = currPinB;
}
#else
// Arduino UNO or older
ISR(PCINT2_vect){
	if(!bitRead(PIND,7)){
		// high to low transition
		rotaryEncoder.setPushed();
	}
}

ISR(PCINT0_vect){
	//todo rotaryEncoder.rotationHandler();
	static bool prevPinA = 1;
	static bool prevPinB = 1;

	bool currPinA = bitRead(PINB,0);
	bool currPinB = bitRead(PINB,1);
	if(currPinA != prevPinA){
		rotaryEncoder.pinAHandler(currPinA);
	}
	if(currPinB != prevPinB){
		rotaryEncoder.pinBHandler(currPinB);
	}
	prevPinA = currPinA;
	prevPinB = currPinB;
}

#endif

#endif

void RotaryEncoder::setPushed(void){
	pushFlag = true;
	display.resetBacklightTimer();
}

void RotaryEncoder::pinAHandler(bool pinState){
	if(ticks.micros() - pinATime < ROTARY_THRESHOLD){
		return;
	}
	pinAHistory = pinASignal;
	pinASignal = pinState;
	if ( pinAHistory==pinASignal ){
		return; // not a transition
	}
	pinATime = ticks.micros();
	if ( pinASignal == pinBSignal ){
		steps++;
	}
	else{
		steps--;
	}
	// loop around at edges
	if(steps > maximum){
		steps = minimum;
	}
	if(steps < minimum){
		steps = maximum;
	}
	display.resetBacklightTimer();
}

void RotaryEncoder::pinBHandler(bool pinState){
	if (ticks.micros() - pinBTime < ROTARY_THRESHOLD ){
		return;
	}
	pinBHistory = pinBSignal;
	pinBSignal = pinState;
	if ( pinBHistory==pinBSignal ){
		return; // not a transition
	}
	pinBTime = ticks.micros();
}

void RotaryEncoder::init(void){
	maximum = INT_MAX;
	minimum = INT_MIN;
	prevRead = 0;
	steps = 0;
	pushFlag = 0;
	pinASignal = 1;
	pinBSignal = 1;
	pinAHistory = 1;
	pinBHistory = 1;
	pinATime = 0;
	pinBTime = 0;

	#if(USE_INTERNAL_PULL_UP_RESISTORS)
	fastPinMode(rotaryAPin, INPUT_PULLUP);
	fastPinMode(rotaryBPin, INPUT_PULLUP);
	fastPinMode(rotarySwitchPin, INPUT_PULLUP);
	#else
	fastPinMode(rotaryAPin, INPUT);
	fastPinMode(rotaryBPin, INPUT);
	fastPinMode(rotarySwitchPin, INPUT);
	#endif

	pinAHandler(true); // call functions ones here for proper initialization
	pinBHandler(true);

#if ENABLE_ROTARY_ENCODER
	#if defined(USBCON) // Arduino Leonardo
		// falling edge interrupt for switch on INT6
		EICRB |= (1<<ISC61) | (0<<ISC60);
		// enable interrupt for INT6
		EIMSK |= (1<<INT6);
		// enable pin change interrupts
		PCICR |= (1<<PCIE0);
		// enable pin change interrupt on Arduino pin 8 and 9
		PCMSK0 |= (1<<PCINT5) | (1<<PCINT4);
	#else // Arduino UNO
		// enable PCINT0 (PCINT0 and PCINT1 pin) and PCINT2 vector (PCINT23 pin)
		PCICR |= (1<<PCIE2) | (1<<PCIE0);
		// enable mask bits for PCINT0 and PCINT1
		PCMSK0 |= (1<<PCINT0) | (1<<PCINT1);
		// enable mask bit for PCINT23
		PCMSK2 |= (1<<PCINT23);
	#endif
#endif
}

void RotaryEncoder::setRange(int start, int minVal, int maxVal){
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
		// this part cannot be interrupted
		// Multiply by two to convert to half steps
		steps = start;
		minimum = minVal;
		maximum = maxVal; // +1 to make sure that one step is still two half steps at overflow
		prevRead = start;
	}
}

bool RotaryEncoder::changed(void){
	// returns one if the value changed since the last call of changed.
	static int prevValue = 0;
	if(read() != prevValue){
		prevValue = read();
		return 1;
	}
	if(pushFlag == true){
		return 1;
	}
	return 0;
}

int RotaryEncoder::read(void){
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
		prevRead = steps;
		return prevRead;
	}
	return 0;
}
<|endoftext|>