Data contracts
DDD is a chain of parts that hand data to one another: the loader reads the description files from disk, the analysis resolves and checks what was read, and the backends turn the result into c code and into a2l. Those parts share no domain logic at all - the c backend has never heard of a2l, the analysis has never heard of either, and none of them reaches into the loader. What holds the chain together instead is a small set of data contracts: the exact descriptions of the json documents that enter and leave the tool, and of the resolved data that travels between the front end and the backends.
Every contract is described exactly once, as a pydantic model in the ddd.models package,
and that one description is shared by every producer and every consumer of the data. The
loader validates a file against it, the checks read the objects it produced, ddd schema
exports its json schema, and the reference at the bottom of this page is generated from it.
Two parts of DDD can therefore never disagree about a file format, and the schema an editor
validates a description file against while it is being typed is not a second, hand
maintained copy of the rules: it is derived from the rules themselves, so a field that
changes cannot leave its documentation or its schema behind.
The data dictionary on the right of the diagram is the same idea applied to data that does not have to be a file at all, and it is important enough to have a page of its own. The contracts on the left are the files a project actually contains, and they are described in prose, with examples, under file formats. What follows here is the discipline all of them are held to, and the generated reference for every model.
Validation at the boundary
A description file is written by a person, in an editor, usually while thinking about something else. It is therefore checked the moment it enters DDD, before anything reads a single field of it, and the resolved data dictionary is validated once more before it is handed to a backend. The point of validating at the boundary rather than at the point of use is where the problem gets reported: a missing datatype noticed while a jinja template is rendering says something about the template, whereas the same problem noticed at the boundary says which file, which declaration and which field.
A violated contract is a finding, not a crash. The loader turns every pydantic validation
error into a diagnostic of the schema check, located at the json path that carries the
offending value, and carries on reading whatever else it can:
$ ddd check sensor_hub.ddd.json
sensor_hub.ddd.json#component.interface[0].definition.name: error[schema]: String should match pattern '^[A-Za-z_][A-Za-z0-9_]*$' (got: '2Value')
sensor_hub.ddd.json#component.interface[1].definition.name: error[schema]: String should have at most 128 characters (got: 'ValueXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...)
2 errors
Both problems are in one file and both are reported by one run, because an author who has to
run the tool once per mistake stops running the tool. schema is one of the few checks
whose severity cannot be relaxed: a file DDD cannot read has nothing further to say about
itself, so downgrading the finding would only delay the failure.
Unknown fields are rejected
Every model refuses keys it does not know. A key DDD silently ignored would be worse than
one it refuses, because the author would go on believing the field had an effect: a mistyped
dimension instead of dimensions does not produce a smaller array, it produces a
scalar, and neither the generated code nor the a2l would ever hint at why.
$ ddd check controller.ddd.json
controller.ddd.json#component.interface[0].definition.dimension: error[schema]: Extra inputs are not permitted (got: [4])
1 error
The same rule applies at the top level of a file: a document naming none of the six
description kinds - project, component, types, units, sections,
constants - or several of them at once, is refused rather than guessed at.
Identifiers are constrained
Anything DDD will later write into a c file or into an a2l file as a name - a project
name, a component name, an object name, an enum name, an enumerator, an a2l display
identifier - has to match ^[A-Za-z_][A-Za-z0-9_]*$ and may be at most 128 characters
long. The pattern is the c identifier rule, because a name that is not one cannot become a
variable. The length is the tighter of the two limits DDD has to satisfy: c compilers are
generous, but ASAP2 1.6.1 caps an identifier at 128 characters, and a name that cannot be
put into the a2l is of no use in a project that generates one.
Constraining a value rather than passing it through also keeps one description file from
being able to damage somebody else’s build. The a2l FORMAT string is checked against
^%\d*\.\d+$ for exactly that reason: it is written into a quoted a2l literal, and a
quote or a backslash in it would unbalance the string so that no calibration tool would
parse the file at all - a whole delivery lost to one typo in one description. For the same
reason a preprocessor condition may not contain a line break, /*, */, // or
#: it is emitted verbatim into #if and into the trailing #endif comment of every
generated file, and a comment marker there would close that trailer early and leave whatever
follows it as live code.
Numbers must be finite
Every number DDD reads - a limit, an initial value, a conversion factor or offset - is
refused if it is infinite or NaN. Neither survives the trip to an output, since there is no c
literal and no a2l number for either, and NaN is actively dangerous on the way there: every
comparison against it is false, so a NaN limit passes every range check in silence instead
of failing one. Python’s json reader accepts NaN, Infinity and -Infinity even
though json itself does not, so the loader refuses them explicitly, before pydantic ever
sees the document:
$ ddd check event_logger.ddd.json
event_logger.ddd.json: error[json-syntax]: 'Infinity' is not valid json; DDD has no representation for it
1 error
Whole numbers are kept whole for a related reason: a number is read as an int first and
only then as a float, because the range of a 64 bit datatype does not survive a float, and a
limit rendered as 18446744073709551616 - one more than uint64 can hold - is a value the
calibration tool would refuse.
Nothing changes behind a caller’s back
Every contract model is frozen: once a document has been validated, no part of DDD modifies it. The analysis therefore cannot quietly “fix up” a consumer’s declaration to match the producer’s, and a backend cannot normalise something on its way into a template. Where a derived value is needed - the limits a datatype and a conversion imply, the shape a curve takes from its axis - it is computed into the data dictionary, which is a separate document, so that the difference between what an author wrote and what DDD concluded stays visible instead of being overwritten.
Publishing the schemas
Because the contracts are pydantic models, their json schema is derived mechanically -
including the field documentation and the rejection of unknown properties - and
ddd schema prints it:
ddd schema project
ddd schema component
ddd schema types
ddd schema units
ddd schema sections
ddd schema constants
ddd schema dictionary
ddd schema all -o schemas
ddd schema component -o .vscode/ddd_component.schema.json
Pointing an editor at those files gives the whole team the validation and the hover
documentation of the contract while a description file is being written, which is where a
typo is cheapest to fix. Writing them out with -o keeps the line endings exactly as
generated, so a schema checked in from Windows does not differ from the same schema checked
in from linux.
Reference
The following is generated from the contracts themselves. Each model carries three things,
which answer three different questions. The field list says what may be written and what
it means. The json schema says exactly what a validator will accept - the precise
pattern, length and range every field is held to - and is the fragment an editor uses. The
entity relationship diagram says how the models fit together, which neither of the other
two shows: that a Declaration holds exactly one of the six kinds of data object, and that
the same Limits and A2lObjectOptions hang off every one of them. Where a field carries
an alias, the alias is the key that belongs in the json file - $schema, not
schema_reference.
Project description
- pydantic model ProjectFile[source]
Root object of a
*.ddd.jsonproject description.projectis the top level key that makes this a project file rather than a component or a types file; DDD decides what a file is from that key alone, so exactly one of them appears here.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.project.Project" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Project</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>includes</td><td port="includes">tuple[str, ...]</td></tr></table>>,
tooltip="ddd.models.project.Project

A project is a named list of components and/or sub-projects.
"];
"ddd.models.project.ProjectFile" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ProjectFile</b></td></tr><tr><td>schema_reference</td><td port="schema_reference">str | None</td></tr><tr><td>project</td><td port="project">Project</td></tr></table>>,
tooltip="ddd.models.project.ProjectFile

Root object of a ``*.ddd.json`` project description.

``project`` is the top level \
key that makes this a project file rather than a component
or a types file; DDD decides what a file is from that key alone, \
so exactly one of them
appears here.
"];
"ddd.models.project.ProjectFile":project:e -> "ddd.models.project.Project":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-a27c1911fdea6dc149869c4893c2a87f95c2b84a.png)
Show JSON schema
{ "title": "DDD project description", "description": "Root object of a ``*.ddd.json`` project description.\n\n``project`` is the top level key that makes this a project file rather than a component\nor a types file; DDD decides what a file is from that key alone, so exactly one of them\nappears here.", "type": "object", "properties": { "$schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Editor binding to a schema written by ``ddd schema -o``; not interpreted by DDD.", "title": "$Schema" }, "project": { "$ref": "#/$defs/Project", "description": "The project this file describes; the key that identifies the file as a project." } }, "$defs": { "Project": { "additionalProperties": false, "description": "A project is a named list of components and/or sub-projects.", "properties": { "name": { "description": "Name of the project; also the a2l project and module name.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the project.", "title": "Description", "type": "string" }, "includes": { "default": [], "description": "Paths to component, types, units, sections, constants or sub-project files,\nrelative to this file.\n\nShell style wildcards (``*``, ``?``, ``**``) are expanded; the kind of every\nincluded file is detected from its top level key.", "items": { "type": "string" }, "title": "Includes", "type": "array" } }, "required": [ "name" ], "title": "Project", "type": "object" } }, "additionalProperties": false, "required": [ "project" ] }
- Fields:
project (ddd.models.project.Project)
- pydantic model Project[source]
A project is a named list of components and/or sub-projects.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.project.Project" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Project</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>includes</td><td port="includes">tuple[str, ...]</td></tr></table>>,
tooltip="ddd.models.project.Project

A project is a named list of components and/or sub-projects.
"];
}](_images/graphviz-3f5afe5da16fa0e86ab5bc23390d55f7157ee231.png)
Show JSON schema
{ "title": "Project", "description": "A project is a named list of components and/or sub-projects.", "type": "object", "properties": { "name": { "description": "Name of the project; also the a2l project and module name.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the project.", "title": "Description", "type": "string" }, "includes": { "default": [], "description": "Paths to component, types, units, sections, constants or sub-project files,\nrelative to this file.\n\nShell style wildcards (``*``, ``?``, ``**``) are expanded; the kind of every\nincluded file is detected from its top level key.", "items": { "type": "string" }, "title": "Includes", "type": "array" } }, "additionalProperties": false, "required": [ "name" ] }
- Fields:
description (str)includes (tuple[str, ...])name (str)
- field name: Identifier [Required]
Name of the project; also the a2l project and module name.
- field description: str = ''
Free text describing the project.
- field includes: tuple[str, ...] = ()
Paths to component, types, units, sections, constants or sub-project files, relative to this file.
Shell style wildcards (
*,?,**) are expanded; the kind of every included file is detected from its top level key.Paths to component, types, units, sections, constants or sub-project files, relative to this file.
Shell style wildcards (
*,?,**) are expanded; the kind of every included file is detected from its top level key.
Software component description
- pydantic model ComponentFile[source]
Root object of a
*.ddd.jsonsoftware component description.componentis the top level key that makes this a component file rather than a project or a types file; DDD decides what a file is from that key alone, so exactly one of them appears here.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.component.Component" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Component</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>interface</td><td port="interface">tuple[Declaration, ...]</td></tr><tr><td>types</td><td port="types">Optional[tuple[StructType | ScalarType | ExternalType, ...]]</td></tr><tr><td>constants</td><td port="constants">Optional[tuple[ConstantDeclaration, ...]]</td></tr></table>>,
tooltip="ddd.models.component.Component

The interface specification of one software component.
"];
"ddd.models.component.Declaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Declaration</b></td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>definition</td><td port="definition">Measurement | Parameter | ValueBlock | Curve | Map | Axis</td></tr></table>>,
tooltip="ddd.models.component.Declaration

One entry of the ``interface`` list of a component.
"];
"ddd.models.component.Component":interface:e -> "ddd.models.component.Declaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.constants.ConstantDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ConstantDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.constants.ConstantDeclaration

One named integer constant, declared once and named wherever a shape needs it.&#\
xA;"];
"ddd.models.component.Component":constants:e -> "ddd.models.constants.ConstantDeclaration":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.ExternalType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ExternalType</b></td></tr><tr><td>type</td><td port="type">Literal['external']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>header</td><td port="header">str</td></tr></table>>,
tooltip="ddd.models.types.ExternalType

A name for a c type that DDD does not declare: a hand written header defines it.

\
DDD generates no typedef for it and knows neither its layout nor its meaning - which is
the point: a driver's status word or \
an operating system's handle already has one
authoritative definition, and a copy of it in the description would drift. Only \
a
structure member may name one, as opaque storage that reaches the generated structure
verbatim; such a member states no \
unit, conversion or limits, because DDD does not check
meaning it cannot see.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.ExternalType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.ScalarType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ScalarType</b></td></tr><tr><td>type</td><td port="type">Literal['scalar']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr></table>>,
tooltip="ddd.models.types.ScalarType

A name for what a number means, so components agree by naming rather than by copying.
&#\
xA;Three components consuming an engine speed each used to write out the datatype, the unit,
the scaling and the limits, leaving \
DDD to notice when one of them was wrong. If all three
say ``Speed_t`` instead, there is nothing left to disagree about - which \
is checking turned
into construction.

It fixes exactly the four things that make two declarations interchangeable, \
and nothing
else. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:
they are properties \
of one object rather than of the type, and two measurements of the same
type may well differ in whether an interrupt writes \
one of them.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.ScalarType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.StructType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StructType</b></td></tr><tr><td>type</td><td port="type">Literal['struct']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[Member, ...]</td></tr></table>>,
tooltip="ddd.models.types.StructType

One structured datatype: a name and the members it lays out, in order.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.StructType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.component.ComponentFile" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ComponentFile</b></td></tr><tr><td>schema_reference</td><td port="schema_reference">str | None</td></tr><tr><td>component</td><td port="component">Component</td></tr></table>>,
tooltip="ddd.models.component.ComponentFile

Root object of a ``*.ddd.json`` software component description.

``component`` \
is the top level key that makes this a component file rather than a project
or a types file; DDD decides what a file is from \
that key alone, so exactly one of them
appears here.
"];
"ddd.models.component.ComponentFile":component:e -> "ddd.models.component.Component":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Axis" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Axis</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.AXIS]</td></tr><tr><td>size</td><td port="size">Union[int, str]</td></tr><tr><td>input</td><td port="input">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.Axis

Shared axis points; several curves and maps may be interpolated over one axis.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Axis":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Curve</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.CURVE]</td></tr><tr><td>axis</td><td port="axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Curve

A one dimensional calibratable table.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Curve":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Map</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MAP]</td></tr><tr><td>x_axis</td><td port="x_axis">str</td></tr><tr><td>y_axis</td><td port="y_axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Map

A two dimensional calibratable table, stored as ``[y][x]``.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Map":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Measurement</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MEASUREMENT]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.Measurement

An online value: written by the software, only measured by the calibration tool.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Measurement":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Parameter</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.PARAMETER]</td></tr></table>>,
tooltip="ddd.models.objects.Parameter

A single calibratable constant.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Parameter":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ValueBlock</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.VALUE_BLOCK]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.ValueBlock

