<commit_before>#include "ofApp.h"
#include "ofxPS3EyeGrabber.h"

#define WIDTH 640
#define HEIGHT 480

//--------------------------------------------------------------
void ofApp::setup(){
    // Set the video grabber to the ofxPS3EyeGrabber.
    vidGrabber.setGrabber(std::make_shared<ofxPS3EyeGrabber>());
    vidGrabber.setup(WIDTH, HEIGHT);

    colorImg.allocate(WIDTH, HEIGHT);
    grayImage.allocate(WIDTH, HEIGHT);
    grayBg.allocate(WIDTH, HEIGHT);
    grayDiff.allocate(WIDTH, HEIGHT);

    bLearnBakground = true;
    threshold = 80;
}

//--------------------------------------------------------------
void ofApp::update(){
    vidGrabber.update();

    if(vidGrabber.isFrameNew())
    {
        colorImg.setFromPixels(vidGrabber.getPixels());
        grayImage = colorImg;
		if (bLearnBakground == true)
        {
            // the = sign copys the pixels from grayImage into grayBg (operator overloading)
			grayBg = grayImage;
			bLearnBakground = false;
		}

		// take the abs value of the difference between background and incoming and then threshold:
		grayDiff.absDiff(grayBg, grayImage);
		grayDiff.threshold(threshold);

		// find contours which are between the size of 20 pixels and 1/3 the w*h pixels.
		// also, find holes is set to true so we will get interior contours as well....
		contourFinder.findContours(grayDiff, 20, (WIDTH*HEIGHT)/3, 10, true);	// find holes
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);
    ofSetColor(255);
    //vidGrabber.draw(0, 0);
    colorImg.draw(0,0);
    //grayDiff.draw(0,0);

    for(int i = 0; i < contourFinder.nBlobs; i++)
    {
        contourFinder.blobs[i].draw(0,0);
    }
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

	switch (key){
		case ' ':
			bLearnBakground = true;
			break;
		case '+':
			threshold ++;
			if (threshold > 255) threshold = 255;
			break;
		case '-':
			threshold --;
			if (threshold < 0) threshold = 0;
			break;
	}
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<commit_msg>actual frame subtraction, don't bother with the abs()<commit_after>#include "ofApp.h"
#include "ofxPS3EyeGrabber.h"

#define WIDTH 640
#define HEIGHT 480

//--------------------------------------------------------------
void ofApp::setup(){
    // Set the video grabber to the ofxPS3EyeGrabber.
    vidGrabber.setGrabber(std::make_shared<ofxPS3EyeGrabber>());

    vidGrabber.setPixelFormat(OF_PIXELS_RGB);
    vidGrabber.setDesiredFrameRate(60);
    vidGrabber.setup(WIDTH, HEIGHT);

    //PS3 Eye specific settings
    vidGrabber.getGrabber<ofxPS3EyeGrabber>()->setAutogain(false);
    vidGrabber.getGrabber<ofxPS3EyeGrabber>()->setAutoWhiteBalance(false);

    colorImg.allocate(WIDTH, HEIGHT);
    grayImage.allocate(WIDTH, HEIGHT);
    grayBg.allocate(WIDTH, HEIGHT);
    grayDiff.allocate(WIDTH, HEIGHT);

    bLearnBakground = true;
    threshold = 80;
}

//--------------------------------------------------------------
void ofApp::update(){
    vidGrabber.update();

    if(vidGrabber.isFrameNew())
    {
        colorImg.setFromPixels(vidGrabber.getPixels());
        grayImage = colorImg;
		if (bLearnBakground == true)
        {
            // the = sign copys the pixels from grayImage into grayBg (operator overloading)
			grayBg = grayImage;
			bLearnBakground = false;
		}

		// take the abs value of the difference between background and incoming and then threshold:
		//grayDiff.absDiff(grayBg, grayImage);
        cvSub(grayImage.getCvImage(), grayBg.getCvImage(), grayDiff.getCvImage());
        grayDiff.flagImageChanged();
        grayDiff.threshold(threshold);

		// find contours which are between the size of 20 pixels and 1/3 the w*h pixels.
		// also, find holes is set to true so we will get interior contours as well....
		contourFinder.findContours(grayDiff, 20, (WIDTH*HEIGHT)/3, 10, true);	// find holes
    }
}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(0);
    ofSetColor(255);

    colorImg.draw(0, 0);
    grayDiff.draw(WIDTH, 0);

    for(int i = 0; i < contourFinder.nBlobs; i++)
    {
        contourFinder.blobs[i].draw(0, 0);
        contourFinder.blobs[i].draw(WIDTH, 0);
    }

    ofSetHexColor(0xffffff);
    stringstream t;
    t << "Threshold: " << threshold << std::endl
      << "Blobs: " << contourFinder.nBlobs << std::endl
      << "FPS: " << ofGetFrameRate();

    ofDrawBitmapString(t.str(), 20, 20);
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){

	switch(key)
    {
		case ' ':
			bLearnBakground = true;
			break;
		case OF_KEY_UP:
			threshold++;
			if (threshold > 255) threshold = 255;
			break;
		case OF_KEY_DOWN:
			threshold--;
			if (threshold < 0) threshold = 0;
			break;
	}
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
<|endoftext|>


<commit_before>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <gtest/gtest.h>
#include <repo/core/handler/repo_database_handler_mongo.h>
#include "../../../repo_test_database_info.h"

using namespace repo::core::handler;

MongoDatabaseHandler* getHandler()
{
	std::string errMsg;
	return 	MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);
}

TEST(MongoDatabaseHandlerTest, GetHandlerDisconnectHandler)
{

	std::string errMsg;
	MongoDatabaseHandler* handler =
		MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);

	EXPECT_TRUE(handler);
	EXPECT_TRUE(errMsg.empty());

	EXPECT_TRUE(MongoDatabaseHandler::getHandler(REPO_GTEST_DBADDRESS));
	MongoDatabaseHandler::disconnectHandler();

	EXPECT_FALSE(MongoDatabaseHandler::getHandler(REPO_GTEST_DBADDRESS));

	MongoDatabaseHandler *wrongAdd = MongoDatabaseHandler::getHandler(errMsg, "blah", REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);

	EXPECT_FALSE(wrongAdd);
	MongoDatabaseHandler *wrongPort = MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, 0001,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);
	EXPECT_FALSE(wrongPort);

	//Check can connect without authentication
	MongoDatabaseHandler *noauth = MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1);

	EXPECT_TRUE(noauth);
	MongoDatabaseHandler::disconnectHandler();
}

TEST(MongoDatabaseHandlerTest, CreateBSONCredentials)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	EXPECT_TRUE(handler->createBSONCredentials("testdb" , "username", "password"));
	EXPECT_TRUE(handler->createBSONCredentials("testdb" , "username", "password", true));
	EXPECT_FALSE(handler->createBSONCredentials(""      , "username", "password"));
	EXPECT_FALSE(handler->createBSONCredentials("testdb", ""        , "password"));
	EXPECT_FALSE(handler->createBSONCredentials("testdb", "username", ""));
}

TEST(MongoDatabaseHandlerTest, CountItemsInCollection)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	auto goldenData = getCollectionCounts(REPO_GTEST_DBNAME1);
	for (const auto &pair : goldenData)
	{
		std::string message;
		EXPECT_EQ(pair.second, handler->countItemsInCollection(REPO_GTEST_DBNAME1, pair.first, message));
		EXPECT_TRUE(message.empty());
	}

	goldenData = getCollectionCounts(REPO_GTEST_DBNAME2);
	for (const auto &pair : goldenData)
	{
		std::string message;
		EXPECT_EQ(pair.second, handler->countItemsInCollection(REPO_GTEST_DBNAME2, pair.first, message));
		EXPECT_TRUE(message.empty());
	}

	std::string message;
	EXPECT_EQ(0, handler->countItemsInCollection("", "", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("", "blah", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("blah", "", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("blah", "blah", message));
	EXPECT_TRUE(message.empty());

}

TEST(MongoDatabaseHandlerTest, GetAllFromCollectionTailable)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	auto goldenData = getGoldenForGetAllFromCollectionTailable();

	std::vector<repo::core::model::RepoBSON> bsons = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second);

	ASSERT_EQ(bsons.size(), goldenData.second.size());
	auto goldenDataDisposable = goldenData.second;
	for (int i = 0; i < bsons.size(); ++i)
	{
		bool foundMatch = false;
		for (int j = 0; j< goldenDataDisposable.size(); ++j)
		{
			if (foundMatch = bsons[i].toString() == goldenDataDisposable[j])
			{
				goldenDataDisposable.erase(goldenDataDisposable.begin() + j);
				break;
			}

		}
		EXPECT_TRUE(foundMatch);

	}

	//Test limit and skip
	std::vector<repo::core::model::RepoBSON> bsonsLimitSkip = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 1, 1);

	ASSERT_EQ(bsonsLimitSkip.size(), 1);

	EXPECT_EQ(bsonsLimitSkip[0].toString(), goldenData.second[1]);

	//test projection
	auto bsonsProjected = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, { "_id", "shared_id" });

	std::vector<repoUUID> ids;

	ASSERT_EQ(bsonsProjected.size(), bsons.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		ids.push_back(bsons[i].getUUIDField("_id"));
		EXPECT_EQ(bsons[i].getUUIDField("_id"), bsonsProjected[i].getUUIDField("_id"));
		EXPECT_EQ(bsons[i].getUUIDField("shared_id"), bsonsProjected[i].getUUIDField("shared_id"));
	}

	//test sort
	auto bsonsSorted = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, {}, "_id", -1);

	std::sort(ids.begin(), ids.end());

	ASSERT_EQ(bsonsSorted.size(), ids.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		EXPECT_EQ(bsonsSorted[i].getUUIDField("_id"), ids[bsons.size() - i - 1]);
	}

	bsonsSorted = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, {}, "_id", 1);

	ASSERT_EQ(bsonsSorted.size(), ids.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		EXPECT_EQ(bsonsSorted[i].getUUIDField("_id"), ids[i]);
	}

	//check error handling - make sure it doesn't crash
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("", "").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("", "blah").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("blah", "").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("blah", "blah").size());
}

TEST(MongoDatabaseHandlerTest, GetCollections)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);

	auto goldenData = getCollectionList(REPO_GTEST_DBNAME1);

	auto collections = handler->getCollections(REPO_GTEST_DBNAME1);

	ASSERT_EQ(goldenData.size(), collections.size());

	std::sort(goldenData.begin(), goldenData.end());
	collections.sort();

	auto colIt = collections.begin();
	auto gdIt = goldenData.begin();
	for (;colIt != collections.end(); ++colIt, ++gdIt)
	{
		EXPECT_EQ(*colIt, *gdIt);
	}

	goldenData = getCollectionList(REPO_GTEST_DBNAME2);
	collections = handler->getCollections(REPO_GTEST_DBNAME2);

	ASSERT_EQ(goldenData.size(), collections.size());

	std::sort(goldenData.begin(), goldenData.end());
	collections.sort();

	colIt = collections.begin();
	gdIt = goldenData.begin();
	for (; colIt != collections.end(); ++colIt, ++gdIt)
	{
		EXPECT_EQ(*colIt, *gdIt);
	}

	//check error handling - make sure it doesn't crash
	EXPECT_EQ(0, handler->getCollections("").size());
	EXPECT_EQ(0, handler->getCollections("blahblah").size());
}<commit_msg>#13 skip content check as it is too non deterministic<commit_after>/**
*  Copyright (C) 2015 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <gtest/gtest.h>
#include <repo/core/handler/repo_database_handler_mongo.h>
#include "../../../repo_test_database_info.h"

using namespace repo::core::handler;

MongoDatabaseHandler* getHandler()
{
	std::string errMsg;
	return 	MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);
}

