Files
qad/mbricks/brick_composite.cpp
Бычков Андрей b3e47dfc99 actual version libs withiout pip
git-svn-id: svn://db.shs.com.ru/libs@2 a8b55f48-bf90-11e4-a774-851b48703e85
2015-03-24 08:14:45 +00:00

534 lines
17 KiB
C++

#include "brick_composite.h"
PIVector<BrickBase * > BrickComposite::baseBricks;
BrickComposite::BrickComposite(): BrickCompositeBase(0, 0, 1) {
type = "Composite";
setName(type);
paramNames[0] = "Scheme file";
note_ = "\"Scheme\" is path to *.mbs file, described this brick";
parameters[0].setValue("");
parameters[0].setType(BrickBase::File);
setComposite(true);
mode_ = Asynchronous;
bi = 0; bo = 0; bp = 0; inf = 0;
}
void BrickComposite::clear() {
for (uint i = 0; i < bricks.size(); ++i)
delete bricks[i];
bricks.clear();
}
void BrickComposite::proceedConnections(bool compositeToo) {
if (compositeToo) {
if (bi != 0) {
for (int i = 0; i < inputsCount(); ++i)
bi->setOutputValue(i, inputs[i]);
bi->proceedConnections();
}
if (bp != 0) {
for (int i = 1; i < parametersCount(); ++i)
bp->setOutputValue(i - 1, parameters[i].toFloat());
bp->proceedConnections();
}
switch (mode_) {
case BrickBase::Synchronous:
for (uint i = 0; i < bricks.size(); ++i)
bricks[i]->proceedConnections();
break;
case BrickBase::Asynchronous: default:
for (uint i = 0; i < tree.size(); ++i) {
tl = &tree[i];
for (uint j = 0; j < tl->size(); ++j)
(*tl)[j]->proceedConnections();
}
break;
}
if (bo != 0)
for (int i = 0; i < outputsCount(); ++i)
outputs[i] = bo->input(i);
}
BrickBase::proceedConnections(compositeToo);
}
void BrickComposite::parameterChanged(int index) {
fillBaseBricks();
if (index != 0) return;
PIConfig sr(parameters[0].toString());
PIString prefix, cname;
BrickBase * b;
int pcnt;
clear();
setMode((Mode)(int)sr.getValue("Mode", 1));
PIStringList names = sr.getValue("Bricks", PIStringList());
for (uint i = 0; i < names.size(); ++i) {
prefix = names[i] + " ";
cname = sr.getValue(prefix + "codeName", "");
b = findBaseBrick(cname)->copy();
BrickComposite::loadBrick(sr, prefix, b);
bricks.push_back(b);
}
uint cnt = sr.getValue("Connections count", 0);
//cout << endl;
for (uint i = 0; i < cnt; ++i) {
prefix = "Connection " + PIString::fromNumber(i) + " ";
BrickBase::connect(findBrick(sr.getValue(prefix + "from Name", "")),
sr.getValue(prefix + "from Port", 0),
findBrick(sr.getValue(prefix + "to Name", "")),
sr.getValue(prefix + "to Port", 0));
}
bi = 0;
for (uint i = 0; i < bricks.size(); ++i)
if (bricks[i]->codeName() == "BrickCompositeInput")
{bi = (BrickCompositeInput * )bricks[i]; break;}
if (bi != 0) {
setInputsCount(bi->outputsCount());
for (int i = 0; i < inputsCount(); ++i)
inNames[i] = bi->parameter(i).toString();
} else setInputsCount(0);
bo = 0;
for (uint i = 0; i < bricks.size(); ++i)
if (bricks[i]->codeName() == "BrickCompositeOutput")
{bo = (BrickCompositeOutput * )bricks[i]; break;}
if (bo != 0) {
setOutputsCount(bo->inputsCount());
for (int i = 0; i < outputsCount(); ++i)
outNames[i] = bo->parameter(i).toString();
} else setOutputsCount(0);
bp = 0;
for (uint i = 0; i < bricks.size(); ++i)
if (bricks[i]->codeName() == "BrickCompositeParameters")
{bp = (BrickCompositeParameters * )bricks[i]; break;}
if (bp != 0) {
pcnt = parametersCount();
setParametersCount(bp->parametersCount() + 1);
for (int i = 1; i < parametersCount(); ++i) {
cname = bp->parameter(i - 1).toString();
int j = cname.toLowerCase().find(':');
if (j < 0) paramNames[i] = cname;
else {
paramNames[i] = cname.left(j).trim();
if (i >= pcnt) parameters[i].setValue(cname.cutLeft(j + 1).toDouble());
}
}
} else setParametersCount(1);
inf = 0;
for (uint i = 0; i < bricks.size(); ++i)
if (bricks[i]->codeName() == "BrickCompositeInformation")
{inf = (BrickCompositeInformation * )bricks[i]; break;}
if (inf != 0) {
type = inf->parameter(0).toString();
note_ = inf->parameter(1).toString();
} else {
type = "Composite";
note_ = "\"Scheme\" is path to *.mbs file, described this brick";
}
buildBrickTree();
//cout << name_ << " load " << bricks.size() << " bricks" << endl;
}
void BrickComposite::loadBrick(PIConfig & sr, const PIString & prefix, BrickBase * b, BrickManager * m) {
b->setName(sr.getValue(prefix + "name", b->name()));
b->setInitial(sr.getValue(prefix + "initial", false));
b->setFrequencyDivider(sr.getValue(prefix + "freqDiv", 1));
b->setOutputsCount(sr.getValue(prefix + "outCount", b->outputsCount()));
b->setInputsCount(sr.getValue(prefix + "inCount", b->inputsCount()));
for (int i = 0; i < b->inputsCount(); ++i)
b->setInputValue(i, sr.getValue(prefix + "in " + PIString::fromNumber(i), b->input(i)));
b->setParametersCount(sr.getValue(prefix + "paramCount", b->parametersCount()));
for (int i = 0; i < b->parametersCount(); ++i)
b->setParameterValue(i, PIVariant::fromValue<PIString>(sr.getValue(prefix + "param " + PIString::fromNumber(i), b->parameter(i).toString())), false);
b->setManager(m);
}
BrickBase * BrickComposite::findBrick(const PIString & name) {
for (uint i = 0; i < bricks.size(); ++i)
if (bricks[i]->name() == name)
return bricks[i];
return 0;
}
BrickBase * BrickComposite::findBaseBrick(const PIString & code_name) {
for (uint i = 0; i < baseBricks.size(); ++i)
if (baseBricks[i]->codeName() == code_name)
return baseBricks[i];
return 0;
}
bool BrickComposite::tick_body(double time) {
if (bi != 0) {
for (int i = 0; i < inputsCount(); ++i)
bi->setOutputValue(i, inputs[i]);
bi->proceedConnections();
}
if (bp != 0) {
for (int i = 1; i < parametersCount(); ++i)
bp->setOutputValue(i - 1, parameters[i].toFloat());
bp->proceedConnections();
}
switch (mode_) {
case BrickBase::Synchronous:
for (uint i = 0; i < bricks.size(); ++i)
bricks[i]->tick(time);
for (uint i = 0; i < bricks.size(); ++i)
bricks[i]->proceedConnections();
break;
case BrickBase::Asynchronous: default:
for (uint i = 0; i < tree.size(); ++i) {
tl = &tree[i];
for (uint j = 0; j < tl->size(); ++j)
(*tl)[j]->tick(time);
for (uint j = 0; j < tl->size(); ++j)
(*tl)[j]->proceedConnections();
}
break;
}
if (bo != 0)
for (int i = 0; i < outputsCount(); ++i)
outputs[i] = bo->input(i);
return true;
}
void BrickComposite::fillBaseBricks() {
if (!baseBricks.isEmpty()) return;
PIStringList libs = PICollection::groups();
piForeachC (PIString & l, libs) {
PIVector<const PIObject * > group = PICollection::groupElements(l);
piForeachC (PIObject * o, group)
baseBricks << (BrickBase * )o;
}
/*baseBricks.push_back(new BrickEmitConst());
baseBricks.push_back(new BrickEmitLinear());
baseBricks.push_back(new BrickEmitSin());
baseBricks.push_back(new BrickEmitDelta());
baseBricks.push_back(new BrickEmitStep());
baseBricks.push_back(new BrickEmitPulse());
baseBricks.push_back(new BrickEmitStrobe());
baseBricks.push_back(new BrickEmitTime());
baseBricks.push_back(new BrickEmitFrequency());
baseBricks.push_back(new BrickEmitNoiseRandom());
baseBricks.push_back(new BrickEmitNoiseNormal());
baseBricks.push_back(new BrickMathAbsolute());
baseBricks.push_back(new BrickMathSign());
baseBricks.push_back(new BrickMathAmplifier());
baseBricks.push_back(new BrickMathSum());
baseBricks.push_back(new BrickMathMultiply());
baseBricks.push_back(new BrickMathDivide());
baseBricks.push_back(new BrickMathPower());
baseBricks.push_back(new BrickMathDeadZone());
baseBricks.push_back(new BrickMathSaturation());
baseBricks.push_back(new BrickMathDelayTicks());
baseBricks.push_back(new BrickMathDelaySeconds());
baseBricks.push_back(new BrickMathRelay());
baseBricks.push_back(new BrickMathDerivate());
baseBricks.push_back(new BrickMathIntegral());
baseBricks.push_back(new BrickMathIntegralSaturated());
baseBricks.push_back(new BrickMathQuantize());
baseBricks.push_back(new BrickMathThreshold());
baseBricks.push_back(new BrickMathFunction());
baseBricks.push_back(new BrickMathFFT());
baseBricks.push_back(new BrickMathCopy());
baseBricks.push_back(new BrickMathBessel());
baseBricks.push_back(new BrickLogicNot());
baseBricks.push_back(new BrickLogicAnd());
baseBricks.push_back(new BrickLogicOr());
baseBricks.push_back(new BrickLogicXor());
baseBricks.push_back(new BrickLogicNAnd());
baseBricks.push_back(new BrickLogicNOr());
baseBricks.push_back(new BrickLogicNXor());
baseBricks.push_back(new BrickLogicMemory());
baseBricks.push_back(new BrickLogicCompare());
baseBricks.push_back(new BrickDigitalTriggerRS());
baseBricks.push_back(new BrickDigitalTriggerD());
baseBricks.push_back(new BrickDigitalTriggerJK());
baseBricks.push_back(new BrickDigitalCounter2());
baseBricks.push_back(new BrickDigitalCounter4());
baseBricks.push_back(new BrickDigitalCounter8());
baseBricks.push_back(new BrickDigitalCoder1());
baseBricks.push_back(new BrickDigitalCoder2());
baseBricks.push_back(new BrickDigitalCoder3());
baseBricks.push_back(new BrickDigitalCoder4());
baseBricks.push_back(new BrickDigitalDecoder1());
baseBricks.push_back(new BrickDigitalDecoder2());
baseBricks.push_back(new BrickDigitalDecoder3());
baseBricks.push_back(new BrickDigitalDecoder4());
baseBricks.push_back(new BrickDigitalMux1());
baseBricks.push_back(new BrickDigitalMux2());
baseBricks.push_back(new BrickDigitalMux3());
baseBricks.push_back(new BrickDigitalMux4());
baseBricks.push_back(new BrickDigitalDemux1());
baseBricks.push_back(new BrickDigitalDemux2());
baseBricks.push_back(new BrickDigitalDemux3());
baseBricks.push_back(new BrickDigitalDemux4());
baseBricks.push_back(new BrickDigitalDigitalToAnalog2());
baseBricks.push_back(new BrickDigitalDigitalToAnalog4());
baseBricks.push_back(new BrickDigitalDigitalToAnalog8());
baseBricks.push_back(new BrickDigitalAnalogToDigital2());
baseBricks.push_back(new BrickDigitalAnalogToDigital4());
baseBricks.push_back(new BrickDigitalAnalogToDigital8());
baseBricks.push_back(new BrickLinkTransferFunction());
baseBricks.push_back(new BrickLinkFilter1Degree());
baseBricks.push_back(new BrickLinkFilterBandpass());
baseBricks.push_back(new BrickInterfaceSerialIn());
baseBricks.push_back(new BrickInterfaceSerialOut());
baseBricks.push_back(new BrickInterfaceUDPIn());
baseBricks.push_back(new BrickInterfaceUDPOut());
baseBricks.push_back(new BrickInterfaceBinFileOut());
baseBricks.push_back(new BrickStatisticMinMaxI());
baseBricks.push_back(new BrickStatisticMinMaxF());
baseBricks.push_back(new BrickStatisticExpectation());
baseBricks.push_back(new BrickStatisticVariance());
baseBricks.push_back(new BrickComposite());
baseBricks.push_back(new BrickCompositeInput());
baseBricks.push_back(new BrickCompositeOutput());
baseBricks.push_back(new BrickCompositeParameters());
baseBricks.push_back(new BrickCompositeInformation());*/
}
void sumTrees(PIVector<PIVector<BrickBase * > > & ft, PIVector<PIVector<BrickBase * > > & st) {
uint mi = piMin<uint>(ft.size(), st.size());
for (uint i = 0; i < mi; ++i)
for (uint j = 0; j < st[i].size(); ++j)
ft[i].push_back(st[i][j]);
if (st.size() > ft.size())
for (uint i = mi; i < st.size(); ++i)
ft.push_back(st[i]);
}
void buildTree(PIVector<BrickBase * > & bricks, PIVector<PIVector<BrickBase * > > & tree) {
PIVector<PIVector<BrickBase * > > ct;
BrickBase * b;
tree.clear();
if (bricks.size() == 0) return;
for (uint i = 0; i < bricks.size(); ++i) {
b = bricks[i];
b->ticked = false;
b->level_ = -666;
b->tmp_ = 0;
}
ct = buildSubtree(bricks, tree);
//cout << "--------" << endl;
while (ct.size() > 0) {
//cout << "subtree " << ct.size() << endl;
sumTrees(tree, ct);
ct = buildSubtree(bricks, tree);
}
//cout << "subtrees built" << endl;
uint tcnt = 0;
for (uint i = 0; i < tree.size(); ++i)
tcnt += tree[i].size();
//cout << "built for " << tcnt << " from " << bricks.size() << endl;
if (tcnt < bricks.size()) {
for (uint i = 0; i < bricks.size(); ++i) {
b = bricks[i];
for (uint j = 0; j < tree.size(); ++j)
for (uint k = 0; k < tree[j].size(); ++k)
if (tree[j][k] == b) goto next;
//cout << "add " << b->name().stdString() << " in level (" << b->level_ << ") ... " << flush;
if (b->level_ < 0) b->level_ = 0;
if ((uint)b->level_ < tree.size() && b->level_ >= 0) tree[b->level_].push_back(b);
else {
tree.resize(b->level_ + 1);
tree[b->level_].push_back(b);
}
//cout << "ok" << endl;
next: ;
}
}
int mlev = bricks[0]->level_;
for (uint i = 1; i < bricks.size(); ++i)
if (mlev > bricks[i]->level_)
mlev = bricks[i]->level_;
if (mlev >= 0) return;
piCout << "minimum level =" << mlev << ", so rebuild tree manually";
tree.clear();
int clev = 0;
uint cnt = 0;
PIVector<BrickBase * > level;
for (uint i = 0; i < bricks.size(); ++i)
bricks[i]->level_ -= mlev;
mlev = 0;
while (bricks.size() > cnt) {
level.clear();
for (uint i = 0; i < bricks.size(); ++i) {
b = bricks[i];
if (b->level_ != clev) continue;
level.push_back(b);
++cnt;
}
if (level.size() > 0) tree.push_back(level);
++clev;
}
}
PIVector<PIVector<BrickBase * > > buildSubtree(PIVector<BrickBase * > & bricks, PIVector<PIVector<BrickBase * > > & tree) {
PIVector<BrickBase * > bbs, tbs, level;
PIVector<PIVector<BrickBase * > > ttree;
BrickBase * b, * sb;
int minlev, clev;
if (bricks.size() == 0) return ttree;
//cout << "initial stage" << endl;
/// Initial stage: first level - initialize bricks
for (uint i = 0; i < bricks.size(); ++i) {
b = bricks[i];
if (b->level_ >= 0) continue;
bbs.push_back(b);
if (!b->isInitial()) {
tbs.push_back(b);
continue;
}
b->level_ = 0;
level.push_back(b);
}
if (level.size() == 0 && tbs.size() == 0) return ttree;
if (level.size() == 0) {
level.push_back(tbs[0]);
level.back()->level_ = 0;
tbs.pop_front();
}
ttree.clear();
ttree.push_back(level);
//cout << "first stage" << endl;
/// First pass: direct bricks bypass
while (tbs.size() > 0) {
level.clear();
for (uint i = 0; i < ttree.back().size(); ++i) {
b = ttree.back()[i];
b->tmp_++;
for (uint j = 0; j < b->connections.size(); ++j) {
sb = b->connections[j].brick_to;
if (sb->ticked) continue;
level.push_back(sb);
sb->level_ = ttree.size();
for (uint k = 0; k < tbs.size(); ++k) {
if (tbs[k] == sb) {
tbs.remove(k);
break;
}
}
}
if (b->tmp_ >= b->inputs_count) b->ticked = true;
}
if (level.size() == 0) break;
ttree.push_back(level);
}
minlev = ttree[0][0]->level_;
if (tbs.size() == 0) goto third;
for (uint i = 0; i < ttree.size(); ++i)
for (uint j = 0; j < ttree[i].size(); ++j)
ttree[i][j]->ticked = true;
//cout << "second stage" << endl;
/// Second pass: ttree complement with invert bypass
while (tbs.size() > 0) {
level.clear();
for (uint i = 0; i < tbs.size(); ++i) {
b = tbs[i];
for (uint j = 0; j < b->connections.size(); ++j) {
sb = b->connections[j].brick_to;
if (!sb->ticked) continue;
level.push_back(b);
b->level_ = sb->level_ - 1;
if (minlev > b->level_) minlev = b->level_;
b->ticked = true;
for (uint k = 0; k < tbs.size(); ++k) {
if (tbs[k] == b) {
tbs.remove(k);
break;
}
}
i = 0;
}
}
if (level.size() == 0) break;
}
//cout << "third stage" << endl;
third:
/// Third pass: rebuild ttree
ttree.clear();
clev = minlev;
level.push_back(0);
while (level.size() > 0) {
level.clear();
for (uint i = 0; i < bbs.size(); ++i) {
b = bbs[i];
if (b->level_ == clev) level.push_back(b);
}
if (level.size() > 0) ttree.push_back(level);
++clev;
}
//cout << "final stage" << endl << endl;
/// Final stage: normalize levels
for (uint i = 0; i < ttree.size(); ++i)
for (uint j = 0; j < ttree[i].size(); ++j)
ttree[i][j]->level_ = i;
return ttree;
}
BrickCompositeInput::BrickCompositeInput(int inputs_num): BrickCompositeBase(0, inputs_num, inputs_num) {
type = "Input";
setName(type);
io_Type = BrickBase::VariableOutputs;
outNames[0] = "0";
note_ += "\"Parameters\" are labels for inputs that will be shown in parent composite brick";
parameters[0].setValue("");
}
BrickCompositeOutput::BrickCompositeOutput(int outputs_num): BrickCompositeBase(outputs_num, 0, outputs_num) {
type = "Output";
setName(type);
io_Type = BrickBase::VariableInputs;
inNames[0] = "0";
note_ += "\"Parameters\" are labels for outputs that will be shown in parent composite brick";
parameters[0].setValue("");
}
BrickCompositeParameters::BrickCompositeParameters(): BrickCompositeBase(0, 1, 1) {
type = "Parameters";
setName(type);
io_Type = BrickBase::VariableOutputs;
note_ = "There are parameters you can set from parent brick\nEach parameter is float and should be typed in format: \"name[:default]\"";
parameters[0].setValue("p");
outNames[0] = "p";
}
void BrickCompositeParameters::parameterChanged(int index) {
PIString s = parameters[index].toString();
int i = s.toLowerCase().find(':');
if (i < 0) outNames[index] = s;
else outNames[index] = s.left(i).trim();
}
BrickCompositeInformation::BrickCompositeInformation(): BrickCompositeBase(0, 0, 2) {
type = "Information";
setName(type);
parametersName_ = "Information";
paramNames[0] = "Type name";
paramNames[1] = "Promt";
note_ = "There are information fields about parent composite brick";
parameters[0].setValue("");
parameters[1].setValue("");
}