An array of calibratable constants.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.ValueBlock":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Axis":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Member</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>member</td><td port="member">MemberKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">Optional[int]</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.models.types.Member

One member of a structure, in the order the structure declares it.

Order is significant: \
it is the order the c struct is generated in, and therefore the order
the compiler lays out. Reordering members of a released \
structure moves every address after
the change, which is why a comparison against a baseline reports it.
"];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.StructType":members:e -> "ddd.models.types.Member":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-0871c63616985d91a7f8f4de4ba95434769cfe5f.png)
Show JSON schema
{ "title": "DDD component description", "description": "Root object of a ``*.ddd.json`` software component description.\n\n``component`` is the top level key that makes this a component file rather than a project\nor a types file; DDD decides what a file is from that key alone, so exactly one of them\nappears here.", "type": "object", "properties": { "$schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Editor binding to a schema written by ``ddd schema -o``; not interpreted by DDD.", "title": "$Schema" }, "component": { "$ref": "#/$defs/Component", "description": "The component this file describes; the key that identifies the file as a component." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Axis": { "additionalProperties": false, "description": "Shared axis points; several curves and maps may be interpolated over one axis.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "axis", "title": "Kind", "type": "string" }, "size": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ], "description": "Number of axis points: an integer of at least 1, or the name of a declared\nconstant.", "title": "Size" }, "input": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement that indexes the axis; the a2l input quantity.", "title": "Input" } }, "required": [ "name", "volatile", "kind", "size" ], "title": "Axis", "type": "object" }, "Component": { "additionalProperties": false, "description": "The interface specification of one software component.", "properties": { "name": { "description": "Name of the component; every component of a project needs a distinct one.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the component, offered to the c templates.", "title": "Description", "type": "string" }, "interface": { "description": "The data interface: everything the component produces, consumes or keeps to itself.\n\nRequired with no default, so that a component with nothing to declare says so with an\nempty list rather than by a key that might merely have been forgotten - the same\nreasoning that makes ``volatile`` and ``kind`` required on a definition.", "items": { "$ref": "#/$defs/Declaration" }, "title": "Interface", "type": "array" }, "types": { "anyOf": [ { "items": { "discriminator": { "mapping": { "external": "#/$defs/ExternalType", "scalar": "#/$defs/ScalarType", "struct": "#/$defs/StructType" }, "propertyName": "type" }, "oneOf": [ { "$ref": "#/$defs/StructType" }, { "$ref": "#/$defs/ScalarType" }, { "$ref": "#/$defs/ExternalType" } ] }, "minItems": 1, "type": "array" }, { "type": "null" } ], "default": null, "description": "Declared types this component publishes, each entry exactly as a types file writes it.\n\nDeclaring them here co-locates a library's contract in one file; it does not scope it.\nThe names join the same project wide namespace as the types of the standalone files,\nevery consistency check applies to them unchanged, and any component of the project may\nname them. Types shared between several components, with no single owner to live inside,\nstay in a standalone types file.", "title": "Types" }, "constants": { "anyOf": [ { "items": { "$ref": "#/$defs/ConstantDeclaration" }, "minItems": 1, "type": "array" }, { "type": "null" } ], "default": null, "description": "Declared constants this component publishes, each entry exactly as a constants file\nwrites it.\n\nCo-located for the reason ``types`` may be, and no more scoped than they are: the names\njoin the same project wide namespace as the constants of the standalone files, and any\nshape of any component names one where it would state a number. ``units`` and\n``sections`` remain project wide vocabularies and have no place inside a component.", "title": "Constants" } }, "required": [ "name", "interface" ], "title": "Component", "type": "object" }, "ConstantDeclaration": { "additionalProperties": false, "description": "One named integer constant, declared once and named wherever a shape needs it.", "properties": { "name": { "description": "The name a shape writes where it would state a number: ``PRESSURE_CELLS``.\n\nAn identifier, because the name reaches the generated code as an identifier of its own;\nthe templates receive every declared constant to emit.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The value, an integer of at least 1, written as a number.\n\nA literal only: an expression would put a parser and an evaluation order into a\ndescription format, and a constant cannot name another constant, so what cannot be\nwritten cannot cycle. At least 1 because the value is an array dimension, and an array\nof no elements is no array.", "minimum": 1, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the constant counts, e.g. ``cells of the pressure manifold``.\n\nThis is where the meaning of a size is written down once, instead of being implied by\nevery object that happens to be dimensioned by it.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "ConstantDeclaration", "type": "object" }, "Curve": { "additionalProperties": false, "description": "A one dimensional calibratable table.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "curve", "title": "Kind", "type": "string" }, "axis": { "description": "Name of the axis object the curve is interpolated over.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "axis" ], "title": "Curve", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "Declaration": { "additionalProperties": false, "description": "One entry of the ``interface`` list of a component.", "properties": { "scope": { "$ref": "#/$defs/Scope", "description": "Direction of the declaration, which is what makes the interfaces check each other.\n\nExactly one component may produce a name - declare it ``output`` or ``local`` - and that\ncomponent's definition is the one the project uses. Every ``input`` declaring the same\nname has to agree with it on datatype, unit, conversion, limits and shape." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "C preprocessor expression wrapping the generated declaration, e.g. ``defined(FEAT_X)``.\n\nOne expression, written as it would appear after ``#if``. It is emitted verbatim into the\ngenerated files, so it cannot span lines and cannot contain ``#``, ``//``, ``/*`` or\n``*/`` - each of which would let a description file put arbitrary directives, or live\ncode, into somebody else's build.", "title": "Condition" }, "definition": { "description": "The data object being declared; its ``kind`` decides which keys it carries.", "discriminator": { "mapping": { "axis": "#/$defs/Axis", "curve": "#/$defs/Curve", "map": "#/$defs/Map", "measurement": "#/$defs/Measurement", "parameter": "#/$defs/Parameter", "value_block": "#/$defs/ValueBlock" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/Measurement" }, { "$ref": "#/$defs/Parameter" }, { "$ref": "#/$defs/ValueBlock" }, { "$ref": "#/$defs/Curve" }, { "$ref": "#/$defs/Map" }, { "$ref": "#/$defs/Axis" } ], "title": "Definition" } }, "required": [ "scope", "definition" ], "title": "Declaration", "type": "object" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "ExternalType": { "additionalProperties": false, "description": "A name for a c type that DDD does not declare: a hand written header defines it.\n\nDDD generates no typedef for it and knows neither its layout nor its meaning - which is\nthe point: a driver's status word or an operating system's handle already has one\nauthoritative definition, and a copy of it in the description would drift. Only a\nstructure member may name one, as opaque storage that reaches the generated structure\nverbatim; such a member states no unit, conversion or limits, because DDD does not check\nmeaning it cannot see.", "properties": { "type": { "const": "external", "description": "Says this entry names an external type rather than declaring one of DDD's own.", "title": "Type", "type": "string" }, "name": { "description": "The type's c identifier, as the defining header spells it.\n\nEvery type of a project needs a distinct name, and the rules are those of the declared\ntypes: it cannot read as a base datatype, and it shares the project wide namespace with\nthe structures and the scalars.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "header": { "description": "The header that defines the type, spelled the way the generated inclusion writes it.\n\n``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form; a subdirectory\npath such as ``drivers/status.h`` is allowed in either.", "minLength": 1, "title": "Header", "type": "string" } }, "required": [ "type", "name", "header" ], "title": "ExternalType", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "Map": { "additionalProperties": false, "description": "A two dimensional calibratable table, stored as ``[y][x]``.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "map", "title": "Kind", "type": "string" }, "x_axis": { "description": "Name of the axis whose index runs fastest; the last dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "X Axis", "type": "string" }, "y_axis": { "description": "Name of the axis selecting the row; the first dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Y Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "x_axis", "y_axis" ], "title": "Map", "type": "object" }, "Measurement": { "additionalProperties": false, "description": "An online value: written by the software, only measured by the calibration tool.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "measurement", "title": "Kind", "type": "string" }, "dimensions": { "default": [], "description": "Array dimensions; empty for a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, in a\nconstants file or in a component - ``[3, 4]`` and ``[\"PRESSURE_CELLS\", 4]`` are both\nshapes.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind" ], "title": "Measurement", "type": "object" }, "Member": { "additionalProperties": false, "description": "One member of a structure, in the order the structure declares it.\n\nOrder is significant: it is the order the c struct is generated in, and therefore the order\nthe compiler lays out. Reordering members of a released structure moves every address after\nthe change, which is why a comparison against a baseline reports it.", "properties": { "name": { "description": "Name of the member, unique within its structure.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "member": { "$ref": "#/$defs/MemberKind", "description": "Which shape this member has, and with it which other keys the member may carry.\n\n* ``value`` needs ``datatype`` or ``typename`` and may add ``dimensions``,\n* ``bits`` needs ``datatype`` and ``bits``.\n\nA key belonging to the other shape is refused rather than ignored: ``bits`` together with\n``dimensions`` has no single meaning - c has no array of bitfields - and quietly dropping\none of the two would put a structure in the generated c that this file does not describe." }, "description": { "default": "", "description": "Free text describing the member, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of this member, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated, here exactly as on a declaration." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a declared type, stated instead of ``datatype``.\n\nA ``value`` member may name a structure, which nests it, a scalar type, which fixes what\nits number means, or an external type, which makes it opaque storage a hand written header\ndefines. A ``bits`` member states a base integer ``datatype``: a bitfield has no room for\na structure, and a scalar type would carry limits the width contradicts.", "title": "Typename" }, "dimensions": { "default": [], "description": "Array dimensions of a ``value`` member, in c declaration order; empty for a scalar.\n\n``[4, 2]`` is declared as ``[4][2]``, the last dimension running fastest in memory.\nEach dimension is an integer of at least 1, or the name of a constant the project\ndeclares, exactly as on a declaration.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "exclusiveMinimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width of a ``bits`` member, in bits; required on one, refused on the other.\n\nIt has to fit the datatype carrying it - at most 16 in a ``uint16`` - and that datatype\nhas to be an integer, since c allows a bitfield in nothing else.", "title": "Bits" }, "unit": { "default": "", "description": "Physical unit of this member, e.g. ``\"degC\"``.\n\nWritten here, or fixed by a scalar type this member names, and never both. Which of the\ntwo to reach for is a question of whether the answer is shared: a unit written here says it\nfor this member of this structure, and a ``Temperature_t`` says it for everything that\nnames it, across every component of the project.", "title": "Unit", "type": "string" }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How this member's raw value maps to a physical one: identity, linear or an enumeration.\n\nRequired on a member whose storage is a base ``datatype``, exactly as on a definition;\na member naming a scalar ``typename`` states none, the type fixing it.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of this member; derived from its storage and conversion if omitted.\n\nFor a ``bits`` member the derivation uses the *width*, not the datatype carrying it: a two\nbit field offered to a calibration tool as ``0 .. 65535`` invites somebody to enter a value\nthe field cannot hold and the software then reads back something else." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this member asks of the a2l file once the structure is flattened into it.\n\nPer member rather than per structure, because that is the granularity the a2l ends up with:\neach member becomes an object of its own, so keeping one of them out of the file, or giving\none of them a display format, is a decision about that member alone." } }, "required": [ "name", "member" ], "title": "Member", "type": "object" }, "MemberKind": { "description": "What shape a structure member has.\n\nStated rather than inferred from which keys are present: a file that omits a key by mistake\nshould be told which member shape it failed to describe, not silently become another one.\nA forgotten ``bits`` would otherwise turn a one bit flag into a full width member and move\nevery offset after it.", "enum": [ "value", "bits" ], "title": "MemberKind", "type": "string" }, "Parameter": { "additionalProperties": false, "description": "A single calibratable constant.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "parameter", "title": "Kind", "type": "string" } }, "required": [ "name", "volatile", "kind" ], "title": "Parameter", "type": "object" }, "ScalarType": { "additionalProperties": false, "description": "A name for what a number means, so components agree by naming rather than by copying.\n\nThree components consuming an engine speed each used to write out the datatype, the unit,\nthe scaling and the limits, leaving DDD to notice when one of them was wrong. If all three\nsay ``Speed_t`` instead, there is nothing left to disagree about - which is checking turned\ninto construction.\n\nIt fixes exactly the four things that make two declarations interchangeable, and nothing\nelse. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:\nthey are properties of one object rather than of the type, and two measurements of the same\ntype may well differ in whether an interrupt writes one of them.", "properties": { "type": { "const": "scalar", "description": "Says this entry names a scalar rather than describing a structure.", "title": "Type", "type": "string" }, "name": { "description": "Name of the type; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, for the reason a structure's name is.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of the value: one of the base datatypes.\n\nA base datatype rather than another declared type, so that a scalar type cannot be defined\nin terms of a second one. A chain of names would have to be resolved, could form a cycle,\nand buys nothing a reader of the one entry could not already see." }, "unit": { "default": "", "description": "Physical unit of the value, e.g. ``\"rpm\"``.", "title": "Unit", "type": "string" }, "conversion": { "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired: fixing what a value means is the one job a scalar type has, and the identity\nis part of the answer rather than a silence to interpret.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits, in the unit above; derived from datatype and conversion if omitted." } }, "required": [ "type", "name", "datatype", "conversion" ], "title": "ScalarType", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" }, "StructType": { "additionalProperties": false, "description": "One structured datatype: a name and the members it lays out, in order.", "properties": { "type": { "const": "struct", "description": "Says this entry describes a structure; stated on every entry of a types file.", "title": "Type", "type": "string" }, "name": { "description": "Name of the structure; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, which would be a type nothing could ever refer to:\nwhere a name is written, a base datatype wins the union.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the structure, offered to the c templates.", "title": "Description", "type": "string" }, "members": { "description": "The members, in the order they are laid out.", "items": { "$ref": "#/$defs/Member" }, "minItems": 1, "title": "Members", "type": "array" } }, "required": [ "type", "name", "members" ], "title": "StructType", "type": "object" }, "ValueBlock": { "additionalProperties": false, "description": "An array of calibratable constants.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "value_block", "title": "Kind", "type": "string" }, "dimensions": { "description": "Array dimensions in c declaration order; a value block is never a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, mixed\nfreely.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "minItems": 1, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind", "dimensions" ], "title": "ValueBlock", "type": "object" } }, "additionalProperties": false, "required": [ "component" ] }
- Fields:
component (ddd.models.component.Component)
- pydantic model Component[source]
The interface specification of one software component.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.component.Component" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Component</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>interface</td><td port="interface">tuple[Declaration, ...]</td></tr><tr><td>types</td><td port="types">Optional[tuple[StructType | ScalarType | ExternalType, ...]]</td></tr><tr><td>constants</td><td port="constants">Optional[tuple[ConstantDeclaration, ...]]</td></tr></table>>,
tooltip="ddd.models.component.Component

