Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cyanobyte-templates/arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ int {{info.title}}::write{{key}}({% if length > 0 %}{{cpp.numtype(length)}} data
{{cpp.registerSize(registers, field.register[12:])}} {{info.title}}::get{{key}}() {
// Read register data
// '#/registers/{{field.register[12:]}}' > '{{field.register[12:]}}'
uint8_t val = read{{field.register[12:]}}();
{{cpp.registerSize(registers, field.register[12:])}} val = read{{field.register[12:]}}();
// Mask register value
val = val & {{utils.mask(field.bitStart, field.bitEnd)}};
{% if field.bitEnd %}
Expand All @@ -200,7 +200,7 @@ int {{info.title}}::set{{key}}(uint8_t data) {
{% endif %}
// Read current register data
// '#/registers/{{field.register[12:]}}' > '{{field.register[12:]}}'
uint8_t register_data = read{{field.register[12:]}}();
{{cpp.registerSize(registers, field.register[12:])}} register_data = read{{field.register[12:]}}();
register_data = register_data | data;
return write{{field.register[12:]}}(register_data);
}
Expand Down
231 changes: 231 additions & 0 deletions cyanobyte-templates/pigweed.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{% import 'macros.jinja2' as utils %}
{% import 'base.c.jinja2' as cpp %}
{% set template = namespace(enum=false, sign=false, math=false, struct=false) %}
/*
{{ utils.pad_string('* ', utils.license(info.copyright.name, info.copyright.date, info.license.name)) -}}
*
* Auto-generated file for {{ info.title }} v{{ info.version }}.
* Generated from {{ fileName }} using Cyanobyte Codegen v{{ version }}
* Class for {{ info.title }}
{{utils.pad_string("* ", info.description)}}
*/

{% macro logic(logicalSteps, function) -%}

{% for step in logicalSteps %}
{% for key in step.keys() %}
{# // Check if a raw read-op #}
{% if step[key] is mapping and 'rawRead' in step[key] %}
{% set bytes = (step[key].rawRead / 8) | round(1, 'ceil') | int %}
ByteBuffer<sizeof(bytes)> byte_buffer;

// can i even call this?
PutRegisterAddressInByteBuffer(
byte_buffer, DEVICE_ADDRESS, order_, register_address_size_
)

if (!byte_buffer.ok()) {
return pw::Status::Internal()
}

ByteSpan return_data;

WriteReadFor(byte_buffer.data(), byte_buffer.size(),
return_data.data(), return_data.size(), std::chrono::seconds(1));

uint8_t _datum;
_datum = return_data.data();
{{key}} = _datum; // Post-process?
{% break %}
{% endif %}
{# // Check if assignment is a send-op #}
{% if key == '$cmdWrite' %}
{% if 'value' in step[key] %}
write{{step[key].register[12:]}}({{step[key].value}});
{% else %}
write{{step[key].register[12:]}}();
{% endif %}
{% break %}
{% endif %}
{% if key == "$delay" %}
{# Blocking impl #}
pw::chrono::SystemClock::time_point before = pw::chrono::SystemClock::now();
while (pw::chrono::SystemClock::now() - before < std::chrono::milliseconds(10)) {}
{{ logic(step[key].after, function) }}
{% break %}
{% endif %}
{# // Check if assignment op #}
{% if step[key] is string and step[key][0:1] == "=" %}
{{key}} {{step[key]}};
{% endif %}
{# // Check if assignment is a send-op #}
{% if key == 'send' %}
write{{function.register[12:]}}({{step[key]}});
{% endif %}
{# // Check if assignment is register read op #}
{% if step[key] is string and step[key][:12] == '#/registers/' %}
{# Unwrap result #}
{{key}} = read{{step[key][12:]}}().value();
{% endif %}
{# // Check if assignment is function call op #}
{% if step[key] is string and step[key][:12] == '#/functions/' %}
{{key}} = {{step[key] | regex_replace('#/functions/(?P<function>.+)/(?P<compute>.+)', '\\g<function>\\g<compute>')}}();
{% endif %}
{# // If the value is a list, then this is a logical setter #}
{% if step[key] is iterable and step[key] is not string %}
{{key}} = {{cpp.recursiveAssignLogic(step[key][0], step[key][0].keys()) -}};
{% endif %}
{% endfor %}
{% endfor %}
{%- endmacro %}

{% if i2c.endian == 'little' %}
static short _swap_endian(short val) {
// Swap the endianness of a short only
return (val & 0xFF00) >> 8 | (val & 0xFF) << 8;
}
{% endif %}

{# Add signing function if needed #}
{% for key,register in registers|dictsort %}
{% if register.signed %}
{% if template.sign is sameas false %}
static short _sign(short val, char length) {
// Convert unsigned integer to signed integer
if (val & (1 << (length - 1))) {
return val - (1 << length);
}
return val;
}
{% set template.sign = true %}
{% endif %}
{% endif %}
{% endfor %}

#include "{{info.title}}.h"

{% if i2c.address is number %}
#define DEVICE_ADDRESS {{i2c.address}}
{% endif %}

{% for key,register in registers|dictsort %}
#define REGISTER_{{key.upper()}} {{register.address}}
{% endfor %}

{{info.title}}::{{info.title}}(pw::i2c::Initiator& initiator{% if i2c.address is iterable and i2c.address is not string %}, pw::i2c::Address address{% endif %}): RegisterDevice(initiator, {% if i2c.address is iterable and i2c.address is not string %}address{% else %}pw::i2c::Address({{i2c.address}}){% endif %}),
{% if i2c.endian == 'little' %} std::endian::little{% else %} std::endian::big{% endif %},
pw::i2c::RegisterAddressSize::k1Byte)
{
{% if i2c.address is iterable and i2c.address is not string %}
DEVICE_ADDRESS ( address )
{% endif %}
}

{% for key,register in registers|dictsort -%}
{% set length = register.length %}
{% set bytes = (register.length / 8) | round(1, 'ceil') | int %}
{% if (not 'readWrite' in register) or ('readWrite' in register and 'R' is in(register.readWrite)) %}
pw::Result<{{cpp.numtype(length)}}> {{info.title}}::read{{key}}() {
// Hard-coded timeout of 1s.
{% if length == 0 %}
return ReadRegister8(REGISTER_{{key.upper()}}, std::chrono::seconds(1));
{% else %}
return ReadRegister{{length}}(REGISTER_{{key.upper()}}, std::chrono::seconds(1));
{% endif %}
}
{% endif %}

{% if (not 'readWrite' in register) or ('readWrite' in register and 'W' is in(register.readWrite)) %}
pw::Status {{info.title}}::write{{key}}({% if length > 0 %}{{cpp.numtype(length)}} data{% endif %}) {
// Hard-coded timeout of 1s.
{% if length == 0 %}
return WriteRegister8(REGISTER_{{key.upper()}}, 0 /* No data */, std::chrono::seconds(1));
{% else %}
return WriteRegister{{length}}(REGISTER_{{key.upper()}}, data, std::chrono::seconds(1));
{% endif %}
}
{% endif %}

{% endfor %}

{% if fields %}
{% for key,field in fields|dictsort %}
{% if 'R' is in(field.readWrite) %}
{# Getter #}
pw::Result<{{cpp.registerSize(registers, field.register[12:])}}> {{info.title}}::get{{key}}() {
// Read register data
// '#/registers/{{field.register[12:]}}' > '{{field.register[12:]}}'
Result<{{cpp.registerSize(registers, field.register[12:])}}> res = read{{field.register[12:]}}();
{# Assume it is good #}
{{cpp.registerSize(registers, field.register[12:])}} val = res.value();
// Mask register value
val = val & {{utils.mask(field.bitStart, field.bitEnd)}};
{% if field.bitEnd %}
// Bitshift value
val = val >> {{field.bitEnd}};
{% endif %}
// Rewrap in a Result
Result<{{cpp.registerSize(registers, field.register[12:])}}> result = new Result(val);
return result;
}
{% endif -%}

{%- if 'W' is in(field.readWrite) %}
{# Setter #}

pw::Status {{info.title}}::set{{key}}(uint8_t data) {
{% if field.bitEnd %}
// Bitshift value
data = data << {{field.bitEnd}};
{% endif %}
// Read current register data
// '#/registers/{{field.register[12:]}}' > '{{field.register[12:]}}'
Result<{{cpp.registerSize(registers, field.register[12:])}}> res = read{{field.register[12:]}}();
{{cpp.registerSize(registers, field.register[12:])}} register_data = res.value()
register_data = register_data | data;
return write{{field.register[12:]}}(register_data);
}
{% endif %}
{% endfor %}
{% endif %}

{% if functions %}
{% for key,function in functions|dictsort %}
{% for ckey,compute in function.computed|dictsort %}
{% if 'input' in compute %}
{{cpp.returnType(compute)}} {{info.title}}::{{key}}{{ckey}}({{cpp.params(compute)}}) {
{% else %}
{{cpp.returnType(compute)}} {{info.title}}::{{key}}{{ckey}}({{cpp.params(compute)}}) {
{% endif %}
{# Declare our variables #}
{{ cpp.variables(compute.variables) }}

{# Read `value` if applicable #}
{% if 'input' in compute %}
{%- for vkey,variable in compute.input|dictsort %}
{% if vkey == 'value' %}
// Read value of register into a variable
{{cpp.numconv(variable)}} value = read{{function.register[12:]}}();
{% endif %}
{% endfor %}
{% endif %}
{# Handle the logic #}
{{ logic(compute.logic, function) }}

{# Return if applicable #}
{# Return a tuple #}
{% if 'return' in compute and compute.return is not string %}
{# In C languages, the array is a parameter `returnArray` you fill #}
{% for variable in compute.return %}
returnArray[{{loop.index - 1}}] = {{variable}};
{% endfor %}
{% endif %}
{# Return a plain value #}
{% if compute.return is string %}
return {{compute.return}};
{% endif %}
}

{% endfor %}
{% endfor %}
{% endif %}
45 changes: 45 additions & 0 deletions cyanobyte-templates/pigweed.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import("//build_overrides/pigweed.gni")

import("$dir_pw_build/target_types.gni")
import("$dir_pw_chrono/backend.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_unit_test/test.gni")

pw_source_set("{{ info.title }}") {
public = [ "{{ info.title }}.h" ]
sources = [ "{{ info.title }}.cc" ]
deps = [
"$dir_pw_bytes",
"$dir_pw_chrono:system_clock",
"$dir_pw_i2c:address",
"$dir_pw_i2c:device",
"$dir_pw_i2c:initiator",
"$dir_pw_result",
"$dir_pw_status",
]
}

pw_test_group("tests") {
tests = [
":{{ info.title }}_test",
]
}

pw_test("{{ info.title }}_test") {
sources = [ "{{ info.title }}_test.cc" ]
deps = [ ":{{ info.title }}" ]
}
Loading