TEST(MongoDatabaseHandlerTest, GetHandlerDisconnectHandler)
{

	std::string errMsg;
	MongoDatabaseHandler* handler =
		MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);

	EXPECT_TRUE(handler);
	EXPECT_TRUE(errMsg.empty());

	EXPECT_TRUE(MongoDatabaseHandler::getHandler(REPO_GTEST_DBADDRESS));
	MongoDatabaseHandler::disconnectHandler();

	EXPECT_FALSE(MongoDatabaseHandler::getHandler(REPO_GTEST_DBADDRESS));

	MongoDatabaseHandler *wrongAdd = MongoDatabaseHandler::getHandler(errMsg, "blah", REPO_GTEST_DBPORT,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);

	EXPECT_FALSE(wrongAdd);
	MongoDatabaseHandler *wrongPort = MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, 0001,
		1,
		REPO_GTEST_AUTH_DATABASE,
		REPO_GTEST_DBUSER, REPO_GTEST_DBPW);
	EXPECT_FALSE(wrongPort);

	//Check can connect without authentication
	MongoDatabaseHandler *noauth = MongoDatabaseHandler::getHandler(errMsg, REPO_GTEST_DBADDRESS, REPO_GTEST_DBPORT,
		1);

	EXPECT_TRUE(noauth);
	MongoDatabaseHandler::disconnectHandler();
}

TEST(MongoDatabaseHandlerTest, CreateBSONCredentials)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	EXPECT_TRUE(handler->createBSONCredentials("testdb" , "username", "password"));
	EXPECT_TRUE(handler->createBSONCredentials("testdb" , "username", "password", true));
	EXPECT_FALSE(handler->createBSONCredentials(""      , "username", "password"));
	EXPECT_FALSE(handler->createBSONCredentials("testdb", ""        , "password"));
	EXPECT_FALSE(handler->createBSONCredentials("testdb", "username", ""));
}

TEST(MongoDatabaseHandlerTest, CountItemsInCollection)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	auto goldenData = getCollectionCounts(REPO_GTEST_DBNAME1);
	for (const auto &pair : goldenData)
	{
		std::string message;
		EXPECT_EQ(pair.second, handler->countItemsInCollection(REPO_GTEST_DBNAME1, pair.first, message));
		EXPECT_TRUE(message.empty());
	}

	goldenData = getCollectionCounts(REPO_GTEST_DBNAME2);
	for (const auto &pair : goldenData)
	{
		std::string message;
		EXPECT_EQ(pair.second, handler->countItemsInCollection(REPO_GTEST_DBNAME2, pair.first, message));
		EXPECT_TRUE(message.empty());
	}

	std::string message;
	EXPECT_EQ(0, handler->countItemsInCollection("", "", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("", "blah", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("blah", "", message));
	EXPECT_FALSE(message.empty());

	message.clear();
	EXPECT_EQ(0, handler->countItemsInCollection("blah", "blah", message));
	EXPECT_TRUE(message.empty());

}

TEST(MongoDatabaseHandlerTest, GetAllFromCollectionTailable)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);
	auto goldenData = getGoldenForGetAllFromCollectionTailable();

	std::vector<repo::core::model::RepoBSON> bsons = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second);

	ASSERT_EQ(bsons.size(), goldenData.second.size());
	/*auto goldenDataDisposable = goldenData.second;
	for (int i = 0; i < bsons.size(); ++i)
	{
		bool foundMatch = false;
		for (int j = 0; j< goldenDataDisposable.size(); ++j)
		{
			if (foundMatch = bsons[i].toString() == goldenDataDisposable[j])
			{
				goldenDataDisposable.erase(goldenDataDisposable.begin() + j);
				break;
			}

		}
		EXPECT_TRUE(foundMatch);

	}*/

	//Test limit and skip
	std::vector<repo::core::model::RepoBSON> bsonsLimitSkip = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 1, 1);

	ASSERT_EQ(bsonsLimitSkip.size(), 1);

	//EXPECT_EQ(bsonsLimitSkip[0].toString(), goldenData.second[1]);

	//test projection
	auto bsonsProjected = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, { "_id", "shared_id" });

	std::vector<repoUUID> ids;

	ASSERT_EQ(bsonsProjected.size(), bsons.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		ids.push_back(bsons[i].getUUIDField("_id"));
		EXPECT_EQ(bsons[i].getUUIDField("_id"), bsonsProjected[i].getUUIDField("_id"));
		EXPECT_EQ(bsons[i].getUUIDField("shared_id"), bsonsProjected[i].getUUIDField("shared_id"));
	}

	//test sort
	auto bsonsSorted = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, {}, "_id", -1);

	std::sort(ids.begin(), ids.end());

	ASSERT_EQ(bsonsSorted.size(), ids.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		EXPECT_EQ(bsonsSorted[i].getUUIDField("_id"), ids[bsons.size() - i - 1]);
	}

	bsonsSorted = handler->getAllFromCollectionTailable(
		goldenData.first.first, goldenData.first.second, 0, 0, {}, "_id", 1);

	ASSERT_EQ(bsonsSorted.size(), ids.size());
	for (int i = 0; i < bsons.size(); ++i)
	{
		EXPECT_EQ(bsonsSorted[i].getUUIDField("_id"), ids[i]);
	}

	//check error handling - make sure it doesn't crash
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("", "").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("", "blah").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("blah", "").size());
	EXPECT_EQ(0, handler->getAllFromCollectionTailable("blah", "blah").size());
}

TEST(MongoDatabaseHandlerTest, GetCollections)
{
	auto handler = getHandler();
	ASSERT_TRUE(handler);

	auto goldenData = getCollectionList(REPO_GTEST_DBNAME1);

	auto collections = handler->getCollections(REPO_GTEST_DBNAME1);

	ASSERT_EQ(goldenData.size(), collections.size());

	std::sort(goldenData.begin(), goldenData.end());
	collections.sort();

	auto colIt = collections.begin();
	auto gdIt = goldenData.begin();
	for (;colIt != collections.end(); ++colIt, ++gdIt)
	{
		EXPECT_EQ(*colIt, *gdIt);
	}

	goldenData = getCollectionList(REPO_GTEST_DBNAME2);
	collections = handler->getCollections(REPO_GTEST_DBNAME2);

	ASSERT_EQ(goldenData.size(), collections.size());

	std::sort(goldenData.begin(), goldenData.end());
	collections.sort();

	colIt = collections.begin();
	gdIt = goldenData.begin();
	for (; colIt != collections.end(); ++colIt, ++gdIt)
	{
		EXPECT_EQ(*colIt, *gdIt);
	}

	//check error handling - make sure it doesn't crash
	EXPECT_EQ(0, handler->getCollections("").size());
	EXPECT_EQ(0, handler->getCollections("blahblah").size());
}<|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/.

//===- non_blocking_work_queue.cc -------------------------------*- C++ -*-===//
//
// Concurrent Work Queue implementation composed from a blocking and
// non-blocking work queues.
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <thread>

#include "blocking_work_queue.h"
#include "environment.h"
#include "llvm/ADT/ArrayRef.h"
#include "non_blocking_work_queue.h"
#include "tfrt/host_context/async_value.h"
#include "tfrt/host_context/concurrent_work_queue.h"
#include "tfrt/host_context/task_function.h"
#include "tfrt/support/latch.h"
#include "tfrt/support/ref_count.h"
#include "tfrt/support/string_util.h"

namespace tfrt {

class MultiThreadedWorkQueue : public ConcurrentWorkQueue {
  using ThreadingEnvironment = ::tfrt::internal::StdThreadingEnvironment;

 public:
  MultiThreadedWorkQueue(int num_threads, int max_blocking_work_queue_threads);
  ~MultiThreadedWorkQueue() override;

  std::string name() const override {
    return StrCat("Multi-threaded C++ work queue (", num_threads_, " threads)");
  }

  int GetParallelismLevel() const final { return num_threads_; }

  void AddTask(TaskFunction task) final;
  Optional<TaskFunction> AddBlockingTask(TaskFunction task,
                                         bool allow_queuing) final;
  void Quiesce() final;
  void Await(ArrayRef<RCReference<AsyncValue>> values) final;

  bool IsInWorkerThread() const final;

 private:
  const int num_threads_;

  std::unique_ptr<internal::QuiescingState> quiescing_state_;
  internal::NonBlockingWorkQueue<ThreadingEnvironment> non_blocking_work_queue_;
  internal::BlockingWorkQueue<ThreadingEnvironment> blocking_work_queue_;
};

MultiThreadedWorkQueue::MultiThreadedWorkQueue(
    int num_threads, int max_blocking_work_queue_threads)
    : num_threads_(num_threads),
      quiescing_state_(std::make_unique<internal::QuiescingState>()),
      non_blocking_work_queue_(quiescing_state_.get(), num_threads),
      blocking_work_queue_(quiescing_state_.get(),
                           max_blocking_work_queue_threads) {}

MultiThreadedWorkQueue::~MultiThreadedWorkQueue() {
  // Pending tasks in the underlying queues might submit new tasks to each other
  // during destruction.
  Quiesce();
}

void MultiThreadedWorkQueue::AddTask(TaskFunction task) {
  non_blocking_work_queue_.AddTask(std::move(task));
}

Optional<TaskFunction> MultiThreadedWorkQueue::AddBlockingTask(
    TaskFunction task, bool allow_queuing) {
  if (allow_queuing) {
    return blocking_work_queue_.EnqueueBlockingTask(std::move(task));
  } else {
    return blocking_work_queue_.RunBlockingTask(std::move(task));
  }
}

void MultiThreadedWorkQueue::Quiesce() {
  // Turn on pending tasks counter inside both work queues.
  auto quiescing = internal::Quiescing::Start(quiescing_state_.get());

  // We call NonBlockingWorkQueue::Quiesce() first because we prefer to keep
  // caller thread busy with compute intensive tasks.
  non_blocking_work_queue_.Quiesce();

  // Wait for completion of all blocking tasks.
  blocking_work_queue_.Quiesce();

  // At this point we might still have tasks in the work queues, but because we
  // enabled quiescing mode earlier, we can rely on empty check as a loop
  // condition.
  while (quiescing.HasPendingTasks()) {
    non_blocking_work_queue_.Quiesce();
    blocking_work_queue_.Quiesce();
  }
}

void MultiThreadedWorkQueue::Await(ArrayRef<RCReference<AsyncValue>> values) {
  // We might block on a latch waiting for the completion of all tasks, and
  // this is not allowed to do inside non blocking work queue.
  non_blocking_work_queue_.CheckCallerThread("MultiThreadedWorkQueue::Await");

  // We are done when values_remaining drops to zero.
  tfrt::latch values_remaining(values.size());

  // As each value becomes available, we decrement the count.
  for (auto& value : values) {
    value->AndThen([&values_remaining]() { values_remaining.count_down(); });
  }

  // Keep stealing tasks from non-blocking workers until we reach a point when
  // all async values are resolved or we could not steal any task.
  //
  // We steal pending tasks globally and potentially can steal a very expensive
  // task, that will unnecessarily delay the completion of this function.
  // Alternative is to immediately block on the latch.
  llvm::Optional<TaskFunction> task = non_blocking_work_queue_.Steal();
  while (task.hasValue() || !values_remaining.try_wait()) {
    if (task.hasValue()) (*task)();
    task = non_blocking_work_queue_.Steal();
  }

  // Wait until all values are resolved.
  values_remaining.wait();
}

bool MultiThreadedWorkQueue::IsInWorkerThread() const {
  return non_blocking_work_queue_.IsInWorkerThread();
}

std::unique_ptr<ConcurrentWorkQueue> CreateMultiThreadedWorkQueue(
    int num_threads, int num_blocking_threads) {
  assert(num_threads > 0 && num_blocking_threads > 0);
  return std::make_unique<MultiThreadedWorkQueue>(num_threads,
                                                  num_blocking_threads);
}

}  // namespace tfrt
<commit_msg>[TFRT] Don't do work stealing in MultiThreadedWorkQueue::Await.<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/.

