<commit_before>//------------------------------------------------------------------------------
//  Emu/KC85Emu.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "KC85Emu.h"
#include "Assets/Gfx/ShapeBuilder.h"
#include "Input/Input.h"
#include "emu_shaders.h"

using namespace yakc;

namespace Oryol {

//------------------------------------------------------------------------------
void
KC85Emu::Setup(const GfxSetup& gfxSetup) {

    // initialize the emulator as KC85/3
    this->emu.kc85.roms.add(kc85_roms::caos31, dump_caos31, sizeof(dump_caos31));
    this->emu.kc85.roms.add(kc85_roms::basic_rom, dump_basic_c0, sizeof(dump_basic_c0));
    this->emu.init();
    this->draw.Setup(gfxSetup, 5);
    this->audio.Setup(this->emu.board.clck);
    this->emu.kc85.audio.setup_callbacks(&this->audio, Audio::cb_sound, Audio::cb_volume, Audio::cb_stop);
    this->fileLoader.Setup(this->emu);

    // register modules
    this->emu.kc85.exp.register_none_module("NO MODULE", "Click to insert module!");
    this->emu.kc85.exp.register_ram_module(kc85_exp::m022_16kbyte, 0xC0, 0x4000, "nohelp");

    // setup a mesh and draw state to render a simple plane
    ShapeBuilder shapeBuilder;
    shapeBuilder.Layout
        .Add(VertexAttr::Position, VertexFormat::Float3)
        .Add(VertexAttr::TexCoord0, VertexFormat::Float2);
    shapeBuilder.Plane(1.0f, 1.0f, 1);
    this->drawState.Mesh[0] = Gfx::CreateResource(shapeBuilder.Build());

    Id shd = Gfx::CreateResource(KCShader::Setup());
    auto pip = PipelineSetup::FromLayoutAndShader(shapeBuilder.Layout, shd);
    pip.DepthStencilState.DepthWriteEnabled = true;
    pip.DepthStencilState.DepthCmpFunc = CompareFunc::LessEqual;
    pip.RasterizerState.SampleCount = gfxSetup.SampleCount;
    pip.BlendState.ColorFormat = gfxSetup.ColorFormat;
    pip.BlendState.DepthFormat = gfxSetup.DepthFormat;
    this->drawState.Pipeline = Gfx::CreateResource(pip);
}

//------------------------------------------------------------------------------
void
KC85Emu::Discard() {
    this->fileLoader.Discard();
    this->emu.poweroff();
    this->audio.Discard();
    this->draw.Discard();
}

//------------------------------------------------------------------------------
void
KC85Emu::Update(Duration frameTime) {
    this->handleInput();
    int micro_secs = (int) frameTime.AsMicroSeconds();
    const uint64_t cpu_min_ahead_cycles = (this->emu.board.clck.base_freq_khz*1000)/100;
    const uint64_t cpu_max_ahead_cycles = (this->emu.board.clck.base_freq_khz*1000)/25;
    const uint64_t audio_cycle_count = this->audio.GetProcessedCycles();
    const uint64_t min_cycle_count = audio_cycle_count + cpu_min_ahead_cycles;
    const uint64_t max_cycle_count = audio_cycle_count + cpu_max_ahead_cycles;
    this->emu.onframe(2, micro_secs, min_cycle_count, max_cycle_count);
    this->audio.Update(this->emu.board.clck);
}

//------------------------------------------------------------------------------
void
KC85Emu::TogglePower() {
    if (this->SwitchedOn()) {
        this->emu.poweroff();
    }
    else {
        this->emu.poweron(device::kc85_3, os_rom::caos_3_1);
        if (!this->emu.kc85.exp.slot_occupied(0x08)) {
            this->emu.kc85.exp.insert_module(0x08, kc85_exp::m022_16kbyte);
        }
        if (!this->emu.kc85.exp.slot_occupied(0x0C)) {
            this->emu.kc85.exp.insert_module(0x0C, kc85_exp::none);
        }
    }
}

//------------------------------------------------------------------------------
bool
KC85Emu::SwitchedOn() const {
    return this->emu.kc85.on;
}

//------------------------------------------------------------------------------
void
KC85Emu::Reset() {
    if (this->SwitchedOn()) {
        this->emu.kc85.reset();
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::StartGame(const char* name) {
    o_assert_dbg(name);
    if (this->SwitchedOn()) {
        for (const auto& item : this->fileLoader.Items) {
            if ((int(item.Compat) & int(this->emu.model)) && (item.Name == name)) {
                this->fileLoader.LoadAndStart(this->emu, item);
            }
        }
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::Render(const glm::mat4& mvp) {

    this->frameIndex++;
    if (this->emu.kc85.on) {
        // update the offscreen texture
        const int width = 320;
        const int height = 256;
        const Id tex = this->draw.irmTexture320x256;
        this->draw.texUpdateAttrs.Sizes[0][0] = width*height*4;
        Gfx::UpdateTexture(tex, this->emu.kc85.video.LinearBuffer, this->draw.texUpdateAttrs);

        KCShader::KCVSParams vsParams;
        vsParams.ModelViewProjection = mvp;
        this->drawState.FSTexture[KCTextures::IRM] = tex;
        Gfx::ApplyDrawState(this->drawState);
        Gfx::ApplyUniformBlock(vsParams);
        Gfx::Draw(0);
    }
    else {
        // switch KC on once after a little while
        if (this->frameIndex == 120) {
            if (!this->SwitchedOn()) {
                this->TogglePower();
            }
        }
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::handleInput() {
    // FIXME: this should go into the yakc emulator
    const Keyboard& kbd = Input::Keyboard();

    #if YAKC_UI
    const Touchpad& touch = Input::Touchpad();
    // don't handle KC input if IMGUI has the keyboard focus
    if (ImGui::GetIO().WantCaptureKeyboard) {
        return;
    }
    // toggle UI?
    if (kbd.KeyDown(Key::Tab) || touch.DoubleTapped) {
        this->ui.Toggle();
    }
    #endif

    const wchar_t* text = kbd.CapturedText();
    ubyte ascii = 0;

    // alpha-numerics
    if (text[0] && (text[0] >= 32) && (text[0] < 127)) {
        ascii = (ubyte) text[0];
        // shift is inverted on KC
        if (islower(ascii)) {
            ascii = toupper(ascii);
        }
        else if (isupper(ascii)) {
            ascii = tolower(ascii);
        }
    }
    if ((ascii == 0) && (kbd.AnyKeyPressed())) {
        ascii = this->last_ascii;
    }
    this->last_ascii = ascii;

    // special keys
    struct toAscii {
        Key::Code key;
        ubyte ascii;
    };
    const static toAscii keyTable[] = {
        // FIXME:
        //  HOME, PAGE UP/DOWN, START/END of line, INSERT,
        { Key::Left, 0x08 },
        { Key::Right, 0x09 },
        { Key::Down, 0x0A },
        { Key::Up, 0x0B },
        { Key::Enter, 0x0D },
        { Key::BackSpace, 0x01 },
        { Key::Escape, 0x03 },
        { Key::F1, 0xF1 },
        { Key::F2, 0xF2 },
        { Key::F3, 0xF3 },
        { Key::F4, 0xF4 },
        { Key::F5, 0xF5 },
        { Key::F6, 0xF6 },
        { Key::F7, 0xF7 },
        { Key::F8, 0xF8 },
        { Key::F9, 0xF9 },
        { Key::F10, 0xFA },
        { Key::F11, 0xFB },
        { Key::F12, 0xFC },
    };
    for (const auto& key : keyTable) {
        if (kbd.KeyPressed(key.key)) {
            // special case: shift-backspace clears screen shift-escape is STP
            if (kbd.KeyPressed(Key::LeftShift) && (key.key == Key::BackSpace)) {
                ascii = 0x0C;
            }
            else if (kbd.KeyPressed(Key::LeftShift) && (key.key == Key::Escape)) {
                ascii = 0x13;
            }
            else {
                ascii = key.ascii;
            }
            break;
        }
    }
    this->emu.put_key(ascii);
}

} // namespace Oryol
<commit_msg>Minor fix in KC85 demo<commit_after>//------------------------------------------------------------------------------
//  Emu/KC85Emu.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "KC85Emu.h"
#include "Assets/Gfx/ShapeBuilder.h"
#include "Input/Input.h"
#include "emu_shaders.h"

using namespace yakc;

namespace Oryol {

//------------------------------------------------------------------------------
void
KC85Emu::Setup(const GfxSetup& gfxSetup) {

    // initialize the emulator as KC85/3
    this->emu.kc85.roms.add(kc85_roms::caos31, dump_caos31, sizeof(dump_caos31));
    this->emu.kc85.roms.add(kc85_roms::basic_rom, dump_basic_c0, sizeof(dump_basic_c0));
    this->emu.init();
    this->draw.Setup(gfxSetup, 5);
    this->audio.Setup(this->emu.board.clck);
    this->emu.kc85.audio.setup_callbacks(&this->audio, Audio::cb_sound, Audio::cb_volume, Audio::cb_stop);
    this->fileLoader.Setup(this->emu);

    // register modules
    this->emu.kc85.exp.register_none_module("NO MODULE", "Click to insert module!");
    this->emu.kc85.exp.register_ram_module(kc85_exp::m022_16kbyte, 0xC0, 0x4000, "nohelp");

    // setup a mesh and draw state to render a simple plane
    ShapeBuilder shapeBuilder;
    shapeBuilder.Layout
        .Add(VertexAttr::Position, VertexFormat::Float3)
        .Add(VertexAttr::TexCoord0, VertexFormat::Float2);
    shapeBuilder.Plane(1.0f, 1.0f, 1);
    this->drawState.Mesh[0] = Gfx::CreateResource(shapeBuilder.Build());

    Id shd = Gfx::CreateResource(KCShader::Setup());
    auto pip = PipelineSetup::FromLayoutAndShader(shapeBuilder.Layout, shd);
    pip.DepthStencilState.DepthWriteEnabled = true;
    pip.DepthStencilState.DepthCmpFunc = CompareFunc::LessEqual;
    pip.RasterizerState.SampleCount = gfxSetup.SampleCount;
    pip.BlendState.ColorFormat = gfxSetup.ColorFormat;
    pip.BlendState.DepthFormat = gfxSetup.DepthFormat;
    this->drawState.Pipeline = Gfx::CreateResource(pip);
}

//------------------------------------------------------------------------------
void
KC85Emu::Discard() {
    this->fileLoader.Discard();
    this->emu.poweroff();
    this->audio.Discard();
    this->draw.Discard();
}

//------------------------------------------------------------------------------
void
KC85Emu::Update(Duration frameTime) {
    this->handleInput();
    int micro_secs = (int) frameTime.AsMicroSeconds();
    const uint64_t cpu_min_ahead_cycles = (this->emu.board.clck.base_freq_khz*1000)/100;
    const uint64_t cpu_max_ahead_cycles = (this->emu.board.clck.base_freq_khz*1000)/25;
    const uint64_t audio_cycle_count = this->audio.GetProcessedCycles();
    const uint64_t min_cycle_count = audio_cycle_count + cpu_min_ahead_cycles;
    const uint64_t max_cycle_count = audio_cycle_count + cpu_max_ahead_cycles;
    this->emu.onframe(2, micro_secs, min_cycle_count, max_cycle_count);
    this->audio.Update(this->emu.board.clck);
}

//------------------------------------------------------------------------------
void
KC85Emu::TogglePower() {
    if (this->SwitchedOn()) {
        this->emu.poweroff();
    }
    else {
        this->emu.poweron(device::kc85_3, os_rom::caos_3_1);
        if (!this->emu.kc85.exp.slot_occupied(0x08)) {
            this->emu.kc85.exp.insert_module(0x08, kc85_exp::m022_16kbyte);
        }
        if (!this->emu.kc85.exp.slot_occupied(0x0C)) {
            this->emu.kc85.exp.insert_module(0x0C, kc85_exp::none);
        }
    }
}

//------------------------------------------------------------------------------
bool
KC85Emu::SwitchedOn() const {
    return this->emu.kc85.on;
}

//------------------------------------------------------------------------------
void
KC85Emu::Reset() {
    if (this->SwitchedOn()) {
        this->emu.kc85.reset();
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::StartGame(const char* name) {
    o_assert_dbg(name);
    if (this->SwitchedOn()) {
        for (const auto& item : this->fileLoader.Items) {
            if ((int(item.Compat) & int(this->emu.model)) && (item.Name == name)) {
                this->fileLoader.LoadAndStart(this->emu, item);
                break;
            }
        }
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::Render(const glm::mat4& mvp) {

    this->frameIndex++;
    if (this->emu.kc85.on) {
        // update the offscreen texture
        const int width = 320;
        const int height = 256;
        const Id tex = this->draw.irmTexture320x256;
        this->draw.texUpdateAttrs.Sizes[0][0] = width*height*4;
        Gfx::UpdateTexture(tex, this->emu.kc85.video.LinearBuffer, this->draw.texUpdateAttrs);

        KCShader::KCVSParams vsParams;
        vsParams.ModelViewProjection = mvp;
        this->drawState.FSTexture[KCTextures::IRM] = tex;
        Gfx::ApplyDrawState(this->drawState);
        Gfx::ApplyUniformBlock(vsParams);
        Gfx::Draw(0);
    }
    else {
        // switch KC on once after a little while
        if (this->frameIndex == 120) {
            if (!this->SwitchedOn()) {
                this->TogglePower();
            }
        }
    }
}

//------------------------------------------------------------------------------
void
KC85Emu::handleInput() {
    // FIXME: this should go into the yakc emulator
    const Keyboard& kbd = Input::Keyboard();

    #if YAKC_UI
    const Touchpad& touch = Input::Touchpad();
    // don't handle KC input if IMGUI has the keyboard focus
    if (ImGui::GetIO().WantCaptureKeyboard) {
        return;
    }
    // toggle UI?
    if (kbd.KeyDown(Key::Tab) || touch.DoubleTapped) {
        this->ui.Toggle();
    }
    #endif

    const wchar_t* text = kbd.CapturedText();
    ubyte ascii = 0;

    // alpha-numerics
    if (text[0] && (text[0] >= 32) && (text[0] < 127)) {
        ascii = (ubyte) text[0];
        // shift is inverted on KC
        if (islower(ascii)) {
            ascii = toupper(ascii);
        }
        else if (isupper(ascii)) {
            ascii = tolower(ascii);
        }
    }
    if ((ascii == 0) && (kbd.AnyKeyPressed())) {
        ascii = this->last_ascii;
    }
    this->last_ascii = ascii;

    // special keys
    struct toAscii {
        Key::Code key;
        ubyte ascii;
    };
    const static toAscii keyTable[] = {
        // FIXME:
        //  HOME, PAGE UP/DOWN, START/END of line, INSERT,
        { Key::Left, 0x08 },
        { Key::Right, 0x09 },
        { Key::Down, 0x0A },
        { Key::Up, 0x0B },
        { Key::Enter, 0x0D },
        { Key::BackSpace, 0x01 },
        { Key::Escape, 0x03 },
        { Key::F1, 0xF1 },
        { Key::F2, 0xF2 },
        { Key::F3, 0xF3 },
        { Key::F4, 0xF4 },
        { Key::F5, 0xF5 },
        { Key::F6, 0xF6 },
        { Key::F7, 0xF7 },
        { Key::F8, 0xF8 },
        { Key::F9, 0xF9 },
        { Key::F10, 0xFA },
        { Key::F11, 0xFB },
        { Key::F12, 0xFC },
    };
    for (const auto& key : keyTable) {
        if (kbd.KeyPressed(key.key)) {
            // special case: shift-backspace clears screen shift-escape is STP
            if (kbd.KeyPressed(Key::LeftShift) && (key.key == Key::BackSpace)) {
                ascii = 0x0C;
            }
            else if (kbd.KeyPressed(Key::LeftShift) && (key.key == Key::Escape)) {
                ascii = 0x13;
            }
            else {
                ascii = key.ascii;
            }
            break;
        }
    }
    this->emu.put_key(ascii);
}

} // namespace Oryol
<|endoftext|>


<commit_before>#include <catch.hpp>

#include <experimental/filesystem>

#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>

namespace fs = std::experimental::filesystem;

////////////////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("[PDDL parser] All the IPC domains are parsed without errors", "[PDDL parser]")
{
	const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};

	for (const auto &competitionDirectory : fs::directory_iterator("data/pddl-instances"))
	{
		if (!fs::is_directory(competitionDirectory))
			continue;

		for (const auto &domainDirectory : fs::directory_iterator(competitionDirectory.path() / "domains"))
		{
			if (!fs::is_directory(domainDirectory))
				continue;

			const auto domainFile = domainDirectory / "domain.pddl";

			pddl::Tokenizer tokenizer;
			tokenizer.read(domainFile);
			pddl::Context context(std::move(tokenizer), ignoreWarnings);

			CHECK_NOTHROW(pddl::parseDescription(context));
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("[PDDL parser] The first instance of every IPC domain is parsed without errors", "[PDDL parser]")
{
	const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};

	for (const auto &competitionDirectory : fs::directory_iterator("data/pddl-instances"))
	{
		if (!fs::is_directory(competitionDirectory))
			continue;

		for (const auto &domainDirectory : fs::directory_iterator(competitionDirectory.path() / "domains"))
		{
			if (!fs::is_directory(domainDirectory))
				continue;

			const auto domainFile = domainDirectory / "domain.pddl";
			const auto instanceFile = domainDirectory / "instances" / "instance-1.pddl";

			pddl::Tokenizer tokenizer;
			tokenizer.read(domainFile);
			tokenizer.read(instanceFile);
			pddl::Context context(std::move(tokenizer), ignoreWarnings);

			CHECK_NOTHROW(pddl::parseDescription(context));
		}
	}
}
<commit_msg>Corrected scope of acceptance tests.<commit_after>#include <catch.hpp>

#include <experimental/filesystem>

#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>

namespace fs = std::experimental::filesystem;

////////////////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("[PDDL parser acceptance] All the IPC domains are parsed without errors", "[PDDL parser acceptance]")
{
	const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};

	for (const auto &competitionDirectory : fs::directory_iterator("data/pddl-instances"))
	{
		if (!fs::is_directory(competitionDirectory))
			continue;

		for (const auto &domainDirectory : fs::directory_iterator(competitionDirectory.path() / "domains"))
		{
			if (!fs::is_directory(domainDirectory))
				continue;

			const auto domainFile = domainDirectory / "domain.pddl";

			pddl::Tokenizer tokenizer;
			tokenizer.read(domainFile);
			pddl::Context context(std::move(tokenizer), ignoreWarnings);

			CHECK_NOTHROW(pddl::parseDescription(context));
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

TEST_CASE("[PDDL parser acceptance] The first instance of every IPC domain is parsed without errors", "[PDDL parser acceptance]")
{
	const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};

	for (const auto &competitionDirectory : fs::directory_iterator("data/pddl-instances"))
	{
		if (!fs::is_directory(competitionDirectory))
			continue;

		for (const auto &domainDirectory : fs::directory_iterator(competitionDirectory.path() / "domains"))
		{
			if (!fs::is_directory(domainDirectory))
				continue;

			const auto domainFile = domainDirectory / "domain.pddl";
			const auto instanceFile = domainDirectory / "instances" / "instance-1.pddl";

			pddl::Tokenizer tokenizer;
			tokenizer.read(domainFile);
			tokenizer.read(instanceFile);
			pddl::Context context(std::move(tokenizer), ignoreWarnings);

			CHECK_NOTHROW(pddl::parseDescription(context));
		}
	}
}
<|endoftext|>


<commit_before>#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "ros/ros.h"
#include "std_msgs/Float64.h"
#include <fstream>

using namespace cv;
using namespace std;

Mat img,imgHSV,imgThresholded,imgSmooth,imgCanny,imgLines;
int lineCount=0;

//parameters in param file should be nearly the same as the commented values
//params for an orange strip
int LowH ; //0
int HighH ; //88

int LowS ; //0
int HighS ; //251

int LowV ; //0
int HighV ; //255

//params for smoothing image
int ksize; //21
int stype; //4  -> decides which type of filter has to be used

//params for bilateral filter in smoothcallback
int sigmaColor; //150
int sigmaSpace; //10

//params for hough line transform
int lineThresh; //60
int minLineLength; //70
int maxLineGap; //10
int houghThresh; //15

double rho=0.1;
double finalAngle;
double minDeviation=0.02;

bool vidCheck=false;

void StretchContrast()
{
	Mat ch[3];
	split(img,ch);
	normalize(ch[1],ch[1],255,0,NORM_MINMAX);
	normalize(ch[2],ch[2],255,0,NORM_MINMAX);
	normalize(ch[0],ch[0],255,0,NORM_MINMAX);
	merge(ch,3,img);
}

//called when large no of line detected

double computeMean(vector<double>& newAngles){
	double sum=0;
	for( size_t i = 0; i < newAngles.size(); i++ ){
    	sum=sum+newAngles[i];
    }
    return sum/newAngles.size();
}
//called when few lines are detected
//to remove errors due to any stray results
double computeMode(vector<double>& newAngles){
	double mode=newAngles[0];
	int freq=1;
	int tempFreq;
	double diff;
	for(int i=0;i<newAngles.size();i++){
		tempFreq=1;

		for(int j=i+1;j<newAngles.size();j++){
			diff=newAngles[j]-newAngles[i]>0.0? newAngles[j]-newAngles[i]:newAngles[i]-newAngles[j];
			if(diff<=minDeviation){
				tempFreq++;
				newAngles.erase(newAngles.begin()+j);
				j=j-1;
			}
		}

		if(tempFreq>=freq){
			mode=newAngles[i];
			freq=tempFreq;
		}
	}

	return mode;
}

//callback for smoothing image
//contains different filters "stype" decides which filter to use
void SmoothCallback(int ,void *){
	if(ksize%2==0) ksize=ksize+1;     //kernel size can not be even
	switch(stype){
		case 1:
			blur( img, imgSmooth, Size( ksize, ksize ) ); //ksize=17
			break;
		case 2:
			GaussianBlur( img, imgSmooth, Size( ksize, ksize ), 0, 0 );
			break;
		case 3:
			medianBlur( img, imgSmooth, ksize );
			break;
		case 4:
			bilateralFilter( img, imgSmooth, ksize, sigmaColor, sigmaSpace);
			break;
		default:
			cout<<"Please enter a smoothing type "<<endl;
	}

}

//contains canny edge detection and houghline transform

void callback(int ,void *){
	cvtColor(imgSmooth, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
	inRange(imgHSV, Scalar(LowH, LowS, LowV), Scalar(HighH, HighS, HighV), imgThresholded); //Threshold the image

	//opening (removes small objects from the foreground)
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
		dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );

	//closing (removes small holes from the foreground)
		dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );

	Canny(imgThresholded,imgCanny,50,150,3,true);//canny edge detection

	vector<Vec4i> lines;

	HoughLinesP(imgCanny, lines, 1, CV_PI/180, lineThresh, minLineLength, maxLineGap );

	img.copyTo(imgLines);
	imgLines=Scalar(0,0,0);
	vector<double> angles(lines.size());

	cout<<"No of lines : "<<lines.size()<<endl<<"Angles(radian): ";

	for( size_t i = 0; i < lines.size(); i++ )
	{
  		Vec4i l = lines[i];
  		line( imgLines, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,255,0), 1, CV_AA);
  		angles[i] = atan(double(l[2]-l[0])/(l[1]-l[3]));
  		cout<<angles[i]<<" ";
	}
	cout<<endl;
	imshow("LINES",imgLines+img);

    //if num of lines are large than one or two stray lines won't affect the mean much
    //but if they are small in number than mode has to be taken to save the error due to those stray line

    if(lines.size()>0 && lines.size()<10) finalAngle=computeMode(angles);
	else if(lines.size()>0) finalAngle=computeMean(angles);

    cout<<"Final Angle: "<<finalAngle<<endl<<endl;
}

int main( int argc, char** argv ) {
	if(argc<2){
		cout<<"please specify whether you want the display or not : "<<endl<<"USAGE: "<<endl<< "add argument 1 if you want the display, otherwise 0"<<endl;
		return 0;
	}

	if(*argv[1]=='1') vidCheck=true;

	//enter the path which contains params.txt
	FILE* fp=fopen("src/linefollowing/src/params.txt","r");
	fscanf(fp,"%d %d %d %d %d %d\n%d %d %d %d\n%d %d %d\n%d",&LowH,&HighH,&LowS,&HighS,&LowV,&HighV,&ksize,&stype,&sigmaSpace,&sigmaColor,&lineThresh,&minLineLength,&maxLineGap,&houghThresh);
	fclose(fp);

    //VideoCapture cap(1); //capture the video from webcam
    //VideoCapture cap("src/linefollowing/src/outputnorm.avi"); //path of the video for checking the code
    //VideoCapture cap("src/linefollowing/src/TestingLine.mp4");
    VideoCapture cap("src/linefollowing/src/test1.avi");

    if ( !cap.isOpened() )  // if not success, exit program
    {
         cout << "Cannot get the stream" << endl;
         return -1;
    }

    if (vidCheck) namedWindow("LINES",CV_WINDOW_AUTOSIZE);

    ros::init(argc, argv, "LineOdroidROS");
	ros::NodeHandle node;
 	ros::Publisher tracker_pub1 = node.advertise<std_msgs::Float64>("lineAngle", 1000);

 	ros::Publisher tracker_pub2 = node.advertise<std_msgs::Float64>("yaw", 1000);
    bool bSuccess;
    while(ros::ok()){

    	std_msgs::Float64 msg;
    	msg.data = -finalAngle*(180/3.14);

    	//cout<<lineCount<<endl;

		tracker_pub1.publish(msg);
		//tracker_pub2.publish(msg);
		ROS_INFO("%lf", msg.data);

		ros::spinOnce();

    	bSuccess = cap.read(img); // read a new frame from video

        if (!bSuccess) //if not success, break loop
        {
             cout << "Cannot read a frame from video stream" << endl;
             break;
        }

        StretchContrast();

        SmoothCallback(0,0); //for assigning imgSmooth initially
		callback(0,0); //for displaying the thresholded image initially

    	char key=cvWaitKey(30);
		if(key==27){
			break;
		}
    }

    destroyAllWindows();
}
<commit_msg>on topic /lineAngle<commit_after>#include <iostream>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "ros/ros.h"
#include "std_msgs/Float64.h"
#include <fstream>

using namespace cv;
using namespace std;

Mat img,imgHSV,imgThresholded,imgSmooth,imgCanny,imgLines;
int lineCount=0;

//parameters in param file should be nearly the same as the commented values
//params for an orange strip
int LowH ; //0
int HighH ; //88

int LowS ; //0
int HighS ; //251

int LowV ; //0
int HighV ; //255

//params for smoothing image
int ksize; //21
int stype; //4  -> decides which type of filter has to be used

//params for bilateral filter in smoothcallback
int sigmaColor; //150
int sigmaSpace; //10

//params for hough line transform
int lineThresh; //60
int minLineLength; //70
int maxLineGap; //10
int houghThresh; //15

double rho=0.1;
double finalAngle;
double minDeviation=0.02;

bool vidCheck=false;

void StretchContrast()
{
	Mat ch[3];
	split(img,ch);
	normalize(ch[1],ch[1],255,0,NORM_MINMAX);
	normalize(ch[2],ch[2],255,0,NORM_MINMAX);
	normalize(ch[0],ch[0],255,0,NORM_MINMAX);
	merge(ch,3,img);
}

//called when large no of line detected

double computeMean(vector<double>& newAngles){
	double sum=0;
	for( size_t i = 0; i < newAngles.size(); i++ ){
    	sum=sum+newAngles[i];
    }
    return sum/newAngles.size();
}
//called when few lines are detected
//to remove errors due to any stray results
double computeMode(vector<double>& newAngles){
	double mode=newAngles[0];
	int freq=1;
	int tempFreq;
	double diff;
	for(int i=0;i<newAngles.size();i++){
		tempFreq=1;

		for(int j=i+1;j<newAngles.size();j++){
			diff=newAngles[j]-newAngles[i]>0.0? newAngles[j]-newAngles[i]:newAngles[i]-newAngles[j];
			if(diff<=minDeviation){
				tempFreq++;
				newAngles.erase(newAngles.begin()+j);
				j=j-1;
			}
		}

		if(tempFreq>=freq){
			mode=newAngles[i];
			freq=tempFreq;
		}
	}

	return mode;
}

//callback for smoothing image
//contains different filters "stype" decides which filter to use
void SmoothCallback(int ,void *){
	if(ksize%2==0) ksize=ksize+1;     //kernel size can not be even
	switch(stype){
		case 1:
			blur( img, imgSmooth, Size( ksize, ksize ) ); //ksize=17
			break;
		case 2:
			GaussianBlur( img, imgSmooth, Size( ksize, ksize ), 0, 0 );
			break;
		case 3:
			medianBlur( img, imgSmooth, ksize );
			break;
		case 4:
			bilateralFilter( img, imgSmooth, ksize, sigmaColor, sigmaSpace);
			break;
		default:
			cout<<"Please enter a smoothing type "<<endl;
	}

}

//contains canny edge detection and houghline transform

void callback(int ,void *){
	cvtColor(imgSmooth, imgHSV, COLOR_BGR2HSV); //Convert the captured frame from BGR to HSV
	inRange(imgHSV, Scalar(LowH, LowS, LowV), Scalar(HighH, HighS, HighV), imgThresholded); //Threshold the image

	//opening (removes small objects from the foreground)
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
		dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );

	//closing (removes small holes from the foreground)
		dilate( imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );
		erode(imgThresholded, imgThresholded, getStructuringElement(MORPH_ELLIPSE, Size(5, 5)) );

	Canny(imgThresholded,imgCanny,50,150,3,true);//canny edge detection

	vector<Vec4i> lines;

	HoughLinesP(imgCanny, lines, 1, CV_PI/180, lineThresh, minLineLength, maxLineGap );

	img.copyTo(imgLines);
	imgLines=Scalar(0,0,0);
	vector<double> angles(lines.size());

	cout<<"No of lines : "<<lines.size()<<endl<<"Angles(radian): ";

	for( size_t i = 0; i < lines.size(); i++ )
	{
  		Vec4i l = lines[i];
  		line( imgLines, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,255,0), 1, CV_AA);
  		angles[i] = atan(double(l[2]-l[0])/(l[1]-l[3]));
  		cout<<angles[i]<<" ";
	}
	cout<<endl;
	imshow("LINES",imgLines+img);

    //if num of lines are large than one or two stray lines won't affect the mean much
    //but if they are small in number than mode has to be taken to save the error due to those stray line

    if(lines.size()>0 && lines.size()<10) finalAngle=computeMode(angles);
	else if(lines.size()>0) finalAngle=computeMean(angles);

    cout<<"Final Angle: "<<finalAngle<<endl<<endl;
}

int main( int argc, char** argv ) {
	if(argc<2){
		cout<<"please specify whether you want the display or not : "<<endl<<"USAGE: "<<endl<< "add argument 1 if you want the display, otherwise 0"<<endl;
		return 0;
	}

	if(*argv[1]=='1') vidCheck=true;

	//enter the path which contains params.txt
	FILE* fp=fopen("src/linefollowing/src/params.txt","r");
	fscanf(fp,"%d %d %d %d %d %d\n%d %d %d %d\n%d %d %d\n%d",&LowH,&HighH,&LowS,&HighS,&LowV,&HighV,&ksize,&stype,&sigmaSpace,&sigmaColor,&lineThresh,&minLineLength,&maxLineGap,&houghThresh);
	fclose(fp);

    //VideoCapture cap(1); //capture the video from webcam
    //VideoCapture cap("src/linefollowing/src/outputnorm.avi"); //path of the video for checking the code
    //VideoCapture cap("src/linefollowing/src/TestingLine.mp4");
    VideoCapture cap("src/linefollowing/src/test1.avi");

    if ( !cap.isOpened() )  // if not success, exit program
    {
         cout << "Cannot get the stream" << endl;
         return -1;
    }

    if (vidCheck) namedWindow("LINES",CV_WINDOW_AUTOSIZE);

    ros::init(argc, argv, "LineOdroidROS");
	ros::NodeHandle node;
 	ros::Publisher tracker_pub1 = node.advertise<std_msgs::Float64>("lineAngle", 1000);
    bool bSuccess;
    while(ros::ok()){

    	std_msgs::Float64 msg;
    	msg.data = -finalAngle*(180/3.14);

    	//cout<<lineCount<<endl;

		tracker_pub1.publish(msg);

		ROS_INFO("%lf", msg.data);

		ros::spinOnce();

    	bSuccess = cap.read(img); // read a new frame from video

        if (!bSuccess) //if not success, break loop
        {
             cout << "Cannot read a frame from video stream" << endl;
             break;
        }

        StretchContrast();

        SmoothCallback(0,0); //for assigning imgSmooth initially
		callback(0,0); //for displaying the thresholded image initially

    	char key=cvWaitKey(30);
		if(key==27){
			break;
		}
    }

    destroyAllWindows();
}
<|endoftext|>


<commit_before>// Program.cpp

#include "stdafx.h"
#include "Program.h"
#include "PythonStuff.h"
#include "tinyxml/tinyxml.h"
#include "ProgramCanvas.h"
#include "NCCode.h"
#include "interface/MarkedObject.h"
#include "interface/PropertyString.h"
#include "interface/PropertyChoice.h"
#include "interface/Tool.h"
#include "Profile.h"
#include "Pocket.h"
#include "ZigZag.h"
#include "Adaptive.h"
#include "Op.h"
#include "CNCConfig.h"

bool COperations::CanAdd(HeeksObj* object)
{
	return object->GetType() == ProfileType || object->GetType() == PocketType || object->GetType() == ZigZagType || object->GetType() == AdaptiveType;
}

void COperations::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Operations" );
	root->LinkEndChild( element );
	WriteBaseXML(element);
}

//static
HeeksObj* COperations::ReadFromXMLElement(TiXmlElement* pElem)
{
	COperations* new_object = new COperations;
	new_object->ReadBaseXML(pElem);
	return new_object;
}

static COperations* object_for_tools = NULL;

class SetAllActive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Active");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = true;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setactive");}
};

static SetAllActive set_all_active;

class SetAllInactive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Inactive");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = false;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setinactive");}
};

static SetAllInactive set_all_inactive;

void COperations::GetTools(std::list<Tool*>* t_list, const wxPoint* p)
{
	object_for_tools = this;
	t_list->push_back(&set_all_active);
	t_list->push_back(&set_all_inactive);

	ObjList::GetTools(t_list, p);
}

CProgram::CProgram():m_nc_code(NULL), m_operations(NULL), m_script_edited(false)
{
	CNCConfig config;
	config.Read(_T("ProgramMachine"), &m_machine, _T("nc.iso"));
#ifdef WIN32
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("test.tap"));
#else
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("/tmp/test.tap"));
#endif
	config.Read(_T("ProgramUnits"), &m_units, 1.0);
}