The interface specification of one software component.
"];
"ddd.models.component.Declaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Declaration</b></td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>definition</td><td port="definition">Measurement | Parameter | ValueBlock | Curve | Map | Axis</td></tr></table>>,
tooltip="ddd.models.component.Declaration

One entry of the ``interface`` list of a component.
"];
"ddd.models.component.Component":interface:e -> "ddd.models.component.Declaration":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.constants.ConstantDeclaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ConstantDeclaration</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.constants.ConstantDeclaration

One named integer constant, declared once and named wherever a shape needs it.&#\
xA;"];
"ddd.models.component.Component":constants:e -> "ddd.models.constants.ConstantDeclaration":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.ExternalType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ExternalType</b></td></tr><tr><td>type</td><td port="type">Literal['external']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>header</td><td port="header">str</td></tr></table>>,
tooltip="ddd.models.types.ExternalType

A name for a c type that DDD does not declare: a hand written header defines it.

\
DDD generates no typedef for it and knows neither its layout nor its meaning - which is
the point: a driver's status word or \
an operating system's handle already has one
authoritative definition, and a copy of it in the description would drift. Only \
a
structure member may name one, as opaque storage that reaches the generated structure
verbatim; such a member states no \
unit, conversion or limits, because DDD does not check
meaning it cannot see.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.ExternalType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.ScalarType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ScalarType</b></td></tr><tr><td>type</td><td port="type">Literal['scalar']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr></table>>,
tooltip="ddd.models.types.ScalarType

A name for what a number means, so components agree by naming rather than by copying.
&#\
xA;Three components consuming an engine speed each used to write out the datatype, the unit,
the scaling and the limits, leaving \
DDD to notice when one of them was wrong. If all three
say ``Speed_t`` instead, there is nothing left to disagree about - which \
is checking turned
into construction.

It fixes exactly the four things that make two declarations interchangeable, \
and nothing
else. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:
they are properties \
of one object rather than of the type, and two measurements of the same
type may well differ in whether an interrupt writes \
one of them.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.ScalarType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.StructType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StructType</b></td></tr><tr><td>type</td><td port="type">Literal['struct']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[Member, ...]</td></tr></table>>,
tooltip="ddd.models.types.StructType

One structured datatype: a name and the members it lays out, in order.
"];
"ddd.models.component.Component":types:e -> "ddd.models.types.StructType":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Axis</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.AXIS]</td></tr><tr><td>size</td><td port="size">Union[int, str]</td></tr><tr><td>input</td><td port="input">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.Axis

Shared axis points; several curves and maps may be interpolated over one axis.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Axis":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Curve</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.CURVE]</td></tr><tr><td>axis</td><td port="axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Curve

A one dimensional calibratable table.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Curve":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Map</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MAP]</td></tr><tr><td>x_axis</td><td port="x_axis">str</td></tr><tr><td>y_axis</td><td port="y_axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Map

A two dimensional calibratable table, stored as ``[y][x]``.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Map":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Measurement</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MEASUREMENT]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.Measurement

An online value: written by the software, only measured by the calibration tool.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Measurement":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Parameter</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.PARAMETER]</td></tr></table>>,
tooltip="ddd.models.objects.Parameter

A single calibratable constant.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Parameter":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ValueBlock</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.VALUE_BLOCK]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.ValueBlock

An array of calibratable constants.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.ValueBlock":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Axis":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Member</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>member</td><td port="member">MemberKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">Optional[int]</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.models.types.Member

One member of a structure, in the order the structure declares it.