//===- non_blocking_work_queue.cc -------------------------------*- C++ -*-===//
//
// Concurrent Work Queue implementation composed from a blocking and
// non-blocking work queues.
//
//===----------------------------------------------------------------------===//

#include <memory>
#include <thread>

#include "blocking_work_queue.h"
#include "environment.h"
#include "llvm/ADT/ArrayRef.h"
#include "non_blocking_work_queue.h"
#include "tfrt/host_context/async_value.h"
#include "tfrt/host_context/concurrent_work_queue.h"
#include "tfrt/host_context/task_function.h"
#include "tfrt/support/latch.h"
#include "tfrt/support/ref_count.h"
#include "tfrt/support/string_util.h"

namespace tfrt {

class MultiThreadedWorkQueue : public ConcurrentWorkQueue {
  using ThreadingEnvironment = ::tfrt::internal::StdThreadingEnvironment;

 public:
  MultiThreadedWorkQueue(int num_threads, int max_blocking_work_queue_threads);
  ~MultiThreadedWorkQueue() override;

  std::string name() const override {
    return StrCat("Multi-threaded C++ work queue (", num_threads_, " threads)");
  }

  int GetParallelismLevel() const final { return num_threads_; }

  void AddTask(TaskFunction task) final;
  Optional<TaskFunction> AddBlockingTask(TaskFunction task,
                                         bool allow_queuing) final;
  void Quiesce() final;
  void Await(ArrayRef<RCReference<AsyncValue>> values) final;

  bool IsInWorkerThread() const final;

 private:
  const int num_threads_;

  std::unique_ptr<internal::QuiescingState> quiescing_state_;
  internal::NonBlockingWorkQueue<ThreadingEnvironment> non_blocking_work_queue_;
  internal::BlockingWorkQueue<ThreadingEnvironment> blocking_work_queue_;
};

MultiThreadedWorkQueue::MultiThreadedWorkQueue(
    int num_threads, int max_blocking_work_queue_threads)
    : num_threads_(num_threads),
      quiescing_state_(std::make_unique<internal::QuiescingState>()),
      non_blocking_work_queue_(quiescing_state_.get(), num_threads),
      blocking_work_queue_(quiescing_state_.get(),
                           max_blocking_work_queue_threads) {}

MultiThreadedWorkQueue::~MultiThreadedWorkQueue() {
  // Pending tasks in the underlying queues might submit new tasks to each other
  // during destruction.
  Quiesce();
}

void MultiThreadedWorkQueue::AddTask(TaskFunction task) {
  non_blocking_work_queue_.AddTask(std::move(task));
}

Optional<TaskFunction> MultiThreadedWorkQueue::AddBlockingTask(
    TaskFunction task, bool allow_queuing) {
  if (allow_queuing) {
    return blocking_work_queue_.EnqueueBlockingTask(std::move(task));
  } else {
    return blocking_work_queue_.RunBlockingTask(std::move(task));
  }
}

void MultiThreadedWorkQueue::Quiesce() {
  // Turn on pending tasks counter inside both work queues.
  auto quiescing = internal::Quiescing::Start(quiescing_state_.get());

  // We call NonBlockingWorkQueue::Quiesce() first because we prefer to keep
  // caller thread busy with compute intensive tasks.
  non_blocking_work_queue_.Quiesce();

  // Wait for completion of all blocking tasks.
  blocking_work_queue_.Quiesce();

  // At this point we might still have tasks in the work queues, but because we
  // enabled quiescing mode earlier, we can rely on empty check as a loop
  // condition.
  while (quiescing.HasPendingTasks()) {
    non_blocking_work_queue_.Quiesce();
    blocking_work_queue_.Quiesce();
  }
}

void MultiThreadedWorkQueue::Await(ArrayRef<RCReference<AsyncValue>> values) {
  // We might block on a latch waiting for the completion of all tasks, and
  // this is not allowed to do inside non blocking work queue.
  non_blocking_work_queue_.CheckCallerThread("MultiThreadedWorkQueue::Await");

  // We are done when values_remaining drops to zero.
  tfrt::latch values_remaining(values.size());

  // As each value becomes available, we decrement the count.
  for (auto& value : values) {
    value->AndThen([&values_remaining]() { values_remaining.count_down(); });
  }

  // Wait until all values are resolved.
  values_remaining.wait();
}

bool MultiThreadedWorkQueue::IsInWorkerThread() const {
  return non_blocking_work_queue_.IsInWorkerThread();
}

std::unique_ptr<ConcurrentWorkQueue> CreateMultiThreadedWorkQueue(
    int num_threads, int num_blocking_threads) {
  assert(num_threads > 0 && num_blocking_threads > 0);
  return std::make_unique<MultiThreadedWorkQueue>(num_threads,
                                                  num_blocking_threads);
}

}  // namespace tfrt
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "ClientSocket.h"

#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>

#include <folly/Conv.h>
#include <folly/FileUtil.h>
#include <folly/ScopeGuard.h>
#include <folly/String.h>

#include <chrono>
#include <thread>

#include "mcrouter/lib/fbi/cpp/util.h"

namespace facebook { namespace memcache {

ClientSocket::ClientSocket(uint16_t port) {
  struct addrinfo hints;
  struct addrinfo* res;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  auto portStr = folly::to<std::string>(port);
  auto ret = ::getaddrinfo("localhost", portStr.data(), &hints, &res);
  checkRuntime(!ret, "Failed to find a local IP: {}", ::gai_strerror(ret));
  SCOPE_EXIT {
    ::freeaddrinfo(res);
  };
  socketFd_ = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  if (socketFd_ < 0) {
    throwRuntime("Failed to create a socket: {}", folly::errnoStr(errno));
  }

  if (::connect(socketFd_, res->ai_addr, res->ai_addrlen) != 0) {
    ::close(socketFd_);
    throwRuntime("Failed to connect: {}", folly::errnoStr(errno));
  }
}

ClientSocket::ClientSocket(ClientSocket&& other) noexcept
    : socketFd_(other.socketFd_) {
  other.socketFd_ = -1;
}

ClientSocket& ClientSocket::operator=(ClientSocket&& other) noexcept {
  if (this != &other) {
    if (socketFd_ >= 0) {
      ::close(socketFd_);
    }
    socketFd_ = other.socketFd_;
    other.socketFd_ = -1;
  }
  return *this;
}

ClientSocket::~ClientSocket() {
  if (socketFd_ >= 0) {
    ::close(socketFd_);
  }
}

void ClientSocket::write(folly::StringPiece data,
                         std::chrono::milliseconds timeout) {
  size_t written = 0;
  auto timeoutMs = static_cast<size_t>(timeout.count());
  for (size_t i = 0; written < data.size() && i <= timeoutMs; ++i) {
    ssize_t n = ::send(socketFd_,
                       data.data() + written, data.size() - written,
                       MSG_DONTWAIT);
    if (n == -1) {
      if (errno == EWOULDBLOCK || errno == EAGAIN) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        continue;
      }
      throwRuntime("failed to write to socket: {}", folly::errnoStr(errno));
    }
    written += n;
  }

  checkRuntime(written == data.size(),
               "failed to write to socket. Written {}, expected {}",
               written, data.size());
}

std::string ClientSocket::sendRequest(folly::StringPiece request,
                                      std::chrono::milliseconds timeout) {
  write(request, timeout);

  // wait for some data to arrive
  fd_set rfds;
  FD_ZERO(&rfds);
  FD_SET(socketFd_, &rfds);
  auto tvTimeout = to<timeval_t>(timeout);
  auto ret = ::select(socketFd_ + 1, &rfds, nullptr, nullptr, &tvTimeout);

  if (ret == -1) {
    throwRuntime("select() failed on socket: {}", folly::errnoStr(errno));
  } if (ret > 0) {
    char replyBuf[kMaxReplySize + 1];
    ssize_t n = ::recv(socketFd_, replyBuf, kMaxReplySize, MSG_DONTWAIT);
    if (n == -1) {
      throwRuntime("failed to read from socket: {}", folly::errnoStr(errno));
    }
    return std::string(replyBuf, n);
  } else {
    throwRuntime("No data available within {}ms", timeout.count());
  }
}

}}  // facebook::memcache
<commit_msg>Fix ClientSocket<commit_after>/*
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 *
 */
#include "ClientSocket.h"

#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>

#include <folly/Conv.h>
#include <folly/FileUtil.h>
#include <folly/ScopeGuard.h>
#include <folly/String.h>

#include <chrono>
#include <thread>

#include "mcrouter/lib/fbi/cpp/util.h"

namespace facebook { namespace memcache {

ClientSocket::ClientSocket(uint16_t port) {
  struct addrinfo hints;
  struct addrinfo* res;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  auto portStr = folly::to<std::string>(port);
  auto ret = ::getaddrinfo("localhost", portStr.data(), &hints, &res);
  checkRuntime(!ret, "Failed to find a local IP: {}", ::gai_strerror(ret));
  SCOPE_EXIT {
    ::freeaddrinfo(res);
  };
  socketFd_ = ::socket(res->ai_family, res->ai_socktype, res->ai_protocol);
  if (socketFd_ < 0) {
    throwRuntime("Failed to create a socket: {}", folly::errnoStr(errno));
  }

  if (::connect(socketFd_, res->ai_addr, res->ai_addrlen) != 0) {
    ::close(socketFd_);
    throwRuntime("Failed to connect: {}", folly::errnoStr(errno));
  }
}

ClientSocket::ClientSocket(ClientSocket&& other) noexcept
    : socketFd_(other.socketFd_) {
  other.socketFd_ = -1;
}

ClientSocket& ClientSocket::operator=(ClientSocket&& other) noexcept {
  if (this != &other) {
    if (socketFd_ >= 0) {
      ::close(socketFd_);
    }
    socketFd_ = other.socketFd_;
    other.socketFd_ = -1;
  }
  return *this;
}

ClientSocket::~ClientSocket() {
  if (socketFd_ >= 0) {
    ::close(socketFd_);
  }
}

void ClientSocket::write(folly::StringPiece data,
                         std::chrono::milliseconds timeout) {
  size_t written = 0;
  auto timeoutMs = static_cast<size_t>(timeout.count());
  for (size_t i = 0; written < data.size() && i <= timeoutMs; ++i) {
    ssize_t n = ::send(socketFd_,
                       data.data() + written, data.size() - written,
                       MSG_DONTWAIT);
    if (n == -1) {
      if (errno == EWOULDBLOCK || errno == EAGAIN) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        continue;
      }
      throwRuntime("failed to write to socket: {}", folly::errnoStr(errno));
    }
    written += n;
  }

  checkRuntime(written == data.size(),
               "failed to write to socket. Written {}, expected {}",
               written, data.size());
}

std::string ClientSocket::sendRequest(folly::StringPiece request,
                                      std::chrono::milliseconds timeout) {
  write(request, timeout);

  // wait for some data to arrive
  auto timeoutMs = static_cast<size_t>(timeout.count());
  for (size_t i = 0; i <= timeoutMs; ++i) {
    char replyBuf[kMaxReplySize + 1];
    ssize_t n = ::recv(socketFd_, replyBuf, kMaxReplySize, MSG_DONTWAIT);
    if (n == -1) {
      if (errno == EWOULDBLOCK || errno == EAGAIN) {
        std::this_thread::sleep_for(std::chrono::milliseconds(1));
        continue;
      }
      throwRuntime("failed to read from socket: {}", folly::errnoStr(errno));
    } else if (n == 0) {
      throwRuntime("peer closed the socket");
    }
    return std::string(replyBuf, n);
  }
  throwRuntime("timeout reading from socket");
}

}}  // facebook::memcache
<|endoftext|>


