Skip to content

Commit

Permalink
implement simple data types
Browse files Browse the repository at this point in the history
  • Loading branch information
Seth10001 committed Sep 19, 2023
1 parent f154023 commit 4cb0ebb
Show file tree
Hide file tree
Showing 20 changed files with 317 additions and 105 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Tests
on: [push]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
with:
python-version: "3.9"

- name: Run image
uses: abatilo/actions-poetry@v2
with:
poetry-version: "1.6.1"

- run: make install
- run: make test
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode
__pycache__
51 changes: 0 additions & 51 deletions FrontLights.cpp

This file was deleted.

4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
.PHONY: install
install:
poetry install

.PHONY: test
test:
poetry run pytest
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Telemetry Parsing Codegen

To eliminate repetitive code, this module takes in a yaml file with the schema of the CAN messages, and generates the cpp modules needed to parse the CAN messages.
23 changes: 0 additions & 23 deletions config.yml

This file was deleted.

Empty file added datamodule/__init__.py
Empty file.
21 changes: 21 additions & 0 deletions datamodule/cpp/DataModuleInfo.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* DataModuleInfo.hpp
*
* THIS IS AUTO GENERATED. DO NOT EDIT
*/

#ifndef SOLARGATORSBSP_DATAMODULES_INC_DATAMODULEINFO_HPP_
#define SOLARGATORSBSP_DATAMODULES_INC_DATAMODULEINFO_HPP_


namespace SolarGators::DataModuleInfo
{
// ---- Addresses ---- //

{% for message in canMessages %}
static constexpr uint32_t {{ message["name"] }}_ID = {{ message["id"] }};
{% endfor %}
}


#endif /* SOLARGATORSBSP_DATAMODULES_INC_DATAMODULEINFO_HPP_ */
28 changes: 20 additions & 8 deletions datamodule/cpp/module.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
#include <{{ moduleName }}.hpp>
#include <DataModuleInfo.hpp>
/*
* {{ moduleName }}.cpp
*
* THIS IS AUTO GENERATED, DO NOT EDIT.
*/

#include "{{ moduleName }}.hpp"
#include "DataModuleInfo.hpp"
#include <cstring>