Order is significant: \
it is the order the c struct is generated in, and therefore the order
the compiler lays out. Reordering members of a released \
structure moves every address after
the change, which is why a comparison against a baseline reports it.
"];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.StructType":members:e -> "ddd.models.types.Member":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-1c52dae3bc3c71acf9148a203ad5b0929b25062e.png)
Show JSON schema
{ "title": "Component", "description": "The interface specification of one software component.", "type": "object", "properties": { "name": { "description": "Name of the component; every component of a project needs a distinct one.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the component, offered to the c templates.", "title": "Description", "type": "string" }, "interface": { "description": "The data interface: everything the component produces, consumes or keeps to itself.\n\nRequired with no default, so that a component with nothing to declare says so with an\nempty list rather than by a key that might merely have been forgotten - the same\nreasoning that makes ``volatile`` and ``kind`` required on a definition.", "items": { "$ref": "#/$defs/Declaration" }, "title": "Interface", "type": "array" }, "types": { "anyOf": [ { "items": { "discriminator": { "mapping": { "external": "#/$defs/ExternalType", "scalar": "#/$defs/ScalarType", "struct": "#/$defs/StructType" }, "propertyName": "type" }, "oneOf": [ { "$ref": "#/$defs/StructType" }, { "$ref": "#/$defs/ScalarType" }, { "$ref": "#/$defs/ExternalType" } ] }, "minItems": 1, "type": "array" }, { "type": "null" } ], "default": null, "description": "Declared types this component publishes, each entry exactly as a types file writes it.\n\nDeclaring them here co-locates a library's contract in one file; it does not scope it.\nThe names join the same project wide namespace as the types of the standalone files,\nevery consistency check applies to them unchanged, and any component of the project may\nname them. Types shared between several components, with no single owner to live inside,\nstay in a standalone types file.", "title": "Types" }, "constants": { "anyOf": [ { "items": { "$ref": "#/$defs/ConstantDeclaration" }, "minItems": 1, "type": "array" }, { "type": "null" } ], "default": null, "description": "Declared constants this component publishes, each entry exactly as a constants file\nwrites it.\n\nCo-located for the reason ``types`` may be, and no more scoped than they are: the names\njoin the same project wide namespace as the constants of the standalone files, and any\nshape of any component names one where it would state a number. ``units`` and\n``sections`` remain project wide vocabularies and have no place inside a component.", "title": "Constants" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Axis": { "additionalProperties": false, "description": "Shared axis points; several curves and maps may be interpolated over one axis.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "axis", "title": "Kind", "type": "string" }, "size": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ], "description": "Number of axis points: an integer of at least 1, or the name of a declared\nconstant.", "title": "Size" }, "input": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement that indexes the axis; the a2l input quantity.", "title": "Input" } }, "required": [ "name", "volatile", "kind", "size" ], "title": "Axis", "type": "object" }, "ConstantDeclaration": { "additionalProperties": false, "description": "One named integer constant, declared once and named wherever a shape needs it.", "properties": { "name": { "description": "The name a shape writes where it would state a number: ``PRESSURE_CELLS``.\n\nAn identifier, because the name reaches the generated code as an identifier of its own;\nthe templates receive every declared constant to emit.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The value, an integer of at least 1, written as a number.\n\nA literal only: an expression would put a parser and an evaluation order into a\ndescription format, and a constant cannot name another constant, so what cannot be\nwritten cannot cycle. At least 1 because the value is an array dimension, and an array\nof no elements is no array.", "minimum": 1, "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the constant counts, e.g. ``cells of the pressure manifold``.\n\nThis is where the meaning of a size is written down once, instead of being implied by\nevery object that happens to be dimensioned by it.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "ConstantDeclaration", "type": "object" }, "Curve": { "additionalProperties": false, "description": "A one dimensional calibratable table.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "curve", "title": "Kind", "type": "string" }, "axis": { "description": "Name of the axis object the curve is interpolated over.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "axis" ], "title": "Curve", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "Declaration": { "additionalProperties": false, "description": "One entry of the ``interface`` list of a component.", "properties": { "scope": { "$ref": "#/$defs/Scope", "description": "Direction of the declaration, which is what makes the interfaces check each other.\n\nExactly one component may produce a name - declare it ``output`` or ``local`` - and that\ncomponent's definition is the one the project uses. Every ``input`` declaring the same\nname has to agree with it on datatype, unit, conversion, limits and shape." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "C preprocessor expression wrapping the generated declaration, e.g. ``defined(FEAT_X)``.\n\nOne expression, written as it would appear after ``#if``. It is emitted verbatim into the\ngenerated files, so it cannot span lines and cannot contain ``#``, ``//``, ``/*`` or\n``*/`` - each of which would let a description file put arbitrary directives, or live\ncode, into somebody else's build.", "title": "Condition" }, "definition": { "description": "The data object being declared; its ``kind`` decides which keys it carries.", "discriminator": { "mapping": { "axis": "#/$defs/Axis", "curve": "#/$defs/Curve", "map": "#/$defs/Map", "measurement": "#/$defs/Measurement", "parameter": "#/$defs/Parameter", "value_block": "#/$defs/ValueBlock" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/Measurement" }, { "$ref": "#/$defs/Parameter" }, { "$ref": "#/$defs/ValueBlock" }, { "$ref": "#/$defs/Curve" }, { "$ref": "#/$defs/Map" }, { "$ref": "#/$defs/Axis" } ], "title": "Definition" } }, "required": [ "scope", "definition" ], "title": "Declaration", "type": "object" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "ExternalType": { "additionalProperties": false, "description": "A name for a c type that DDD does not declare: a hand written header defines it.\n\nDDD generates no typedef for it and knows neither its layout nor its meaning - which is\nthe point: a driver's status word or an operating system's handle already has one\nauthoritative definition, and a copy of it in the description would drift. Only a\nstructure member may name one, as opaque storage that reaches the generated structure\nverbatim; such a member states no unit, conversion or limits, because DDD does not check\nmeaning it cannot see.", "properties": { "type": { "const": "external", "description": "Says this entry names an external type rather than declaring one of DDD's own.", "title": "Type", "type": "string" }, "name": { "description": "The type's c identifier, as the defining header spells it.\n\nEvery type of a project needs a distinct name, and the rules are those of the declared\ntypes: it cannot read as a base datatype, and it shares the project wide namespace with\nthe structures and the scalars.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "header": { "description": "The header that defines the type, spelled the way the generated inclusion writes it.\n\n``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form; a subdirectory\npath such as ``drivers/status.h`` is allowed in either.", "minLength": 1, "title": "Header", "type": "string" } }, "required": [ "type", "name", "header" ], "title": "ExternalType", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "Map": { "additionalProperties": false, "description": "A two dimensional calibratable table, stored as ``[y][x]``.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "map", "title": "Kind", "type": "string" }, "x_axis": { "description": "Name of the axis whose index runs fastest; the last dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "X Axis", "type": "string" }, "y_axis": { "description": "Name of the axis selecting the row; the first dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Y Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "x_axis", "y_axis" ], "title": "Map", "type": "object" }, "Measurement": { "additionalProperties": false, "description": "An online value: written by the software, only measured by the calibration tool.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "measurement", "title": "Kind", "type": "string" }, "dimensions": { "default": [], "description": "Array dimensions; empty for a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, in a\nconstants file or in a component - ``[3, 4]`` and ``[\"PRESSURE_CELLS\", 4]`` are both\nshapes.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind" ], "title": "Measurement", "type": "object" }, "Member": { "additionalProperties": false, "description": "One member of a structure, in the order the structure declares it.\n\nOrder is significant: it is the order the c struct is generated in, and therefore the order\nthe compiler lays out. Reordering members of a released structure moves every address after\nthe change, which is why a comparison against a baseline reports it.", "properties": { "name": { "description": "Name of the member, unique within its structure.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "member": { "$ref": "#/$defs/MemberKind", "description": "Which shape this member has, and with it which other keys the member may carry.\n\n* ``value`` needs ``datatype`` or ``typename`` and may add ``dimensions``,\n* ``bits`` needs ``datatype`` and ``bits``.\n\nA key belonging to the other shape is refused rather than ignored: ``bits`` together with\n``dimensions`` has no single meaning - c has no array of bitfields - and quietly dropping\none of the two would put a structure in the generated c that this file does not describe." }, "description": { "default": "", "description": "Free text describing the member, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of this member, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated, here exactly as on a declaration." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a declared type, stated instead of ``datatype``.\n\nA ``value`` member may name a structure, which nests it, a scalar type, which fixes what\nits number means, or an external type, which makes it opaque storage a hand written header\ndefines. A ``bits`` member states a base integer ``datatype``: a bitfield has no room for\na structure, and a scalar type would carry limits the width contradicts.", "title": "Typename" }, "dimensions": { "default": [], "description": "Array dimensions of a ``value`` member, in c declaration order; empty for a scalar.\n\n``[4, 2]`` is declared as ``[4][2]``, the last dimension running fastest in memory.\nEach dimension is an integer of at least 1, or the name of a constant the project\ndeclares, exactly as on a declaration.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "exclusiveMinimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width of a ``bits`` member, in bits; required on one, refused on the other.\n\nIt has to fit the datatype carrying it - at most 16 in a ``uint16`` - and that datatype\nhas to be an integer, since c allows a bitfield in nothing else.", "title": "Bits" }, "unit": { "default": "", "description": "Physical unit of this member, e.g. ``\"degC\"``.\n\nWritten here, or fixed by a scalar type this member names, and never both. Which of the\ntwo to reach for is a question of whether the answer is shared: a unit written here says it\nfor this member of this structure, and a ``Temperature_t`` says it for everything that\nnames it, across every component of the project.", "title": "Unit", "type": "string" }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How this member's raw value maps to a physical one: identity, linear or an enumeration.\n\nRequired on a member whose storage is a base ``datatype``, exactly as on a definition;\na member naming a scalar ``typename`` states none, the type fixing it.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of this member; derived from its storage and conversion if omitted.\n\nFor a ``bits`` member the derivation uses the *width*, not the datatype carrying it: a two\nbit field offered to a calibration tool as ``0 .. 65535`` invites somebody to enter a value\nthe field cannot hold and the software then reads back something else." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this member asks of the a2l file once the structure is flattened into it.\n\nPer member rather than per structure, because that is the granularity the a2l ends up with:\neach member becomes an object of its own, so keeping one of them out of the file, or giving\none of them a display format, is a decision about that member alone." } }, "required": [ "name", "member" ], "title": "Member", "type": "object" }, "MemberKind": { "description": "What shape a structure member has.\n\nStated rather than inferred from which keys are present: a file that omits a key by mistake\nshould be told which member shape it failed to describe, not silently become another one.\nA forgotten ``bits`` would otherwise turn a one bit flag into a full width member and move\nevery offset after it.", "enum": [ "value", "bits" ], "title": "MemberKind", "type": "string" }, "Parameter": { "additionalProperties": false, "description": "A single calibratable constant.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "parameter", "title": "Kind", "type": "string" } }, "required": [ "name", "volatile", "kind" ], "title": "Parameter", "type": "object" }, "ScalarType": { "additionalProperties": false, "description": "A name for what a number means, so components agree by naming rather than by copying.\n\nThree components consuming an engine speed each used to write out the datatype, the unit,\nthe scaling and the limits, leaving DDD to notice when one of them was wrong. If all three\nsay ``Speed_t`` instead, there is nothing left to disagree about - which is checking turned\ninto construction.\n\nIt fixes exactly the four things that make two declarations interchangeable, and nothing\nelse. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:\nthey are properties of one object rather than of the type, and two measurements of the same\ntype may well differ in whether an interrupt writes one of them.", "properties": { "type": { "const": "scalar", "description": "Says this entry names a scalar rather than describing a structure.", "title": "Type", "type": "string" }, "name": { "description": "Name of the type; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, for the reason a structure's name is.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of the value: one of the base datatypes.\n\nA base datatype rather than another declared type, so that a scalar type cannot be defined\nin terms of a second one. A chain of names would have to be resolved, could form a cycle,\nand buys nothing a reader of the one entry could not already see." }, "unit": { "default": "", "description": "Physical unit of the value, e.g. ``\"rpm\"``.", "title": "Unit", "type": "string" }, "conversion": { "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired: fixing what a value means is the one job a scalar type has, and the identity\nis part of the answer rather than a silence to interpret.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits, in the unit above; derived from datatype and conversion if omitted." } }, "required": [ "type", "name", "datatype", "conversion" ], "title": "ScalarType", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" }, "StructType": { "additionalProperties": false, "description": "One structured datatype: a name and the members it lays out, in order.", "properties": { "type": { "const": "struct", "description": "Says this entry describes a structure; stated on every entry of a types file.", "title": "Type", "type": "string" }, "name": { "description": "Name of the structure; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, which would be a type nothing could ever refer to:\nwhere a name is written, a base datatype wins the union.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the structure, offered to the c templates.", "title": "Description", "type": "string" }, "members": { "description": "The members, in the order they are laid out.", "items": { "$ref": "#/$defs/Member" }, "minItems": 1, "title": "Members", "type": "array" } }, "required": [ "type", "name", "members" ], "title": "StructType", "type": "object" }, "ValueBlock": { "additionalProperties": false, "description": "An array of calibratable constants.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "value_block", "title": "Kind", "type": "string" }, "dimensions": { "description": "Array dimensions in c declaration order; a value block is never a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, mixed\nfreely.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "minItems": 1, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind", "dimensions" ], "title": "ValueBlock", "type": "object" } }, "additionalProperties": false, "required": [ "name", "interface" ] }
- Fields:
constants (tuple[ddd.models.constants.ConstantDeclaration, ...] | None)description (str)interface (tuple[ddd.models.component.Declaration, ...])name (str)types (tuple[ddd.models.types.StructType | ddd.models.types.ScalarType | ddd.models.types.ExternalType, ...] | None)
- field name: Identifier [Required]
Name of the component; every component of a project needs a distinct one.
- field description: str = ''
Free text describing the component, offered to the c templates.
- field interface: tuple[Declaration, ...] [Required]
The data interface: everything the component produces, consumes or keeps to itself.
Required with no default, so that a component with nothing to declare says so with an empty list rather than by a key that might merely have been forgotten - the same reasoning that makes
volatileandkindrequired on a definition.The data interface: everything the component produces, consumes or keeps to itself.
Required with no default, so that a component with nothing to declare says so with an empty list rather than by a key that might merely have been forgotten - the same reasoning that makes
volatileandkindrequired on a definition.
- field types: Annotated[tuple[AnyType, ...], Field(min_length=1)] | None = None
Declared types this component publishes, each entry exactly as a types file writes it.
Declaring them here co-locates a library’s contract in one file; it does not scope it. The names join the same project wide namespace as the types of the standalone files, every consistency check applies to them unchanged, and any component of the project may name them. Types shared between several components, with no single owner to live inside, stay in a standalone types file.
Declared types this component publishes, each entry exactly as a types file writes it.
Declaring them here co-locates a library’s contract in one file; it does not scope it. The names join the same project wide namespace as the types of the standalone files, every consistency check applies to them unchanged, and any component of the project may name them. Types shared between several components, with no single owner to live inside, stay in a standalone types file.
- field constants: Annotated[tuple[ConstantDeclaration, ...], Field(min_length=1)] | None = None
Declared constants this component publishes, each entry exactly as a constants file writes it.
Co-located for the reason
typesmay be, and no more scoped than they are: the names join the same project wide namespace as the constants of the standalone files, and any shape of any component names one where it would state a number.unitsandsectionsremain project wide vocabularies and have no place inside a component.Declared constants this component publishes, each entry exactly as a constants file writes it.
Co-located for the reason
typesmay be, and no more scoped than they are: the names join the same project wide namespace as the constants of the standalone files, and any shape of any component names one where it would state a number.unitsandsectionsremain project wide vocabularies and have no place inside a component.
- pydantic model Declaration[source]
One entry of the
interfacelist of a component.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.component.Declaration" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Declaration</b></td></tr><tr><td>scope</td><td port="scope">Scope</td></tr><tr><td>condition</td><td port="condition">str | None</td></tr><tr><td>definition</td><td port="definition">Measurement | Parameter | ValueBlock | Curve | Map | Axis</td></tr></table>>,
tooltip="ddd.models.component.Declaration

One entry of the ``interface`` list of a component.
"];
"ddd.models.objects.Axis" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Axis</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.AXIS]</td></tr><tr><td>size</td><td port="size">Union[int, str]</td></tr><tr><td>input</td><td port="input">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.Axis

Shared axis points; several curves and maps may be interpolated over one axis.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Axis":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Curve</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.CURVE]</td></tr><tr><td>axis</td><td port="axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Curve

A one dimensional calibratable table.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Curve":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Map</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MAP]</td></tr><tr><td>x_axis</td><td port="x_axis">str</td></tr><tr><td>y_axis</td><td port="y_axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Map

A two dimensional calibratable table, stored as ``[y][x]``.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Map":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Measurement</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MEASUREMENT]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.Measurement

An online value: written by the software, only measured by the calibration tool.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Measurement":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Parameter</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.PARAMETER]</td></tr></table>>,
tooltip="ddd.models.objects.Parameter

A single calibratable constant.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.Parameter":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ValueBlock</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.VALUE_BLOCK]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.ValueBlock

An array of calibratable constants.
"];
"ddd.models.component.Declaration":definition:e -> "ddd.models.objects.ValueBlock":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Axis":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Curve":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-e87b1386be4cc300ae34ef04d0cd1a307284663f.png)
Show JSON schema
{ "title": "Declaration", "description": "One entry of the ``interface`` list of a component.", "type": "object", "properties": { "scope": { "$ref": "#/$defs/Scope", "description": "Direction of the declaration, which is what makes the interfaces check each other.\n\nExactly one component may produce a name - declare it ``output`` or ``local`` - and that\ncomponent's definition is the one the project uses. Every ``input`` declaring the same\nname has to agree with it on datatype, unit, conversion, limits and shape." }, "condition": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "C preprocessor expression wrapping the generated declaration, e.g. ``defined(FEAT_X)``.\n\nOne expression, written as it would appear after ``#if``. It is emitted verbatim into the\ngenerated files, so it cannot span lines and cannot contain ``#``, ``//``, ``/*`` or\n``*/`` - each of which would let a description file put arbitrary directives, or live\ncode, into somebody else's build.", "title": "Condition" }, "definition": { "description": "The data object being declared; its ``kind`` decides which keys it carries.", "discriminator": { "mapping": { "axis": "#/$defs/Axis", "curve": "#/$defs/Curve", "map": "#/$defs/Map", "measurement": "#/$defs/Measurement", "parameter": "#/$defs/Parameter", "value_block": "#/$defs/ValueBlock" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/Measurement" }, { "$ref": "#/$defs/Parameter" }, { "$ref": "#/$defs/ValueBlock" }, { "$ref": "#/$defs/Curve" }, { "$ref": "#/$defs/Map" }, { "$ref": "#/$defs/Axis" } ], "title": "Definition" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Axis": { "additionalProperties": false, "description": "Shared axis points; several curves and maps may be interpolated over one axis.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "axis", "title": "Kind", "type": "string" }, "size": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ], "description": "Number of axis points: an integer of at least 1, or the name of a declared\nconstant.", "title": "Size" }, "input": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement that indexes the axis; the a2l input quantity.", "title": "Input" } }, "required": [ "name", "volatile", "kind", "size" ], "title": "Axis", "type": "object" }, "Curve": { "additionalProperties": false, "description": "A one dimensional calibratable table.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "curve", "title": "Kind", "type": "string" }, "axis": { "description": "Name of the axis object the curve is interpolated over.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "axis" ], "title": "Curve", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "Map": { "additionalProperties": false, "description": "A two dimensional calibratable table, stored as ``[y][x]``.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "map", "title": "Kind", "type": "string" }, "x_axis": { "description": "Name of the axis whose index runs fastest; the last dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "X Axis", "type": "string" }, "y_axis": { "description": "Name of the axis selecting the row; the first dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Y Axis", "type": "string" } }, "required": [ "name", "volatile", "kind", "x_axis", "y_axis" ], "title": "Map", "type": "object" }, "Measurement": { "additionalProperties": false, "description": "An online value: written by the software, only measured by the calibration tool.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "measurement", "title": "Kind", "type": "string" }, "dimensions": { "default": [], "description": "Array dimensions; empty for a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, in a\nconstants file or in a component - ``[3, 4]`` and ``[\"PRESSURE_CELLS\", 4]`` are both\nshapes.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind" ], "title": "Measurement", "type": "object" }, "Parameter": { "additionalProperties": false, "description": "A single calibratable constant.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "parameter", "title": "Kind", "type": "string" } }, "required": [ "name", "volatile", "kind" ], "title": "Parameter", "type": "object" }, "Scope": { "description": "Direction of a variable with respect to the declaring component.", "enum": [ "input", "output", "local" ], "title": "Scope", "type": "string" }, "ValueBlock": { "additionalProperties": false, "description": "An array of calibratable constants.", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "value_block", "title": "Kind", "type": "string" }, "dimensions": { "description": "Array dimensions in c declaration order; a value block is never a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, mixed\nfreely.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "minItems": 1, "title": "Dimensions", "type": "array" } }, "required": [ "name", "volatile", "kind", "dimensions" ], "title": "ValueBlock", "type": "object" } }, "additionalProperties": false, "required": [ "scope", "definition" ] }
- Fields:
condition (str | None)definition (ddd.models.objects.Measurement | ddd.models.objects.Parameter | ddd.models.objects.ValueBlock | ddd.models.objects.Curve | ddd.models.objects.Map | ddd.models.objects.Axis)scope (ddd.models.component.Scope)
- field scope: Scope [Required]
Direction of the declaration, which is what makes the interfaces check each other.
Exactly one component may produce a name - declare it
outputorlocal- and that component’s definition is the one the project uses. Everyinputdeclaring the same name has to agree with it on datatype, unit, conversion, limits and shape.Direction of the declaration, which is what makes the interfaces check each other.
Exactly one component may produce a name - declare it
outputorlocal- and that component’s definition is the one the project uses. Everyinputdeclaring the same name has to agree with it on datatype, unit, conversion, limits and shape.
- field condition: str | None = None
C preprocessor expression wrapping the generated declaration, e.g.
defined(FEAT_X).One expression, written as it would appear after
#if. It is emitted verbatim into the generated files, so it cannot span lines and cannot contain#,//,/*or*/- each of which would let a description file put arbitrary directives, or live code, into somebody else’s build.C preprocessor expression wrapping the generated declaration, e.g.
defined(FEAT_X).One expression, written as it would appear after
#if. It is emitted verbatim into the generated files, so it cannot span lines and cannot contain#,//,/*or*/- each of which would let a description file put arbitrary directives, or live code, into somebody else’s build.
- field definition: AnyDataObject [Required]
The data object being declared; its
kinddecides which keys it carries.
Structured datatype description
The types file. A member states which shape it has and carries only the keys that shape needs; what it never carries is a bit position or an offset, because c leaves both to the compiler.
- pydantic model TypesFile[source]
Root object of a
*.ddd.jsontype description.typesis the top level key that makes this a types file rather than a project or a component file; DDD decides what a file is from that key alone, so exactly one of them appears here.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.types.ExternalType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ExternalType</b></td></tr><tr><td>type</td><td port="type">Literal['external']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>header</td><td port="header">str</td></tr></table>>,
tooltip="ddd.models.types.ExternalType

A name for a c type that DDD does not declare: a hand written header defines it.

\
DDD generates no typedef for it and knows neither its layout nor its meaning - which is
the point: a driver's status word or \
an operating system's handle already has one
authoritative definition, and a copy of it in the description would drift. Only \
a
structure member may name one, as opaque storage that reaches the generated structure
verbatim; such a member states no \
unit, conversion or limits, because DDD does not check
meaning it cannot see.
"];
"ddd.models.types.Member" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Member</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>member</td><td port="member">MemberKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">Optional[int]</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.models.types.Member

One member of a structure, in the order the structure declares it.

Order is significant: \
it is the order the c struct is generated in, and therefore the order
the compiler lays out. Reordering members of a released \
structure moves every address after
the change, which is why a comparison against a baseline reports it.
"];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ScalarType</b></td></tr><tr><td>type</td><td port="type">Literal['scalar']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">IdentityConversion | LinearConversion | EnumConversion</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr></table>>,
tooltip="ddd.models.types.ScalarType

A name for what a number means, so components agree by naming rather than by copying.
&#\
xA;Three components consuming an engine speed each used to write out the datatype, the unit,
the scaling and the limits, leaving \
DDD to notice when one of them was wrong. If all three
say ``Speed_t`` instead, there is nothing left to disagree about - which \
is checking turned
into construction.

It fixes exactly the four things that make two declarations interchangeable, \
and nothing
else. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:
they are properties \
of one object rather than of the type, and two measurements of the same
type may well differ in whether an interrupt writes \
one of them.
"];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.ScalarType":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.StructType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StructType</b></td></tr><tr><td>type</td><td port="type">Literal['struct']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[Member, ...]</td></tr></table>>,
tooltip="ddd.models.types.StructType

One structured datatype: a name and the members it lays out, in order.
"];
"ddd.models.types.StructType":members:e -> "ddd.models.types.Member":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.types.TypesFile" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>TypesFile</b></td></tr><tr><td>schema_reference</td><td port="schema_reference">str | None</td></tr><tr><td>types</td><td port="types">tuple[StructType | ScalarType | ExternalType, ...]</td></tr></table>>,
tooltip="ddd.models.types.TypesFile

Root object of a ``*.ddd.json`` type description.

``types`` is the top level key that \
makes this a types file rather than a project or a
component file; DDD decides what a file is from that key alone, so exactly \
one of them
appears here.
"];
"ddd.models.types.TypesFile":types:e -> "ddd.models.types.ExternalType":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.types.TypesFile":types:e -> "ddd.models.types.ScalarType":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.types.TypesFile":types:e -> "ddd.models.types.StructType":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-f742b5fafd35b4ad67fb09fc88ad67b1691e0da2.png)
Show JSON schema
{ "title": "DDD type description", "description": "Root object of a ``*.ddd.json`` type description.\n\n``types`` is the top level key that makes this a types file rather than a project or a\ncomponent file; DDD decides what a file is from that key alone, so exactly one of them\nappears here.", "type": "object", "properties": { "$schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Editor binding to a schema written by ``ddd schema -o``; not interpreted by DDD.", "title": "$Schema" }, "types": { "description": "The types this file declares.", "items": { "discriminator": { "mapping": { "external": "#/$defs/ExternalType", "scalar": "#/$defs/ScalarType", "struct": "#/$defs/StructType" }, "propertyName": "type" }, "oneOf": [ { "$ref": "#/$defs/StructType" }, { "$ref": "#/$defs/ScalarType" }, { "$ref": "#/$defs/ExternalType" } ] }, "minItems": 1, "title": "Types", "type": "array" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "ExternalType": { "additionalProperties": false, "description": "A name for a c type that DDD does not declare: a hand written header defines it.\n\nDDD generates no typedef for it and knows neither its layout nor its meaning - which is\nthe point: a driver's status word or an operating system's handle already has one\nauthoritative definition, and a copy of it in the description would drift. Only a\nstructure member may name one, as opaque storage that reaches the generated structure\nverbatim; such a member states no unit, conversion or limits, because DDD does not check\nmeaning it cannot see.", "properties": { "type": { "const": "external", "description": "Says this entry names an external type rather than declaring one of DDD's own.", "title": "Type", "type": "string" }, "name": { "description": "The type's c identifier, as the defining header spells it.\n\nEvery type of a project needs a distinct name, and the rules are those of the declared\ntypes: it cannot read as a base datatype, and it shares the project wide namespace with\nthe structures and the scalars.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "header": { "description": "The header that defines the type, spelled the way the generated inclusion writes it.\n\n``my_driver.h`` for the quoted form, ``<os_types.h>`` for the angle form; a subdirectory\npath such as ``drivers/status.h`` is allowed in either.", "minLength": 1, "title": "Header", "type": "string" } }, "required": [ "type", "name", "header" ], "title": "ExternalType", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "Member": { "additionalProperties": false, "description": "One member of a structure, in the order the structure declares it.\n\nOrder is significant: it is the order the c struct is generated in, and therefore the order\nthe compiler lays out. Reordering members of a released structure moves every address after\nthe change, which is why a comparison against a baseline reports it.", "properties": { "name": { "description": "Name of the member, unique within its structure.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "member": { "$ref": "#/$defs/MemberKind", "description": "Which shape this member has, and with it which other keys the member may carry.\n\n* ``value`` needs ``datatype`` or ``typename`` and may add ``dimensions``,\n* ``bits`` needs ``datatype`` and ``bits``.\n\nA key belonging to the other shape is refused rather than ignored: ``bits`` together with\n``dimensions`` has no single meaning - c has no array of bitfields - and quietly dropping\none of the two would put a structure in the generated c that this file does not describe." }, "description": { "default": "", "description": "Free text describing the member, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of this member, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated, here exactly as on a declaration." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a declared type, stated instead of ``datatype``.\n\nA ``value`` member may name a structure, which nests it, a scalar type, which fixes what\nits number means, or an external type, which makes it opaque storage a hand written header\ndefines. A ``bits`` member states a base integer ``datatype``: a bitfield has no room for\na structure, and a scalar type would carry limits the width contradicts.", "title": "Typename" }, "dimensions": { "default": [], "description": "Array dimensions of a ``value`` member, in c declaration order; empty for a scalar.\n\n``[4, 2]`` is declared as ``[4][2]``, the last dimension running fastest in memory.\nEach dimension is an integer of at least 1, or the name of a constant the project\ndeclares, exactly as on a declaration.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "exclusiveMinimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width of a ``bits`` member, in bits; required on one, refused on the other.\n\nIt has to fit the datatype carrying it - at most 16 in a ``uint16`` - and that datatype\nhas to be an integer, since c allows a bitfield in nothing else.", "title": "Bits" }, "unit": { "default": "", "description": "Physical unit of this member, e.g. ``\"degC\"``.\n\nWritten here, or fixed by a scalar type this member names, and never both. Which of the\ntwo to reach for is a question of whether the answer is shared: a unit written here says it\nfor this member of this structure, and a ``Temperature_t`` says it for everything that\nnames it, across every component of the project.", "title": "Unit", "type": "string" }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How this member's raw value maps to a physical one: identity, linear or an enumeration.\n\nRequired on a member whose storage is a base ``datatype``, exactly as on a definition;\na member naming a scalar ``typename`` states none, the type fixing it.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of this member; derived from its storage and conversion if omitted.\n\nFor a ``bits`` member the derivation uses the *width*, not the datatype carrying it: a two\nbit field offered to a calibration tool as ``0 .. 65535`` invites somebody to enter a value\nthe field cannot hold and the software then reads back something else." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this member asks of the a2l file once the structure is flattened into it.\n\nPer member rather than per structure, because that is the granularity the a2l ends up with:\neach member becomes an object of its own, so keeping one of them out of the file, or giving\none of them a display format, is a decision about that member alone." } }, "required": [ "name", "member" ], "title": "Member", "type": "object" }, "MemberKind": { "description": "What shape a structure member has.\n\nStated rather than inferred from which keys are present: a file that omits a key by mistake\nshould be told which member shape it failed to describe, not silently become another one.\nA forgotten ``bits`` would otherwise turn a one bit flag into a full width member and move\nevery offset after it.", "enum": [ "value", "bits" ], "title": "MemberKind", "type": "string" }, "ScalarType": { "additionalProperties": false, "description": "A name for what a number means, so components agree by naming rather than by copying.\n\nThree components consuming an engine speed each used to write out the datatype, the unit,\nthe scaling and the limits, leaving DDD to notice when one of them was wrong. If all three\nsay ``Speed_t`` instead, there is nothing left to disagree about - which is checking turned\ninto construction.\n\nIt fixes exactly the four things that make two declarations interchangeable, and nothing\nelse. ``kind``, ``dimensions``, ``init``, ``volatile`` and ``a2l`` stay on the variable:\nthey are properties of one object rather than of the type, and two measurements of the same\ntype may well differ in whether an interrupt writes one of them.", "properties": { "type": { "const": "scalar", "description": "Says this entry names a scalar rather than describing a structure.", "title": "Type", "type": "string" }, "name": { "description": "Name of the type; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, for the reason a structure's name is.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing what the type is, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "$ref": "#/$defs/Datatype", "description": "Storage of the value: one of the base datatypes.\n\nA base datatype rather than another declared type, so that a scalar type cannot be defined\nin terms of a second one. A chain of names would have to be resolved, could form a cycle,\nand buys nothing a reader of the one entry could not already see." }, "unit": { "default": "", "description": "Physical unit of the value, e.g. ``\"rpm\"``.", "title": "Unit", "type": "string" }, "conversion": { "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired: fixing what a value means is the one job a scalar type has, and the identity\nis part of the answer rather than a silence to interpret.", "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ], "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits, in the unit above; derived from datatype and conversion if omitted." } }, "required": [ "type", "name", "datatype", "conversion" ], "title": "ScalarType", "type": "object" }, "StructType": { "additionalProperties": false, "description": "One structured datatype: a name and the members it lays out, in order.", "properties": { "type": { "const": "struct", "description": "Says this entry describes a structure; stated on every entry of a types file.", "title": "Type", "type": "string" }, "name": { "description": "Name of the structure; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, which would be a type nothing could ever refer to:\nwhere a name is written, a base datatype wins the union.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the structure, offered to the c templates.", "title": "Description", "type": "string" }, "members": { "description": "The members, in the order they are laid out.", "items": { "$ref": "#/$defs/Member" }, "minItems": 1, "title": "Members", "type": "array" } }, "required": [ "type", "name", "members" ], "title": "StructType", "type": "object" } }, "additionalProperties": false, "required": [ "types" ] }
- Fields:
types (tuple[ddd.models.types.StructType | ddd.models.types.ScalarType | ddd.models.types.ExternalType, ...])
- field types: tuple[AnyType, ...] [Required]
The types this file declares.
- Constraints:
min_length = 1
- pydantic model StructType[source]
One structured datatype: a name and the members it lays out, in order.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.types.Member" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Member</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>member</td><td port="member">MemberKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">Optional[int]</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.models.types.Member

One member of a structure, in the order the structure declares it.

Order is significant: \
it is the order the c struct is generated in, and therefore the order
the compiler lays out. Reordering members of a released \
structure moves every address after
the change, which is why a comparison against a baseline reports it.
"];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.StructType" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>StructType</b></td></tr><tr><td>type</td><td port="type">Literal['struct']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>members</td><td port="members">tuple[Member, ...]</td></tr></table>>,
tooltip="ddd.models.types.StructType

One structured datatype: a name and the members it lays out, in order.
"];
"ddd.models.types.StructType":members:e -> "ddd.models.types.Member":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-08438fc0f1776595e1a7b7b38bc3beb0516a3582.png)
Show JSON schema
{ "title": "StructType", "description": "One structured datatype: a name and the members it lays out, in order.", "type": "object", "properties": { "type": { "const": "struct", "description": "Says this entry describes a structure; stated on every entry of a types file.", "title": "Type", "type": "string" }, "name": { "description": "Name of the structure; every type of a project needs a distinct one.\n\nRefused if it reads as a base datatype, which would be a type nothing could ever refer to:\nwhere a name is written, a base datatype wins the union.", "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "description": { "default": "", "description": "Free text describing the structure, offered to the c templates.", "title": "Description", "type": "string" }, "members": { "description": "The members, in the order they are laid out.", "items": { "$ref": "#/$defs/Member" }, "minItems": 1, "title": "Members", "type": "array" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "Member": { "additionalProperties": false, "description": "One member of a structure, in the order the structure declares it.\n\nOrder is significant: it is the order the c struct is generated in, and therefore the order\nthe compiler lays out. Reordering members of a released structure moves every address after\nthe change, which is why a comparison against a baseline reports it.", "properties": { "name": { "description": "Name of the member, unique within its structure.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "member": { "$ref": "#/$defs/MemberKind", "description": "Which shape this member has, and with it which other keys the member may carry.\n\n* ``value`` needs ``datatype`` or ``typename`` and may add ``dimensions``,\n* ``bits`` needs ``datatype`` and ``bits``.\n\nA key belonging to the other shape is refused rather than ignored: ``bits`` together with\n``dimensions`` has no single meaning - c has no array of bitfields - and quietly dropping\none of the two would put a structure in the generated c that this file does not describe." }, "description": { "default": "", "description": "Free text describing the member, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of this member, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated, here exactly as on a declaration." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a declared type, stated instead of ``datatype``.\n\nA ``value`` member may name a structure, which nests it, a scalar type, which fixes what\nits number means, or an external type, which makes it opaque storage a hand written header\ndefines. A ``bits`` member states a base integer ``datatype``: a bitfield has no room for\na structure, and a scalar type would carry limits the width contradicts.", "title": "Typename" }, "dimensions": { "default": [], "description": "Array dimensions of a ``value`` member, in c declaration order; empty for a scalar.\n\n``[4, 2]`` is declared as ``[4][2]``, the last dimension running fastest in memory.\nEach dimension is an integer of at least 1, or the name of a constant the project\ndeclares, exactly as on a declaration.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "exclusiveMinimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width of a ``bits`` member, in bits; required on one, refused on the other.\n\nIt has to fit the datatype carrying it - at most 16 in a ``uint16`` - and that datatype\nhas to be an integer, since c allows a bitfield in nothing else.", "title": "Bits" }, "unit": { "default": "", "description": "Physical unit of this member, e.g. ``\"degC\"``.\n\nWritten here, or fixed by a scalar type this member names, and never both. Which of the\ntwo to reach for is a question of whether the answer is shared: a unit written here says it\nfor this member of this structure, and a ``Temperature_t`` says it for everything that\nnames it, across every component of the project.", "title": "Unit", "type": "string" }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How this member's raw value maps to a physical one: identity, linear or an enumeration.\n\nRequired on a member whose storage is a base ``datatype``, exactly as on a definition;\na member naming a scalar ``typename`` states none, the type fixing it.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of this member; derived from its storage and conversion if omitted.\n\nFor a ``bits`` member the derivation uses the *width*, not the datatype carrying it: a two\nbit field offered to a calibration tool as ``0 .. 65535`` invites somebody to enter a value\nthe field cannot hold and the software then reads back something else." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this member asks of the a2l file once the structure is flattened into it.\n\nPer member rather than per structure, because that is the granularity the a2l ends up with:\neach member becomes an object of its own, so keeping one of them out of the file, or giving\none of them a display format, is a decision about that member alone." } }, "required": [ "name", "member" ], "title": "Member", "type": "object" }, "MemberKind": { "description": "What shape a structure member has.\n\nStated rather than inferred from which keys are present: a file that omits a key by mistake\nshould be told which member shape it failed to describe, not silently become another one.\nA forgotten ``bits`` would otherwise turn a one bit flag into a full width member and move\nevery offset after it.", "enum": [ "value", "bits" ], "title": "MemberKind", "type": "string" } }, "additionalProperties": false, "required": [ "type", "name", "members" ] }
- Fields:
description (str)members (tuple[ddd.models.types.Member, ...])name (str)type (Literal['struct'])
- field type: Literal['struct'] [Required]
Says this entry describes a structure; stated on every entry of a types file.
- field name: TypeName [Required]
Name of the structure; every type of a project needs a distinct one.
Refused if it reads as a base datatype, which would be a type nothing could ever refer to: where a name is written, a base datatype wins the union.
Name of the structure; every type of a project needs a distinct one.
Refused if it reads as a base datatype, which would be a type nothing could ever refer to: where a name is written, a base datatype wins the union.
- field description: str = ''
Free text describing the structure, offered to the c templates.
- pydantic model Member[source]
One member of a structure, in the order the structure declares it.
Order is significant: it is the order the c struct is generated in, and therefore the order the compiler lays out. Reordering members of a released structure moves every address after the change, which is why a comparison against a baseline reports it.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.types.Member" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Member</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>member</td><td port="member">MemberKind</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr><tr><td>bits</td><td port="bits">Optional[int]</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr></table>>,
tooltip="ddd.models.types.Member

One member of a structure, in the order the structure declares it.

Order is significant: \
it is the order the c struct is generated in, and therefore the order
the compiler lays out. Reordering members of a released \
structure moves every address after
the change, which is why a comparison against a baseline reports it.
"];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.types.Member":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.types.Member":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-8ecd12f4b54fb5be6793a3cb6e7d8de940007c09.png)
Show JSON schema
{ "title": "Member", "description": "One member of a structure, in the order the structure declares it.\n\nOrder is significant: it is the order the c struct is generated in, and therefore the order\nthe compiler lays out. Reordering members of a released structure moves every address after\nthe change, which is why a comparison against a baseline reports it.", "type": "object", "properties": { "name": { "description": "Name of the member, unique within its structure.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "member": { "$ref": "#/$defs/MemberKind", "description": "Which shape this member has, and with it which other keys the member may carry.\n\n* ``value`` needs ``datatype`` or ``typename`` and may add ``dimensions``,\n* ``bits`` needs ``datatype`` and ``bits``.\n\nA key belonging to the other shape is refused rather than ignored: ``bits`` together with\n``dimensions`` has no single meaning - c has no array of bitfields - and quietly dropping\none of the two would put a structure in the generated c that this file does not describe." }, "description": { "default": "", "description": "Free text describing the member, offered to the c templates.", "title": "Description", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of this member, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated, here exactly as on a declaration." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a declared type, stated instead of ``datatype``.\n\nA ``value`` member may name a structure, which nests it, a scalar type, which fixes what\nits number means, or an external type, which makes it opaque storage a hand written header\ndefines. A ``bits`` member states a base integer ``datatype``: a bitfield has no room for\na structure, and a scalar type would carry limits the width contradicts.", "title": "Typename" }, "dimensions": { "default": [], "description": "Array dimensions of a ``value`` member, in c declaration order; empty for a scalar.\n\n``[4, 2]`` is declared as ``[4][2]``, the last dimension running fastest in memory.\nEach dimension is an integer of at least 1, or the name of a constant the project\ndeclares, exactly as on a declaration.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" }, "bits": { "anyOf": [ { "exclusiveMinimum": 0, "type": "integer" }, { "type": "null" } ], "default": null, "description": "Width of a ``bits`` member, in bits; required on one, refused on the other.\n\nIt has to fit the datatype carrying it - at most 16 in a ``uint16`` - and that datatype\nhas to be an integer, since c allows a bitfield in nothing else.", "title": "Bits" }, "unit": { "default": "", "description": "Physical unit of this member, e.g. ``\"degC\"``.\n\nWritten here, or fixed by a scalar type this member names, and never both. Which of the\ntwo to reach for is a question of whether the answer is shared: a unit written here says it\nfor this member of this structure, and a ``Temperature_t`` says it for everything that\nnames it, across every component of the project.", "title": "Unit", "type": "string" }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How this member's raw value maps to a physical one: identity, linear or an enumeration.\n\nRequired on a member whose storage is a base ``datatype``, exactly as on a definition;\na member naming a scalar ``typename`` states none, the type fixing it.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of this member; derived from its storage and conversion if omitted.\n\nFor a ``bits`` member the derivation uses the *width*, not the datatype carrying it: a two\nbit field offered to a calibration tool as ``0 .. 65535`` invites somebody to enter a value\nthe field cannot hold and the software then reads back something else." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this member asks of the a2l file once the structure is flattened into it.\n\nPer member rather than per structure, because that is the granularity the a2l ends up with:\neach member becomes an object of its own, so keeping one of them out of the file, or giving\none of them a display format, is a decision about that member alone." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "MemberKind": { "description": "What shape a structure member has.\n\nStated rather than inferred from which keys are present: a file that omits a key by mistake\nshould be told which member shape it failed to describe, not silently become another one.\nA forgotten ``bits`` would otherwise turn a one bit flag into a full width member and move\nevery offset after it.", "enum": [ "value", "bits" ], "title": "MemberKind", "type": "string" } }, "additionalProperties": false, "required": [ "name", "member" ] }
- Fields:
a2l (ddd.models.objects.A2lObjectOptions)bits (int | None)conversion (ddd.models.conversion.IdentityConversion | ddd.models.conversion.LinearConversion | ddd.models.conversion.EnumConversion | None)datatype (ddd.models.common.Datatype | None)description (str)dimensions (tuple[int | str, ...])limits (ddd.models.objects.Limits | None)member (ddd.models.types.MemberKind)name (str)typename (str | None)unit (str)
- field name: Identifier [Required]
Name of the member, unique within its structure.
- field member: MemberKind [Required]
Which shape this member has, and with it which other keys the member may carry.
valueneedsdatatypeortypenameand may adddimensions,bitsneedsdatatypeandbits.
A key belonging to the other shape is refused rather than ignored:
bitstogether withdimensionshas no single meaning - c has no array of bitfields - and quietly dropping one of the two would put a structure in the generated c that this file does not describe.Which shape this member has, and with it which other keys the member may carry.
valueneedsdatatypeortypenameand may adddimensions,bitsneedsdatatypeandbits.
A key belonging to the other shape is refused rather than ignored:
bitstogether withdimensionshas no single meaning - c has no array of bitfields - and quietly dropping one of the two would put a structure in the generated c that this file does not describe.
- field description: str = ''
Free text describing the member, offered to the c templates.
- field datatype: Datatype | None = None
Storage of this member, one of the eleven base datatypes.
Exactly one of
datatypeandtypenameis stated, here exactly as on a declaration.
- field typename: TypeName | None = None
Name of a declared type, stated instead of
datatype.A
valuemember may name a structure, which nests it, a scalar type, which fixes what its number means, or an external type, which makes it opaque storage a hand written header defines. Abitsmember states a base integerdatatype: a bitfield has no room for a structure, and a scalar type would carry limits the width contradicts.Name of a declared type, stated instead of
datatype.A
valuemember may name a structure, which nests it, a scalar type, which fixes what its number means, or an external type, which makes it opaque storage a hand written header defines. Abitsmember states a base integerdatatype: a bitfield has no room for a structure, and a scalar type would carry limits the width contradicts.
- field dimensions: tuple[Dimension, ...] = ()
Array dimensions of a
valuemember, in c declaration order; empty for a scalar.[4, 2]is declared as[4][2], the last dimension running fastest in memory. Each dimension is an integer of at least 1, or the name of a constant the project declares, exactly as on a declaration.Array dimensions of a
valuemember, in c declaration order; empty for a scalar.[4, 2]is declared as[4][2], the last dimension running fastest in memory. Each dimension is an integer of at least 1, or the name of a constant the project declares, exactly as on a declaration.
- field bits: PositiveInt | None = None
Width of a
bitsmember, in bits; required on one, refused on the other.It has to fit the datatype carrying it - at most 16 in a
uint16- and that datatype has to be an integer, since c allows a bitfield in nothing else.Width of a
bitsmember, in bits; required on one, refused on the other.It has to fit the datatype carrying it - at most 16 in a
uint16- and that datatype has to be an integer, since c allows a bitfield in nothing else.
- field unit: str = ''
Physical unit of this member, e.g.
"degC".Written here, or fixed by a scalar type this member names, and never both. Which of the two to reach for is a question of whether the answer is shared: a unit written here says it for this member of this structure, and a
Temperature_tsays it for everything that names it, across every component of the project.Physical unit of this member, e.g.
"degC".Written here, or fixed by a scalar type this member names, and never both. Which of the two to reach for is a question of whether the answer is shared: a unit written here says it for this member of this structure, and a
Temperature_tsays it for everything that names it, across every component of the project.
- field conversion: Conversion | None = None
How this member’s raw value maps to a physical one: identity, linear or an enumeration.
Required on a member whose storage is a base
datatype, exactly as on a definition; a member naming a scalartypenamestates none, the type fixing it.How this member’s raw value maps to a physical one: identity, linear or an enumeration.
Required on a member whose storage is a base
datatype, exactly as on a definition; a member naming a scalartypenamestates none, the type fixing it.
- field limits: Limits | None = None
Physical limits of this member; derived from its storage and conversion if omitted.
For a
bitsmember the derivation uses the width, not the datatype carrying it: a two bit field offered to a calibration tool as0 .. 65535invites somebody to enter a value the field cannot hold and the software then reads back something else.Physical limits of this member; derived from its storage and conversion if omitted.
For a
bitsmember the derivation uses the width, not the datatype carrying it: a two bit field offered to a calibration tool as0 .. 65535invites somebody to enter a value the field cannot hold and the software then reads back something else.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
What this member asks of the a2l file once the structure is flattened into it.
Per member rather than per structure, because that is the granularity the a2l ends up with: each member becomes an object of its own, so keeping one of them out of the file, or giving one of them a display format, is a decision about that member alone.
What this member asks of the a2l file once the structure is flattened into it.
Per member rather than per structure, because that is the granularity the a2l ends up with: each member becomes an object of its own, so keeping one of them out of the file, or giving one of them a display format, is a decision about that member alone.
Data objects
The definition of a declaration is a tagged union discriminated on kind, and kind
is required on every definition - a measurement states "kind": "measurement" like every
other. A defaulted discriminator would leave a bare definition matching more than one variant
in the published schema, which an editor validating the file reports as an ambiguity; stating
it keeps the schema and the loader in agreement. ddd.models.DataObject holds what all six
kinds have in common, and the six models after it document only what their own kind adds;
the json schema shown with each of them is nevertheless the complete document a declaration
of that kind is validated against. volatile is one of the common fields, and one of the five
an author always has to write - the others are name, kind, the storage (exactly one of
datatype and typename) and, whenever datatype is the one stated, conversion. It
carries no
default because there is no answer DDD could derive from the rest of the description, so a
definition that leaves it out is a schema finding like any other missing field.
- pydantic model DataObject[source]
Attributes shared by every kind of data object.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.DataObject" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>DataObject</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">ObjectKind</td></tr></table>>,
tooltip="ddd.models.objects.DataObject

Attributes shared by every kind of data object.
"];
"ddd.models.objects.DataObject":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.DataObject":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.DataObject":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.DataObject":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.DataObject":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-eb3f961c06516b80bad38c5f0fb235dfe6d177ce.png)
Show JSON schema
{ "title": "DataObject", "description": "Attributes shared by every kind of data object.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "$ref": "#/$defs/ObjectKind", "description": "Which sort of object this is; stated on every definition.\n\nIt also decides which further keys the definition may carry: ``dimensions`` on a\nmeasurement or a value block, ``size`` and ``input`` on an axis, ``axis`` on a curve,\n``x_axis`` and ``y_axis`` on a map, and none of them on a parameter." } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" }, "ObjectKind": { "description": "What sort of data object a definition describes.", "enum": [ "measurement", "parameter", "value_block", "curve", "map", "axis" ], "title": "ObjectKind", "type": "string" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind" ] }
- Fields:
a2l (ddd.models.objects.A2lObjectOptions)conversion (ddd.models.conversion.IdentityConversion | ddd.models.conversion.LinearConversion | ddd.models.conversion.EnumConversion | None)datatype (ddd.models.common.Datatype | None)description (str)init (ddd.models.objects.InitValue | None)kind (ddd.models.objects.ObjectKind)limits (ddd.models.objects.Limits | None)name (str)section (str | None)typename (str | None)unit (str)volatile (bool)
- field name: Identifier [Required]
C identifier of the object; also its name in the a2l.
- field datatype: Datatype | None = None
Storage of one element, one of the eleven base datatypes.
Exactly one of
datatypeandtypenameis stated. Two keys rather than one union, so that the published schema saysdatatypeis one of eleven values - an editor completes and documents exactly them, and a mistyped one is refused as it is typed - and so that a declaration tells its reader at a glance whether storage is base or declared.Storage of one element, one of the eleven base datatypes.
Exactly one of
datatypeandtypenameis stated. Two keys rather than one union, so that the published schema saysdatatypeis one of eleven values - an editor completes and documents exactly them, and a mistyped one is refused as it is typed - and so that a declaration tells its reader at a glance whether storage is base or declared.
- field typename: TypeName | None = None
Name of a type the project declares, stated instead of
datatype.Naming a structure is what makes this object a structured one; naming a scalar type is what lets several components agree about a value by naming it rather than by each copying out its unit, its scaling and its limits - and a declaration that names a type may not restate any of them.
Name of a type the project declares, stated instead of
datatype.Naming a structure is what makes this object a structured one; naming a scalar type is what lets several components agree about a value by naming it rather than by each copying out its unit, its scaling and its limits - and a declaration that names a type may not restate any of them.
- field description: str = ''
What the object is, offered to the c templates and used as the a2l long identifier.
- field unit: str = ''
Physical unit, e.g.
"Hz".Free text, so DDD does not know that
rpmand1/minare the same thing; it only checks that every component declaring this object spells the unit the same way.Physical unit, e.g.
"Hz".Free text, so DDD does not know that
rpmand1/minare the same thing; it only checks that every component declaring this object spells the unit the same way.
- field section: str | None = None
Linker section the object is placed in, named in the project’s sections file.
A storage key like
init: the producer states it, a consumer stating one claims storage it does not own (consumer-storage), and a structured object is placed whole. Left out, the object goes wherever the toolchain’s defaults put it.Linker section the object is placed in, named in the project’s sections file.
A storage key like
init: the producer states it, a consumer stating one claims storage it does not own (consumer-storage), and a structured object is placed whole. Left out, the object goes wherever the toolchain’s defaults put it.
- field init: InitValue | None = None
Raw initial value, in the stored domain rather than the physical one.
nullleaves the object zero initialised by the startup code. For an array shaped object, either a nested list matching the shape exactly, or a single scalar, which initialises every element with that value.Raw initial value, in the stored domain rather than the physical one.
nullleaves the object zero initialised by the startup code. For an array shaped object, either a nested list matching the shape exactly, or a single scalar, which initialises every element with that value.
- field conversion: Conversion | None = None
How a raw value maps to a physical one: identity, linear scaling or an enumeration.
Required wherever storage is named by
datatype, although the identity would be derivable: raw equalling physical is an engineering claim about the data, not a formatting accident, and a forgotten scaling on a fixed point value displays raw counts without anything looking broken. A definition naming atypenamestates no conversion - the type fixes it.kindmay be left out when the keys make it unambiguous:factororoffsetmeanslinear,enumeratorsornamemeansenum, and{}meansidentity.How a raw value maps to a physical one: identity, linear scaling or an enumeration.
Required wherever storage is named by
datatype, although the identity would be derivable: raw equalling physical is an engineering claim about the data, not a formatting accident, and a forgotten scaling on a fixed point value displays raw counts without anything looking broken. A definition naming atypenamestates no conversion - the type fixes it.kindmay be left out when the keys make it unambiguous:factororoffsetmeanslinear,enumeratorsornamemeansenum, and{}meansidentity.
- field limits: Limits | None = None
Physical limits of the object, in the unit given by
unit.Omitted, they are derived from
datatypeandconversion: the whole range the storage can hold, converted. State them to say that the software handles less than that, which is what stops a calibration tool offering a value the software cannot take.Physical limits of the object, in the unit given by
unit.Omitted, they are derived from
datatypeandconversion: the whole range the storage can hold, converted. State them to say that the software handles less than that, which is what stops a calibration tool offering a value the software cannot take.
- field a2l: A2lObjectOptions = A2lObjectOptions(export=None, format=None, display_identifier=None)
What this object asks of the a2l file: whether to export it, how to display it.
Only the a2l backend reads it, so a project that generates no a2l can leave it out entirely.
What this object asks of the a2l file: whether to export it, how to display it.
Only the a2l backend reads it, so a project that generates no a2l can leave it out entirely.
- field volatile: bool [Required]
Whether the c declaration carries
volatile; stated on every definition.Required, with no default, and on every kind rather than on measurements alone. Both follow from what the qualifier does, which is to forbid the compiler to assume it already knows the value.
A measurement needs it when something outside the reading component’s control writes the variable - an interrupt, a second core, a peripheral. A calibration object needs it when the calibration tool is to change the value in a running ecu: without it the compiler is entitled to use the initialiser in place of a read wherever it can see it - within one translation unit at every optimisation level,
-O0included, and across them under link time optimisation - and, where the load does survive, to serve two reads from one of them. Either way the tool writes a new value the software does not pick up.Interface rather than storage, because it reaches every component that reads the object: their header declares it
extern volatile, which is what tells their code not to cache the value and not to expect two reads to agree. Every declaration of one object therefore has to say the same thing, and a disagreement is an error.There is no default because there is no answer DDD could derive - unlike
limits, which follow from the datatype and the conversion. The two answers have different costs and only the project knows which it is paying:truekeeps a value tunable and, on a typical toolchain, moves a calibration object out of read-only memory;falsekeeps it in flash and lets the optimiser cache it. Saying nothing would pick one of them silently, and the one it picked would be wrong roughly as often as not.Whether the c declaration carries
volatile; stated on every definition.Required, with no default, and on every kind rather than on measurements alone. Both follow from what the qualifier does, which is to forbid the compiler to assume it already knows the value.
A measurement needs it when something outside the reading component’s control writes the variable - an interrupt, a second core, a peripheral. A calibration object needs it when the calibration tool is to change the value in a running ecu: without it the compiler is entitled to use the initialiser in place of a read wherever it can see it - within one translation unit at every optimisation level,
-O0included, and across them under link time optimisation - and, where the load does survive, to serve two reads from one of them. Either way the tool writes a new value the software does not pick up.Interface rather than storage, because it reaches every component that reads the object: their header declares it
extern volatile, which is what tells their code not to cache the value and not to expect two reads to agree. Every declaration of one object therefore has to say the same thing, and a disagreement is an error.There is no default because there is no answer DDD could derive - unlike
limits, which follow from the datatype and the conversion. The two answers have different costs and only the project knows which it is paying:truekeeps a value tunable and, on a typical toolchain, moves a calibration object out of read-only memory;falsekeeps it in flash and lets the optimiser cache it. Saying nothing would pick one of them silently, and the one it picked would be wrong roughly as often as not.
- field kind: ObjectKind [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- pydantic model Measurement[source]
An online value: written by the software, only measured by the calibration tool.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Measurement" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Measurement</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MEASUREMENT]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.Measurement

An online value: written by the software, only measured by the calibration tool.
"];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Measurement":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Measurement":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-f97cee5bde1dd401a667ff543d451b9d34d26a17.png)
Show JSON schema
{ "title": "Measurement", "description": "An online value: written by the software, only measured by the calibration tool.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "measurement", "title": "Kind", "type": "string" }, "dimensions": { "default": [], "description": "Array dimensions; empty for a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, in a\nconstants file or in a component - ``[3, 4]`` and ``[\"PRESSURE_CELLS\", 4]`` are both\nshapes.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "title": "Dimensions", "type": "array" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind" ] }
- Fields:
dimensions (tuple[Dimension, ...])kind (Literal[ObjectKind.MEASUREMENT])
- field kind: Literal[ObjectKind.MEASUREMENT] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- field dimensions: tuple[Dimension, ...] = ()
Array dimensions; empty for a scalar.
Each an integer of at least 1, or the name of a constant the project declares, in a constants file or in a component -
[3, 4]and["PRESSURE_CELLS", 4]are both shapes.Array dimensions; empty for a scalar.
Each an integer of at least 1, or the name of a constant the project declares, in a constants file or in a component -
[3, 4]and["PRESSURE_CELLS", 4]are both shapes.
- pydantic model Parameter[source]
A single calibratable constant.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Parameter" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Parameter</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.PARAMETER]</td></tr></table>>,
tooltip="ddd.models.objects.Parameter

A single calibratable constant.
"];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Parameter":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Parameter":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-4b5e2bd4803d696e2379b697d3af058a190c5904.png)
Show JSON schema
{ "title": "Parameter", "description": "A single calibratable constant.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "parameter", "title": "Kind", "type": "string" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind" ] }
- Fields:
kind (Literal[ObjectKind.PARAMETER])
- field kind: Literal[ObjectKind.PARAMETER] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- pydantic model ValueBlock[source]
An array of calibratable constants.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.ValueBlock" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>ValueBlock</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.VALUE_BLOCK]</td></tr><tr><td>dimensions</td><td port="dimensions">tuple[Union[int, str], ...]</td></tr></table>>,
tooltip="ddd.models.objects.ValueBlock

An array of calibratable constants.
"];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.ValueBlock":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-815259f27123832d568e2a6ba4a1d6f236c0f536.png)
Show JSON schema
{ "title": "ValueBlock", "description": "An array of calibratable constants.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "value_block", "title": "Kind", "type": "string" }, "dimensions": { "description": "Array dimensions in c declaration order; a value block is never a scalar.\n\nEach an integer of at least 1, or the name of a constant the project declares, mixed\nfreely.", "items": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ] }, "minItems": 1, "title": "Dimensions", "type": "array" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind", "dimensions" ] }
- Fields:
dimensions (Annotated[tuple[Dimension, ...], Field(min_length=1)])kind (Literal[ObjectKind.VALUE_BLOCK])
- field kind: Literal[ObjectKind.VALUE_BLOCK] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- field dimensions: Annotated[tuple[Dimension, ...], Field(min_length=1)] [Required]
Array dimensions in c declaration order; a value block is never a scalar.
Each an integer of at least 1, or the name of a constant the project declares, mixed freely.
Array dimensions in c declaration order; a value block is never a scalar.
Each an integer of at least 1, or the name of a constant the project declares, mixed freely.
- Constraints:
min_length = 1
- pydantic model Axis[source]
Shared axis points; several curves and maps may be interpolated over one axis.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Axis" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Axis</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.AXIS]</td></tr><tr><td>size</td><td port="size">Union[int, str]</td></tr><tr><td>input</td><td port="input">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.Axis

Shared axis points; several curves and maps may be interpolated over one axis.
"];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Axis":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Axis":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-ba6fec9137382f64ad57bddcb936280b03fe474e.png)
Show JSON schema
{ "title": "Axis", "description": "Shared axis points; several curves and maps may be interpolated over one axis.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "axis", "title": "Kind", "type": "string" }, "size": { "anyOf": [ { "minimum": 1, "type": "integer" }, { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" } ], "description": "Number of axis points: an integer of at least 1, or the name of a declared\nconstant.", "title": "Size" }, "input": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Measurement that indexes the axis; the a2l input quantity.", "title": "Input" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind", "size" ] }
- Fields:
input (Identifier | None)kind (Literal[ObjectKind.AXIS])size (Dimension)
- field kind: Literal[ObjectKind.AXIS] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- field size: Dimension [Required]
Number of axis points: an integer of at least 1, or the name of a declared constant.
Number of axis points: an integer of at least 1, or the name of a declared constant.
- field input: Identifier | None = None
Measurement that indexes the axis; the a2l input quantity.
- pydantic model Curve[source]
A one dimensional calibratable table.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Curve" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Curve</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.CURVE]</td></tr><tr><td>axis</td><td port="axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Curve

A one dimensional calibratable table.
"];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Curve":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Curve":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-e0b7d15334497616c8fbfa1f338a19cd1f0635c7.png)
Show JSON schema
{ "title": "Curve", "description": "A one dimensional calibratable table.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "curve", "title": "Kind", "type": "string" }, "axis": { "description": "Name of the axis object the curve is interpolated over.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Axis", "type": "string" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind", "axis" ] }
- Fields:
axis (Identifier)kind (Literal[ObjectKind.CURVE])
- field kind: Literal[ObjectKind.CURVE] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- field axis: Identifier [Required]
Name of the axis object the curve is interpolated over.
- pydantic model Map[source]
A two dimensional calibratable table, stored as
[y][x].![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
"ddd.models.objects.Map" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Map</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>datatype</td><td port="datatype">Datatype | None</td></tr><tr><td>typename</td><td port="typename">Optional[str]</td></tr><tr><td>description</td><td port="description">str</td></tr><tr><td>unit</td><td port="unit">str</td></tr><tr><td>section</td><td port="section">str | None</td></tr><tr><td>init</td><td port="init">InitValue | None</td></tr><tr><td>conversion</td><td port="conversion">Optional[IdentityConversion | LinearConversion | EnumConversion]</td></tr><tr><td>limits</td><td port="limits">Limits | None</td></tr><tr><td>a2l</td><td port="a2l">A2lObjectOptions</td></tr><tr><td>volatile</td><td port="volatile">bool</td></tr><tr><td>kind</td><td port="kind">Literal[ObjectKind.MAP]</td></tr><tr><td>x_axis</td><td port="x_axis">str</td></tr><tr><td>y_axis</td><td port="y_axis">str</td></tr></table>>,
tooltip="ddd.models.objects.Map

A two dimensional calibratable table, stored as ``[y][x]``.
"];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.EnumConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.IdentityConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":conversion:e -> "ddd.models.conversion.LinearConversion":_root:w [arrowhead=noneteeodot,
arrowtail=nonenone];
"ddd.models.objects.Map":a2l:e -> "ddd.models.objects.A2lObjectOptions":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
"ddd.models.objects.Map":limits:e -> "ddd.models.objects.Limits":_root:w [arrowhead=noneteetee,
arrowtail=nonenone];
}](_images/graphviz-09effbf89143c2da57ff373c64d40a16d60c5daa.png)
Show JSON schema
{ "title": "Map", "description": "A two dimensional calibratable table, stored as ``[y][x]``.", "type": "object", "properties": { "name": { "description": "C identifier of the object; also its name in the a2l.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "datatype": { "anyOf": [ { "$ref": "#/$defs/Datatype" }, { "type": "null" } ], "default": null, "description": "Storage of one element, one of the eleven base datatypes.\n\nExactly one of ``datatype`` and ``typename`` is stated. Two keys rather than one union,\nso that the published schema says ``datatype`` is one of eleven values - an editor\ncompletes and documents exactly them, and a mistyped one is refused as it is typed - and\nso that a declaration tells its reader at a glance whether storage is base or declared." }, "typename": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^(?!(?:boolean|float32|float64|sint16|sint32|sint64|sint8|uint16|uint32|uint64|uint8)$)[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Name of a type the project declares, stated instead of ``datatype``.\n\nNaming a structure is what makes this object a structured one; naming a scalar type is\nwhat lets several components agree about a value by naming it rather than by each copying\nout its unit, its scaling and its limits - and a declaration that names a type may not\nrestate any of them.", "title": "Typename" }, "description": { "default": "", "description": "What the object is, offered to the c templates and used as the a2l long identifier.", "title": "Description", "type": "string" }, "unit": { "default": "", "description": "Physical unit, e.g. ``\"Hz\"``.\n\nFree text, so DDD does not know that ``rpm`` and ``1/min`` are the same thing; it only\nchecks that every component declaring this object spells the unit the same way.", "title": "Unit", "type": "string" }, "section": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "Linker section the object is placed in, named in the project's sections file.\n\nA storage key like ``init``: the producer states it, a consumer stating one claims\nstorage it does not own (``consumer-storage``), and a structured object is placed whole.\nLeft out, the object goes wherever the toolchain's defaults put it.", "title": "Section" }, "init": { "anyOf": [ { "$ref": "#/$defs/InitValue" }, { "type": "null" } ], "default": null, "description": "Raw initial value, in the stored domain rather than the physical one.\n\n``null`` leaves the object zero initialised by the startup code. For an array shaped\nobject, either a nested list matching the shape exactly, or a single scalar, which\ninitialises every element with that value." }, "conversion": { "anyOf": [ { "discriminator": { "mapping": { "enum": "#/$defs/EnumConversion", "identity": "#/$defs/IdentityConversion", "linear": "#/$defs/LinearConversion" }, "propertyName": "kind" }, "oneOf": [ { "$ref": "#/$defs/IdentityConversion" }, { "$ref": "#/$defs/LinearConversion" }, { "$ref": "#/$defs/EnumConversion" } ] }, { "type": "null" } ], "default": null, "description": "How a raw value maps to a physical one: identity, linear scaling or an enumeration.\n\nRequired wherever storage is named by ``datatype``, although the identity would be\nderivable: raw equalling physical is an engineering claim about the data, not a\nformatting accident, and a forgotten scaling on a fixed point value displays raw counts\nwithout anything looking broken. A definition naming a ``typename`` states no conversion\n- the type fixes it. ``kind`` may be left out when the keys make it unambiguous:\n``factor`` or ``offset`` means ``linear``, ``enumerators`` or ``name`` means ``enum``,\nand ``{}`` means ``identity``.", "title": "Conversion" }, "limits": { "anyOf": [ { "$ref": "#/$defs/Limits" }, { "type": "null" } ], "default": null, "description": "Physical limits of the object, in the unit given by ``unit``.\n\nOmitted, they are derived from ``datatype`` and ``conversion``: the whole range the\nstorage can hold, converted. State them to say that the software handles less than that,\nwhich is what stops a calibration tool offering a value the software cannot take." }, "a2l": { "$ref": "#/$defs/A2lObjectOptions", "default": { "export": null, "format": null, "display_identifier": null }, "description": "What this object asks of the a2l file: whether to export it, how to display it.\n\nOnly the a2l backend reads it, so a project that generates no a2l can leave it out\nentirely." }, "volatile": { "description": "Whether the c declaration carries ``volatile``; stated on every definition.\n\nRequired, with no default, and on every kind rather than on measurements alone. Both\nfollow from what the qualifier does, which is to forbid the compiler to assume it already\nknows the value.\n\nA measurement needs it when something outside the reading component's control writes the\nvariable - an interrupt, a second core, a peripheral. A calibration object needs it when\nthe calibration tool is to change the value in a running ecu: without it the compiler is\nentitled to use the initialiser in place of a read wherever it can see it - within one\ntranslation unit at every optimisation level, ``-O0`` included, and across them under link\ntime optimisation - and, where the load does survive, to serve two reads from one of them.\nEither way the tool writes a new value the software does not pick up.\n\nInterface rather than storage, because it reaches every component that reads the object:\ntheir header declares it ``extern volatile``, which is what tells their code not to cache\nthe value and not to expect two reads to agree. Every declaration of one object therefore\nhas to say the same thing, and a disagreement is an error.\n\nThere is no default because there is no answer DDD could derive - unlike ``limits``, which\nfollow from the datatype and the conversion. The two answers have different costs and only\nthe project knows which it is paying: ``true`` keeps a value tunable and, on a typical\ntoolchain, moves a calibration object out of read-only memory; ``false`` keeps it in flash\nand lets the optimiser cache it. Saying nothing would pick one of them silently, and the\none it picked would be wrong roughly as often as not.", "title": "Volatile", "type": "boolean" }, "kind": { "const": "map", "title": "Kind", "type": "string" }, "x_axis": { "description": "Name of the axis whose index runs fastest; the last dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "X Axis", "type": "string" }, "y_axis": { "description": "Name of the axis selecting the row; the first dimension of the c array.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Y Axis", "type": "string" } }, "$defs": { "A2lObjectOptions": { "additionalProperties": false, "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "title": "A2lObjectOptions", "type": "object" }, "Datatype": { "description": "The base datatypes DDD can allocate storage for.", "enum": [ "boolean", "uint8", "sint8", "uint16", "sint16", "uint32", "sint32", "uint64", "sint64", "float32", "float64" ], "title": "Datatype", "type": "string" }, "EnumConversion": { "additionalProperties": false, "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "required": [ "name", "enumerators" ], "title": "EnumConversion", "type": "object" }, "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" }, "IdentityConversion": { "additionalProperties": false, "description": "``physical == raw``; the default for every variable.", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "title": "IdentityConversion", "type": "object" }, "InitValue": { "anyOf": [ { "type": "boolean" }, { "type": "integer" }, { "type": "number" }, { "items": { "$ref": "#/$defs/InitValue" }, "type": "array" } ] }, "Limits": { "additionalProperties": false, "description": "Physical lower/upper limit of a data object.", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "required": [ "min", "max" ], "title": "Limits", "type": "object" }, "LinearConversion": { "additionalProperties": false, "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "title": "LinearConversion", "type": "object" } }, "additionalProperties": false, "required": [ "name", "volatile", "kind", "x_axis", "y_axis" ] }
- Fields:
kind (Literal[ObjectKind.MAP])x_axis (Identifier)y_axis (Identifier)
- field kind: Literal[ObjectKind.MAP] [Required]
Which sort of object this is; stated on every definition.
It also decides which further keys the definition may carry:
dimensionson a measurement or a value block,sizeandinputon an axis,axison a curve,x_axisandy_axison a map, and none of them on a parameter.
- field x_axis: Identifier [Required]
Name of the axis whose index runs fastest; the last dimension of the c array.
- field y_axis: Identifier [Required]
Name of the axis selecting the row; the first dimension of the c array.
- pydantic model Limits[source]
Physical lower/upper limit of a data object.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.objects.Limits" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Limits</b></td></tr><tr><td>min</td><td port="min">Union[int, float]</td></tr><tr><td>max</td><td port="max">Union[int, float]</td></tr></table>>,
tooltip="ddd.models.objects.Limits

Physical lower/upper limit of a data object.
"];
}](_images/graphviz-6c62081c77701c4b055b57eb4743e97da6bec55a.png)
Show JSON schema
{ "title": "Limits", "description": "Physical lower/upper limit of a data object.", "type": "object", "properties": { "min": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Smallest physical value the object may take.", "title": "Min" }, "max": { "anyOf": [ { "type": "integer" }, { "type": "number" } ], "description": "Largest physical value the object may take; at least ``min``.", "title": "Max" } }, "additionalProperties": false, "required": [ "min", "max" ] }
- Fields:
max (int | float)min (int | float)
- field min: Number [Required]
Smallest physical value the object may take.
- field max: Number [Required]
Largest physical value the object may take; at least
min.
- pydantic model A2lObjectOptions[source]
What a declaration asks of the a2l backend. Only that backend interprets it.
Nothing here changes the generated c or the meaning of the object; a project that generates no a2l can leave the whole block out.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.objects.A2lObjectOptions" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>A2lObjectOptions</b></td></tr><tr><td>export</td><td port="export">bool | None</td></tr><tr><td>format</td><td port="format">Optional[str]</td></tr><tr><td>display_identifier</td><td port="display_identifier">Optional[str]</td></tr></table>>,
tooltip="ddd.models.objects.A2lObjectOptions

What a declaration asks of the a2l backend. Only that backend interprets it.
&#\
xA;Nothing here changes the generated c or the meaning of the object; a project that
generates no a2l can leave the whole block \
out.
"];
}](_images/graphviz-2a505a34ef96867f0cf5ca9fb448d1e27245a066.png)
Show JSON schema
{ "title": "A2lObjectOptions", "description": "What a declaration asks of the a2l backend. Only that backend interprets it.\n\nNothing here changes the generated c or the meaning of the object; a project that\ngenerates no a2l can leave the whole block out.", "type": "object", "properties": { "export": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "description": "Whether the object belongs in the a2l file; omitted, it does.\n\nThe one a2l option any component may state, not only the producer. Which signals a\ncalibration engineer needs to see is not a property of whoever happens to write the\nvariable: a component reading a value from a library it does not own has as good a claim\nto measuring it.\n\nStated by several, the answer is yes if any of them says so - see :func:`resolve_export`.", "title": "Export" }, "format": { "anyOf": [ { "pattern": "^%\\d*\\.\\d+$", "type": "string" }, { "type": "null" } ], "default": null, "description": "a2l ``FORMAT`` string, e.g. ``\"%8.3\"``: total width, then decimal places.", "title": "Format" }, "display_identifier": { "anyOf": [ { "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "type": "string" }, { "type": "null" } ], "default": null, "description": "Alternative name shown by the calibration tool.", "title": "Display Identifier" } }, "additionalProperties": false }
- Fields:
display_identifier (str | None)export (bool | None)format (str | None)
- field export: bool | None = None
Whether the object belongs in the a2l file; omitted, it does.
The one a2l option any component may state, not only the producer. Which signals a calibration engineer needs to see is not a property of whoever happens to write the variable: a component reading a value from a library it does not own has as good a claim to measuring it.
Stated by several, the answer is yes if any of them says so - see
resolve_export().Whether the object belongs in the a2l file; omitted, it does.
The one a2l option any component may state, not only the producer. Which signals a calibration engineer needs to see is not a property of whoever happens to write the variable: a component reading a value from a library it does not own has as good a claim to measuring it.
Stated by several, the answer is yes if any of them says so - see
resolve_export().
- field format: A2lFormat | None = None
a2l
FORMATstring, e.g."%8.3": total width, then decimal places.
- field display_identifier: Identifier | None = None
Alternative name shown by the calibration tool.
Conversions
The conversion of a data object is a second tagged union, again discriminated on
kind, and again kind may be left out when the shape of the block makes it
unambiguous: a block carrying enumerators or a name is an enum, one carrying
factor or offset is linear, and an empty one is the identity.
- pydantic model IdentityConversion[source]
physical == raw; the default for every variable.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.IdentityConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>IdentityConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['identity']</td></tr></table>>,
tooltip="ddd.models.conversion.IdentityConversion

``physical == raw``; the default for every variable.
"];
}](_images/graphviz-c537609c37867346be5e068508eade531a31899c.png)
Show JSON schema
{ "title": "IdentityConversion", "description": "``physical == raw``; the default for every variable.", "type": "object", "properties": { "kind": { "const": "identity", "default": "identity", "title": "Kind", "type": "string" } }, "additionalProperties": false }
- Fields:
kind (Literal['identity'])
- field kind: Literal['identity'] = 'identity'
- pydantic model LinearConversion[source]
physical = raw * factor + offset, the scaling of a fixed point value.![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.LinearConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>LinearConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['linear']</td></tr><tr><td>factor</td><td port="factor">float</td></tr><tr><td>offset</td><td port="offset">float</td></tr></table>>,
tooltip="ddd.models.conversion.LinearConversion

``physical = raw * factor + offset``, the scaling of a fixed point value.
"];
}](_images/graphviz-493c55bd52633200d9b43d8860ac202593d1043b.png)
Show JSON schema
{ "title": "LinearConversion", "description": "``physical = raw * factor + offset``, the scaling of a fixed point value.", "type": "object", "properties": { "kind": { "const": "linear", "default": "linear", "title": "Kind", "type": "string" }, "factor": { "default": 1.0, "description": "Scaling; must not be zero, or nothing could be converted back.", "title": "Factor", "type": "number" }, "offset": { "default": 0.0, "description": "What raw zero stands for, in the physical unit.", "title": "Offset", "type": "number" } }, "additionalProperties": false }
- Fields:
factor (float)kind (Literal['linear'])offset (float)
- field kind: Literal['linear'] = 'linear'
- field factor: Real = 1.0
Scaling; must not be zero, or nothing could be converted back.
- Constraints:
allow_inf_nan = False
- field offset: Real = 0.0
What raw zero stands for, in the physical unit.
- Constraints:
allow_inf_nan = False
- pydantic model EnumConversion[source]
A verbal conversion table; the raw value is the physical value.
Accepts both the explicit form:
{"kind": "enum", "name": "StateA", "enumerators": [{"name": "STATE_OFF", "value": 0}]}
and the mapping shorthand:
{"kind": "enum", "name": "StateA", "enumerators": {"STATE_OFF": 0}}
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.EnumConversion" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>EnumConversion</b></td></tr><tr><td>kind</td><td port="kind">Literal['enum']</td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>enumerators</td><td port="enumerators">tuple[Enumerator, ...]</td></tr></table>>,
tooltip="ddd.models.conversion.EnumConversion

A verbal conversion table; the raw value *is* the physical value.

Accepts \
both the explicit form::

 {\"kind\": \"enum\", \"name\": \"StateA\",
 \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": \
0}]}

and the mapping shorthand::

 {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}
"];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
"ddd.models.conversion.EnumConversion":enumerators:e -> "ddd.models.conversion.Enumerator":_root:w [arrowhead=crownone,
arrowtail=nonenone];
}](_images/graphviz-ca28d717a1477b588f8dbc333895db6f86bb208d.png)
Show JSON schema
{ "title": "EnumConversion", "description": "A verbal conversion table; the raw value *is* the physical value.\n\nAccepts both the explicit form::\n\n {\"kind\": \"enum\", \"name\": \"StateA\",\n \"enumerators\": [{\"name\": \"STATE_OFF\", \"value\": 0}]}\n\nand the mapping shorthand::\n\n {\"kind\": \"enum\", \"name\": \"StateA\", \"enumerators\": {\"STATE_OFF\": 0}}", "type": "object", "properties": { "kind": { "const": "enum", "default": "enum", "title": "Kind", "type": "string" }, "name": { "description": "C identifier of the generated ``typedef enum``; shared enums must agree everywhere.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "enumerators": { "description": "The named values, either as objects or as a ``{\"NAME\": value}`` mapping.", "items": { "$ref": "#/$defs/Enumerator" }, "minItems": 1, "title": "Enumerators", "type": "array" } }, "$defs": { "Enumerator": { "additionalProperties": false, "description": "One named value of an enum conversion, and what that value means.", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "required": [ "name", "value" ], "title": "Enumerator", "type": "object" } }, "additionalProperties": false, "required": [ "name", "enumerators" ] }
- Fields:
enumerators (tuple[ddd.models.conversion.Enumerator, ...])kind (Literal['enum'])name (str)
- field kind: Literal['enum'] = 'enum'
- field name: Identifier [Required]
C identifier of the generated
typedef enum; shared enums must agree everywhere.
- field enumerators: Annotated[tuple[Enumerator, ...], Field(min_length=1)] [Required]
The named values, either as objects or as a
{"NAME": value}mapping.
- pydantic model Enumerator[source]
One named value of an enum conversion, and what that value means.
![digraph "Entity Relationship Diagram created by erdantic" {
graph [fontcolor=gray66,
fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=9,
nodesep=0.5,
rankdir=LR,
ranksep=1.5
];
node [fontname="Times New Roman,Times,Liberation Serif,serif",
fontsize=14,
label="\N",
shape=plain
];
edge [dir=both];
"ddd.models.conversion.Enumerator" [label=<<table border="0" cellborder="1" cellspacing="0"><tr><td port="_root" colspan="2"><b>Enumerator</b></td></tr><tr><td>name</td><td port="name">str</td></tr><tr><td>value</td><td port="value">int</td></tr><tr><td>description</td><td port="description">str</td></tr></table>>,
tooltip="ddd.models.conversion.Enumerator

One named value of an enum conversion, and what that value means.
"];
}](_images/graphviz-c25d7aa10c4afcd5d7e97c01d60b6f11beadbc22.png)
Show JSON schema
{ "title": "Enumerator", "description": "One named value of an enum conversion, and what that value means.", "type": "object", "properties": { "name": { "description": "C identifier of the enumerator; enumerators of all enums share one c namespace.", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z_][A-Za-z0-9_]*$", "title": "Name", "type": "string" }, "value": { "description": "The raw value; every enumerator of one enum needs a value of its own.", "title": "Value", "type": "integer" }, "description": { "default": "", "description": "What the value means; documentation, not interface.", "title": "Description", "type": "string" } }, "additionalProperties": false, "required": [ "name", "value" ] }
- Fields:
description (str)name (str)value (int)
- field name: Identifier [Required]
C identifier of the enumerator; enumerators of all enums share one c namespace.
- field value: int [Required]
The raw value; every enumerator of one enum needs a value of its own.
- field description: str = ''
What the value means; documentation, not interface.