<commit_before>#ifndef slic3r_MainFrame_hpp_
#define slic3r_MainFrame_hpp_

#include "libslic3r/PrintConfig.hpp"

#include <wx/frame.h>
#include <wx/string.h>

#include <string>
#include <map>

#include "GUI_Utils.hpp"
#include "Plater.hpp"
#include "Event.hpp"

class wxNotebook;
class wxProgressDialog;

namespace Slic3r {

class ProgressStatusBar;

namespace GUI
{

class Tab;
class PrintHostQueueDialog;

enum QuickSlice
{
    qsUndef = 0,
    qsReslice = 1,
    qsSaveAs = 2,
    qsExportSVG = 4,
    qsExportPNG = 8
};

struct PresetTab {
    std::string       name;
    Tab*              panel;
    PrinterTechnology technology;
};

class MainFrame : public DPIFrame
{
    bool        m_loaded {false};

    wxString    m_qs_last_input_file = wxEmptyString;
    wxString    m_qs_last_output_file = wxEmptyString;
    wxString    m_last_config = wxEmptyString;

    wxMenuItem* m_menu_item_repeat { nullptr };
    wxMenuItem* m_menu_item_reslice_now { nullptr };

    PrintHostQueueDialog *m_printhost_queue_dlg;

    std::string     get_base_name(const wxString &full_name, const char *extension = nullptr) const;
    std::string     get_dir_name(const wxString &full_name) const;

    void on_presets_changed(SimpleEvent&);
    void on_value_changed(wxCommandEvent&);

    bool can_save() const;
    bool can_export_model() const;
    bool can_export_gcode() const;
    bool can_slice() const;
    bool can_change_view() const;
    bool can_select() const;
    bool can_delete() const;
    bool can_delete_all() const;

protected:
    virtual void on_dpi_changed(const wxRect &suggested_rect);

public:
    MainFrame();
    ~MainFrame() {}

    Plater*     plater() { return m_plater; }

    void        init_tabpanel();
    void        create_preset_tabs();
    void        add_created_tab(Tab* panel);
    void        init_menubar();

    void        update_ui_from_settings();
    bool        is_loaded() const { return m_loaded; }
    bool        is_last_input_file() const  { return !m_qs_last_input_file.IsEmpty(); }

    void        quick_slice(const int qs = qsUndef);
    void        reslice_now();
    void        repair_stl();
    void        export_config();
    // Query user for the config file and open it.
    void        load_config_file();
    // Open a config file. Return true if loaded.
    bool        load_config_file(const std::string &path);
    void        export_configbundle();
    void        load_configbundle(wxString file = wxEmptyString);
    void        load_config(const DynamicPrintConfig& config);
    void        select_tab(size_t tab) const;
    void        select_view(const std::string& direction);
    // Propagate changed configuration from the Tab to the Platter and save changes to the AppConfig
    void        on_config_changed(DynamicPrintConfig* cfg) const ;

    PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }

    Plater*             m_plater { nullptr };
    wxNotebook*         m_tabpanel { nullptr };
    wxProgressDialog*   m_progress_dialog { nullptr };
    ProgressStatusBar*  m_statusbar { nullptr };
};

} // GUI
} //Slic3r

#endif // slic3r_MainFrame_hpp_
<commit_msg>Fixed missing header (clang is picky)<commit_after>#ifndef slic3r_MainFrame_hpp_
#define slic3r_MainFrame_hpp_

#include "libslic3r/PrintConfig.hpp"

#include <wx/frame.h>
#include <wx/settings.h>
#include <wx/string.h>

#include <string>
#include <map>

#include "GUI_Utils.hpp"
#include "Plater.hpp"
#include "Event.hpp"

class wxNotebook;
class wxProgressDialog;

namespace Slic3r {

class ProgressStatusBar;

namespace GUI
{

class Tab;
class PrintHostQueueDialog;

enum QuickSlice
{
    qsUndef = 0,
    qsReslice = 1,
    qsSaveAs = 2,
    qsExportSVG = 4,
    qsExportPNG = 8
};

struct PresetTab {
    std::string       name;
    Tab*              panel;
    PrinterTechnology technology;
};

class MainFrame : public DPIFrame
{
    bool        m_loaded {false};

    wxString    m_qs_last_input_file = wxEmptyString;
    wxString    m_qs_last_output_file = wxEmptyString;
    wxString    m_last_config = wxEmptyString;

    wxMenuItem* m_menu_item_repeat { nullptr };
    wxMenuItem* m_menu_item_reslice_now { nullptr };

    PrintHostQueueDialog *m_printhost_queue_dlg;

    std::string     get_base_name(const wxString &full_name, const char *extension = nullptr) const;
    std::string     get_dir_name(const wxString &full_name) const;

    void on_presets_changed(SimpleEvent&);
    void on_value_changed(wxCommandEvent&);

    bool can_save() const;
    bool can_export_model() const;
    bool can_export_gcode() const;
    bool can_slice() const;
    bool can_change_view() const;
    bool can_select() const;
    bool can_delete() const;
    bool can_delete_all() const;

protected:
    virtual void on_dpi_changed(const wxRect &suggested_rect);

public:
    MainFrame();
    ~MainFrame() {}

    Plater*     plater() { return m_plater; }

    void        init_tabpanel();
    void        create_preset_tabs();
    void        add_created_tab(Tab* panel);
    void        init_menubar();

    void        update_ui_from_settings();
    bool        is_loaded() const { return m_loaded; }
    bool        is_last_input_file() const  { return !m_qs_last_input_file.IsEmpty(); }

    void        quick_slice(const int qs = qsUndef);
    void        reslice_now();
    void        repair_stl();
    void        export_config();
    // Query user for the config file and open it.
    void        load_config_file();
    // Open a config file. Return true if loaded.
    bool        load_config_file(const std::string &path);
    void        export_configbundle();
    void        load_configbundle(wxString file = wxEmptyString);
    void        load_config(const DynamicPrintConfig& config);
    void        select_tab(size_t tab) const;
    void        select_view(const std::string& direction);
    // Propagate changed configuration from the Tab to the Platter and save changes to the AppConfig
    void        on_config_changed(DynamicPrintConfig* cfg) const ;

    PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }

    Plater*             m_plater { nullptr };
    wxNotebook*         m_tabpanel { nullptr };
    wxProgressDialog*   m_progress_dialog { nullptr };
    ProgressStatusBar*  m_statusbar { nullptr };
};

} // GUI
} //Slic3r

#endif // slic3r_MainFrame_hpp_
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "output.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "session.h"
#include "report.h"

namespace ledger {

format_posts::format_posts(report_t&	 _report,
			   const string& format,
			   bool		 _print_raw)
  : report(_report), last_xact(NULL), last_post(NULL),
    print_raw(_print_raw)
{
  TRACE_CTOR(format_posts, "report&, const string&");

  const char * f = format.c_str();

  if (const char * p = std::strstr(f, "%/")) {
    first_line_format.parse(string(f, 0, p - f));
    const char * n = p + 2;
    if (const char * p = std::strstr(n, "%/")) {
      next_lines_format.parse(string(n, 0, p - n));
      between_format.parse(string(p + 2));
    } else {
      next_lines_format.parse(n);
    }
  } else {
    first_line_format.parse(format);
    next_lines_format.parse(format);
  }
}

void format_posts::flush()
{
  report.output_stream.flush();
}

void format_posts::operator()(post_t& post)
{
  std::ostream& out(report.output_stream);

  if (print_raw) {
    if (! post.has_xdata() ||
	! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
      if (last_xact != post.xact) {
	if (last_xact) {
	  bind_scope_t xact_scope(report, *last_xact);
	  between_format.format(out, xact_scope);
	}
	print_item(out, *post.xact);
	out << '\n';
	last_xact = post.xact;
      }
      post.xdata().add_flags(POST_EXT_DISPLAYED);
      last_post = &post;
    }
  }
  else if (! post.has_xdata() ||
	   ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
    bind_scope_t bound_scope(report, post);
    if (last_xact != post.xact) {
      if (last_xact) {
	bind_scope_t xact_scope(report, *last_xact);
	between_format.format(out, xact_scope);
      }
      first_line_format.format(out, bound_scope);
      last_xact = post.xact;
    }
    else if (last_post && last_post->date() != post.date()) {
      first_line_format.format(out, bound_scope);
    }
    else {
      next_lines_format.format(out, bound_scope);
    }

    post.xdata().add_flags(POST_EXT_DISPLAYED);
    last_post = &post;
  }
}

format_accounts::format_accounts(report_t&     _report,
				 const string& format)
  : report(_report), disp_pred()
{
  TRACE_CTOR(format_accounts, "report&, const string&");

  const char * f = format.c_str();

  if (const char * p = std::strstr(f, "%/")) {
    account_line_format.parse(string(f, 0, p - f));
    const char * n = p + 2;
    if (const char * p = std::strstr(n, "%/")) {
      total_line_format.parse(string(n, 0, p - n));
      separator_format.parse(string(p + 2));
    } else {
      total_line_format.parse(n);
    }
  } else {
    account_line_format.parse(format);
    total_line_format.parse(format);
  }
}

void format_accounts::post_account(account_t& account)
{
  if (account.xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY)) {
    account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);

    bind_scope_t bound_scope(report, account);
    account_line_format.format(report.output_stream, bound_scope);
  }
}

std::pair<std::size_t, std::size_t>
format_accounts::mark_accounts(account_t& account, const bool flat)
{
  std::size_t visited	 = 0;
  std::size_t to_display = 0;

  foreach (accounts_map::value_type& pair, account.accounts) {
    std::pair<std::size_t, std::size_t> i = mark_accounts(*pair.second, flat);
    visited    += i.first;
    to_display += i.second;
  }

#if defined(DEBUG_ON)
  DEBUG("account.display", "Considering account: " << account.fullname());
  if (account.has_flags(ACCOUNT_EXT_VISITED))
    DEBUG("account.display", "  it was visited itself");
  DEBUG("account.display", "  it has " << visited << " visited children");
  DEBUG("account.display",
	"  it has " << to_display << " children to display");
#endif

  if (account.has_flags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0)) {
    bind_scope_t bound_scope(report, account);
    if (disp_pred(bound_scope) && (flat || to_display != 1)) {
      account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY);
      DEBUG("account.display", "Marking account as TO_DISPLAY");
      to_display = 1;
    }
    visited = 1;
  }

  return std::pair<std::size_t, std::size_t>(visited, to_display);
}

void format_accounts::flush()
{
  std::ostream& out(report.output_stream);

  if (report.HANDLED(display_)) {
    DEBUG("account.display",
	  "Account display predicate: " << report.HANDLER(display_).str());
    disp_pred.predicate.parse(report.HANDLER(display_).str());
  }

  std::size_t top_displayed = 0;

  mark_accounts(*report.session.master, report.HANDLED(flat));

  foreach (account_t * account, posted_accounts) {
    post_account(*account);

    if (report.HANDLED(flat) && account->has_flags(ACCOUNT_EXT_DISPLAYED))
      top_displayed++;
  }

  if (! report.HANDLED(flat)) {
    foreach (accounts_map::value_type pair, report.session.master->accounts) {
      if (pair.second->has_flags(ACCOUNT_EXT_DISPLAYED) ||
	  pair.second->children_with_flags(ACCOUNT_EXT_DISPLAYED)) {
	top_displayed++;
      }
    }
  }

  if (! report.HANDLED(no_total) && top_displayed > 1 &&
      report.session.master->family_total()) {
    bind_scope_t bound_scope(report, *report.session.master);
    separator_format.format(out, bound_scope);
    total_line_format.format(out, bound_scope);
  }

  out.flush();
}

