Skip to content

Commit

Permalink
Merge branch 'main' into #83-ADS131M04-driver
Browse files Browse the repository at this point in the history
  • Loading branch information
nwdepatie committed Jun 4, 2024
2 parents aadd188 + aaca92f commit 045c06a
Show file tree
Hide file tree
Showing 48 changed files with 2,201 additions and 840 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_cerberus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jobs:
run-build:
runs-on: ubuntu-latest
container:
image: nwdepatie/ner-gcc-arm:latest
image: ghcr.io/northeastern-electric-racing/embedded-base:docker-compose
timeout-minutes: 10
steps:
- name: Clone Cerberus
Expand Down
43 changes: 32 additions & 11 deletions cangen/CANField.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,40 @@
from __future__ import annotations
from .Decoding import *
from ruamel.yaml import Optional
from typing import Optional
from dataclasses import dataclass

@dataclass
class CANPoint:
'''
Represents one set of bits in a CAN message.
Seperates CAN decoding logic from MQTT encoding information.
'''
size: int # in bits
signed : bool = False
endianness : str = "big"
final_type: str = "f32"
format: Optional[str] = None

def get_size_bytes(self):
# Calculate max number of bytes to represent value
num_bytes = self.size / 8
if (self.size % 8):
num_bytes += 1

return int(num_bytes)

def get_size_bits(self):
return self.size

@dataclass
class CANField:
class NetField:
'''
Represents a field in a CAN message. Has an id, a name, a unit, a size,
and an optional Format and Decodings. Also knows its own
index within its parent CANMsg, which is assigned at load from YAML.
Represents a field in a CAN message. Contains a MQTT name and unit.
Think 1 MQTT Topic per 1 Net Field
'''

name: str
unit: str
size: int
index: int = -1
final_type: str = "f32"
decodings: Optional[list[Decoding]] = None
format: Optional[str] = None
points: list[CANPoint]
send: bool = True
topic_append: bool = False
15 changes: 4 additions & 11 deletions cangen/CANMsg.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
from __future__ import annotations
from dataclasses import dataclass
from .NetworkEncoding import NetworkEncoding
from .CANField import NetField

@dataclass
class CANMsg:
'''
Represents a CAN message. Has an id, a description, and a number of individual fields.
'''
id: str
desc: str
networkEncoding: list[NetworkEncoding]

def __post_init__(self) -> None:
idx: int = 0
for field in self.networkEncoding[0].fields:
if (field.index is not None):
field.index = idx
idx += field.size
id: str # Hex value of CAN ID, i.e. `0x88`
desc: str # Brief name of CAN message, used for generating function names
fields: list[NetField] # List of CAN fields in the message

def __setstate__(self, state):
self.__init__(**state)
32 changes: 0 additions & 32 deletions cangen/Decoding.py

This file was deleted.

47 changes: 8 additions & 39 deletions cangen/Format.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,18 @@ class Format:
repr: str = ""

@dataclass
class Temperature(Format):
repr: str = "temperature"
class Divide10(Format):
repr: str = "divide10"

@dataclass
class LowVoltage(Format):
repr: str = "low_voltage"
class Divide100(Format):
repr: str = "divide100"

@dataclass
class Torque(Format):
repr: str = "torque"
class Divide10000(Format):
repr: str = "divide10000"

@dataclass
class HighVoltage(Format):
repr: str = "high_voltage"
class Acceleration(Format):
repr: str = "acceleration"

@dataclass
class Current(Format):
repr: str = "current"

@dataclass
class Angle(Format):
repr: str = "angle"

@dataclass
class AngularVelocity(Format):
repr: str = "angular_velocity"

@dataclass
class Frequency(Format):
repr: str = "frequency"

@dataclass
class Power(Format):
repr: str = "power"

@dataclass
class Timer(Format):
repr: str = "timer"

@dataclass
class Flux(Format):
repr: str = "flux"

@dataclass
class CellVoltage(Format):
repr: str = "cell_voltage"
2 changes: 1 addition & 1 deletion cangen/Messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
@dataclass
class Messages:
'''
Represents a list of CAN messages. Has a list of CANMsgs.
Represents a list of CAN messages, used to create a container for each YAML
'''
msgs: list[CANMsg]
23 changes: 0 additions & 23 deletions cangen/NetworkEncoding.py

This file was deleted.

75 changes: 75 additions & 0 deletions cangen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# CANGEN
> Definition of all CAN messages to be sent across the car with Python scripts to generate code to encode and decode
Here is a custom Python module built to generate embedded code for encoding and decoding CAN messages.

## Adding Messages

Messages should follow these rules:
1. Most significant bit should be the leftmost bit in each byte of data
2. Messages <=8 bits endianness should not be specified and will not do anything
3. Wherever possible, bit-wise decoding and byte-wise decoding should happen in seperate bytes to avoid confusion.
Ex. If there are 5 messages of size one (booleans), add a 3 bit filler before adding a 16 bit number
4. Message totals should be byte aligned, meaning total bit size of a message should be a power of 2
5. **Signed messages must be 8,16,or 32 bits!**
6. **Little endian messages must be 8,16, or 32 bits!**
7. Maximum size of a sent message (default, aka send=True), is 32 bits

Message guide:
1. Use previous examples for most things
2. Use an existing formatter if possible. To create a new one, add it to Format.py and RustSynth.py. Name it what it does if it could be reused by unrelated functins (ex. divide by 100 --> divide100) or if its very obscure use whats its used for (ex. multiply by 0029 in IMU datasheet --> acceleration).

Note: Single bit messages are memcpy-ed wrong by default, you may need to use `reverse_bits` in `c_utils.h`
Note: Please use big endian whenever possible, as that is the standard at which our MC, Charger Box, etc. expect it. Use `endian_swap` in `c_utils.h`

YAML info.
```
# all files start with this yaml
!Messages
msgs:
- !CANMsg
id: "0x80" # hexadecimal string of the CAN ID (extended CAN supported)
desc: "a quick description goes here"
fields: # list of MQTT messages being sent from this CANMsg
- !NetField
name: "The/Topic/Name" # the message topic name, going 3 levels of slashes is usally prefered, dont put trailing slashes
unit: "unit_here" # the unit of the data, ex. mph
send: true # (optional) whether this message should be sent over the network, default is true
topic_append: false # (optional) whether to append the topic name with the value of the first CANPoint in points
points: # list of CAN bits to be used for this message
- !CANPoint:
size: 8 # the integer size to be read, in bits
signed: false # (optional) whether the number is in signed twos complement form, default is false
endianness: "big" # (optional) the byte endianness of the bits being read, "big" or "false", "big" is default
format: "formatter_name" # (optional) the name of the formatter to use, default is no formatting, see above for formatter info
final_type: "f32" # (optional, not recommended) the final type of the data
```

### Directory Structure
```
|
|───CANField.py:
| |───NetField # a class which describes the topic and unit of one or more can points
| └──────CANPoint # a class which describes the decoding operations done to bits of a can message
|
|───CANMsg.py:
| └───CANMsg # Represents a full CAN message
|
|───Messages.py:
| └───Messages # Container for all messages related to a node
|
|───Decoding.py:
| |───LittleEndian
| |───BigEndian
| └───TwosComplement
|
|───YAMLParser.py:
| └───YAMLParser # Parses a YAML file into CAN message structures
|
|───RustSynth.py:
| └───RustSynth # Generates Rust code from a CAN messages structure
|
|───CSynth.py:
| └───CSynth # Generates code from a CAN messages structure
|
└───README.md # This file!
Loading

0 comments on commit 045c06a

Please sign in to comment.