Skip to content

Commit

Permalink
Adds helper functions to generate different DCC packet types: (#502)
Browse files Browse the repository at this point in the history
- functions 29 to 68
- binary states
- analog states
  • Loading branch information
balazsracz authored Jan 6, 2021
1 parent a2e2124 commit 66698b2
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 8 deletions.
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

0 comments on commit 66698b2

Please sign in to comment.