void format_accounts::operator()(account_t& account)
{
  posted_accounts.push_back(&account);
}

} // namespace ledger
<commit_msg>Moved a variable initialization<commit_after>/*
 * Copyright (c) 2003-2009, John Wiegley.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of New Artisans LLC nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <system.hh>

#include "output.h"
#include "xact.h"
#include "post.h"
#include "account.h"
#include "session.h"
#include "report.h"

namespace ledger {

format_posts::format_posts(report_t&	 _report,
			   const string& format,
			   bool		 _print_raw)
  : report(_report), last_xact(NULL), last_post(NULL),
    print_raw(_print_raw)
{
  TRACE_CTOR(format_posts, "report&, const string&");

  const char * f = format.c_str();

  if (const char * p = std::strstr(f, "%/")) {
    first_line_format.parse(string(f, 0, p - f));
    const char * n = p + 2;
    if (const char * p = std::strstr(n, "%/")) {
      next_lines_format.parse(string(n, 0, p - n));
      between_format.parse(string(p + 2));
    } else {
      next_lines_format.parse(n);
    }
  } else {
    first_line_format.parse(format);
    next_lines_format.parse(format);
  }
}

void format_posts::flush()
{
  report.output_stream.flush();
}

void format_posts::operator()(post_t& post)
{
  std::ostream& out(report.output_stream);

  if (print_raw) {
    if (! post.has_xdata() ||
	! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
      if (last_xact != post.xact) {
	if (last_xact) {
	  bind_scope_t xact_scope(report, *last_xact);
	  between_format.format(out, xact_scope);
	}
	print_item(out, *post.xact);
	out << '\n';
	last_xact = post.xact;
      }
      post.xdata().add_flags(POST_EXT_DISPLAYED);
      last_post = &post;
    }
  }
  else if (! post.has_xdata() ||
	   ! post.xdata().has_flags(POST_EXT_DISPLAYED)) {
    bind_scope_t bound_scope(report, post);
    if (last_xact != post.xact) {
      if (last_xact) {
	bind_scope_t xact_scope(report, *last_xact);
	between_format.format(out, xact_scope);
      }
      first_line_format.format(out, bound_scope);
      last_xact = post.xact;
    }
    else if (last_post && last_post->date() != post.date()) {
      first_line_format.format(out, bound_scope);
    }
    else {
      next_lines_format.format(out, bound_scope);
    }

    post.xdata().add_flags(POST_EXT_DISPLAYED);
    last_post = &post;
  }
}

format_accounts::format_accounts(report_t&     _report,
				 const string& format)
  : report(_report), disp_pred()
{
  TRACE_CTOR(format_accounts, "report&, const string&");

  const char * f = format.c_str();

  if (const char * p = std::strstr(f, "%/")) {
    account_line_format.parse(string(f, 0, p - f));
    const char * n = p + 2;
    if (const char * p = std::strstr(n, "%/")) {
      total_line_format.parse(string(n, 0, p - n));
      separator_format.parse(string(p + 2));
    } else {
      total_line_format.parse(n);
    }
  } else {
    account_line_format.parse(format);
    total_line_format.parse(format);
  }
}

void format_accounts::post_account(account_t& account)
{
  if (account.xdata().has_flags(ACCOUNT_EXT_TO_DISPLAY)) {
    account.xdata().add_flags(ACCOUNT_EXT_DISPLAYED);

    bind_scope_t bound_scope(report, account);
    account_line_format.format(report.output_stream, bound_scope);
  }
}

std::pair<std::size_t, std::size_t>
format_accounts::mark_accounts(account_t& account, const bool flat)
{
  std::size_t visited	 = 0;
  std::size_t to_display = 0;

  foreach (accounts_map::value_type& pair, account.accounts) {
    std::pair<std::size_t, std::size_t> i = mark_accounts(*pair.second, flat);
    visited    += i.first;
    to_display += i.second;
  }

#if defined(DEBUG_ON)
  DEBUG("account.display", "Considering account: " << account.fullname());
  if (account.has_flags(ACCOUNT_EXT_VISITED))
    DEBUG("account.display", "  it was visited itself");
  DEBUG("account.display", "  it has " << visited << " visited children");
  DEBUG("account.display",
	"  it has " << to_display << " children to display");
#endif

  if (account.has_flags(ACCOUNT_EXT_VISITED) || (! flat && visited > 0)) {
    bind_scope_t bound_scope(report, account);
    if (disp_pred(bound_scope) && (flat || to_display != 1)) {
      account.xdata().add_flags(ACCOUNT_EXT_TO_DISPLAY);
      DEBUG("account.display", "Marking account as TO_DISPLAY");
      to_display = 1;
    }
    visited = 1;
  }

  return std::pair<std::size_t, std::size_t>(visited, to_display);
}

void format_accounts::flush()
{
  std::ostream& out(report.output_stream);

  if (report.HANDLED(display_)) {
    DEBUG("account.display",
	  "Account display predicate: " << report.HANDLER(display_).str());
    disp_pred.predicate.parse(report.HANDLER(display_).str());
  }

  mark_accounts(*report.session.master, report.HANDLED(flat));

  std::size_t top_displayed = 0;

  foreach (account_t * account, posted_accounts) {
    post_account(*account);

    if (report.HANDLED(flat) && account->has_flags(ACCOUNT_EXT_DISPLAYED))
      top_displayed++;
  }

  if (! report.HANDLED(flat)) {
    foreach (accounts_map::value_type pair, report.session.master->accounts) {
      if (pair.second->has_flags(ACCOUNT_EXT_DISPLAYED) ||
	  pair.second->children_with_flags(ACCOUNT_EXT_DISPLAYED)) {
	top_displayed++;
      }
    }
  }

  if (! report.HANDLED(no_total) && top_displayed > 1 &&
      report.session.master->family_total()) {
    bind_scope_t bound_scope(report, *report.session.master);
    separator_format.format(out, bound_scope);
    total_line_format.format(out, bound_scope);
  }

  out.flush();
}

void format_accounts::operator()(account_t& account)
{
  posted_accounts.push_back(&account);
}

} // namespace ledger
<|endoftext|>


<commit_before>#include "lsearch_init.h"

using namespace nano;

scalar_t lsearch_unit_init_t::get(const solver_state_t&, const int)
{
        return 1;
}

scalar_t lsearch_linear_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        const auto dg = state.d.dot(state.g);
        switch (iteration)
        {
        case 0:
                t0 = 1;
                break;

        default:
                // NB: the line-search length is from the previous iteration!
                t0 = state.t * m_prevdg / dg;
                break;
        }

        m_prevdg = dg;
        return t0;
}

scalar_t lsearch_quadratic_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        switch (iteration)
        {
        case 0:
                t0 = 1;
                break;

        default:
                t0 = scalar_t(1.01) * 2 * (state.f - m_prevf) / state.d.dot(state.g);
                break;
        }

        m_prevf = state.f;
        return t0;
}

scalar_t lsearch_cgdescent_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        const auto phi0 = scalar_t(0.01);
        const auto phi2 = scalar_t(2.0);

        switch (iteration)
        {
        case 0:
                {
                        const auto xnorm = state.x.lpNorm<Eigen::Infinity>();
                        const auto fnorm = std::fabs(state.f);

                        if (xnorm > 0)
                        {
                                t0 = phi0 * xnorm / state.g.lpNorm<Eigen::Infinity>();
                        }
                        else if (fnorm > 0)
                        {
                                t0 = phi0 * fnorm / state.g.squaredNorm();
                        }
                        else
                        {
                                t0 = 1;
                        }
                }
                break;

        default:
                // NB: the line-search length is from the previous iteration!
                t0 = state.t * phi2;
                break;
        }

        return t0;
}
<commit_msg>cg_descent lsearch initial step with quadratic interpolation (to finish)<commit_after>#include "lsearch_init.h"

using namespace nano;

scalar_t lsearch_unit_init_t::get(const solver_state_t&, const int)
{
        return 1;
}

scalar_t lsearch_linear_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        const auto dg = state.d.dot(state.g);
        switch (iteration)
        {
        case 0:
                t0 = 1;
                break;

        default:
                // NB: the line-search length is from the previous iteration!
                t0 = state.t * m_prevdg / dg;
                break;
        }

        m_prevdg = dg;
        return t0;
}

scalar_t lsearch_quadratic_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        switch (iteration)
        {
        case 0:
                t0 = 1;
                break;

        default:
                t0 = scalar_t(1.01) * 2 * (state.f - m_prevf) / state.d.dot(state.g);
                break;
        }

        m_prevf = state.f;
        return t0;
}

scalar_t lsearch_cgdescent_init_t::get(const solver_state_t& state, const int iteration)
{
        scalar_t t0;

        const auto phi0 = scalar_t(0.01);
        const auto phi1 = scalar_t(0.1);
        const auto phi2 = scalar_t(2.0);

        switch (iteration)
        {
        case 0:
                {
                        const auto xnorm = state.x.lpNorm<Eigen::Infinity>();
                        const auto fnorm = std::fabs(state.f);

                        if (xnorm > 0)
                        {
                                t0 = phi0 * xnorm / state.g.lpNorm<Eigen::Infinity>();
                        }
                        else if (fnorm > 0)
                        {
                                t0 = phi0 * fnorm / state.g.squaredNorm();
                        }
                        else
                        {
                                t0 = 1;
                        }
                }
                break;

        default:
                {
                        // NB: the line-search length is from the previous iteration!
                        lsearch_strategy_t::step_t step0 = state;
                        lsearch_strategy_t::step_t stepx;
                        stepx.t = state.t * phi1;
                        stepx.f = state.function->vgrad(state.x + stepx.t * state.d);
                        stepx.g = 0;

                        const auto tq = lsearch_strategy_t::quadratic(step0, stepx);
                        if (stepx.f < step0.f && tq > 0 && tq < stepx.t)
                        {
                                // todo: check here if the quadratic interpolant is convex!!!
                                t0 = tq;
                        }
                        else
                        {
                                t0 = state.t * phi2;
                        }
                }
                break;
        }

        return t0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#pragma once

#include <ostream>
#include <cstdint>
#include <tuple>
#include <type_traits>

namespace stub
{
    /// Specialization chosen for empty tuples or when Index reaches the
    /// sizeof the tuple (i.e. the number of values in the tuple), see
    /// description below.
    template
    <
        uint32_t Index = 0,
        class... Args,
        typename std::enable_if<Index == sizeof...(Args), uint8_t>::type = 0
    >
    inline void print_arguments(std::ostream& out, const std::tuple<Args...>& t)
    {
        (void) out;
        (void) t;
    }

    /// Prints the content of a tuple to the specified std::ostream.
    ///
    /// The two functions print_arguments use SFINAE (Substitution Failure
    /// Is Not An Error) to select which overload to call.
    ///
    /// The overloading works like this:
    ///
    ///   1. If print_arguments is called with an empty tuple then
    ///      Index==sizeof...(Args) will be true and the empty overload
    ///      will be chosen.
    ///
    ///   2. If print_argument is called with a non-empty tuple the
    ///      Index!=sizeof(Args) is true and the overload writing to the
    ///      std::ostream will be called. This will then recursively call
    ///      print_arguments incrementing the Index. A some point
    ///      Index==sizeof(Args) and the empty overload gets chosen and we
    ///      are done.
    ///
    ///Note that if called with an empty tuple then
    /// Index != sizeof...(Args) will be false and the empty
    /// print_arguments will be called
    template
    <
        uint32_t Index = 0,
        class... Args,
        typename std::enable_if<Index != sizeof...(Args), uint8_t>::type = 0
    >
    inline void print_arguments(std::ostream& out, const std::tuple<Args...>& t)
    {
        out << "Arg " << Index << ": " << std::get<Index>(t) << "\n";
        print_arguments<Index + 1>(out, t);
    }
}
<commit_msg>Make win32 happy<commit_after>// Copyright (c) 2015 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.

#pragma once

#include <ostream>
#include <cstdint>
#include <tuple>
#include <type_traits>

namespace stub
{

    inline void print_arguments(std::ostream& out, const std::tuple<>& t)
    {
        (void) out;
        (void) t;
    }

    /// Specialization chosen for empty tuples or when Index reaches the
    /// sizeof the tuple (i.e. the number of values in the tuple), see
    /// description below.
    template
    <
        uint32_t Index = 0,
        class... Args,
        typename std::enable_if<Index == sizeof...(Args), uint8_t>::type = 0
    >
    inline void print_arguments(std::ostream& out, const std::tuple<Args...>& t)
    {
        (void) out;
        (void) t;
    }

    /// Prints the content of a tuple to the specified std::ostream.
    ///
    /// The two functions print_arguments use SFINAE (Substitution Failure
    /// Is Not An Error) to select which overload to call.
    ///
    /// The overloading works like this:
    ///
    ///   1. If print_arguments is called with an empty tuple then
    ///      Index==sizeof...(Args) will be true and the empty overload
    ///      will be chosen.
    ///
    ///   2. If print_argument is called with a non-empty tuple the
    ///      Index!=sizeof(Args) is true and the overload writing to the
    ///      std::ostream will be called. This will then recursively call
    ///      print_arguments incrementing the Index. A some point
    ///      Index==sizeof(Args) and the empty overload gets chosen and we
    ///      are done.
    ///
    ///Note that if called with an empty tuple then
    /// Index != sizeof...(Args) will be false and the empty
    /// print_arguments will be called
    template
    <
        uint32_t Index = 0,
        class... Args,
        typename std::enable_if<Index != sizeof...(Args), uint8_t>::type = 0
    >
    inline void print_arguments(std::ostream& out, const std::tuple<Args...>& t)
    {
        out << "Arg " << Index << ": " << std::get<Index>(t) << "\n";
        print_arguments<Index + 1>(out, t);
    }
}
<|endoftext|>


<commit_before>#pragma once
#include "type.hpp"
#include "error.hpp"
#define BOOST_PP_VARIADICS 1
#include <boost/preprocessor.hpp>

namespace spn {
	template <class... Ts>
	struct ValueHolder {
		template <class T2>
		void ref(T2*) {}
		template <class T2>
		void cref(T2*) const {}
	};
	template <class T, class... Ts>
	struct ValueHolder<T, Ts...> : ValueHolder<Ts...> {
		using base = ValueHolder<Ts...>;
		using value_type = typename T::value_type;
		value_type	value;

		value_type& ref(T*) { return value; }
		const value_type& cref(T*) const { return value; }
		template <class T2>
		auto ref(T2* p) -> decltype(base::ref(p)) {
			return base::ref(p); }
		template <class T2>
		auto cref(T2* p) const -> decltype(base::cref(p)) {
			return base::cref(p); }
	};
	//! キャッシュ変数の自動管理クラス
	template <class Class, class... Ts>
	class RFlag : public ValueHolder<Ts...> {
		public:
			using FlagValue = uint32_t;
		private:
			using base = ValueHolder<Ts...>;
			using ct_base = spn::CType<Ts...>;
			template <class T>
			static T* _GetNull() { return reinterpret_cast<T*>(0); }

			mutable FlagValue _rflag = All();
			//! integral_constantの値がtrueなら引数テンプレートのOr()を返す
			template <class T0>
			static constexpr FlagValue _Add_If(std::integral_constant<bool,false>) { return 0; }
			template <class T0>
			static constexpr FlagValue _Add_If(std::integral_constant<bool,true>) { return OrLH<T0>(); }
			template <class T, int N>
			static constexpr FlagValue _IterateLH(std::integral_constant<int,N>) {
				using T0 = typename ct_base::template At<N>::type;
				using T0Has = typename T0::template Has<T>;
				return _Add_If<T0>(T0Has()) |
						_IterateLH<T>(std::integral_constant<int,N+1>());
			}
			template <class T>
			static constexpr FlagValue _IterateLH(std::integral_constant<int,ct_base::size>) { return 0; }

			template <class T, int N>
			static constexpr FlagValue _IterateHL(std::integral_constant<int,N>) {
				using T0 = typename T::template At<N>::type;
				return OrHL<T0>() | _IterateHL<T>(std::integral_constant<int,N-1>());
			}
			template <class T>
			static constexpr FlagValue _IterateHL(std::integral_constant<int,-1>) { return 0; }

			template <class T>
			auto _refresh(const Class* self) const -> decltype(base::cref(_GetNull<T>())) {
				const base* ptrC = this;
				base* ptr = const_cast<base*>(ptrC);
				_rflag &= ~(self->_refresh(ptr->ref(_GetNull<T>()), _GetNull<T>()));
				_rflag &= ~Get<T>();
				AssertP(Trap, !(_rflag & OrHL<T>()), "refresh flag was not cleared correctly")
				return ptrC->cref(_GetNull<T>());
			}
			template <class TA>
			static constexpr FlagValue _GetSingle() {
				return 1 << ct_base::template Find<TA>::result;
			}
			template <class... TsA>
			static constexpr FlagValue _Sum(std::integral_constant<int,0>) { return 0; }
			template <class TA, class... TsA, int N>
			static constexpr FlagValue _Sum(std::integral_constant<int,N>) {
				return _GetSingle<TA>() | _Sum<TsA...>(std::integral_constant<int,N-1>());
			}

			template <class... TsA>
			void _setFlag(std::integral_constant<int,0>) {}
			template <class T, class... TsA, int N>
			void _setFlag(std::integral_constant<int,N>) {
				_rflag |= OrLH<T>();
				_setFlag<TsA...>(std::integral_constant<int,N-1>());
			}

		public:
			template <class... TsA>
			static constexpr FlagValue Get() {
				return _Sum<TsA...>(std::integral_constant<int,sizeof...(TsA)>());
			}
			static constexpr FlagValue All() {
				return (1 << (sizeof...(Ts)+1)) -1;
			}
			FlagValue GetFlag() const {
				return _rflag;
			}
			template <class... TsA>
			FlagValue Test() const {
				return GetFlag() & Get<TsA...>();
			}

			template <class T>
			static constexpr FlagValue OrLH() {
				// TypeListを巡回、A::Has<T>ならOr<A>()をたす
				return Get<T>() | _IterateLH<T>(std::integral_constant<int,0>());
			}
			template <class T>
			static constexpr FlagValue OrHL() {
				return Get<T>() | _IterateHL<T>(std::integral_constant<int,T::size-1>());
			}

			//! 更新フラグだけを立てる
			template <class... TsA>
			void setFlag() {
				_setFlag<TsA...>(std::integral_constant<int,sizeof...(TsA)>());
			}

			template <class T>
			auto get(const Class* self) const -> decltype(base::cref(_GetNull<T>())) {
				if(!(_rflag & Get<T>()))
					return base::cref(_GetNull<T>());
				return _refresh<T>(self);
			}
			template <class T>
			auto ref() const -> typename std::decay<decltype(base::cref(_GetNull<T>()))>::type& {
				// 更新チェックなしで参照を返す
				const auto& ret = base::cref(_GetNull<T>());
				return const_cast<typename std::decay<decltype(ret)>::type&>(ret);
			}
			template <class T>
			auto refF() -> decltype(ref<T>()) {
				// 更新フラグありで参照を返す
				setFlag<T>();
				return ref<T>();
			}
			//! キャッシュ機能付きの値を変更する際に使用
			template <class T, class TA>
			void set(TA&& t) {
				refF<T>() = std::forward<TA>(t);
			}
	};

	#define RFLAG(clazz, seq) \
		using RFlag_t = spn::RFlag<clazz, BOOST_PP_SEQ_ENUM(seq)>; \
		RFlag_t _rflag; \
		template <class T, class... Ts> \
		friend class spn::RFlag;
	#define RFLAG_RVALUE_BASE(name, valueT, ...) \
		struct name : spn::CType<__VA_ARGS__> { \
			using value_type = valueT; \
			value_type value; };
	#define RFLAG_RVALUE(name, ...) \
			RFLAG_RVALUE_BASE(name, __VA_ARGS__) \
			BOOST_PP_IF( \
				BOOST_PP_LESS_EQUAL( \
					BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
					1 \
				), \
				RFLAG_RVALUE_, \
				RFLAG_RVALUE_D_ \
			)(name, __VA_ARGS__)
	#define RFLAG_RVALUE_D_(name, valueT, ...) \
		uint32_t _refresh(valueT&, name*) const;
	#define RFLAG_RVALUE_(name, valueT) \
		uint32_t _refresh(valueT&, name*) const { return 0; }
	#define RFLAG_GETMETHOD(name) auto get##name() const -> decltype(_rflag.get<name>(this)) { return _rflag.get<name>(this); }
	#define PASS_THROUGH(func, ...)		func(__VA_ARGS__)
	#define RFLAG_FUNC(z, data, elem)	PASS_THROUGH(RFLAG_RVALUE, BOOST_PP_SEQ_ENUM(elem))
	#define SEQ_GETFIRST(z, data, elem)	(BOOST_PP_SEQ_ELEM(0,elem))
	#define RFLAG_S(clazz, seq)	\
		BOOST_PP_SEQ_FOR_EACH( \
			RFLAG_FUNC, \
			BOOST_PP_NIL, \
			seq \
		) \
		RFLAG( \
			clazz, \
			BOOST_PP_SEQ_FOR_EACH( \
				SEQ_GETFIRST, \
				BOOST_PP_NIL, \
				seq \
			) \
		)

	#define RFLAG_FUNC2(z, data, elem)	RFLAG_GETMETHOD(elem)
	#define RFLAG_GETMETHOD_S(seq) \
		BOOST_PP_SEQ_FOR_EACH( \
			RFLAG_FUNC2, \
			BOOST_PP_NIL, \
			BOOST_PP_SEQ_FOR_EACH( \
				SEQ_GETFIRST, \
				BOOST_PP_NIL, \
				seq \
			) \
		)
	/* class MyClass {
		RFLAG_RVALUE(Value0, Type0)
		RFLAG_RVALUE(Value0, Type0, Depends....) をクラス内に変数分だけ書く
		更新関数を uint32_t _refresh(Type0&, Value0*) const; の形で記述
		RFLAG(MyClass, Value0, Value0...)
		public:
			// 参照用の関数
			RFLAG_GETMETHOD(Value0)
			RFLAG_GETMETHOD(Value1)

		参照する時は _rflag.get<Value0>(this) とやるか、
		getValue0()とすると依存変数の自動更新
		_rfvalue.ref<Value0>(this)とすれば依存関係を無視して取り出せる

		--- 上記の簡略系 ---
		#define SEQ ((Value0)(Type0))((Value1)(Type1)(Depend))
		private:
			RFLAG_S(MyClass, SEQ)
		public:
			RFLAG_GETMETHOD_S(SEQ) */

	#define VARIADIC_FOR_EACH_FUNC(z, n, data)	BOOST_PP_TUPLE_ELEM(0, data)(1, BOOST_PP_TUPLE_ELEM(1,data), BOOST_PP_TUPLE_ELEM(BOOST_PP_ADD(n,2),data))
	#define VARIADIC_FOR_EACH(macro, data, ...)	BOOST_PP_REPEAT(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), VARIADIC_FOR_EACH_FUNC, BOOST_PP_VARIADIC_TO_TUPLE(macro, data, __VA_ARGS__))
}