HeeksObj *CProgram::MakeACopy(void)const
{
	return new CProgram(*this);
}

void CProgram::CopyFrom(const HeeksObj* object)
{
	operator=(*((CProgram*)object));
}

static void on_set_machine(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_machine = value;
	CNCConfig config;
	config.Write(_T("ProgramMachine"), ((CProgram*)object)->m_machine);
}

static void on_set_output_file(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_output_file = value;
	CNCConfig config;
	config.Write(_T("ProgramOutputFile"), ((CProgram*)object)->m_output_file);
}

static void on_set_units(int value, HeeksObj* object)
{
	((CProgram*)object)->m_units = (value == 0) ? 1.0:25.4;
	CNCConfig config;
	config.Write(_T("ProgramUnits"), ((CProgram*)object)->m_units);

	// also change HeeksCAD's view units automatically
	heeksCAD->SetViewUnits(((CProgram*)object)->m_units, true);
}

void CProgram::GetProperties(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("machine"), m_machine, this, on_set_machine));
	list->push_back(new PropertyString(_("output file"), m_output_file, this, on_set_output_file));
	{
		std::list< wxString > choices;
		choices.push_back ( wxString ( _("mm") ) );
		choices.push_back ( wxString ( _("inch") ) );
		int choice = 0;
		if(m_units > 25.0)choice = 1;
		list->push_back ( new PropertyChoice ( _("units"),  choices, choice, this, on_set_units ) );
	}
	HeeksObj::GetProperties(list);
}

