Skip to content

Commit

Permalink
improve const evals, add hacky formatting, fix example
Browse files Browse the repository at this point in the history
  • Loading branch information
jr1221 committed Aug 2, 2024
1 parent 86bae1e commit b211777
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 31 deletions.
4 changes: 2 additions & 2 deletions cangen/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Messages should follow these rules:
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!**
5. **Signed messages must be 8,16,or 32 bits and byte aligned!**
6. **Little endian messages must be 8,16, or 32 bits and byte aligned!**
7. Maximum size of a sent message (default, aka send=True), is 32 bits
8. Unsent messages should only contain the size parameter
9. Make the topic of an EncodableCANMsg be "Calypso/Bidir/State/{key}/{field_name}"
Expand Down
70 changes: 47 additions & 23 deletions cangen/RustSynth.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def map_msg_to_decoder(self, msg: CANMsg) -> str:
Helper function that maps a given CANMsg to its decode function
"""
return f" {msg.id} => DecodeMessageInfo::new({self.function_name_decode(msg.desc)}),\n"

def map_msg_to_encoder(self, msg: EncodableCANMsg) -> str:
"""
Helper function that maps a given EncodableCANMsg to its encode function
Expand Down Expand Up @@ -85,7 +85,7 @@ def synthesize_decode(self, msg: CANMsg) -> str:
+ [RustSnippets.decode_close]
)
return "\n".join(total_list)