<commit_msg>rflag: 中間層への値セット setMethodの自動定義マクロ<commit_after>#pragma once
#include "type.hpp"
#include "error.hpp"
#define BOOST_PP_VARIADICS 1
#include <boost/preprocessor.hpp>

namespace spn {
	template <class... Ts>
	struct ValueHolder {
		template <class T2>
		void ref(T2*) {}
		template <class T2>
		void cref(T2*) const {}
	};
	template <class T, class... Ts>
	struct ValueHolder<T, Ts...> : ValueHolder<Ts...> {
		using base = ValueHolder<Ts...>;
		using value_type = typename T::value_type;
		value_type	value;

		value_type& ref(T*) { return value; }
		const value_type& cref(T*) const { return value; }
		template <class T2>
		auto ref(T2* p) -> decltype(base::ref(p)) {
			return base::ref(p); }
		template <class T2>
		auto cref(T2* p) const -> decltype(base::cref(p)) {
			return base::cref(p); }
	};
	//! キャッシュ変数の自動管理クラス
	template <class Class, class... Ts>
	class RFlag : public ValueHolder<Ts...> {
		public:
			using FlagValue = uint32_t;
		private:
			using base = ValueHolder<Ts...>;
			using ct_base = spn::CType<Ts...>;
			template <class T>
			static T* _GetNull() { return reinterpret_cast<T*>(0); }