bool CProgram::CanAdd(HeeksObj* object)
{
	return object->GetType() == NCCodeType || object->GetType() == OperationsType;
}

bool CProgram::CanAddTo(HeeksObj* owner)
{
	return owner->GetType() == DocumentType;
}

void CProgram::SetClickMarkPoint(MarkedObject* marked_object, const double* ray_start, const double* ray_direction)
{
	if(marked_object->m_map.size() > 0)
	{
		MarkedObject* sub_marked_object = marked_object->m_map.begin()->second;
		if(sub_marked_object)
		{
			HeeksObj* object = sub_marked_object->m_map.begin()->first;
			if(object && object->GetType() == NCCodeType)
			{
				((CNCCode*)object)->SetClickMarkPoint(sub_marked_object, ray_start, ray_direction);
			}
		}
	}
}

void CProgram::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Program" );
	root->LinkEndChild( element );
	element->SetAttribute("machine", Ttc(m_machine.c_str()));
	element->SetAttribute("output_file", Ttc(m_output_file.c_str()));
	element->SetAttribute("program", Ttc(theApp.m_program_canvas->m_textCtrl->GetValue()));
	element->SetDoubleAttribute("units", m_units);

	WriteBaseXML(element);
}

bool CProgram::Add(HeeksObj* object, HeeksObj* prev_object)
{
	if(object->GetType() == NCCodeType)m_nc_code = (CNCCode*)object;
	if(object->GetType() == OperationsType)m_operations = (COperations*)object;
	return ObjList::Add(object, prev_object);
}