namespace SolarGators {
namespace DataModules {
Expand All @@ -8,9 +15,12 @@ namespace {
}

{{ moduleName }}::{{ moduleName }}():
DataModule(SolarGators::DataModuleInfo::FRONT_LIGHTS_ID, 0, SIZE),
DataModule(SolarGators::DataModuleInfo::{{ moduleName }}_ID, 0, SIZE),
{% for attribute in attributes %}
{{ attribute["name"] }}({{ attribute["default"] }})
{% if not loop.last %}
,
{% endif %}
{% endfor %}
{ }

Expand All @@ -26,17 +36,19 @@ namespace {

void {{ moduleName }}::ToByteArray(uint8_t* buff) const
{
size_t index = 0;
{% for attribute in attributes %}
{%- for byte in range(attribute["bytes"]) %}
buff[{{ byte }}] = static_cast<uint8_t>({{ attribute["name"] }} >> {{ byte }});
{% endfor %}
memcpy(buff + index, &{{ attribute["name"] }}, sizeof({{ attribute["name"] }}));
index += sizeof({{ attribute["name"] }});
{% endfor %}
}

void {{ moduleName }}::FromByteArray(uint8_t* buff)
{
size_t index = 0;
{% for attribute in attributes %}
// TODO: This one is much harder and prone to error
throttle_ = static_cast<uint16_t>(buff[1]) << 8 | buff[0];
memcpy(&{{ attribute["name"] }}, buff + index,sizeof({{ attribute["name"] }}));
index += sizeof({{ attribute["name"] }});
{% endfor %}
}

Expand Down
26 changes: 12 additions & 14 deletions datamodule/cpp/module.h
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
/*
* FrontLights.hpp
*
* Created on: Jan 17, 2022
* Author: John Carr
* THIS IS AUTO GENERATED, DO NOT EDIT
*/

#ifndef SOLARGATORSBSP_STM_DATAMODULES_INC_FRONTLIGHTS_HPP_
#define SOLARGATORSBSP_STM_DATAMODULES_INC_FRONTLIGHTS_HPP_

#include <DataModule.hpp>
#include "DataModule.hpp"
#define BUFF_SIZE 50

namespace SolarGators {
namespace DataModules {

class FrontLights: public DataModule {
class {{ moduleName }}: public DataModule {
public:
FrontLights();
~FrontLights();
uint16_t GetThrottleVal() const;
bool GetBreaksVal() const;
uint8_t buffCtr;
uint16_t breaksBuffer[BUFF_SIZE];
{{ moduleName }}();
~{{ moduleName }}();
{% for attribute in attributes %}
{{ attribute["type"] }} Get{{ attribute["name"] }}Val() const;
{% endfor %}

// CAN Functions
void ToByteArray(uint8_t* buff) const;
void FromByteArray(uint8_t* buff);
Expand All @@ -30,10 +29,9 @@ class FrontLights: public DataModule {
#endif

protected:
uint16_t throttle_;
bool breaks_;

// TODO: Accelerometer values
{% for attribute in attributes %}
{{ attribute["type"] }} {{ attribute["name"] }};
{% endfor %}
};

} /* namespace DataModules */
Expand Down
31 changes: 22 additions & 9 deletions datamodule/generate.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import os
import sys
from pathlib import Path
import yaml
from jinja2 import Environment, FileSystemLoader, select_autoescape
from jinja2 import Environment, FileSystemLoader


def main():
config_file = sys.argv[1]

def main(config_file: str):
with open(config_file, "r") as f:
config = yaml.safe_load(f)


env = Environment(loader=FileSystemLoader(os.path.dirname(os.path.abspath(__file__))))
env = Environment(loader=FileSystemLoader(Path(__file__).parent))

cpp_template = env.get_template("cpp/module.cpp")
hpp_template = env.get_template("cpp/module.h")
info_template = env.get_template("cpp/DataModuleInfo.hpp")

for can_message in config["can_messages"]:

# ensure the fist letter is caps
for attribute in can_message["schema"]:
attribute["bytes"] = 2
attribute["name"] = attribute["name"][0].upper() + attribute["name"][1:]

with open(f"{can_message['name']}.cpp", "w") as f:
file = cpp_template.render(
Expand All @@ -27,6 +27,19 @@ def main():
)
f.write(file)

with open(f"{can_message['name']}.hpp", "w") as f:
file = hpp_template.render(
moduleName=can_message["name"],
attributes=can_message["schema"],
)
f.write(file)

with open(f"DataModuleInfo.hpp", "w") as f:
file = info_template.render(
canMessages=config["can_messages"],
)
f.write(file)


if __name__ == "__main__":
main()
main(sys.argv[1])
Empty file added tests/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions tests/goldens/16bit/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
can_messages:
- id: 0x11
name: "RX0"
schema:
- type: "uint16_t"
name: "first"
default: 0

- type: "uint16_t"
name: "second"
default: 0
34 changes: 34 additions & 0 deletions tests/goldens/16bit/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <sstream>
#include <cstring>
#include <csignal>
#include "RX0.hpp"

int main() {
uint8_t data[4] = {0x37, 0x44, 0x20, 0x40};
SolarGators::DataModules::RX0 RX0;

RX0.FromByteArray(data);

std::cout << "input first: " << RX0.GetFirstVal() << std::endl;
std::cout << "input second: " << RX0.GetSecondVal() << std::endl;
if (RX0.GetFirstVal() != 0x4437) {
std::cout << "first is wrong!" << std::endl;
return -1;
}

if (RX0.GetSecondVal() != 0x4020) {
std::cout << "second is wrong!" << std::endl;
return -1;
}

RX0.ToByteArray(data);
if (data[0] != 0x37 || data[1] != 0x44) {
std::cout << "first to byte array is wrong!" << std::endl;
return -1;
}
if (data[2] != 0x20 || data[3] != 0x40) {
std::cout << "second to byte array is wrong!" << std::endl;
return -1;
}
}
11 changes: 11 additions & 0 deletions tests/goldens/8bit/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
can_messages:
- id: 0x11
name: "RX0"
schema:
- type: "uint8_t"
name: "first"
default: 0

- type: "uint8_t"
name: "second"
default: 0
34 changes: 34 additions & 0 deletions tests/goldens/8bit/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <iostream>
#include <sstream>
#include <cstring>
#include <csignal>
#include "RX0.hpp"

int main() {
uint8_t data[2] = {0x37, 0x44};
SolarGators::DataModules::RX0 RX0;

RX0.FromByteArray(data);

std::cout << "input first: " << RX0.GetFirstVal() << std::endl;
std::cout << "input second: " << RX0.GetSecondVal() << std::endl;
if (RX0.GetFirstVal() != data[0]) {
std::cout << "first is wrong!" << std::endl;
return -1;
}

if (RX0.GetSecondVal() != data[1]) {
std::cout << "second is wrong!" << std::endl;
return -1;
}

RX0.ToByteArray(data);
if (data[0] != 0x37) {
std::cout << "first to byte array is wrong!" << std::endl;
return -1;
}
if (data[1] != 0x44) {
std::cout << "second to byte array is wrong!" << std::endl;
return -1;
}
}
11 changes: 11 additions & 0 deletions tests/goldens/floats/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
can_messages:
- id: 0x11
name: "RX0"
schema:
- type: "float"
name: "first"
default: 0

- type: "float"
name: "second"
default: 0
Loading

0 comments on commit 4cb0ebb

Please sign in to comment.