#ifndef BRICK_DIGITAL_H
#define BRICK_DIGITAL_H

#include "brick_base.h"


class BrickDigitalBase: public BrickBase {
public: BrickDigitalBase(int inputs_num = 1, int outputs_num = 1, int parameters_num = 0): BrickBase(inputs_num, outputs_num, parameters_num) {lib = "Digital"; inNames[0] = outNames[0] = "0";}
};


class BrickDigitalTriggerRS: public BrickDigitalBase {
	MBRICK(BrickDigitalTriggerRS)
	BrickDigitalTriggerRS(): BrickDigitalBase(2, 2) {
		type = "RStrigger";
		setName(type);
		inNames[0] = "S";
		inNames[1] = "R";
		outNames[0] = "T";
		outNames[1] = "To";
	}
	enum Inputs {S, R};
	enum Outputs {T, To};
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalTriggerRS)


class BrickDigitalTriggerD: public BrickDigitalBase {
	MBRICK(BrickDigitalTriggerD)
	BrickDigitalTriggerD(): BrickDigitalBase(2, 2) {
		type = "Dtrigger";
		setName(type);
		inNames[0] = "D";
		inNames[1] = "C";
		outNames[0] = "T";
		outNames[1] = "To";
	}
	enum Inputs {D, C};
	enum Outputs {T, To};
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalTriggerD)


class BrickDigitalTriggerJK: public BrickDigitalBase {
	MBRICK(BrickDigitalTriggerJK)
	BrickDigitalTriggerJK(): BrickDigitalBase(3, 2) {
		type = "JKtrigger";
		setName(type);
		inNames[0] = "J";
		inNames[1] = "C";
		inNames[2] = "K";
		outNames[0] = "T";
		outNames[1] = "To";
	}
	enum Inputs {J, C, K};
	enum Outputs {T, To};
	virtual void reset_specified() {pc = 0.;}
	virtual bool tick_body(double time);
private:
	double pc;
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalTriggerJK)


class BrickDigitalCounter2: public BrickDigitalBase {
	MBRICK(BrickDigitalCounter2)
	BrickDigitalCounter2(): BrickDigitalBase(2, 2) {type = "Counter2"; setName(type); inNames[0] = "/ C"; inNames[1] = "R"; v = 0.;}
	enum Inputs {C, R};
	virtual void reset_specified() {v = dv = 0.;}
	virtual bool tick_body(double time);
private:
	double v, dv;
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCounter2)


class BrickDigitalCounter4: public BrickDigitalBase {
	MBRICK(BrickDigitalCounter4)
	BrickDigitalCounter4(): BrickDigitalBase(2, 4) {type = "Counter4"; setName(type); inNames[0] = "/ C"; inNames[1] = "R"; v = 0.;}
	enum Inputs {C, R};
	virtual bool tick_body(double time);
private:
	double v, dv;
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCounter4)


class BrickDigitalCounter8: public BrickDigitalBase {
	MBRICK(BrickDigitalCounter8)
	BrickDigitalCounter8(): BrickDigitalBase(2, 8) {type = "Counter8"; setName(type); inNames[0] = "/ C"; inNames[1] = "R"; v = 0.;}
	enum Inputs {C, R};
	virtual bool tick_body(double time);
private:
	double v, dv;
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCounter8)


class BrickDigitalCoder1: public BrickDigitalBase {
	MBRICK(BrickDigitalCoder1)
	BrickDigitalCoder1(): BrickDigitalBase(2, 1) {type = "Coder1"; setName(type);}
	virtual bool tick_body(double time) {if (inputs[1] > 0.) outputs[0] = 1.; else outputs[0] = 0.; return true;}
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCoder1)