void CProgram::Remove(HeeksObj* object)
{
	 // these shouldn't happen, though
	if(object == m_nc_code)m_nc_code = NULL;
	else if(object == m_operations)m_operations = NULL;

	ObjList::Remove(object);
}

// static member function
HeeksObj* CProgram::ReadFromXMLElement(TiXmlElement* pElem)
{
	CProgram* new_object = new CProgram;

	// get the attributes
	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "machine"){new_object->m_machine.assign(Ctt(a->Value()));}
		else if(name == "output_file"){new_object->m_output_file.assign(Ctt(a->Value()));}
		else if(name == "program"){theApp.m_program_canvas->m_textCtrl->SetValue(Ctt(a->Value()));}
		else if(name == "units"){new_object->m_units = a->DoubleValue();}
	}

	new_object->ReadBaseXML(pElem);
	theApp.m_program = new_object;

	return new_object;
}

void CProgram::RewritePythonProgram()
{
	theApp.m_program_canvas->m_textCtrl->Clear();
	CZigZag::number_for_stl_file = 1;
	CAdaptive::number_for_stl_file = 1;

	bool profile_op_exists = false;
	bool pocket_op_exists = false;
	bool zigzag_op_exists = false;
	bool adaptive_op_exists = false;
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		if(object->GetType() == ProfileType)
		{
			if(((CProfile*)object)->m_active)profile_op_exists = true;
		}
		else if(object->GetType() == PocketType)
		{
			if(((CPocket*)object)->m_active)pocket_op_exists = true;
		}
		else if(object->GetType() == ZigZagType)
		{
			if(((CZigZag*)object)->m_active)zigzag_op_exists = true;
		}
		else if(object->GetType() == AdaptiveType)
		{
			if(((CAdaptive*)object)->m_active)adaptive_op_exists = true;
		}
	}

	// add standard stuff at the top
	//hackhack, make it work on unix with FHS
