mirror of
https://github.com/xodio/xod.git
synced 2026-03-19 23:26:57 +01:00
feat(xod-project): support binding input pulses to ‘ON_BOOT’ and ‘CONTINUOUSLY’
This commit is contained in:
@@ -7,17 +7,26 @@ import * as Node from './node';
|
||||
import * as Link from './link';
|
||||
import * as Patch from './patch';
|
||||
import * as Project from './project';
|
||||
import { PIN_TYPE, INPUT_PULSE_PIN_BINDING_OPTIONS } from './constants';
|
||||
import { def } from './types';
|
||||
|
||||
const CONST_NODETYPES = {
|
||||
number: 'xod/core/constant-number',
|
||||
boolean: 'xod/core/constant-boolean',
|
||||
// TODO: it will be either 'xod/core/boot'
|
||||
// or 'xod/core/continuously'
|
||||
pulse: 'xod/core/constant-boolean',
|
||||
string: 'xod/core/constant-string',
|
||||
};
|
||||
|
||||
const PULSE_CONST_NODETYPES = {
|
||||
[INPUT_PULSE_PIN_BINDING_OPTIONS.ON_BOOT]: 'xod/core/boot',
|
||||
[INPUT_PULSE_PIN_BINDING_OPTIONS.CONTINUOUSLY]: 'xod/core/continuously',
|
||||
};
|
||||
|
||||
const CONST_PATCH_PATHS = R.compose(
|
||||
R.uniq,
|
||||
R.values,
|
||||
R.merge
|
||||
)(CONST_NODETYPES, PULSE_CONST_NODETYPES);
|
||||
|
||||
const isNodeWithCurriedPins = def(
|
||||
'isNodeWithCurriedPins :: Node -> Boolean',
|
||||
R.compose(
|
||||
@@ -92,54 +101,65 @@ const getMapOfNodePinTypes = def(
|
||||
)
|
||||
);
|
||||
|
||||
// :: { NodeId: { PinKey: PinType } } -> { NodeId: { PinKey: PatchPath } }
|
||||
const convertMapOfPinTypesIntoMapOfPinPaths = def(
|
||||
'convertMapOfPinTypesIntoMapOfPinPaths :: Map NodeId (Map PinKey DataType) -> Map NodeId (Map PinKey PatchPath)',
|
||||
R.map(R.map(R.prop(R.__, CONST_NODETYPES)))
|
||||
);
|
||||
|
||||
const getMapOfPinPaths = def(
|
||||
'getMapOfPinPaths :: Map NodeId (Map PinKey DataValue) -> [Node] -> Project -> Map NodeId (Map PinKey PatchPath)',
|
||||
const getMapOfExtractablePinPaths = def(
|
||||
'getMapOfExtractablePinPaths :: Map NodeId (Map PinKey DataValue) -> [Node] -> Project -> Map NodeId (Map PinKey PatchPath)',
|
||||
R.compose(
|
||||
convertMapOfPinTypesIntoMapOfPinPaths,
|
||||
getMapOfNodePinTypes
|
||||
R.map(R.reject(R.isNil)),
|
||||
R.map(R.map(
|
||||
([pinType, pinValue]) => (
|
||||
pinType === PIN_TYPE.PULSE
|
||||
? PULSE_CONST_NODETYPES[pinValue]
|
||||
: CONST_NODETYPES[pinType]
|
||||
)
|
||||
)),
|
||||
R.converge(
|
||||
R.mergeWith(R.mergeWith(Array.of)),
|
||||
[
|
||||
getMapOfNodePinTypes,
|
||||
R.identity,
|
||||
]
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const getMapOfPathsToPinKeys = def(
|
||||
'getMapOfPathsToPinKeys :: Map DataType PatchPath -> Project -> Map PatchPath PinKey',
|
||||
'getMapOfPathsToPinKeys :: [PatchPath] -> Project -> Map PatchPath PinKey',
|
||||
(constantPaths, project) => R.compose(
|
||||
R.fromPairs,
|
||||
R.map(constPath => R.compose(
|
||||
constPinKey => [constPath, constPinKey],
|
||||
Pin.getPinKey,
|
||||
R.head,
|
||||
Patch.listOutputPins,
|
||||
Project.getPatchByPathUnsafe(R.__, project)
|
||||
R.map(
|
||||
constPath => R.compose(
|
||||
constPinKey => [constPath, constPinKey],
|
||||
Pin.getPinKey,
|
||||
R.head,
|
||||
Patch.listOutputPins,
|
||||
Project.getPatchByPathUnsafe(R.__, project)
|
||||
)(constPath)
|
||||
),
|
||||
R.uniq,
|
||||
R.values
|
||||
)
|
||||
)(constantPaths)
|
||||
);
|
||||
|
||||
const createNodesWithBoundValues = def(
|
||||
'createNodesWithBoundValues :: Map NodeId (Map PinKey DataValue) -> Map NodeId (Map PinKey PatchPath) -> Map PatchPath PinKey -> Map NodeId (Map PinKey Node)',
|
||||
(mapOfPinValues, mapOfPinPaths, mapOfPinKeys) => R.mapObjIndexed(
|
||||
(pinsData, nodeId) => R.mapObjIndexed(
|
||||
(pinValue, pinKey) => {
|
||||
const type = R.path([nodeId, pinKey], mapOfPinPaths);
|
||||
const constPinKey = R.prop(type, mapOfPinKeys);
|
||||
(allInputPinValues, extractablePinPaths, mapOfPinKeys) =>
|
||||
R.mapObjIndexed(
|
||||
(pinsData, nodeId) => R.compose(
|
||||
R.mapObjIndexed((pinValue, pinKey) => {
|
||||
const type = R.path([nodeId, pinKey], extractablePinPaths);
|
||||
const constPinKey = R.prop(type, mapOfPinKeys);
|
||||
|
||||
return R.compose(
|
||||
Node.setBoundValue(constPinKey, pinValue),
|
||||
Node.createNode({ x: 0, y: 0 })
|
||||
)(type);
|
||||
},
|
||||
pinsData
|
||||
),
|
||||
mapOfPinValues
|
||||
)
|
||||
return R.compose(
|
||||
R.unless(
|
||||
R.always(R.equals(PIN_TYPE.PULSE, type)),
|
||||
// do not transfer bound values to 'pulse constants'
|
||||
Node.setBoundValue(constPinKey, pinValue)
|
||||
),
|
||||
Node.createNode({ x: 0, y: 0 })
|
||||
)(type);
|
||||
}),
|
||||
R.pickBy((pinValue, pinKey) => R.path([nodeId, pinKey], extractablePinPaths))
|
||||
)(pinsData),
|
||||
allInputPinValues
|
||||
)
|
||||
);
|
||||
|
||||
const nestedValues = def(
|
||||
@@ -292,7 +312,7 @@ const extractBoundInputsToConstNodes = def(
|
||||
const occupiedNodePins = getMapOfNodePinsWithLinks(entryPointNodes, entryPointLinks);
|
||||
const outputNodePins = getMapOfNodeOutputPins(entryPointNodes, origProject);
|
||||
const pinsToOmit = R.mergeWith(R.concat, occupiedNodePins, outputNodePins);
|
||||
const nodePinValues = R.compose(
|
||||
const allInputPinValues = R.compose(
|
||||
R.mapObjIndexed(
|
||||
(pins, nodeId) => R.omit(
|
||||
R.propOr([], nodeId, pinsToOmit),
|
||||
@@ -302,17 +322,25 @@ const extractBoundInputsToConstNodes = def(
|
||||
getMapOfNodePinValues
|
||||
)(entryPointNodes);
|
||||
|
||||
const pinPaths = getMapOfPinPaths(nodePinValues, nodesWithCurriedPins, flatProject);
|
||||
const constPinKeys = getMapOfPathsToPinKeys(CONST_NODETYPES, origProject);
|
||||
const extractablePinPaths = getMapOfExtractablePinPaths(
|
||||
allInputPinValues,
|
||||
nodesWithCurriedPins,
|
||||
flatProject
|
||||
);
|
||||
const constPinKeys = getMapOfPathsToPinKeys(CONST_PATCH_PATHS, origProject);
|
||||
|
||||
const newConstNodes = createNodesWithBoundValues(nodePinValues, pinPaths, constPinKeys);
|
||||
const newConstNodes = createNodesWithBoundValues(
|
||||
allInputPinValues,
|
||||
extractablePinPaths,
|
||||
constPinKeys
|
||||
);
|
||||
const newLinks = createLinksFromCurriedPins(newConstNodes, constPinKeys);
|
||||
const newPatch = updatePatch(newLinks, newConstNodes, nodePinValues, entryPointPatch);
|
||||
const newPatch = updatePatch(newLinks, newConstNodes, allInputPinValues, entryPointPatch);
|
||||
|
||||
return R.compose(
|
||||
explodeEither,
|
||||
Project.assocPatch(path, newPatch),
|
||||
copyConstPatches(pinPaths, origProject)
|
||||
copyConstPatches(extractablePinPaths, origProject)
|
||||
)(flatProject);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -131,6 +131,8 @@ export const getCastPatchPath = (typeIn, typeOut) => `xod/core/cast-${typeIn}-to
|
||||
// utils for constant patches
|
||||
//
|
||||
|
||||
// TODO: these are no longer correct
|
||||
|
||||
const constantTypeRegExp =
|
||||
new RegExp(`xod/core/constant-(${dataTypes.join('|')})$`);
|
||||
|
||||
|
||||
@@ -108,6 +108,75 @@ const constantPatches = {
|
||||
cpp: 'struct State {};\n\n{{ GENERATED_CODE }}\n\nvoid evaluate(NodeId nid, State* state) {\n reemitValue<Outputs::VAL>(nid);\n}\n',
|
||||
},
|
||||
},
|
||||
'xod/core/boot': {
|
||||
description: 'Outputs a single pulse when the program starts',
|
||||
links: {},
|
||||
nodes: {
|
||||
noNativeImpl: {
|
||||
boundValues: {},
|
||||
description: '',
|
||||
id: 'noNativeImpl',
|
||||
label: '',
|
||||
position: {
|
||||
x: 100,
|
||||
y: 100,
|
||||
},
|
||||
type: 'xod/patch-nodes/not-implemented-in-xod',
|
||||
},
|
||||
ryVmUAOrvkb: {
|
||||
boundValues: {
|
||||
__in__: false,
|
||||
},
|
||||
description: '',
|
||||
id: 'ryVmUAOrvkb',
|
||||
label: 'BOOT',
|
||||
position: {
|
||||
x: 10,
|
||||
y: 224,
|
||||
},
|
||||
type: 'xod/patch-nodes/output-pulse',
|
||||
},
|
||||
},
|
||||
path: 'xod/core/boot',
|
||||
impls: {
|
||||
cpp: 'struct State {\n};\n\n{{ GENERATED_CODE }}\n\nvoid evaluate(NodeId nid, State* state) {\n emitValue<Outputs::BOOT>(nid, 1);\n}\n',
|
||||
js: 'module.exports.evaluate = function(e) {\n e.fire({ BOOT: PULSE });\n};\n',
|
||||
},
|
||||
},
|
||||
'xod/core/continuously': {
|
||||
description: 'Continuously outputs pulses',
|
||||
links: {},
|
||||
nodes: {
|
||||
BLKANE3xW: {
|
||||
boundValues: {},
|
||||
description: '',
|
||||
id: 'BLKANE3xW',
|
||||
label: '',
|
||||
position: {
|
||||
x: 138,
|
||||
y: 120,
|
||||
},
|
||||
type: 'xod/patch-nodes/not-implemented-in-xod',
|
||||
},
|
||||
C0nt1n10Wl: {
|
||||
boundValues: {
|
||||
__in__: 'false',
|
||||
},
|
||||
description: 'Continuous pulses',
|
||||
id: 'C0nt1n10Wl',
|
||||
label: 'TICK',
|
||||
position: {
|
||||
x: 138,
|
||||
y: 224,
|
||||
},
|
||||
type: 'xod/patch-nodes/output-pulse',
|
||||
},
|
||||
},
|
||||
path: 'xod/core/continuously',
|
||||
impls: {
|
||||
cpp: 'struct State {\n};\n\n{{ GENERATED_CODE }}\n\nvoid evaluate(NodeId nid, State* state) {\n emitValue<Outputs::TICK>(nid, 1);\n setTimeout(nid, 0);\n}\n',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('extractBoundInputsToConstNodes', () => {
|
||||
@@ -165,9 +234,10 @@ describe('extractBoundInputsToConstNodes', () => {
|
||||
const testBoundPin = (
|
||||
dataType,
|
||||
boundValue,
|
||||
expectedConstNodeType
|
||||
expectedConstNodeType,
|
||||
checkConstNodeBoundValue = true // TODO: this flag is a bit hacky
|
||||
) =>
|
||||
it(`should 'extract' bound ${dataType} pin to ${expectedConstNodeType} node`, () => {
|
||||
it(`should extract bound '${dataType}' pin value '${boundValue}' to '${expectedConstNodeType}' node`, () => {
|
||||
const boundPinKey = getInputPinKey(dataType);
|
||||
const testNodeId = 'test-node';
|
||||
|
||||
@@ -241,22 +311,73 @@ describe('extractBoundInputsToConstNodes', () => {
|
||||
`link must be to test node's ${boundPinKey} pin`
|
||||
);
|
||||
|
||||
const maybeBoundValue = XP.getBoundValue(constantNodeOutputPinKey, constantNode);
|
||||
assert(maybeBoundValue.isJust);
|
||||
assert.equal(
|
||||
maybeBoundValue.getOrElse(undefined),
|
||||
boundValue,
|
||||
`value from test node's pin must be bound to ${expectedConstNodeType}'s output`
|
||||
);
|
||||
if (checkConstNodeBoundValue) {
|
||||
const maybeBoundValue = XP.getBoundValue(constantNodeOutputPinKey, constantNode);
|
||||
assert(maybeBoundValue.isJust);
|
||||
assert.equal(
|
||||
maybeBoundValue.getOrElse(undefined),
|
||||
boundValue,
|
||||
`value from test node's pin must be bound to ${expectedConstNodeType}'s output`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
testBoundPin(XP.PIN_TYPE.BOOLEAN, true, XP.getConstantPatchPath(XP.PIN_TYPE.BOOLEAN));
|
||||
testBoundPin(XP.PIN_TYPE.NUMBER, 42, XP.getConstantPatchPath(XP.PIN_TYPE.NUMBER));
|
||||
testBoundPin(XP.PIN_TYPE.STRING, 'hello', XP.getConstantPatchPath(XP.PIN_TYPE.STRING));
|
||||
|
||||
testBoundPin( // current behaviour. it is wrong.
|
||||
testBoundPin(
|
||||
XP.PIN_TYPE.PULSE,
|
||||
XP.INPUT_PULSE_PIN_BINDING_OPTIONS.ON_BOOT,
|
||||
XP.getConstantPatchPath(XP.PIN_TYPE.BOOLEAN)
|
||||
'xod/core/boot',
|
||||
false
|
||||
);
|
||||
testBoundPin(
|
||||
XP.PIN_TYPE.PULSE,
|
||||
XP.INPUT_PULSE_PIN_BINDING_OPTIONS.CONTINUOUSLY,
|
||||
'xod/core/continuously',
|
||||
false
|
||||
);
|
||||
|
||||
it('discards any other values bound to pulse pins', () => {
|
||||
const dataType = XP.PIN_TYPE.PULSE;
|
||||
const boundValue = XP.INPUT_PULSE_PIN_BINDING_OPTIONS.NEVER;
|
||||
const boundPinKey = getInputPinKey(dataType);
|
||||
const testNodeId = 'test-node';
|
||||
|
||||
const project = Helper.defaultizeProject({
|
||||
patches: R.merge(constantPatches, {
|
||||
[mainPatchPath]: {
|
||||
nodes: {
|
||||
[testNodeId]: {
|
||||
type: testPatchPath,
|
||||
boundValues: {
|
||||
[boundPinKey]: boundValue,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[testPatchPath]: testPatch,
|
||||
}),
|
||||
});
|
||||
|
||||
const transformedProject = XP.extractBoundInputsToConstNodes(project, mainPatchPath, project);
|
||||
|
||||
const patch = XP.getPatchByPathUnsafe(mainPatchPath, transformedProject);
|
||||
|
||||
const nodesByNodeType = R.compose(
|
||||
R.indexBy(XP.getNodeType),
|
||||
XP.listNodes
|
||||
)(patch);
|
||||
assert.lengthOf(R.values(nodesByNodeType), 1, 'no new nodes must be created');
|
||||
const testNode = nodesByNodeType[testPatchPath];
|
||||
|
||||
assert.isTrue(
|
||||
XP.getBoundValue(boundPinKey, testNode).isNothing,
|
||||
`bound value for ${boundPinKey} must be deleted from test node`
|
||||
);
|
||||
|
||||
const links = XP.listLinks(patch);
|
||||
assert.lengthOf(links, 0, 'no links must be created');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -631,7 +631,7 @@ template <typename T> class List {
|
||||
*
|
||||
=============================================================================*/
|
||||
|
||||
#define NODE_COUNT 8
|
||||
#define NODE_COUNT 5
|
||||
#define MAX_OUTPUT_COUNT 1
|
||||
|
||||
// Uncomment to trace the program in the Serial Monitor
|
||||
@@ -1069,32 +1069,6 @@ void evaluate(NodeId nid, State* state) {
|
||||
|
||||
} // namespace xod__core__constant_number
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// xod/core/constant_boolean implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace xod__core__constant_boolean {
|
||||
|
||||
struct State {
|
||||
};
|
||||
|
||||
struct Storage {
|
||||
State state;
|
||||
OutputPin<Logic> output_VAL;
|
||||
};
|
||||
|
||||
namespace Inputs {
|
||||
}
|
||||
|
||||
namespace Outputs {
|
||||
using VAL = OutputDescriptor<Logic, offsetof(Storage, output_VAL), 0>;
|
||||
}
|
||||
|
||||
void evaluate(NodeId nid, State* state) {
|
||||
reemitValue<Outputs::VAL>(nid);
|
||||
}
|
||||
|
||||
} // namespace xod__core__constant_boolean
|
||||
|
||||
} // namespace _program
|
||||
|
||||
/*=============================================================================
|
||||
@@ -1111,22 +1085,22 @@ namespace _program {
|
||||
xod__core__clock::Storage storage_0 = {
|
||||
{ }, // state
|
||||
{ NodeId(3), xod__core__constant_number::Outputs::VAL::KEY }, // input_IVAL
|
||||
{ NodeId(4), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_RST
|
||||
{ NO_NODE, 0 }, // input_RST
|
||||
{ false, links_0_TICK } // output_TICK
|
||||
};
|
||||
|
||||
xod__core__digital_output::Storage storage_1 = {
|
||||
{ }, // state
|
||||
{ NodeId(5), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(4), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(2), xod__core__flip_flop::Outputs::MEM::KEY }, // input_SIG
|
||||
};
|
||||
|
||||
NodeId links_2_MEM[] = { 1, NO_NODE };
|
||||
xod__core__flip_flop::Storage storage_2 = {
|
||||
{ }, // state
|
||||
{ NodeId(7), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_SET
|
||||
{ NO_NODE, 0 }, // input_SET
|
||||
{ NodeId(0), xod__core__clock::Outputs::TICK::KEY }, // input_TGL
|
||||
{ NodeId(6), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_RST
|
||||
{ NO_NODE, 0 }, // input_RST
|
||||
{ false, links_2_MEM } // output_MEM
|
||||
};
|
||||
|
||||
@@ -1136,28 +1110,10 @@ namespace _program {
|
||||
{ 0.25, links_3_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_4_VAL[] = { 0, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_4 = {
|
||||
NodeId links_4_VAL[] = { 1, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_4 = {
|
||||
{ }, // state
|
||||
{ false, links_4_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_5_VAL[] = { 1, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_5 = {
|
||||
{ }, // state
|
||||
{ 13, links_5_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_6_VAL[] = { 2, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_6 = {
|
||||
{ }, // state
|
||||
{ false, links_6_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_7_VAL[] = { 2, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_7 = {
|
||||
{ }, // state
|
||||
{ false, links_7_VAL } // output_VAL
|
||||
{ 13, links_4_VAL } // output_VAL
|
||||
};
|
||||
|
||||
void* storages[NODE_COUNT] = {
|
||||
@@ -1165,10 +1121,7 @@ namespace _program {
|
||||
&storage_1,
|
||||
&storage_2,
|
||||
&storage_3,
|
||||
&storage_4,
|
||||
&storage_5,
|
||||
&storage_6,
|
||||
&storage_7
|
||||
&storage_4
|
||||
};
|
||||
|
||||
EvalFuncPtr evaluationFuncs[NODE_COUNT] = {
|
||||
@@ -1176,16 +1129,10 @@ namespace _program {
|
||||
(EvalFuncPtr)&xod__core__digital_output::evaluate,
|
||||
(EvalFuncPtr)&xod__core__flip_flop::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate
|
||||
};
|
||||
|
||||
DirtyFlags dirtyFlags[NODE_COUNT] = {
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
@@ -1194,7 +1141,7 @@ namespace _program {
|
||||
};
|
||||
|
||||
NodeId topology[NODE_COUNT] = {
|
||||
3, 4, 5, 6, 7, 0, 2, 1
|
||||
3, 4, 0, 2, 1
|
||||
};
|
||||
|
||||
TimeMs schedule[NODE_COUNT] = { 0 };
|
||||
|
||||
@@ -631,7 +631,7 @@ template <typename T> class List {
|
||||
*
|
||||
=============================================================================*/
|
||||
|
||||
#define NODE_COUNT 13
|
||||
#define NODE_COUNT 12
|
||||
#define MAX_OUTPUT_COUNT 1
|
||||
|
||||
// Uncomment to trace the program in the Serial Monitor
|
||||
@@ -1141,32 +1141,6 @@ void evaluate(NodeId nid, State* state) {
|
||||
|
||||
} // namespace xod__core__constant_string
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// xod/core/constant_boolean implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace xod__core__constant_boolean {
|
||||
|
||||
struct State {
|
||||
};
|
||||
|
||||
struct Storage {
|
||||
State state;
|
||||
OutputPin<Logic> output_VAL;
|
||||
};
|
||||
|
||||
namespace Inputs {
|
||||
}
|
||||
|
||||
namespace Outputs {
|
||||
using VAL = OutputDescriptor<Logic, offsetof(Storage, output_VAL), 0>;
|
||||
}
|
||||
|
||||
void evaluate(NodeId nid, State* state) {
|
||||
reemitValue<Outputs::VAL>(nid);
|
||||
}
|
||||
|
||||
} // namespace xod__core__constant_boolean
|
||||
|
||||
} // namespace _program
|
||||
|
||||
/*=============================================================================
|
||||
@@ -1202,7 +1176,7 @@ namespace _program {
|
||||
xod__core__clock::Storage storage_2 = {
|
||||
{ }, // state
|
||||
{ NodeId(11), xod__core__constant_number::Outputs::VAL::KEY }, // input_IVAL
|
||||
{ NodeId(12), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_RST
|
||||
{ NO_NODE, 0 }, // input_RST
|
||||
{ false, links_2_TICK } // output_TICK
|
||||
};
|
||||
|
||||
@@ -1261,12 +1235,6 @@ namespace _program {
|
||||
{ 0.01, links_11_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_12_VAL[] = { 2, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_12 = {
|
||||
{ }, // state
|
||||
{ false, links_12_VAL } // output_VAL
|
||||
};
|
||||
|
||||
void* storages[NODE_COUNT] = {
|
||||
&storage_0,
|
||||
&storage_1,
|
||||
@@ -1279,8 +1247,7 @@ namespace _program {
|
||||
&storage_8,
|
||||
&storage_9,
|
||||
&storage_10,
|
||||
&storage_11,
|
||||
&storage_12
|
||||
&storage_11
|
||||
};
|
||||
|
||||
EvalFuncPtr evaluationFuncs[NODE_COUNT] = {
|
||||
@@ -1295,8 +1262,7 @@ namespace _program {
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate
|
||||
};
|
||||
|
||||
DirtyFlags dirtyFlags[NODE_COUNT] = {
|
||||
@@ -1311,12 +1277,11 @@ namespace _program {
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1)
|
||||
};
|
||||
|
||||
NodeId topology[NODE_COUNT] = {
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 12, 2, 0, 3, 1
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 2, 0, 3, 1
|
||||
};
|
||||
|
||||
TimeMs schedule[NODE_COUNT] = { 0 };
|
||||
|
||||
@@ -631,7 +631,7 @@ template <typename T> class List {
|
||||
*
|
||||
=============================================================================*/
|
||||
|
||||
#define NODE_COUNT 13
|
||||
#define NODE_COUNT 11
|
||||
#define MAX_OUTPUT_COUNT 2
|
||||
|
||||
// Uncomment to trace the program in the Serial Monitor
|
||||
@@ -1150,32 +1150,6 @@ void evaluate(NodeId nid, State* state) {
|
||||
|
||||
} // namespace xod__core__constant_number
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// xod/core/constant_boolean implementation
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace xod__core__constant_boolean {
|
||||
|
||||
struct State {
|
||||
};
|
||||
|
||||
struct Storage {
|
||||
State state;
|
||||
OutputPin<Logic> output_VAL;
|
||||
};
|
||||
|
||||
namespace Inputs {
|
||||
}
|
||||
|
||||
namespace Outputs {
|
||||
using VAL = OutputDescriptor<Logic, offsetof(Storage, output_VAL), 0>;
|
||||
}
|
||||
|
||||
void evaluate(NodeId nid, State* state) {
|
||||
reemitValue<Outputs::VAL>(nid);
|
||||
}
|
||||
|
||||
} // namespace xod__core__constant_boolean
|
||||
|
||||
} // namespace _program
|
||||
|
||||
/*=============================================================================
|
||||
@@ -1192,7 +1166,7 @@ namespace _program {
|
||||
xod__core__clock::Storage storage_0 = {
|
||||
{ }, // state
|
||||
{ NodeId(7), xod__core__constant_number::Outputs::VAL::KEY }, // input_IVAL
|
||||
{ NodeId(8), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_RST
|
||||
{ NO_NODE, 0 }, // input_RST
|
||||
{ false, links_0_TICK } // output_TICK
|
||||
};
|
||||
|
||||
@@ -1209,7 +1183,7 @@ namespace _program {
|
||||
NodeId links_2_SIG[] = { 1, NO_NODE };
|
||||
xod__core__digital_input::Storage storage_2 = {
|
||||
{ }, // state
|
||||
{ NodeId(9), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(8), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(0), xod__core__clock::Outputs::TICK::KEY }, // input_UPD
|
||||
{ false, links_2_SIG } // output_SIG
|
||||
};
|
||||
@@ -1218,7 +1192,7 @@ namespace _program {
|
||||
xod__core__flip_flop::Storage storage_3 = {
|
||||
{ }, // state
|
||||
{ NodeId(4), xod__core__gate::Outputs::F::KEY }, // input_SET
|
||||
{ NodeId(10), xod__core__constant_boolean::Outputs::VAL::KEY }, // input_TGL
|
||||
{ NO_NODE, 0 }, // input_TGL
|
||||
{ NodeId(1), xod__core__gate::Outputs::F::KEY }, // input_RST
|
||||
{ false, links_3_MEM } // output_MEM
|
||||
};
|
||||
@@ -1236,14 +1210,14 @@ namespace _program {
|
||||
NodeId links_5_SIG[] = { 4, NO_NODE };
|
||||
xod__core__digital_input::Storage storage_5 = {
|
||||
{ }, // state
|
||||
{ NodeId(11), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(9), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(0), xod__core__clock::Outputs::TICK::KEY }, // input_UPD
|
||||
{ false, links_5_SIG } // output_SIG
|
||||
};
|
||||
|
||||
xod__core__digital_output::Storage storage_6 = {
|
||||
{ }, // state
|
||||
{ NodeId(12), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(10), xod__core__constant_number::Outputs::VAL::KEY }, // input_PORT
|
||||
{ NodeId(3), xod__core__flip_flop::Outputs::MEM::KEY }, // input_SIG
|
||||
};
|
||||
|
||||
@@ -1253,34 +1227,22 @@ namespace _program {
|
||||
{ 0.02, links_7_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_8_VAL[] = { 0, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_8 = {
|
||||
NodeId links_8_VAL[] = { 2, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_8 = {
|
||||
{ }, // state
|
||||
{ false, links_8_VAL } // output_VAL
|
||||
{ 12, links_8_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_9_VAL[] = { 2, NO_NODE };
|
||||
NodeId links_9_VAL[] = { 5, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_9 = {
|
||||
{ }, // state
|
||||
{ 12, links_9_VAL } // output_VAL
|
||||
{ 11, links_9_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_10_VAL[] = { 3, NO_NODE };
|
||||
xod__core__constant_boolean::Storage storage_10 = {
|
||||
NodeId links_10_VAL[] = { 6, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_10 = {
|
||||
{ }, // state
|
||||
{ false, links_10_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_11_VAL[] = { 5, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_11 = {
|
||||
{ }, // state
|
||||
{ 11, links_11_VAL } // output_VAL
|
||||
};
|
||||
|
||||
NodeId links_12_VAL[] = { 6, NO_NODE };
|
||||
xod__core__constant_number::Storage storage_12 = {
|
||||
{ }, // state
|
||||
{ 13, links_12_VAL } // output_VAL
|
||||
{ 13, links_10_VAL } // output_VAL
|
||||
};
|
||||
|
||||
void* storages[NODE_COUNT] = {
|
||||
@@ -1294,9 +1256,7 @@ namespace _program {
|
||||
&storage_7,
|
||||
&storage_8,
|
||||
&storage_9,
|
||||
&storage_10,
|
||||
&storage_11,
|
||||
&storage_12
|
||||
&storage_10
|
||||
};
|
||||
|
||||
EvalFuncPtr evaluationFuncs[NODE_COUNT] = {
|
||||
@@ -1308,9 +1268,7 @@ namespace _program {
|
||||
(EvalFuncPtr)&xod__core__digital_input::evaluate,
|
||||
(EvalFuncPtr)&xod__core__digital_output::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_boolean::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate,
|
||||
(EvalFuncPtr)&xod__core__constant_number::evaluate
|
||||
};
|
||||
@@ -1326,13 +1284,11 @@ namespace _program {
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1),
|
||||
DirtyFlags(-1)
|
||||
};
|
||||
|
||||
NodeId topology[NODE_COUNT] = {
|
||||
7, 8, 9, 10, 11, 12, 0, 2, 5, 1, 4, 3, 6
|
||||
7, 8, 9, 10, 0, 2, 5, 1, 4, 3, 6
|
||||
};
|
||||
|
||||
TimeMs schedule[NODE_COUNT] = { 0 };
|
||||
|
||||
Reference in New Issue
Block a user