			mutable FlagValue _rflag = All();
			//! integral_constantの値がtrueなら引数テンプレートのOr()を返す
			template <class T0>
			static constexpr FlagValue _Add_If(std::integral_constant<bool,false>) { return 0; }
			template <class T0>
			static constexpr FlagValue _Add_If(std::integral_constant<bool,true>) { return OrLH<T0>(); }
			template <class T, int N>
			static constexpr FlagValue _IterateLH(std::integral_constant<int,N>) {
				using T0 = typename ct_base::template At<N>::type;
				using T0Has = typename T0::template Has<T>;
				return _Add_If<T0>(T0Has()) |
						_IterateLH<T>(std::integral_constant<int,N+1>());
			}
			template <class T>
			static constexpr FlagValue _IterateLH(std::integral_constant<int,ct_base::size>) { return 0; }

			template <class T, int N>
			static constexpr FlagValue _IterateHL(std::integral_constant<int,N>) {
				using T0 = typename T::template At<N>::type;
				return OrHL<T0>() | _IterateHL<T>(std::integral_constant<int,N-1>());
			}
			template <class T>
			static constexpr FlagValue _IterateHL(std::integral_constant<int,-1>) { return 0; }

			template <class T>
			auto _refresh(const Class* self) const -> decltype(base::cref(_GetNull<T>())) {
				const base* ptrC = this;
				base* ptr = const_cast<base*>(ptrC);
				_rflag &= ~(self->_refresh(ptr->ref(_GetNull<T>()), _GetNull<T>()));
				_rflag &= ~Get<T>();
				AssertP(Trap, !(_rflag & OrHL<T>()), "refresh flag was not cleared correctly")
				return ptrC->cref(_GetNull<T>());
			}
			template <class TA>
			static constexpr FlagValue _GetSingle() {
				return 1 << ct_base::template Find<TA>::result;
			}
			template <class... TsA>
			static constexpr FlagValue _Sum(std::integral_constant<int,0>) { return 0; }
			template <class TA, class... TsA, int N>
			static constexpr FlagValue _Sum(std::integral_constant<int,N>) {
				return _GetSingle<TA>() | _Sum<TsA...>(std::integral_constant<int,N-1>());
			}

			template <class... TsA>
			void _setFlag(std::integral_constant<int,0>) {}
			template <class T, class... TsA, int N>
			void _setFlag(std::integral_constant<int,N>) {
				// 自分より下の階層はフラグを下ろす
				_rflag &= ~OrHL<T>();
				// 自分の階層より上の変数は全てフラグを立てる
				_rflag |= OrLH<T>();
				_setFlag<TsA...>(std::integral_constant<int,N-1>());
			}

		public:
			template <class... TsA>
			static constexpr FlagValue Get() {
				return _Sum<TsA...>(std::integral_constant<int,sizeof...(TsA)>());
			}
			static constexpr FlagValue All() {
				return (1 << (sizeof...(Ts)+1)) -1;
			}
			FlagValue GetFlag() const {
				return _rflag;
			}
			template <class... TsA>
			FlagValue Test() const {
				return GetFlag() & Get<TsA...>();
			}

			template <class T>
			static constexpr FlagValue OrLH() {
				// TypeListを巡回、A::Has<T>ならOr<A>()をたす
				return Get<T>() | _IterateLH<T>(std::integral_constant<int,0>());
			}
			template <class T>
			static constexpr FlagValue OrHL() {
				return Get<T>() | _IterateHL<T>(std::integral_constant<int,T::size-1>());
			}

			//! 更新フラグだけを立てる
			template <class... TsA>
			void setFlag() {
				_setFlag<TsA...>(std::integral_constant<int,sizeof...(TsA)>());
			}

			template <class T>
			auto get(const Class* self) const -> decltype(base::cref(_GetNull<T>())) {
				if(!(_rflag & Get<T>()))
					return base::cref(_GetNull<T>());
				return _refresh<T>(self);
			}
			template <class T>
			auto ref() const -> typename std::decay<decltype(base::cref(_GetNull<T>()))>::type& {
				// 更新チェックなしで参照を返す
				const auto& ret = base::cref(_GetNull<T>());
				return const_cast<typename std::decay<decltype(ret)>::type&>(ret);
			}
			template <class T>
			auto refF() -> decltype(ref<T>()) {
				// 更新フラグありで参照を返す
				setFlag<T>();
				return ref<T>();
			}
			//! キャッシュ機能付きの値を変更する際に使用
			template <class T, class TA>
			void set(TA&& t) {
				refF<T>() = std::forward<TA>(t);
			}
	};

	#define RFLAG(clazz, seq) \
		using RFlag_t = spn::RFlag<clazz, BOOST_PP_SEQ_ENUM(seq)>; \
		RFlag_t _rflag; \
		template <class T, class... Ts> \
		friend class spn::RFlag;
	#define RFLAG_RVALUE_BASE(name, valueT, ...) \
		struct name : spn::CType<__VA_ARGS__> { \
			using value_type = valueT; \
			value_type value; };
	#define RFLAG_RVALUE(name, ...) \
			RFLAG_RVALUE_BASE(name, __VA_ARGS__) \
			BOOST_PP_IF( \
				BOOST_PP_LESS_EQUAL( \
					BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), \
					1 \
				), \
				RFLAG_RVALUE_, \
				RFLAG_RVALUE_D_ \
			)(name, __VA_ARGS__)
	#define RFLAG_RVALUE_D_(name, valueT, ...) \
		uint32_t _refresh(valueT&, name*) const;
	#define RFLAG_RVALUE_(name, valueT) \
		uint32_t _refresh(valueT&, name*) const { return 0; }
	#define RFLAG_GETMETHOD(name) auto get##name() const -> decltype(_rflag.get<name>(this)) { return _rflag.get<name>(this); }
	#define PASS_THROUGH(func, ...)		func(__VA_ARGS__)
	#define RFLAG_FUNC(z, data, elem)	PASS_THROUGH(RFLAG_RVALUE, BOOST_PP_SEQ_ENUM(elem))
	#define SEQ_GETFIRST(z, data, elem)	(BOOST_PP_SEQ_ELEM(0,elem))
	#define RFLAG_S(clazz, seq)	\
		BOOST_PP_SEQ_FOR_EACH( \
			RFLAG_FUNC, \
			BOOST_PP_NIL, \
			seq \
		) \
		RFLAG( \
			clazz, \
			BOOST_PP_SEQ_FOR_EACH( \
				SEQ_GETFIRST, \
				BOOST_PP_NIL, \
				seq \
			) \
		)

	#define RFLAG_FUNC2(z, data, elem)	RFLAG_GETMETHOD(elem)
	#define RFLAG_GETMETHOD_S(seq) \
		BOOST_PP_SEQ_FOR_EACH( \
			RFLAG_FUNC2, \
			BOOST_PP_NIL, \
			BOOST_PP_SEQ_FOR_EACH( \
				SEQ_GETFIRST, \
				BOOST_PP_NIL, \
				seq \
			) \
		)

	#define RFLAG_SETMETHOD(name) \
		template <class TArg> \
		void BOOST_PP_CAT(set, name(TArg&& t)) { _rflag.set<name>(std::forward<TArg>(t)); }
	#define RFLAG_FUNC3(z, dummy, seq)	\
		BOOST_PP_IF( \
			BOOST_PP_LESS_EQUAL( \
				BOOST_PP_SEQ_SIZE(seq), \
				2 \
			), \
			RFLAG_SETMETHOD, \
			NOTHING_ARG \
		)(BOOST_PP_SEQ_ELEM(0, seq))

	#define RFLAG_SETMETHOD_S(seq) \
		BOOST_PP_SEQ_FOR_EACH( \
			RFLAG_FUNC3, \
			BOOST_PP_NIL, \
			seq \
		)
	/* class MyClass {
		RFLAG_RVALUE(Value0, Type0)
		RFLAG_RVALUE(Value0, Type0, Depends....) をクラス内に変数分だけ書く
		更新関数を uint32_t _refresh(Type0&, Value0*) const; の形で記述
		RFLAG(MyClass, Value0, Value0...)
		public:
			// 参照用の関数
			RFLAG_GETMETHOD(Value0)
			RFLAG_GETMETHOD(Value1)

		参照する時は _rflag.get<Value0>(this) とやるか、
		getValue0()とすると依存変数の自動更新
		_rfvalue.ref<Value0>(this)とすれば依存関係を無視して取り出せる

		--- 上記の簡略系 ---
		#define SEQ ((Value0)(Type0))((Value1)(Type1)(Depend))
		private:
			RFLAG_S(MyClass, SEQ)
		public:
			RFLAG_GETMETHOD_S(SEQ) */

	#define VARIADIC_FOR_EACH_FUNC(z, n, data)	BOOST_PP_TUPLE_ELEM(0, data)(1, BOOST_PP_TUPLE_ELEM(1,data), BOOST_PP_TUPLE_ELEM(BOOST_PP_ADD(n,2),data))
	#define VARIADIC_FOR_EACH(macro, data, ...)	BOOST_PP_REPEAT(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), VARIADIC_FOR_EACH_FUNC, BOOST_PP_VARIADIC_TO_TUPLE(macro, data, __VA_ARGS__))
}

<|endoftext|>


<commit_before>

#include "RFM02.h"

uint8_t _pinFSK;
uint8_t _pinNIRQ;
uint8_t _pinSOMI;
uint8_t _pinSIMO;
uint8_t _pinChipSelect;
uint8_t _pinSerialClock;

// Booster Pack Pins FR5969
    //  7 - P2.2 for SPI_CLK mode
    // 15 - P1.6 for SPI_SIMO mode
	// 14 - P1.7 for SPI_SOMI mode
	//  5 - P2.5 output pin for SPI_CS
    // 18 - P3.0 nIRQ for sending data
    //  3 - P2.6 as FSK input data
    // Set display's VCC and DISP pins to high

static const uint8_t P_CS   = 4;
static const uint8_t P_FSK  = 3;
static const uint8_t P_NIRQ = 18;

// empty constructor
RFM02::RFM02() {
	RFM02(P_CS, P_FSK, P_NIRQ);
}

// constructor with variables
RFM02::RFM02(uint8_t pinChipSelect, uint8_t pinFSK, uint8_t pinNIRQ){
	_pinChipSelect = pinChipSelect;
	_pinFSK = pinFSK;
	_pinNIRQ = pinNIRQ;
}

