diff --git a/firmware/projects/Demo/Bitset/bitset.dbc b/firmware/projects/Demo/Bitset/bitset.dbc index 27db36cf1..bfbc30af2 100644 --- a/firmware/projects/Demo/Bitset/bitset.dbc +++ b/firmware/projects/Demo/Bitset/bitset.dbc @@ -4,9 +4,11 @@ BS_: BU_: BITSET -BO_ 940 SampleMessage: 4 BITSET +BO_ 940 SampleMessage: 5 BITSET SG_ Val1a : 0|4@1+ (1,0) [0|1] "unitless" BITSET SG_ Val1b : 4|4@1+ (1,0) [0|1] "unitless" BITSET - SG_ Val2 : 8|8@1+ (1,0) [0|1] "unitless" BITSET - SG_ Val3 : 16|8@1+ (1,0) [0|1] "unitless" BITSET - SG_ Val4 : 24|8@1+ (1,0) [0|1] "unitless" BITSET + SG_ Val2 : 8|8@1+ (1,10) [0|1] "unitless" BITSET + SG_ Val3a : 16|3@1+ (1,0) [0|1] "unitless" BITSET + SG_ Val3b : 19|5@1+ (1,0) [0|1] "unitless" BITSET + SG_ Val4 : 24|8@1+ (3,0) [0|1] "unitless" BITSET + SG_ Val5 : 32|8@1+ (6,2) [0|1] "unitless" BITSET diff --git a/firmware/projects/Demo/Bitset/main.cc b/firmware/projects/Demo/Bitset/main.cc index df4fc6a18..950350589 100644 --- a/firmware/projects/Demo/Bitset/main.cc +++ b/firmware/projects/Demo/Bitset/main.cc @@ -14,8 +14,8 @@ int main(void) { { // these braces limit the scope of the variables. It lets us reuse the // same variable names later - uint8_t test_data[] = {0xA1, 0x02, 0x03, 0x04}; - shared::can::RawMessage raw_msg(940, false, 4, test_data); + uint8_t test_data[] = {0xA1, 0x02, 0xB3, 0x04, 0x05}; + shared::can::RawMessage raw_msg(940, false, 5, test_data); // The constructor is usually private. I "hacked" the jinja template to // make it public for your testing. @@ -25,9 +25,48 @@ int main(void) { // 1a is bit 0-3 and 1b is bit7. assert(unpacked_msg.Val1a() == 0x1); assert(unpacked_msg.Val1b() == 0xA); - assert(unpacked_msg.Val2() == 0x2); - assert(unpacked_msg.Val3() == 0x3); - assert(unpacked_msg.Val4() == 0x4); + assert(unpacked_msg.Val2() == 0xC); + assert(unpacked_msg.Val3a() == 0x3); + assert(unpacked_msg.Val3b() == 0x16); + assert(unpacked_msg.Val4() == 0xC); + assert(unpacked_msg.Val5() == 0x20); + + // uint8_t test_data2[] = {0x01, 0x02, 0x03, 0x04}; + // shared::can::RawMessage raw_msg2(941, false, 4, test_data2); + + // // The constructor is usually private. I "hacked" the jinja template + // to + // // make it public for your testing. + // generated::can::RxSampleMessage unpacked_msg2(raw_msg2, 0); + + // // Notice that 1a and 1b share the same byte. See bitset.dbc + // // 1a is bit 0-3 and 1b is bit7. + // assert(unpacked_msg2.Val1c() == 0x1); + // assert(unpacked_msg2.Val2c() == 0x2); + // assert(unpacked_msg2.Val3c() == 0x3); + // assert(unpacked_msg2.Val4c() == 0x4); + + // uint8_t test_data[] = {0xA4, 0xA5, 0xA6, 0xA7, 0x08, 0x09, 0x0A, + // 0x0B}; shared::can::RawMessage raw_msg(645, false, 11, test_data); + + // // The constructor is usually private. I "hacked" the jinja template + // to + // // make it public for your testing. + // generated::can::RxSampleMessage unpacked_msg(raw_msg, 0); + + // // Notice that 1a and 1b share the same byte. See bitset.dbc + // // 1a is bit 0-3 and 1b is bit7. + // assert(unpacked_msg.AMK_MagnetizingCurrent() == 0x1); + // assert(unpacked_msg.AMK_TorqueCurrent() == 0xA); + // assert(unpacked_msg.AMK_ActualVelocity() == 0xC); + // assert(unpacked_msg.AMK_bDerating() == 0x1); // done + // assert(unpacked_msg.AMK_bInverterOn() == 0x0); // done + // assert(unpacked_msg.AMK_bQuitInverterOn() == 0x1); // done + // assert(unpacked_msg.AMK_bDcOn() == 0x0); // done + // assert(unpacked_msg.AMK_bQuitDcOn() == 0x1); // done + // assert(unpacked_msg.AMK_bWarn() == 0x0); // done + // assert(unpacked_msg.AMK_bError() == 0x1); // done + // assert(unpacked_msg.AMK_bSystemReady() == 0x1); // done printf("All unpack tests passed!\n"); } @@ -38,17 +77,35 @@ int main(void) { .val1a = 0x1, .val1b = 0xA, .val2 = 0x2, - .val3 = 0x3, + .val3a = 0x3, + .val3b = 0xB, .val4 = 0x4, + .val5 = 0x5, }; shared::can::RawMessage raw_unpacked_msg = packed_msg.pack(); assert(raw_unpacked_msg.id == 940); assert(raw_unpacked_msg.data[0] == 0xA1); - assert(raw_unpacked_msg.data[1] == 0x02); - assert(raw_unpacked_msg.data[2] == 0x03); - assert(raw_unpacked_msg.data[3] == 0x04); + assert(raw_unpacked_msg.data[1] == 0xF8); + assert(raw_unpacked_msg.data[2] == 0x5B); + assert(raw_unpacked_msg.data[3] == 0x01); + assert(raw_unpacked_msg.data[4] == 0x00); + + // generated::can::TxSampleMessage packed_msg2{ + // .val1c = 0x1, + // .val2c = 0x2, + // .val3c = 0x3, + // .val4c = 0x4, + // }; + + // shared::can::RawMessage raw_unpacked_msg2 = packed_msg2.pack(); + + // assert(raw_unpacked_msg2.id == 941); + // assert(raw_unpacked_msg2.data[0] == 0x01); + // assert(raw_unpacked_msg2.data[1] == 0x02); + // assert(raw_unpacked_msg2.data[2] == 0x03); + // assert(raw_unpacked_msg2.data[3] == 0x04); printf("All pack tests passed!\n"); } diff --git a/scripts/cangen/cangen/templates/messages.hpp.jinja2 b/scripts/cangen/cangen/templates/messages.hpp.jinja2 index 409c2b2cc..97b7e0989 100644 --- a/scripts/cangen/cangen/templates/messages.hpp.jinja2 +++ b/scripts/cangen/cangen/templates/messages.hpp.jinja2 @@ -12,6 +12,7 @@ #include #include "shared/comms/can/msg.hpp" +#include "etl/bitset.h" namespace generated::can { @@ -80,14 +81,20 @@ public: // HACK for testing {% set i = loop.index0 %} {% set shift = shifts[i] %} {% if mask != 0 %} + etl::bitset<8> temp_bitset_{{ sig_var | camel_to_snake }}(raw_msg.data[{{ i }}]); + etl::bitset<8> temp_mask_{{ sig_var | camel_to_snake }}({{ mask | decimal_to_hex }}U); + temp_bitset_{{ sig_var | camel_to_snake }} &= temp_mask_{{ sig_var | camel_to_snake }}; {% if shift >= 0 %} - {{ temp_sig_var }} |= shared::can::unpack_left_shift<{{ temp_sig_var_type }}>(raw_msg.data[{{ i }}], {{ shift }}U, {{ mask | decimal_to_hex }}U); + temp_bitset_{{ sig_var | camel_to_snake }} <<= {{ shift }}U; {% else %} - {{ temp_sig_var }} |= shared::can::unpack_right_shift<{{ temp_sig_var_type }}>(raw_msg.data[{{ i }}], {{ -shift }}U, {{ mask | decimal_to_hex }}U); + temp_bitset_{{ sig_var | camel_to_snake }} >>= {{ -shift }}U; {% endif %} + {{ temp_sig_var }} |= static_cast<{{ temp_sig_var_type }}>((int)(temp_bitset_{{ sig_var | camel_to_snake }}.to_ulong())); {% endif %} + {% endfor %} {{ sig_var }}_ = static_cast<{{ sig_var_type }}>(static_cast({{ temp_sig_var }}) * {{ sig_var_scale }} + {{ sig_var_offset }}); + {% endfor %} } {{ class_name }}() = delete; @@ -126,11 +133,16 @@ public: {% set i = loop.index0 %} {% set shift = shifts[i] %} {% if mask != 0 %} + etl::bitset<8> temp_bitset_{{ sig_var | camel_to_snake }}(temp_{{ sig_var }}); + etl::bitset<8> temp_mask_{{ sig_var | camel_to_snake }}({{ mask | decimal_to_hex }}U); {% if shift >= 0 %} - data[{{ i }}] |= shared::can::pack_right_shift(temp_{{ sig_var }}, {{ shift }}U, {{ mask | decimal_to_hex }}U); + temp_bitset_{{ sig_var | camel_to_snake }} >>= {{ shift }}U; {% else %} - data[{{ i }}] |= shared::can::pack_left_shift(temp_{{ sig_var }}, {{ -(shift) }}U, {{ mask | decimal_to_hex }}U); + temp_bitset_{{ sig_var | camel_to_snake }} <<= {{ -shift }}U; {% endif %} + temp_bitset_{{ sig_var | camel_to_snake }} &= temp_mask_{{ sig_var | camel_to_snake }}; + data[{{ i }}] |= static_cast((int)(temp_bitset_{{ sig_var | camel_to_snake }}.to_ulong())); + {% endif %} {% endfor %} {% endfor %}