some refactoring. Also compute crc over payload AND header

This commit is contained in:
Thies Lennart Alff 2025-02-24 21:04:36 +01:00
parent 588ea34510
commit f3336e911d
Signed by: lennartalff
GPG key ID: 4EC67D34D594104D
5 changed files with 111 additions and 25 deletions

View file

@ -62,11 +62,11 @@ typedef struct {msg_struct} {{
{struct_fields_str}
}} {msg_type};
void {NS_PREFIX_LOWER}{m.name_lower}_msg_encode(uint8_t src_id, uint8_t dst_id, const {msg_type} *msg, {GENERIC_MSG_TYPE} *packet) {{
static inline void {NS_PREFIX_LOWER}msg_{m.name_lower}_encode(uint8_t src_id, uint8_t dst_id, const {msg_type} *msg, {GENERIC_MSG_TYPE} *packet) {{
packet->id = {MSG_ID_PREFIX}{m.name};
packet->src_id = src_id;
packet->dst_id = dst_id;
packet->length = {MSG_ID_PREFIX}{m.id}_LEN + HYDROLINK_NON_PAYLOAD_LEN;
packet->payload_length = {MSG_ID_PREFIX}{m.id}_LEN + HYDROLINK_NON_PAYLOAD_LEN;
{encode_payload_str}
}}
""")
@ -77,6 +77,6 @@ static inline {field.type} {msg_name}_get_{field.name}(const {GENERIC_MSG_TYPE}
return HYDROLINK_RETURN_{field.type}(packet, {field.wire_offset});
}}""")
f.write(f"""
static inline void {NS_PREFIX_LOWER}msg{m.name_lower}_decode(const {GENERIC_MSG_TYPE} *packet, {msg_type} *{m.name_lower}) {{
static inline void {NS_PREFIX_LOWER}msg_{m.name_lower}_decode(const {GENERIC_MSG_TYPE} *packet, {msg_type} *{m.name_lower}) {{
{decode_payload_str(m)}
}}""")

View file

@ -13,10 +13,11 @@ def generate_main_header(msgs, dir):
with open(os.path.join(dir, "hydrolink.h"), "w") as f:
f.write(f"""#pragma once
#include "protocol.h"
#include "hydrolink_enums.h"
{"\n".join(f"#include \"{GENERIC_MSG_NAME}_{msg.name_lower}.h\"" for msg in msgs)}
""")
def generate_protocol(xml, dir):
def generate_protocol(xml, msgs, dir):
put_defines = []
for typename in TYPE_LENGTHS:
length = TYPE_LENGTHS[typename]
@ -41,6 +42,44 @@ def generate_protocol(xml, dir):
#define HYDROLINK_MAX_PAYLOAD_LEN {xml.largest_payload}
#define HYDROLINK_MAX_MSG_LEN (HYDROLINK_MAX_PAYLOAD_LEN + HYDROLINK_NON_PAYLOAD_LEN)
typedef struct {{
uint8_t msg_id;
uint8_t crc_extra;
}} hydrolink_crc_extra_t;
#define HYDROLINK_MSG_CRCS {{{", ".join(f"{{{msg.id}, {msg.crc_extra}}}" for msg in msgs)}}}
/**
* @brief Get the crc_extra byte corresponding to msg_id
*
* @param msg_id the message's id
* @param crc[out] the crc_extra byte as output of this function
* @return Return 1 if successfull, 0 otherwise.
**/
static inline uint8_t hydrolink_get_crc_extra(uint8_t msg_id, uint8_t *crc) {{
static const hydrolink_crc_extra_t crcs[] = HYDROLINK_MSG_CRCS;
uint8_t left = 0;
uint8_t right = sizeof(crcs) / sizeof(crcs[0]) - 1;
while (left < right) {{
uint8_t center = (left+right+1) / 2;
if (msg_id < crcs[center].msg_id) {{
right = center - 1;
continue;
}}
if (msg_id > crcs[center].msg_id) {{
left = center;
continue;
}}
left = center;
break;
}}
if (crcs[left].msg_id != msg_id) {{
return 0;
}}
*crc = crcs[left].crc_extra;
return 1;
}}
struct {GENERIC_MSG_STRUCT};
typedef struct {GENERIC_MSG_STRUCT} {GENERIC_MSG_TYPE};
@ -59,19 +98,19 @@ struct {GENERIC_MSG_STRUCT} {{
{put_defines_str}
inline void byte_swap_2(char *dst, const char *src) {{
static inline void byte_swap_2(char *dst, const char *src) {{
dst[0] = src[1];
dst[1] = src[0];
}}
inline void byte_swap_4(char *dst, const char *src) {{
static inline void byte_swap_4(char *dst, const char *src) {{
dst[0] = src[3];
dst[1] = src[2];
dst[2] = src[1];
dst[3] = src[0];
}}
inline void byte_swap_8(char *dst, const char *src) {{
static inline void byte_swap_8(char *dst, const char *src) {{
dst[0] = src[7];
dst[1] = src[6];
dst[2] = src[5];
@ -100,9 +139,9 @@ static inline TYPE HYDROLINK_RETURN_## TYPE(const {GENERIC_MSG_TYPE} *msg, uint8
HYDROLINK_MSG_RETURN_TYPE({typename}, {length})
""")
f.write("""
inline void crc_xmodem_init(uint16_t *crc) { *crc = 0; }
static inline void crc_xmodem_init(uint16_t *crc) { *crc = 0; }
inline void crc_xmodem_accumulate(uint8_t data, uint16_t *crc) {
static inline void crc_xmodem_accumulate(uint8_t data, uint16_t *crc) {
*crc = *crc ^ ((uint16_t)data << 8);
for (uint8_t j = 0; j < 8; j++) {
if (*crc & 0x8000) {
@ -113,7 +152,7 @@ inline void crc_xmodem_accumulate(uint8_t data, uint16_t *crc) {
}
}
inline uint16_t crc_xmodem_calculate(const uint8_t *data, uint8_t length) {
static inline uint16_t crc_xmodem_calculate(const uint8_t *data, uint8_t length) {
uint16_t crc;
crc_xmodem_init(&crc);
for (uint8_t i = 0; i < length; i++) {
@ -121,15 +160,29 @@ inline uint16_t crc_xmodem_calculate(const uint8_t *data, uint8_t length) {
}
return crc;
}
""")
f.write(f"""
void hydrolink_fill_header_and_crc({GENERIC_MSG_TYPE} *msg, uint8_t msg_id, uint8_t payload_length, uint8_t dst_id, uint8_t src_id, uint8_t crc_extra) {{
msg->id = msg_id;
msg->payload_length = payload_length;
msg->dst_id = dst_id;
msg->src_id = src_id;
static inline uint16_t hydrolink_calculate_crc(const uint8_t *payload, uint8_t length, uint8_t crc_extra) {
uint16_t crc;
crc_xmodem_init(&crc);
for(int i = 0; i < length; ++i) {
crc_xmodem_accumulate(payload[i], &crc);
}
crc_xmodem_accumulate(crc_extra, &crc);
return crc;
}
""")
f.write(f"""
static inline void hydrolink_fill_header_and_crc({GENERIC_MSG_TYPE} *msg, uint8_t msg_id, uint8_t payload_length, uint8_t dst_id, uint8_t src_id, uint8_t crc_extra) {{
uint16_t crc;
crc_xmodem_init(&crc);
msg->id = msg_id;
crc_xmodem_accumulate(msg->id, &crc);
msg->payload_length = payload_length;
crc_xmodem_accumulate(msg->payload_length, &crc);
msg->dst_id = dst_id;
crc_xmodem_accumulate(msg->dst_id, &crc);
msg->src_id = src_id;
crc_xmodem_accumulate(msg->src_id, &crc);
for(int i = 0; i < msg->payload_length; ++i) {{
crc_xmodem_accumulate(msg->payload[i], &crc);
}}
@ -137,7 +190,7 @@ void hydrolink_fill_header_and_crc({GENERIC_MSG_TYPE} *msg, uint8_t msg_id, uint
msg->crc = crc;
}}
uint8_t hydrolink_serialize_message({GENERIC_MSG_TYPE} *msg, uint8_t *buffer) {{
static inline uint8_t hydrolink_serialize_message({GENERIC_MSG_TYPE} *msg, uint8_t *buffer) {{
buffer[0] = msg->id;
buffer[1] = msg->payload_length;
buffer[2] = msg->dst_id;
@ -151,7 +204,7 @@ uint8_t hydrolink_serialize_message({GENERIC_MSG_TYPE} *msg, uint8_t *buffer) {{
return HYDROLINK_NON_PAYLOAD_LEN + msg->payload_length;
}}
uint8_t hydrolink_deserialize_header({GENERIC_MSG_TYPE} *msg, uint8_t *buffer, uint8_t buffer_length) {{
static inline uint8_t hydrolink_deserialize_header({GENERIC_MSG_TYPE} *msg, uint8_t *buffer, uint8_t buffer_length) {{
if (buffer_length < HYDROLINK_NON_PAYLOAD_LEN) {{
return 0;
}}
@ -176,8 +229,9 @@ def generate(xmls, out_dir):
msgs = []
for x in xmls:
msgs.extend(x.messages)
sorted(msgs, key=lambda msg: msg.id)
for msg in msgs:
generate_message_h(os.path.join(out_dir), msg)
generate_main_header(msgs, out_dir)
generate_protocol(xmls[0], out_dir)
generate_protocol(xmls[0], msgs, out_dir)
generate_enums_h(out_dir, xmls[0].enums)

View file

@ -45,7 +45,41 @@ def generate_hydrolink(out_dir, msgs):
from .hydrolink_msg import HydrolinkHeader, HydrolinkMessage, CrcXmodem
from .hydrolink_msg_ids import {", ".join(f"HYDROLINK_MSG_ID_{msg.name}" for msg in msgs)}
{"\n".join(f"from .hydrolink_{msg.name_lower}_message import Hydrolink{to_camel_case(msg.name)}Message" for msg in msgs)}
import hydrolink_enums as ENUMS
from . import hydrolink_enums as ENUMS
def cobs_decode(data):
output = []
index = 1
offset = data[0] - 1
while index < len(data):
if offset == 0:
output.append(0)
offset = data[index]
else:
output.append(data[index])
index = index + 1
offset = offset - 1
return bytearray(output)
def cobs_encode(data):
output = [0 for i in range(len(data) + 2)]
dst_index = 1
zero_offset = 1
for src_byte in data:
if src_byte == 0:
output[dst_index - zero_offset] = zero_offset
zero_offset = 1
else:
output[dst_index] = src_byte
zero_offset += 1
dst_index += 1
output[dst_index - zero_offset] = zero_offset
output[dst_index] = 0
return output
MSG_ID_TO_CLASS_MAP = {{

View file

@ -161,11 +161,9 @@ class HydrolinkMessage:
self._header.payload_length = len(self._payload)
self._msg_buffer = self._header.pack() + self._payload
crc = CrcXmodem()
print(f"Computing crc over {[int(x) for x in self._msg_buffer]}")
crc.accumulate(self._msg_buffer)
crc.accumulate(struct.pack("B", crc_extra))
self._crc = crc.crc
print(f"Computed crc: {self._crc}")
self._msg_buffer += struct.pack("!H", self._crc)
return self._msg_buffer

View file

@ -4,7 +4,7 @@
<entry name="SWITCH">
<description>Command for getting/setting the state of a switch</description>
</entry>
<entry name="CMD_ID_PWM">
<entry name="PWM">
<description>Command for getting/setting the value of a PWM channel</description>
</entry>
</enum>
@ -37,7 +37,7 @@
<field type="uint8" name="cmd_id" enum="CMD_ID"></field>
<field type="uint8" name="index"></field>
</message>
<message id="3" name="GET_RESPONSE">
<message id="5" name="GET_RESPONSE">
<field type="uint8" name="cmd_id" enum="CMD_ID"></field>
<field type="uint8" name="result" enum="CMD_RESULT"></field>
<field type="int32" name="value"></field>