class BrickDigitalCoder2: public BrickDigitalBase {
	MBRICK(BrickDigitalCoder2)
	BrickDigitalCoder2(): BrickDigitalBase(4, 2) {type = "Coder2"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCoder2)


class BrickDigitalCoder3: public BrickDigitalBase {
	MBRICK(BrickDigitalCoder3)
	BrickDigitalCoder3(): BrickDigitalBase(8, 3) {type = "Coder3"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCoder3)


class BrickDigitalCoder4: public BrickDigitalBase {
	MBRICK(BrickDigitalCoder4)
	BrickDigitalCoder4(): BrickDigitalBase(16, 4) {type = "Coder4"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalCoder4)


class BrickDigitalDecoder1: public BrickDigitalBase {
	MBRICK(BrickDigitalDecoder1)
	BrickDigitalDecoder1(): BrickDigitalBase(1, 2) {type = "Decoder1"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDecoder1)


class BrickDigitalDecoder2: public BrickDigitalBase {
	MBRICK(BrickDigitalDecoder2)
	BrickDigitalDecoder2(): BrickDigitalBase(2, 4) {type = "Decoder2"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDecoder2)


class BrickDigitalDecoder3: public BrickDigitalBase {
	MBRICK(BrickDigitalDecoder3)
	BrickDigitalDecoder3(): BrickDigitalBase(3, 8) {type = "Decoder3"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDecoder3)


class BrickDigitalDecoder4: public BrickDigitalBase {
	MBRICK(BrickDigitalDecoder4)
	BrickDigitalDecoder4(): BrickDigitalBase(4, 16) {type = "Decoder4"; setName(type);}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDecoder4)


class BrickDigitalMux1: public BrickDigitalBase {
	MBRICK(BrickDigitalMux1)
	BrickDigitalMux1(): BrickDigitalBase(3, 1) {type = "Mux1"; setName(type); inNames[2] = "A0";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalMux1)


class BrickDigitalMux2: public BrickDigitalBase {
	MBRICK(BrickDigitalMux2)
	BrickDigitalMux2(): BrickDigitalBase(6, 1) {type = "Mux2"; setName(type); inNames[4] = "A0"; inNames[5] = "A1";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalMux2)


class BrickDigitalMux3: public BrickDigitalBase {
	MBRICK(BrickDigitalMux3)
	BrickDigitalMux3(): BrickDigitalBase(11, 1) {type = "Mux3"; setName(type); inNames[8] = "A0"; inNames[9] = "A1"; inNames[10] = "A2";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalMux3)


class BrickDigitalMux4: public BrickDigitalBase {
	MBRICK(BrickDigitalMux4)
	BrickDigitalMux4(): BrickDigitalBase(20, 1) {type = "Mux4"; setName(type); inNames[16] = "A0"; inNames[17] = "A1"; inNames[18] = "A2"; inNames[19] = "A3";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalMux4)


class BrickDigitalDemux1: public BrickDigitalBase {
	MBRICK(BrickDigitalDemux1)
	BrickDigitalDemux1(): BrickDigitalBase(2, 2) {type = "Demux1"; setName(type); inNames[1] = "A0";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDemux1)


class BrickDigitalDemux2: public BrickDigitalBase {
	MBRICK(BrickDigitalDemux2)
	BrickDigitalDemux2(): BrickDigitalBase(3, 4) {type = "Demux2"; setName(type); inNames[1] = "A0"; inNames[2] = "A1";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDemux2)


class BrickDigitalDemux3: public BrickDigitalBase {
	MBRICK(BrickDigitalDemux3)
	BrickDigitalDemux3(): BrickDigitalBase(4, 8) {type = "Demux3"; setName(type); inNames[1] = "A0"; inNames[2] = "A1"; inNames[3] = "A2";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDemux3)


class BrickDigitalDemux4: public BrickDigitalBase {
	MBRICK(BrickDigitalDemux4)
	BrickDigitalDemux4(): BrickDigitalBase(5, 16) {type = "Demux4"; setName(type); inNames[1] = "A0"; inNames[2] = "A1"; inNames[3] = "A2"; inNames[4] = "A3";}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDemux4)


class BrickDigitalDigitalToAnalog2: public BrickDigitalBase {
	MBRICK(BrickDigitalDigitalToAnalog2)
	BrickDigitalDigitalToAnalog2(): BrickDigitalBase(3, 1) {type = "DigitalToAnalog2"; setName(type); inNames[2] = "Max"; outNames[0] = "Output"; inputs[2] = 1.;}
	virtual bool tick_body(double time) {outputs[0] = inputs[2] * (dbool(inputs[0]) + 2. * dbool(inputs[1])) / 3.; return true;}
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDigitalToAnalog2)


class BrickDigitalDigitalToAnalog4: public BrickDigitalBase {
	MBRICK(BrickDigitalDigitalToAnalog4)
	BrickDigitalDigitalToAnalog4(): BrickDigitalBase(5, 1) {type = "DigitalToAnalog4"; setName(type); inNames[4] = "Max"; outNames[0] = "Output"; inputs[4] = 1.;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDigitalToAnalog4)


class BrickDigitalDigitalToAnalog8: public BrickDigitalBase {
	MBRICK(BrickDigitalDigitalToAnalog8)
	BrickDigitalDigitalToAnalog8(): BrickDigitalBase(9, 1) { type = "DigitalToAnalog8"; setName(type); inNames[8] = "Max"; outNames[0] = "Output"; inputs[8] = 1.;}
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalDigitalToAnalog8)


class BrickDigitalAnalogToDigital2: public BrickDigitalBase {
	MBRICK(BrickDigitalAnalogToDigital2)
	BrickDigitalAnalogToDigital2(): BrickDigitalBase(2, 2) {type = "AnalogToDigital2"; setName(type); inNames[0] = "Input"; inNames[1] = "Max"; inputs[1] = 1.;}
	enum Inputs {Input, Max};
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalAnalogToDigital2)


class BrickDigitalAnalogToDigital4: public BrickDigitalBase {
	MBRICK(BrickDigitalAnalogToDigital4)
	BrickDigitalAnalogToDigital4(): BrickDigitalBase(2, 4) {type = "AnalogToDigital4"; setName(type); inNames[0] = "Input"; inNames[1] = "Max"; inputs[1] = 1.;}
	enum Inputs {Input, Max};
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalAnalogToDigital4)


class BrickDigitalAnalogToDigital8: public BrickDigitalBase {
	MBRICK(BrickDigitalAnalogToDigital8)
	BrickDigitalAnalogToDigital8(): BrickDigitalBase(2, 8) {type = "AnalogToDigital8"; setName(type); inNames[0] = "Input"; inNames[1] = "Max"; inputs[1] = 1.;}
	enum Inputs {Input, Max};
	virtual bool tick_body(double time);
};
ADD_NEW_TO_COLLECTION(Digital, BrickDigitalAnalogToDigital8)

#endif // BRICK_DIGITAL_H