void RFM02::begin() {
	digitalWrite(_pinChipSelect, HIGH);  // set chip select high
	pinMode(_pinChipSelect, OUTPUT);     // set chip select pin as output

	digitalWrite(_pinFSK, LOW);			// set FSK to low
	pinMode(_pinFSK, OUTPUT);			// set FSK pin as output

	pinMode(P_NIRQ, INPUT);				// set nIRQ pin as input

	configureDeviceSettings();			// configure RFM01 to correct settings

	pinMode(RED_LED, OUTPUT);			// set pin with red led as output
	digitalWrite(RED_LED, HIGH);		// blink red led 50 ms to indicate setup ready
	delay(50);
	digitalWrite(RED_LED, LOW);
}

void RFM02::writeRegister(uint8_t HighByte, uint8_t LowByte) {
	digitalWrite(_pinChipSelect,LOW);
	SPI.transfer(HighByte);
	SPI.transfer(LowByte);
	digitalWrite(_pinChipSelect,HIGH);
}

void RFM02::configureDeviceSettings() {
	writeRegister(0xCC,0x00);	// read status
	writeRegister(0x93,0x82);	// 868MHz Band +/- 90kHz Bandbreite
	writeRegister(0xA6,0x86);	// 868.35 MHz
	writeRegister(0xD0,0x40);	// RATE/2
	writeRegister(0xC8,0x23);	// 4.8kbps
	writeRegister(0xC2,0x20);	// Bit Sync active
	writeRegister(0xC0,0x01);	// disable TX
	writeRegister(0xD2,0x40);	// PLL 25%
	writeRegister(0xB0,0x00);	// -9 db
	writeRegister(0xE0,0x00);	// 'disable wakeup timer

}

// Data via FSK
/******************************************************************************/
/*         Sending data via the FSK-Pin as Input-Pin                          */
/*                                                                            */
/*         After the PowerAmplifier has turned on ( ea=1 ) from rfm02-module  */
/*         comes a clock corresponding to the data-rate set before on nIRQ.   */
/*         The data to be transmitted is bitwise set on the FSK-Pin of the    */
/*         module, after the falling edge of nIRQ. With the following edge    */
/*         of nIRQ this bit is read in and sent out.                          */
/*         nSEL must be high, SCK low, both all the time                      */
/*                                                                            */
/*                                                                            */
/* TESTED: 28.09.2014 with Deviation +/- 90kHz and 435.000 MHz                */
/*                  up to 115.000BPS                                          */
/*                                                                            */
/* Support & Copyright: tigarus.programming@web.de                            */
/******************************************************************************/
void RFM02::RFM02_TX_DataByte_FSK(uint8_t DataByte){
uint8_t i=8;
// PowerAmplifier is here already enabled, impulses on nIRQ corresponding to the
// set data-rate, nSEL is high, SCK is low
	digitalWrite(_pinChipSelect,HIGH);
      while(i){            // do 8 times..., (any number of bit's will do, also 9 or 121)
        i=i-1;
		while(!(digitalRead(_pinNIRQ))); // wait for the 0-1-edge of nIRQ, reading in the data
		while((digitalRead(_pinNIRQ)));   // wait for 1-0-edge to send the last bit

        if( DataByte & BIT7 )   // if not '0' write over with '1'
			digitalWrite(_pinFSK, HIGH); // ...write '1' if most significant bit is '1'
        else
			digitalWrite(_pinFSK, LOW); //OUT_PORT_REG &= ~FSK; // first set Bitx as '0'

        DataByte <<= 1;         // shift DataByte one bit left to write the next bit
      }
}

void RFM02::sendMessage(uint8_t *txData, uint8_t size)
{

   //digitalWrite(_pinChipSelect, LOW); // CS LOW
   writeRegister(0xC0,0x39); // enable TX
   //digitalWrite(_pinChipSelect, HIGH); // CS HIGH
   //delay(1000);
   RFM02_TX_DataByte_FSK(0xAA); // preamble
   RFM02_TX_DataByte_FSK(0xAA); // preamble
   RFM02_TX_DataByte_FSK(0xAA); // preamble

   RFM02_TX_DataByte_FSK(0x2D); // sync word high
   RFM02_TX_DataByte_FSK(0xD4); // sync word low

   for(int myLoop=0;myLoop<MESSAGELENGTH;myLoop++)
 {
   RFM02_TX_DataByte_FSK(txData[myLoop]); // sync word lowtxData[myLoop] = myLoop;
 }

   /*
   RFM02_TX_DataByte_FSK('H'); // data
   RFM02_TX_DataByte_FSK('E'); // data
   RFM02_TX_DataByte_FSK('L'); // data
   RFM02_TX_DataByte_FSK('L'); // data
   RFM02_TX_DataByte_FSK('O'); // data

   RFM02_TX_DataByte_FSK(1); // data
   RFM02_TX_DataByte_FSK(2); // data
   RFM02_TX_DataByte_FSK(3); // data
   RFM02_TX_DataByte_FSK(4); // data

   RFM02_TX_DataByte_FSK(0xA5); // ende zeichen
   */
   delay(1); // delay until carrier turn off

   //digitalWrite(_pinChipSelect, LOW); // CS LOW
   writeRegister(0xC0,0x01); // disable TX
   //digitalWrite(_pinChipSelect, HIGH); // CS HIGH

}
<commit_msg>corrected upper-case letter error in include for rfm02.h to make linux compatible<commit_after>

#include "rfm02.h"

uint8_t _pinFSK;
uint8_t _pinNIRQ;
uint8_t _pinSOMI;
uint8_t _pinSIMO;
uint8_t _pinChipSelect;
uint8_t _pinSerialClock;

// Booster Pack Pins FR5969
//  7 - P2.2 for SPI_CLK mode
// 15 - P1.6 for SPI_SIMO mode
// 14 - P1.7 for SPI_SOMI mode
//  5 - P2.5 output pin for SPI_CS
// 18 - P3.0 nIRQ for sending data
//  3 - P2.6 as FSK input data
// Set display's VCC and DISP pins to high

static const uint8_t P_CS   = 4;
static const uint8_t P_FSK  = 3;
static const uint8_t P_NIRQ = 18;

// empty constructor
RFM02::RFM02() {
	RFM02(P_CS, P_FSK, P_NIRQ);
}

// constructor with variables
RFM02::RFM02(uint8_t pinChipSelect, uint8_t pinFSK, uint8_t pinNIRQ)
{
	_pinChipSelect = pinChipSelect;
	_pinFSK = pinFSK;
	_pinNIRQ = pinNIRQ;
}

void RFM02::begin() {
	digitalWrite(_pinChipSelect, HIGH);  	// set chip select high
	pinMode(_pinChipSelect, OUTPUT);     	// set chip select as output

	digitalWrite(_pinFSK, LOW);		// set FSK to low
	pinMode(_pinFSK, OUTPUT);		// set FSK pin as output

	pinMode(P_NIRQ, INPUT);			// set nIRQ pin as input

	configureDeviceSettings();		// configure RFM01

	pinMode(RED_LED, OUTPUT);		// set red led as output
	digitalWrite(RED_LED, HIGH);		// blink red led 50 ms
						// to indicate setup ready
	delay(50);
	digitalWrite(RED_LED, LOW);
}

void RFM02::writeRegister(uint8_t HighByte, uint8_t LowByte) {
	digitalWrite(_pinChipSelect,LOW);
	SPI.transfer(HighByte);
	SPI.transfer(LowByte);
	digitalWrite(_pinChipSelect,HIGH);
}

void RFM02::configureDeviceSettings() {
	writeRegister(0xCC,0x00);	// read status
	writeRegister(0x93,0x82);	// 868MHz Band +/- 90kHz Bandbreite
	writeRegister(0xA6,0x86);	// 868.35 MHz
	writeRegister(0xD0,0x40);	// RATE/2
	writeRegister(0xC8,0x23);	// 4.8kbps
	writeRegister(0xC2,0x20);	// Bit Sync active
	writeRegister(0xC0,0x01);	// disable TX
	writeRegister(0xD2,0x40);	// PLL 25%
	writeRegister(0xB0,0x00);	// -9 db
	writeRegister(0xE0,0x00);	// 'disable wakeup timer

}

// Data via FSK
/******************************************************************************/
/*         Sending data via the FSK-Pin as Input-Pin                          */
/*                                                                            */
/*         After the PowerAmplifier has turned on ( ea=1 ) from rfm02-module  */
/*         comes a clock corresponding to the data-rate set before on nIRQ.   */
/*         The data to be transmitted is bitwise set on the FSK-Pin of the    */
/*         module, after the falling edge of nIRQ. With the following edge    */
/*         of nIRQ this bit is read in and sent out.                          */
/*         nSEL must be high, SCK low, both all the time                      */
/*                                                                            */
/*                                                                            */
/* TESTED: 28.09.2014 with Deviation +/- 90kHz and 435.000 MHz                */
/*                  up to 115.000BPS                                          */
/*                                                                            */
/* Support & Copyright: tigarus.programming@web.de                            */
/******************************************************************************/
void RFM02::RFM02_TX_DataByte_FSK(uint8_t DataByte){
uint8_t i=8;
// PowerAmplifier is here already enabled, impulses on nIRQ corresponding to the
// set data-rate, nSEL is high, SCK is low
	digitalWrite(_pinChipSelect,HIGH);
      while(i){            // do 8 times..., (any number of bit's will do, also 9 or 121)
        i=i-1;
		while(!(digitalRead(_pinNIRQ))); // wait for the 0-1-edge of nIRQ, reading in the data
		while((digitalRead(_pinNIRQ)));   // wait for 1-0-edge to send the last bit

        if( DataByte & BIT7 )   // if not '0' write over with '1'
			digitalWrite(_pinFSK, HIGH); // ...write '1' if most significant bit is '1'
        else
			digitalWrite(_pinFSK, LOW); //OUT_PORT_REG &= ~FSK; // first set Bitx as '0'

        DataByte <<= 1;         // shift DataByte one bit left to write the next bit
      }
}

void RFM02::sendMessage(uint8_t *txData, uint8_t size)
{

   //digitalWrite(_pinChipSelect, LOW); // CS LOW
   writeRegister(0xC0,0x39); // enable TX
   //digitalWrite(_pinChipSelect, HIGH); // CS HIGH
   //delay(1000);
   RFM02_TX_DataByte_FSK(0xAA); // preamble
   RFM02_TX_DataByte_FSK(0xAA); // preamble
   RFM02_TX_DataByte_FSK(0xAA); // preamble

   RFM02_TX_DataByte_FSK(0x2D); // sync word high
   RFM02_TX_DataByte_FSK(0xD4); // sync word low

   for(int myLoop=0;myLoop<MESSAGELENGTH;myLoop++)
 {
   RFM02_TX_DataByte_FSK(txData[myLoop]); // sync word lowtxData[myLoop] = myLoop;
 }

   /*
   RFM02_TX_DataByte_FSK('H'); // data
   RFM02_TX_DataByte_FSK('E'); // data
   RFM02_TX_DataByte_FSK('L'); // data
   RFM02_TX_DataByte_FSK('L'); // data
   RFM02_TX_DataByte_FSK('O'); // data

   RFM02_TX_DataByte_FSK(1); // data
   RFM02_TX_DataByte_FSK(2); // data
   RFM02_TX_DataByte_FSK(3); // data
   RFM02_TX_DataByte_FSK(4); // data

   RFM02_TX_DataByte_FSK(0xA5); // ende zeichen
   */
   delay(1); // delay until carrier turn off

   //digitalWrite(_pinChipSelect, LOW); // CS LOW
   writeRegister(0xC0,0x01); // disable TX
   //digitalWrite(_pinChipSelect, HIGH); // CS HIGH

}
<|endoftext|>