diff --git a/gen_c/gen_messages.py b/gen_c/gen_messages.py index a44a829..54cddf8 100644 --- a/gen_c/gen_messages.py +++ b/gen_c/gen_messages.py @@ -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)} }}""") diff --git a/gen_c/hydrolink_gen_c.py b/gen_c/hydrolink_gen_c.py index 7682e22..65ea1fc 100644 --- a/gen_c/hydrolink_gen_c.py +++ b/gen_c/hydrolink_gen_c.py @@ -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) diff --git a/gen_python/hydrolink_gen_python.py b/gen_python/hydrolink_gen_python.py index 4816f6a..7b2c33b 100644 --- a/gen_python/hydrolink_gen_python.py +++ b/gen_python/hydrolink_gen_python.py @@ -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 = {{ diff --git a/gen_python/hydrolink_msg.py b/gen_python/hydrolink_msg.py index bf1c779..37c8d14 100644 --- a/gen_python/hydrolink_msg.py +++ b/gen_python/hydrolink_msg.py @@ -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 diff --git a/hydrolink_def.xml b/hydrolink_def.xml index 085025b..688bb6e 100644 --- a/hydrolink_def.xml +++ b/hydrolink_def.xml @@ -4,7 +4,7 @@ Command for getting/setting the state of a switch - + Command for getting/setting the value of a PWM channel @@ -37,7 +37,7 @@ - +