#ifndef WIN32
	theApp.m_program_canvas->AppendText(_T("import sys\n"));
	theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'/usr/lib/heekscnc/')\n"));
#endif
	// kurve related things
	if(profile_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import kurve\n"));
		theApp.m_program_canvas->AppendText(_T("import kurve_funcs\n"));
	}

	// area related things
	if(pocket_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import area\n"));
		if(fabs(m_units - 1.0) > 0.00000001)
		{
			theApp.m_program_canvas->AppendText(_T("area.set_units("));
			theApp.m_program_canvas->AppendText(m_units);
			theApp.m_program_canvas->AppendText(_T(")\n"));
		}
		theApp.m_program_canvas->AppendText(_T("import area_funcs\n"));
	}

	// pycam stuff
	if(zigzag_op_exists)
	{
#ifdef WIN32
		theApp.m_program_canvas->AppendText(_T("import sys\n"));
#endif
		theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'PyCam/trunk')\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Geometry import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.SphericalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.CylindricalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.ToroidalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Importers.STLImporter import ImportModel\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.PathGenerators.DropCutter import DropCutter\n"));
		theApp.m_program_canvas->AppendText(_T("from PyCamToHeeks import HeeksCNCExporter\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// actp
	if(adaptive_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import actp_funcs\n"));
		theApp.m_program_canvas->AppendText(_T("import actp\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// machine general stuff
	theApp.m_program_canvas->AppendText(_T("from nc.nc import *\n"));

	// specific machine
	theApp.m_program_canvas->AppendText(_T("import ") + m_machine + _T("\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// output file
	theApp.m_program_canvas->AppendText(_T("output('") + m_output_file + _T("')\n"));

	// begin program
	//theApp.m_program_canvas->AppendText(_T("program_begin(123, 'Test program')\n"));
	theApp.m_program_canvas->AppendText(_T("absolute()\n"));
	if(m_units > 25.0)
	{
		theApp.m_program_canvas->AppendText(_T("imperial()\n"));
	}
	else
	{
		theApp.m_program_canvas->AppendText(_T("metric()\n"));
	}
	theApp.m_program_canvas->AppendText(_T("set_plane(0)\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// write the operations
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		switch(object->GetType())
		{
		case ProfileType:
			if(((CProfile*)object)->m_active)((CProfile*)object)->AppendTextToProgram();
			break;
		case PocketType:
			if(((CPocket*)object)->m_active)((CPocket*)object)->AppendTextToProgram();
			break;
		case ZigZagType:
			if(((CZigZag*)object)->m_active)((CZigZag*)object)->AppendTextToProgram();
			break;
		case AdaptiveType:
			if(((CAdaptive*)object)->m_active)((CAdaptive*)object)->AppendTextToProgram();
			break;
		}
	}
}

ProgramUserType CProgram::GetUserType()
{
	if(m_nc_code->m_user_edited)return ProgramUserTypeNC;
	if(m_script_edited)return ProgramUserTypeScript;
	if(m_operations->GetFirstChild())return ProgramUserTypeTree;
	return ProgramUserTypeUnkown;
}

void CProgram::UpdateFromUserType()
{
#if 0
	switch(GetUserType())
	{
	case ProgramUserTypeUnkown:

	case tree:
   Enable "Operations" icon in tree
     editing the tree, recreates the python script
   Read only "Program" window
     pressing "Post-process" creates the NC code ( and backplots it )
   Read only "Output" window
   Disable all buttons on "Output" window

	}
#endif
}
<commit_msg>always write area.set_units<commit_after>// Program.cpp

#include "stdafx.h"
#include "Program.h"
#include "PythonStuff.h"
#include "tinyxml/tinyxml.h"
#include "ProgramCanvas.h"
#include "NCCode.h"
#include "interface/MarkedObject.h"
#include "interface/PropertyString.h"
#include "interface/PropertyChoice.h"
#include "interface/Tool.h"
#include "Profile.h"
#include "Pocket.h"
#include "ZigZag.h"
#include "Adaptive.h"
#include "Op.h"
#include "CNCConfig.h"

bool COperations::CanAdd(HeeksObj* object)
{
	return object->GetType() == ProfileType || object->GetType() == PocketType || object->GetType() == ZigZagType || object->GetType() == AdaptiveType;
}

void COperations::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Operations" );
	root->LinkEndChild( element );
	WriteBaseXML(element);
}

//static
HeeksObj* COperations::ReadFromXMLElement(TiXmlElement* pElem)
{
	COperations* new_object = new COperations;
	new_object->ReadBaseXML(pElem);
	return new_object;
}

static COperations* object_for_tools = NULL;

class SetAllActive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Active");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = true;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setactive");}
};

static SetAllActive set_all_active;

class SetAllInactive: public Tool{
	// Tool's virtual functions
	const wxChar* GetTitle(){return _("Set All Operations Inactive");}
	void Run()
	{
		for(HeeksObj* object = object_for_tools->GetFirstChild(); object; object = object_for_tools->GetNextChild())
		{
			if(COp::IsAnOperation(object->GetType()))
			{
				((COp*)object)->m_active = false;
				heeksCAD->WasModified(object);
			}
		}
	}
	wxString BitmapPath(){ return _T("setinactive");}
};

static SetAllInactive set_all_inactive;

void COperations::GetTools(std::list<Tool*>* t_list, const wxPoint* p)
{
	object_for_tools = this;
	t_list->push_back(&set_all_active);
	t_list->push_back(&set_all_inactive);

	ObjList::GetTools(t_list, p);
}

CProgram::CProgram():m_nc_code(NULL), m_operations(NULL), m_script_edited(false)
{
	CNCConfig config;
	config.Read(_T("ProgramMachine"), &m_machine, _T("nc.iso"));
#ifdef WIN32
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("test.tap"));
#else
	config.Read(_T("ProgramOutputFile"), &m_output_file, _T("/tmp/test.tap"));
#endif
	config.Read(_T("ProgramUnits"), &m_units, 1.0);
}

HeeksObj *CProgram::MakeACopy(void)const
{
	return new CProgram(*this);
}

void CProgram::CopyFrom(const HeeksObj* object)
{
	operator=(*((CProgram*)object));
}

static void on_set_machine(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_machine = value;
	CNCConfig config;
	config.Write(_T("ProgramMachine"), ((CProgram*)object)->m_machine);
}

static void on_set_output_file(const wxChar* value, HeeksObj* object)
{
	((CProgram*)object)->m_output_file = value;
	CNCConfig config;
	config.Write(_T("ProgramOutputFile"), ((CProgram*)object)->m_output_file);
}

static void on_set_units(int value, HeeksObj* object)
{
	((CProgram*)object)->m_units = (value == 0) ? 1.0:25.4;
	CNCConfig config;
	config.Write(_T("ProgramUnits"), ((CProgram*)object)->m_units);

	// also change HeeksCAD's view units automatically
	heeksCAD->SetViewUnits(((CProgram*)object)->m_units, true);
}

void CProgram::GetProperties(std::list<Property *> *list)
{
	list->push_back(new PropertyString(_("machine"), m_machine, this, on_set_machine));
	list->push_back(new PropertyString(_("output file"), m_output_file, this, on_set_output_file));
	{
		std::list< wxString > choices;
		choices.push_back ( wxString ( _("mm") ) );
		choices.push_back ( wxString ( _("inch") ) );
		int choice = 0;
		if(m_units > 25.0)choice = 1;
		list->push_back ( new PropertyChoice ( _("units"),  choices, choice, this, on_set_units ) );
	}
	HeeksObj::GetProperties(list);
}

bool CProgram::CanAdd(HeeksObj* object)
{
	return object->GetType() == NCCodeType || object->GetType() == OperationsType;
}

bool CProgram::CanAddTo(HeeksObj* owner)
{
	return owner->GetType() == DocumentType;
}

void CProgram::SetClickMarkPoint(MarkedObject* marked_object, const double* ray_start, const double* ray_direction)
{
	if(marked_object->m_map.size() > 0)
	{
		MarkedObject* sub_marked_object = marked_object->m_map.begin()->second;
		if(sub_marked_object)
		{
			HeeksObj* object = sub_marked_object->m_map.begin()->first;
			if(object && object->GetType() == NCCodeType)
			{
				((CNCCode*)object)->SetClickMarkPoint(sub_marked_object, ray_start, ray_direction);
			}
		}
	}
}

void CProgram::WriteXML(TiXmlNode *root)
{
	TiXmlElement * element;
	element = new TiXmlElement( "Program" );
	root->LinkEndChild( element );
	element->SetAttribute("machine", Ttc(m_machine.c_str()));
	element->SetAttribute("output_file", Ttc(m_output_file.c_str()));
	element->SetAttribute("program", Ttc(theApp.m_program_canvas->m_textCtrl->GetValue()));
	element->SetDoubleAttribute("units", m_units);

	WriteBaseXML(element);
}

bool CProgram::Add(HeeksObj* object, HeeksObj* prev_object)
{
	if(object->GetType() == NCCodeType)m_nc_code = (CNCCode*)object;
	if(object->GetType() == OperationsType)m_operations = (COperations*)object;
	return ObjList::Add(object, prev_object);
}

void CProgram::Remove(HeeksObj* object)
{
	 // these shouldn't happen, though
	if(object == m_nc_code)m_nc_code = NULL;
	else if(object == m_operations)m_operations = NULL;

	ObjList::Remove(object);
}

// static member function
HeeksObj* CProgram::ReadFromXMLElement(TiXmlElement* pElem)
{
	CProgram* new_object = new CProgram;

	// get the attributes
	for(TiXmlAttribute* a = pElem->FirstAttribute(); a; a = a->Next())
	{
		std::string name(a->Name());
		if(name == "machine"){new_object->m_machine.assign(Ctt(a->Value()));}
		else if(name == "output_file"){new_object->m_output_file.assign(Ctt(a->Value()));}
		else if(name == "program"){theApp.m_program_canvas->m_textCtrl->SetValue(Ctt(a->Value()));}
		else if(name == "units"){new_object->m_units = a->DoubleValue();}
	}

	new_object->ReadBaseXML(pElem);
	theApp.m_program = new_object;

	return new_object;
}

void CProgram::RewritePythonProgram()
{
	theApp.m_program_canvas->m_textCtrl->Clear();
	CZigZag::number_for_stl_file = 1;
	CAdaptive::number_for_stl_file = 1;

	bool profile_op_exists = false;
	bool pocket_op_exists = false;
	bool zigzag_op_exists = false;
	bool adaptive_op_exists = false;
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		if(object->GetType() == ProfileType)
		{
			if(((CProfile*)object)->m_active)profile_op_exists = true;
		}
		else if(object->GetType() == PocketType)
		{
			if(((CPocket*)object)->m_active)pocket_op_exists = true;
		}
		else if(object->GetType() == ZigZagType)
		{
			if(((CZigZag*)object)->m_active)zigzag_op_exists = true;
		}
		else if(object->GetType() == AdaptiveType)
		{
			if(((CAdaptive*)object)->m_active)adaptive_op_exists = true;
		}
	}

	// add standard stuff at the top
	//hackhack, make it work on unix with FHS
#ifndef WIN32
	theApp.m_program_canvas->AppendText(_T("import sys\n"));
	theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'/usr/lib/heekscnc/')\n"));
#endif
	// kurve related things
	if(profile_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import kurve\n"));
		theApp.m_program_canvas->AppendText(_T("import kurve_funcs\n"));
	}

	// area related things
	if(pocket_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import area\n"));
		theApp.m_program_canvas->AppendText(_T("area.set_units("));
		theApp.m_program_canvas->AppendText(m_units);
		theApp.m_program_canvas->AppendText(_T(")\n"));
		theApp.m_program_canvas->AppendText(_T("import area_funcs\n"));
	}

	// pycam stuff
	if(zigzag_op_exists)
	{
#ifdef WIN32
		theApp.m_program_canvas->AppendText(_T("import sys\n"));
#endif
		theApp.m_program_canvas->AppendText(_T("sys.path.insert(0,'PyCam/trunk')\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Geometry import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.SphericalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.CylindricalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Cutters.ToroidalCutter import *\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.Importers.STLImporter import ImportModel\n"));
		theApp.m_program_canvas->AppendText(_T("from pycam.PathGenerators.DropCutter import DropCutter\n"));
		theApp.m_program_canvas->AppendText(_T("from PyCamToHeeks import HeeksCNCExporter\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// actp
	if(adaptive_op_exists)
	{
		theApp.m_program_canvas->AppendText(_T("import actp_funcs\n"));
		theApp.m_program_canvas->AppendText(_T("import actp\n"));
		theApp.m_program_canvas->AppendText(_T("\n"));
	}

	// machine general stuff
	theApp.m_program_canvas->AppendText(_T("from nc.nc import *\n"));

	// specific machine
	theApp.m_program_canvas->AppendText(_T("import ") + m_machine + _T("\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// output file
	theApp.m_program_canvas->AppendText(_T("output('") + m_output_file + _T("')\n"));

	// begin program
	//theApp.m_program_canvas->AppendText(_T("program_begin(123, 'Test program')\n"));
	theApp.m_program_canvas->AppendText(_T("absolute()\n"));
	if(m_units > 25.0)
	{
		theApp.m_program_canvas->AppendText(_T("imperial()\n"));
	}
	else
	{
		theApp.m_program_canvas->AppendText(_T("metric()\n"));
	}
	theApp.m_program_canvas->AppendText(_T("set_plane(0)\n"));
	theApp.m_program_canvas->AppendText(_T("\n"));

	// write the operations
	for(HeeksObj* object = m_operations->GetFirstChild(); object; object = m_operations->GetNextChild())
	{
		switch(object->GetType())
		{
		case ProfileType:
			if(((CProfile*)object)->m_active)((CProfile*)object)->AppendTextToProgram();
			break;
		case PocketType:
			if(((CPocket*)object)->m_active)((CPocket*)object)->AppendTextToProgram();
			break;
		case ZigZagType:
			if(((CZigZag*)object)->m_active)((CZigZag*)object)->AppendTextToProgram();
			break;
		case AdaptiveType:
			if(((CAdaptive*)object)->m_active)((CAdaptive*)object)->AppendTextToProgram();
			break;
		}
	}
}

ProgramUserType CProgram::GetUserType()
{
	if(m_nc_code->m_user_edited)return ProgramUserTypeNC;
	if(m_script_edited)return ProgramUserTypeScript;
	if(m_operations->GetFirstChild())return ProgramUserTypeTree;
	return ProgramUserTypeUnkown;
}

void CProgram::UpdateFromUserType()
{
#if 0
	switch(GetUserType())
	{
	case ProgramUserTypeUnkown:

	case tree:
   Enable "Operations" icon in tree
     editing the tree, recreates the python script
   Read only "Program" window
     pressing "Post-process" creates the NC code ( and backplots it )
   Read only "Output" window
   Disable all buttons on "Output" window

	}
#endif
}
<|endoftext|>


<commit_before>#ifndef LOGGER_HPP
#define LOGGER_HPP

#include <fstream>
#include <string>

namespace swift
{
	class Logger
	{
		public:
			enum class LogType
			{
			    ERROR,
			    WARNING,
				DEBUG,
			    INFO
			};

			explicit Logger(const std::string& header, const std::string& logFile = "./data/swift.log")
			{
				warnings = 0;
				errors = 0;

				fout.open(logFile);

				// Write the first lines
				if(fout.is_open())
				{
					fout << header << std::endl << std::endl;
				}
			}

			~Logger()
			{
				if(fout.is_open())
				{
					fout << std::endl << std::endl;

					// Report number of errors and warnings
					fout << warnings << " warnings" << std::endl;
					fout << errors << " errors" << std::endl;

					fout.close();
				}
			}

			// Make it Non Copyable
			Logger(const Logger &) = delete;
			Logger& operator =(const Logger &) = delete;

			Logger& operator <<(const LogType type)
			{
				switch(type)
				{
					case LogType::ERROR:
						fout << "[ERROR]: ";
						errors++;
						break;

					case LogType::WARNING:
						fout << "[WARNING]: ";
						warnings++;
						break;

					case LogType::DEBUG:
						fout << "[DEBUG]: ";
						break;

					default:
						fout << "[INFO]: ";
						break;
				}

				return *this;
			}

			Logger& operator <<(char c)
			{
				fout << c;
				return *this;
			}

			Logger& operator <<(const std::string& text)
			{
				fout << text;
				return *this;
			}

		private:
			std::ofstream fout;

			unsigned warnings;
			unsigned errors;
	};

	//Logger log("Swift Alpha");
}

#endif // LOGGER_HPP
<commit_msg>Removed commented-out code<commit_after>#ifndef LOGGER_HPP
#define LOGGER_HPP

#include <fstream>
#include <string>

namespace swift
{
	class Logger
	{
		public:
			enum class LogType
			{
			    ERROR,
			    WARNING,
				DEBUG,
			    INFO
			};

			explicit Logger(const std::string& header, const std::string& logFile = "./data/swift.log")
			{
				warnings = 0;
				errors = 0;

				fout.open(logFile);

				// Write the first lines
				if(fout.is_open())
				{
					fout << header << std::endl << std::endl;
				}
			}

			~Logger()
			{
				if(fout.is_open())
				{
					fout << std::endl << std::endl;

					// Report number of errors and warnings
					fout << warnings << " warnings" << std::endl;
					fout << errors << " errors" << std::endl;

					fout.close();
				}
			}

			// Make it Non Copyable
			Logger(const Logger &) = delete;
			Logger& operator =(const Logger &) = delete;

			Logger& operator <<(const LogType type)
			{
				switch(type)
				{
					case LogType::ERROR:
						fout << "[ERROR]: ";
						errors++;
						break;

					case LogType::WARNING:
						fout << "[WARNING]: ";
						warnings++;
						break;

					case LogType::DEBUG:
						fout << "[DEBUG]: ";
						break;

					default:
						fout << "[INFO]: ";
						break;
				}

				return *this;
			}

			Logger& operator <<(char c)
			{
				fout << c;
				return *this;
			}

			Logger& operator <<(const std::string& text)
			{
				fout << text;
				return *this;
			}

		private:
			std::ofstream fout;

			unsigned warnings;
			unsigned errors;
	};
}

#endif // LOGGER_HPP
<|endoftext|>


<commit_before>/*
 *  VHDL code generation for LPM devices.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cassert>

/*
 * Return the base of a part select.
 */
static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_expr *off;
   ivl_nexus_t base = ivl_lpm_data(lpm, 1);
   if (base != NULL)
      off = nexus_to_var_ref(scope, base);
   else
      off = new vhdl_const_int(ivl_lpm_base(lpm));

   // Array indexes must be integers
   vhdl_type integer(VHDL_TYPE_INTEGER);
   return off->cast(&integer);
}

vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0));
   if (NULL == out) {
      vhdl_type *type =
         vhdl_type::type_for(ivl_lpm_width(lpm),
                             ivl_lpm_signed(lpm) != 0);
      string name("LPM");
      name += ivl_lpm_basename(lpm);
      name += "_Out";

      if (!scope->have_declared(name)) {
         scope->add_decl
            (new vhdl_signal_decl(name.c_str(), new vhdl_type(*type)));
      }

      out = new vhdl_var_ref(name.c_str(), type);
   }

   if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) {
      vhdl_expr *off = part_select_base(scope, lpm);
      assert(off);

      out->set_slice(off, ivl_lpm_width(lpm) - 1);
   }

   return out;
}