def synthesize_encode(self, msg: EncodableCANMsg) -> str:
"""
Helper function that synthesizes the encode function for a given EncodableCANMsg
Expand Down Expand Up @@ -115,7 +115,7 @@ def parse_msg_decode(self, msg: CANMsg) -> list[str]:
for index, field in enumerate(msg.fields, start=0):
if field.send:
topic_suffix: str = None
# if we have a topic append, then we create a standalone variable to read the bits before we
# if we have a topic append, then we create a standalone variable to read the bits before we
# push all the points
if field.topic_append:
# point to append
Expand All @@ -132,13 +132,13 @@ def parse_msg_decode(self, msg: CANMsg) -> list[str]:
result.append(self.finalize_line(field.name, field.unit, values, topic_appends_name=topic_suffix))

result.append(f" {RustSnippets.network_encoding_closing}")
elif index < len(msg.fields) -1:
elif index < len(msg.fields) -1:
# if field isnt sent, still decode it to get to the next bits, but only if it isnt the last point
# if it is the last point, we can just exit out and save the resources of decoding it
result.append(f" {','.join(self.decode_field_value(point, skip=True) for point in field.points)};")

return result

def parse_msg_encode(self, msg: EncodableCANMsg) -> list[str]:
result = []
# flatten list to get points
Expand All @@ -161,7 +161,7 @@ def decode_field_value(self, field: CANPoint, skip=False) -> str:
"""
Parse can point to do conversions on it, and maybe wrap in formatter
"""
return f"{self.format_data(field, self.parse_decoders(field, skip))}"
return f"{self.decode_format_data(field, self.parse_decoders(field, skip))}"

def encode_field_value(self, field: CANPoint, index: int) -> str:
"""
Expand Down Expand Up @@ -189,7 +189,7 @@ def signature_decode(self, desc: str) -> str:
given CANMsg based off the can message description
"""
return f"pub fn {self.function_name_decode(desc)}(data: &[u8]) -> {RustSnippets.decode_return_type} {{"

def signature_encode(self, desc: str) -> str:
"""
Helper function that generates the signature of a decode function for a
Expand All @@ -201,7 +201,7 @@ def finalize_line(self, topic: str, unit: str, val: str, topic_appends_name: Opt
"""
Helper function that generates a line the data struct for a given CANPoint value
"""
# basically attach the name of the variable of the mqtt data to the topic should it exist,
# basically attach the name of the variable of the mqtt data to the topic should it exist,
# otherwise format the plain string topic (should compile out)
format_topic: str = f'&format!("{topic}'
if topic_appends_name is not None:
Expand All @@ -220,13 +220,13 @@ def parse_decoders(self, field: CANPoint, skip) -> str:

if skip:
return f"reader.skip({field.size}).unwrap()"

if field.endianness == "big":
if field.signed:
# doesnt need exact sign bit as it is in big endian form, the form of the native stream
base = f"reader.read_signed::<i32>({field.size}).unwrap()"
base = f"reader.read_signed_in::<{field.size}, i32>().unwrap()"
else:
base = f"reader.read::<u32>({field.size}).unwrap()"
base = f"reader.read_in::<{field.size}, u32>().unwrap()"
elif field.endianness == "little":
if (field.size != field.get_size_min_bytes()):
print("You cannot have a non byte sized signed number!")
Expand All @@ -249,14 +249,14 @@ def parse_encoders(self, field: CANPoint, index: int) -> str:
"""

default_statement = f"&({field.default}_f32)"
float_final = self.format_data(field, f"*data.get({index}).unwrap_or({default_statement})")
float_final = self.encode_format_data(field, f"*data.get({index}).unwrap_or({default_statement})")

if field.endianness == "big":
if field.signed:
# doesnt need exact sign bit as it is in big endian form, the form of the native stream
base = f"writer.write_signed::<i{field.get_size_min_bytes()}>({field.size}, {float_final} as i{field.get_size_min_bytes()}).unwrap()"
base = f"writer.write_signed_out::<{field.size}, i{field.get_size_min_bytes()}>({float_final} as i{field.get_size_min_bytes()}).unwrap()"
else:
base = f"writer.write::<u{field.get_size_min_bytes()}>({field.size}, {float_final} as u{field.get_size_min_bytes()}).unwrap()"
base = f"writer.write_out::<{field.size}, u{field.get_size_min_bytes()}>({float_final} as u{field.get_size_min_bytes()}).unwrap()"
elif field.endianness == "little":
if (field.size != field.get_size_min_bytes()):
print("You cannot have a non byte sized signed number!")
Expand All @@ -272,14 +272,24 @@ def parse_encoders(self, field: CANPoint, index: int) -> str:

return base

def format_data(self, field: CANPoint, decoded_data: str) -> str:
def decode_format_data(self, field: CANPoint, decoded_data: str) -> str:
"""
Helper function that formats the data for a given CANPoint based off the
format of the CANPoint if it exists
format of the CANPoint if it exists, for the decoding
"""
cf = decoded_data
if field.format:
cf = f"FormatData::{field.format}({decoded_data})"
cf = f"FormatData::{field.format}_d({decoded_data})"
return cf

def encode_format_data(self, field: CANPoint, encoded_data: str) -> str:
"""
Helper function that formats the data for a given CANPoint based off the
format of the CANPoint if it exists, for the encoding alternative
"""
cf = encoded_data
if field.format:
cf = f"FormatData::{field.format}_e({encoded_data})"
return cf

def create_encode_key(self, list_of_keys) -> str:
Expand Down Expand Up @@ -311,26 +321,40 @@ class RustSnippets:
format_impl = """
/**
* Class to contain the data formatting functions
* _d = a func to decode a value
* _e = its counterpart to encode a value for sending on CAN line
*/
pub struct FormatData {}
impl FormatData {
pub fn divide10(value: f32) -> f32 {
pub fn divide10_d(value: f32) -> f32 {
value / 10.0
}
pub fn divide10_e(value: f32) -> f32 {
value * 10.0
}
pub fn divide100(value: f32) -> f32 {
pub fn divide100_d(value: f32) -> f32 {
value / 100.0
}
pub fn divide100_e(value: f32) -> f32 {
value * 100.0
}
pub fn divide10000(value: f32) -> f32 {
pub fn divide10000_d(value: f32) -> f32 {
value / 10000.0
}
pub fn divide10000_e(value: f32) -> f32 {
value * 10000.0
}
/* Acceleration values must be offset by 0.0029 according to datasheet */
pub fn acceleration(value: f32) -> f32 {
pub fn acceleration_d(value: f32) -> f32 {
value * 0.0029
}
pub fn acceleration_e(value: f32) -> f32 {
value / 0.0029
}
}"""

bitreader_create = " let mut reader = BitReader::endian(Cursor::new(&data), BigEndian);"
Expand Down Expand Up @@ -396,7 +420,7 @@ class RustSnippets:
)

encode_master_mapping_signature: str = (
"pub fn get_message_info(key: String) -> EncodeMessageInfo {\n let key_owned = key.as_str();\n match key_owned {"
"pub fn get_message_info(key: String) -> EncodeMessageInfo {\n let key_owned = key.as_str();\n match key_owned {"
# The signature of the master_mapping function
)

Expand Down
12 changes: 6 additions & 6 deletions cangen/can-messages/calypso_cmd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,24 @@ msgs:
unit: "Z"
points:
- !CANPoint
size: 16
endianness: "little"
size: 32
endianness: "big"
format: "divide10000"
default: 69.55
default: 18.443
- !NetField
name: "Calypso/Bidir/State/FirstOff/B"
unit: "G"
points:
- !CANPoint
size: 16
endianness: "big"
size: 8
signed: true
default: 35.4
- !NetField
name: "Calypso/Bidir/State/FirstOff/C"
unit: "G"
points:
- !CANPoint
size: 16
size: 8
endianness: "big"
default: 19
- !NetField
Expand All @@ -39,6 +38,7 @@ msgs:
- !CANPoint
size: 16
endianness: "little"
format: "divide100"
signed: true
default: -21.8

Expand Down

0 comments on commit b211777

Please sign in to comment.