Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds helper functions to generate different DCC packet types: #502

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions src/dcc/Packet.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ enum
DCC_FUNCTION2_F9 = 0b10100000,
DCC_FEATURE_EXP_F13 = 0b11011110,
DCC_FEATURE_EXP_F21 = 0b11011111,
DCC_FEATURE_EXP_FNHI = 0b11011000,
DCC_BINARY_SHORT = 0b11011101,
DCC_BINARY_LONG = 0b11000000,
DCC_ANALOG_FN = 0b00111101,

DCC_PROG_READ1 = 0b11100100,
DCC_PROG_WRITE1 = 0b11101100,
Expand Down Expand Up @@ -234,17 +238,39 @@ void Packet::add_dcc_function9_12(unsigned values)
add_dcc_checksum();
}

void Packet::add_dcc_function13_20(unsigned values)
void Packet::add_dcc_function_hi(uint8_t base, uint8_t values)
{
payload[dlc++] = DCC_FEATURE_EXP_F13;
payload[dlc++] = values & 0xff;
base -= 13;
HASSERT((base & 0b111) == 0);
HASSERT(base <= (61 - 13));
base >>= 3;
base -= 2;
payload[dlc++] = DCC_FEATURE_EXP_FNHI | (base & 0b111);
payload[dlc++] = values;
add_dcc_checksum();
}

void Packet::add_dcc_function21_28(unsigned values)
void Packet::add_dcc_binary_state(uint16_t fn, bool value)
{
payload[dlc++] = DCC_FEATURE_EXP_F21;
payload[dlc++] = values & 0xff;
if (fn <= 127)
{
payload[dlc++] = DCC_BINARY_SHORT;
payload[dlc++] = fn | (value ? 0x80 : 0);
}
else
{
payload[dlc++] = DCC_BINARY_LONG;
payload[dlc++] = (fn & 0x7F) | (value ? 0x80 : 0);
payload[dlc++] = (fn >> 8) & 0xFF;
}
add_dcc_checksum();
}

void Packet::add_dcc_analog_function(uint8_t fn, uint8_t value)
{
payload[dlc++] = DCC_ANALOG_FN;
payload[dlc++] = fn;
payload[dlc++] = value;
add_dcc_checksum();
}

Expand Down
69 changes: 69 additions & 0 deletions src/dcc/Packet.cxxtest
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,75 @@ TEST_F(PacketTest, Fn20)
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011111, 0xAA, _));
}

TEST_F(PacketTest, Fn29)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_function_hi(29, 0x5A);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011000, 0x5A, _));
}

TEST_F(PacketTest, Fn37)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_function_hi(37, 0x11);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011001, 0x11, _));
}

TEST_F(PacketTest, Fn45)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_function_hi(45, 0x11);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011010, 0x11, _));
}

TEST_F(PacketTest, Fn53)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_function_hi(53, 0x11);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011011, 0x11, _));
}

TEST_F(PacketTest, Fn61)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_function_hi(61, 0x11);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011100, 0x11, _));
}

TEST_F(PacketTest, BinaryStateShort)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_binary_state(61, true);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011101, 61 | 0x80, _));
}

TEST_F(PacketTest, BinaryStateShortOff)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_binary_state(127, false);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11011101, 127, _));
}

TEST_F(PacketTest, BinaryStateLongOn)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_binary_state(16 * 256 + 61, true);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11000000, 61 + 0x80, 16, _));
}

TEST_F(PacketTest, BinaryStateLongOff)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_binary_state(16 * 256 + 61, false);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b11000000, 61, 16, _));
}

TEST_F(PacketTest, AnalogFunction)
{
pkt_.add_dcc_address(DccShortAddress(55));
pkt_.add_dcc_analog_function(17, 99);
EXPECT_THAT(get_packet(), ElementsAre(55, 0b00111101, 17, 99, _));
}

TEST_F(PacketTest, DccBasicAccyOn)
{
Expand Down
27 changes: 25 additions & 2 deletions src/dcc/Packet.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,34 @@ struct Packet : public DCCPacket
/** Adds a DCC function group command to the packet. The lowest numbered
* function is always at bit zero. @param values are bitmask of functions
* to send to the loco. */
void add_dcc_function13_20(unsigned values);
void add_dcc_function13_20(unsigned values)
{
add_dcc_function_hi(13, values);
}
/** Adds a DCC function group command to the packet. The lowest numbered
* function is always at bit zero. @param values are bitmask of functions
* to send to the loco. */
void add_dcc_function21_28(unsigned values);
void add_dcc_function21_28(unsigned values)
{
add_dcc_function_hi(21, values);
}
/** Adds a DCC function group command to the packet. The lowest numbered
* function is always at bit zero.
* @param base is a valid function number base, 13, 21, 29, 37, 45, 53
* or 61.
* @param values are bitmask of functions to send to the loco. */
void add_dcc_function_hi(uint8_t base, uint8_t values);

/** Adds a DCC binary state control command to the packet. Automatically
* picks the short or long form, depending on the range of the argument.
* @param fn is a binary function variable, 0 to 32767.
* @param value true/false, what to set to. */
void add_dcc_binary_state(uint16_t fn, bool value);

/** Adds a DCC analog function control command to the packet.
* @param fn is an analog function variable, 0 to 255.
* @param value to set it to, 0 to 255. */
void add_dcc_analog_function(uint8_t fn, uint8_t value);

/** Helper function for adding programming mode packets. */
void add_dcc_prog_command(
Expand Down