static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_type *result_type =
      vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
   vhdl_binop_expr *expr =
      new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);

   for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) {
      vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == e)
         return NULL;

      expr->add_expr(e);
   }

   return expr;
}

static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op)
{
   vhdl_type *result_type =
      vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
   vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);

   for (int i = 0; i < 2; i++) {
      vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == e)
         return NULL;

      expr->add_expr(e);
   }

   if (op == VHDL_BINOP_MULT) {
      // Need to resize the output to the desired size,
      // as this does not happen automatically in VHDL

      unsigned out_width = ivl_lpm_width(lpm);
      vhdl_fcall *resize =
         new vhdl_fcall("Resize", vhdl_type::nsigned(out_width));
      resize->add_expr(expr);
      resize->add_expr(new vhdl_const_int(out_width));

      return resize;
   }
   else
      return expr;
}

static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_var_ref *selfrom = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (NULL == selfrom)
      return NULL;

   vhdl_expr *off = part_select_base(scope, lpm);;
   if (NULL == off)
      return NULL;

   selfrom->set_slice(off, ivl_lpm_width(lpm) - 1);
   return selfrom;
}

static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   return nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
}

static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_fcall *fcall = new vhdl_fcall(ivl_lpm_basename(lpm), NULL);

   for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
      vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == ref)
         return NULL;

      fcall->add_expr(ref);
   }

   return fcall;
}

static vhdl_expr *reduction_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
                                     const char *rfunc, bool invert)
{
   vhdl_fcall *fcall = new vhdl_fcall(rfunc, vhdl_type::std_logic());

   vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (NULL == ref)
      return NULL;

   fcall->add_expr(ref);

   if (invert)
      return new vhdl_unaryop_expr
         (VHDL_UNARYOP_NOT, fcall, vhdl_type::std_logic());
   else
      return fcall;
}

static vhdl_expr *sign_extend_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_expr *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (ref)
      return ref->resize(ivl_lpm_width(lpm));
   else
      return NULL;
}

static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   ivl_signal_t array = ivl_lpm_array(lpm);
   if (!seen_signal_before(array))
      return NULL;

   const char *renamed = get_renamed_signal(array).c_str();

   vhdl_decl *adecl = scope->get_decl(renamed);
   assert(adecl);

   vhdl_type *atype = new vhdl_type(*adecl->get_type());

   vhdl_expr *select = nexus_to_var_ref(scope, ivl_lpm_select(lpm));
   if (NULL == select)
      return NULL;

   vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
   ref->set_slice(select);

   return ref;
}

static vhdl_expr *shift_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
                                    vhdl_binop_t shift_op)
{
   vhdl_expr *lhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   vhdl_expr *rhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 1));
   if (!lhs || !rhs)
      return NULL;

   // The RHS must be an integer
   vhdl_type integer(VHDL_TYPE_INTEGER);
   vhdl_expr *r_cast = rhs->cast(&integer);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, shift_op, r_cast, rtype);
}

static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   switch (ivl_lpm_type(lpm)) {
   case IVL_LPM_ADD:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_ADD);
   case IVL_LPM_SUB:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_SUB);
   case IVL_LPM_MULT:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MULT);
   case IVL_LPM_CONCAT:
      return concat_lpm_to_expr(scope, lpm);
   case IVL_LPM_PART_VP:
      return part_select_vp_lpm_to_expr(scope, lpm);
   case IVL_LPM_PART_PV:
      return part_select_pv_lpm_to_expr(scope, lpm);
   case IVL_LPM_UFUNC:
      return ufunc_lpm_to_expr(scope, lpm);
   case IVL_LPM_RE_AND:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", false);
   case IVL_LPM_RE_NAND:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", true);
   case IVL_LPM_RE_NOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_OR", true);
   case IVL_LPM_RE_OR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_OR", false);
   case IVL_LPM_RE_XOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_XOR", false);
   case IVL_LPM_RE_XNOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_XNOR", false);
   case IVL_LPM_SIGN_EXT:
      return sign_extend_lpm_to_expr(scope, lpm);
   case IVL_LPM_ARRAY:
      return array_lpm_to_expr(scope, lpm);
   case IVL_LPM_SHIFTL:
      return shift_lpm_to_expr(scope, lpm, VHDL_BINOP_SL);
   case IVL_LPM_SHIFTR:
      return shift_lpm_to_expr(scope, lpm, VHDL_BINOP_SR);
   default:
      error("Unsupported LPM type: %d", ivl_lpm_type(lpm));
      return NULL;
   }
}

int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
{
   vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm);
   if (NULL == f)
      return 0;

   vhdl_var_ref *out = lpm_output(arch->get_scope(), lpm);
   arch->add_stmt(new vhdl_cassign_stmt(out, f));

   return 0;
}

<commit_msg>Add IVL_LPM_CMP_EEQ support<commit_after>/*
 *  VHDL code generation for LPM devices.
 *
 *  Copyright (C) 2008  Nick Gasson (nick@nickg.me.uk)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "vhdl_target.h"

#include <iostream>
#include <cassert>

/*
 * Return the base of a part select.
 */
static vhdl_expr *part_select_base(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_expr *off;
   ivl_nexus_t base = ivl_lpm_data(lpm, 1);
   if (base != NULL)
      off = nexus_to_var_ref(scope, base);
   else
      off = new vhdl_const_int(ivl_lpm_base(lpm));

   // Array indexes must be integers
   vhdl_type integer(VHDL_TYPE_INTEGER);
   return off->cast(&integer);
}

vhdl_var_ref *lpm_output(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_var_ref *out = nexus_to_var_ref(scope, ivl_lpm_q(lpm, 0));
   if (NULL == out) {
      vhdl_type *type =
         vhdl_type::type_for(ivl_lpm_width(lpm),
                             ivl_lpm_signed(lpm) != 0);
      string name("LPM");
      name += ivl_lpm_basename(lpm);
      name += "_Out";

      if (!scope->have_declared(name)) {
         scope->add_decl
            (new vhdl_signal_decl(name.c_str(), new vhdl_type(*type)));
      }

      out = new vhdl_var_ref(name.c_str(), type);
   }

   if (ivl_lpm_type(lpm) == IVL_LPM_PART_PV) {
      vhdl_expr *off = part_select_base(scope, lpm);
      assert(off);

      out->set_slice(off, ivl_lpm_width(lpm) - 1);
   }

   return out;
}

static vhdl_expr *concat_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_type *result_type =
      vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
   vhdl_binop_expr *expr =
      new vhdl_binop_expr(VHDL_BINOP_CONCAT, result_type);

   for (int i = ivl_lpm_selects(lpm) - 1; i >= 0; i--) {
      vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == e)
         return NULL;

      expr->add_expr(e);
   }

   return expr;
}

static vhdl_expr *binop_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op)
{
   vhdl_type *result_type =
      vhdl_type::type_for(ivl_lpm_width(lpm), ivl_lpm_signed(lpm) != 0);
   vhdl_binop_expr *expr = new vhdl_binop_expr(op, result_type);

   for (int i = 0; i < 2; i++) {
      vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == e)
         return NULL;

      expr->add_expr(e);
   }

   if (op == VHDL_BINOP_MULT) {
      // Need to resize the output to the desired size,
      // as this does not happen automatically in VHDL

      unsigned out_width = ivl_lpm_width(lpm);
      vhdl_fcall *resize =
         new vhdl_fcall("Resize", vhdl_type::nsigned(out_width));
      resize->add_expr(expr);
      resize->add_expr(new vhdl_const_int(out_width));

      return resize;
   }
   else
      return expr;
}

static vhdl_expr *rel_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm, vhdl_binop_t op)
{
   vhdl_binop_expr *expr = new vhdl_binop_expr(op, vhdl_type::boolean());

   for (int i = 0; i < 2; i++) {
      vhdl_expr *e = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == e)
         return NULL;

      expr->add_expr(e);
   }

   return expr;
}

static vhdl_expr *part_select_vp_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_var_ref *selfrom = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (NULL == selfrom)
      return NULL;

   vhdl_expr *off = part_select_base(scope, lpm);;
   if (NULL == off)
      return NULL;

   selfrom->set_slice(off, ivl_lpm_width(lpm) - 1);
   return selfrom;
}

static vhdl_expr *part_select_pv_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   return nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
}

static vhdl_expr *ufunc_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_fcall *fcall = new vhdl_fcall(ivl_lpm_basename(lpm), NULL);

   for (unsigned i = 0; i < ivl_lpm_size(lpm); i++) {
      vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, i));
      if (NULL == ref)
         return NULL;

      fcall->add_expr(ref);
   }

   return fcall;
}

static vhdl_expr *reduction_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
                                     const char *rfunc, bool invert)
{
   vhdl_fcall *fcall = new vhdl_fcall(rfunc, vhdl_type::std_logic());

   vhdl_var_ref *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (NULL == ref)
      return NULL;

   fcall->add_expr(ref);

   if (invert)
      return new vhdl_unaryop_expr
         (VHDL_UNARYOP_NOT, fcall, vhdl_type::std_logic());
   else
      return fcall;
}

static vhdl_expr *sign_extend_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   vhdl_expr *ref = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   if (ref)
      return ref->resize(ivl_lpm_width(lpm));
   else
      return NULL;
}

static vhdl_expr *array_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   ivl_signal_t array = ivl_lpm_array(lpm);
   if (!seen_signal_before(array))
      return NULL;

   const char *renamed = get_renamed_signal(array).c_str();

   vhdl_decl *adecl = scope->get_decl(renamed);
   assert(adecl);

   vhdl_type *atype = new vhdl_type(*adecl->get_type());

   vhdl_expr *select = nexus_to_var_ref(scope, ivl_lpm_select(lpm));
   if (NULL == select)
      return NULL;

   vhdl_var_ref *ref = new vhdl_var_ref(renamed, atype);
   ref->set_slice(select);

   return ref;
}

static vhdl_expr *shift_lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm,
                                    vhdl_binop_t shift_op)
{
   vhdl_expr *lhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 0));
   vhdl_expr *rhs = nexus_to_var_ref(scope, ivl_lpm_data(lpm, 1));
   if (!lhs || !rhs)
      return NULL;

   // The RHS must be an integer
   vhdl_type integer(VHDL_TYPE_INTEGER);
   vhdl_expr *r_cast = rhs->cast(&integer);

   vhdl_type *rtype = new vhdl_type(*lhs->get_type());
   return new vhdl_binop_expr(lhs, shift_op, r_cast, rtype);
}

static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
{
   switch (ivl_lpm_type(lpm)) {
   case IVL_LPM_ADD:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_ADD);
   case IVL_LPM_SUB:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_SUB);
   case IVL_LPM_MULT:
      return binop_lpm_to_expr(scope, lpm, VHDL_BINOP_MULT);
   case IVL_LPM_CONCAT:
      return concat_lpm_to_expr(scope, lpm);
   case IVL_LPM_CMP_EEQ:
      return rel_lpm_to_expr(scope, lpm, VHDL_BINOP_EQ);
   case IVL_LPM_PART_VP:
      return part_select_vp_lpm_to_expr(scope, lpm);
   case IVL_LPM_PART_PV:
      return part_select_pv_lpm_to_expr(scope, lpm);
   case IVL_LPM_UFUNC:
      return ufunc_lpm_to_expr(scope, lpm);
   case IVL_LPM_RE_AND:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", false);
   case IVL_LPM_RE_NAND:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", true);
   case IVL_LPM_RE_NOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_OR", true);
   case IVL_LPM_RE_OR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_OR", false);
   case IVL_LPM_RE_XOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_XOR", false);
   case IVL_LPM_RE_XNOR:
      return reduction_lpm_to_expr(scope, lpm, "Reduce_XNOR", false);
   case IVL_LPM_SIGN_EXT:
      return sign_extend_lpm_to_expr(scope, lpm);
   case IVL_LPM_ARRAY:
      return array_lpm_to_expr(scope, lpm);
   case IVL_LPM_SHIFTL:
      return shift_lpm_to_expr(scope, lpm, VHDL_BINOP_SL);
   case IVL_LPM_SHIFTR:
      return shift_lpm_to_expr(scope, lpm, VHDL_BINOP_SR);
   default:
      error("Unsupported LPM type: %d", ivl_lpm_type(lpm));
      return NULL;
   }
}

int draw_lpm(vhdl_arch *arch, ivl_lpm_t lpm)
{
   vhdl_expr *f = lpm_to_expr(arch->get_scope(), lpm);
   if (NULL == f)
      return 0;

   vhdl_var_ref *out = lpm_output(arch->get_scope(), lpm);
   arch->add_stmt(new vhdl_cassign_stmt(out, f));

   return 0;
}

<|endoftext|>