Skip to content

Commit

Permalink
Adds functions to generate paged-mode programming packets. (#500)
Browse files Browse the repository at this point in the history
  • Loading branch information
balazsracz authored Jan 2, 2021
1 parent 6a149cf commit 8e9690d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/dcc/Packet.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ enum
DCC_SVC_BITVAL_VERIFY = 0b11100000,
DCC_SVC_BITVAL_VALUE = 0b00001000,

DCC_SVC_PAGED_WRITE = 0b01111000,
DCC_SVC_PAGED_VERIFY = 0b01110000,

DCC_BASIC_ACCESSORY_B1 = 0b10000000,
DCC_BASIC_ACCESSORY_B2 = 0b10000000,

Expand Down Expand Up @@ -293,6 +296,24 @@ void Packet::set_dcc_svc_write_bit(
add_dcc_prog_command(DCC_SVC_BIT_MANIPULATE, cv_number, vvv);
}

void Packet::set_dcc_svc_paged_write_reg(uint8_t reg, uint8_t value)
{
HASSERT(reg < 8);
start_dcc_svc_packet();
payload[dlc++] = DCC_SVC_PAGED_WRITE | reg;
payload[dlc++] = value;
add_dcc_checksum();
}

void Packet::set_dcc_svc_paged_verify_reg(uint8_t reg, uint8_t value)
{
HASSERT(reg < 8);
start_dcc_svc_packet();
payload[dlc++] = DCC_SVC_PAGED_VERIFY | reg;
payload[dlc++] = value;
add_dcc_checksum();
}

void Packet::add_dcc_basic_accessory(unsigned address, bool is_activate) {
payload[dlc++] = DCC_BASIC_ACCESSORY_B1 | ((address >> 3) & 0b111111);
uint8_t b2 = 1;
Expand Down
36 changes: 36 additions & 0 deletions src/dcc/Packet.cxxtest
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ protected:
return vector<uint8_t>(pkt_.payload + 0, pkt_.payload + pkt_.dlc);
}

/// @return true if pkt_ has correct checksum.
bool check_checksum()
{
uint8_t p = 0;
for (unsigned i = 0; i < pkt_.dlc; i++)
{
p ^= pkt_.payload[i];
}
return p == 0;
}

vector<uint8_t> packet(const std::initializer_list<int> &data)
{
vector<uint8_t> v;
Expand Down Expand Up @@ -205,6 +216,31 @@ TEST_F(PacketTest, SvcProgDirectBit)
EXPECT_THAT(get_packet(), ElementsAre(b1, b2, b3, b1 ^ b2 ^ b3));
}

TEST_F(PacketTest, SvcProgPagedWrite)
{
pkt_.set_dcc_svc_paged_set_page();
EXPECT_THAT(get_packet(), ElementsAre(0b01111101, 0b00000001, 0b01111100));
EXPECT_TRUE(pkt_.packet_header.send_long_preamble);
EXPECT_TRUE(check_checksum());

pkt_.set_dcc_svc_paged_write_reg(3, 0xaa);
EXPECT_THAT(get_packet(), ElementsAre(0b01111011, 0xaa, _));
EXPECT_TRUE(check_checksum());
}

TEST_F(PacketTest, SvcProgPagedVerify)
{
pkt_.set_dcc_svc_paged_set_page(55);
EXPECT_THAT(get_packet(), ElementsAre(0b01111101, 55, _));
EXPECT_TRUE(pkt_.packet_header.send_long_preamble);
EXPECT_TRUE(check_checksum());

pkt_.set_dcc_svc_paged_verify_reg(0, 0x34);
EXPECT_THAT(get_packet(), ElementsAre(0b01110000, 0x34, _));
EXPECT_TRUE(pkt_.packet_header.send_long_preamble);
EXPECT_TRUE(check_checksum());
}

TEST_F(PacketTest, MMOld)
{
pkt_.start_mm_packet();
Expand Down
32 changes: 32 additions & 0 deletions src/dcc/Packet.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ struct Packet : public DCCPacket
* for marklin-14-step speed commands. */
static const unsigned CHANGE_DIR = DCC_PACKET_EMERGENCY_STOP;

/** Used for page-preset packets. */
static const unsigned PAGE_REGISTER_ID = 0b101;

Packet()
{
clear();
Expand Down Expand Up @@ -230,6 +233,35 @@ struct Packet : public DCCPacket
* @param desired is true if bit:=1 should be written */
void set_dcc_svc_write_bit(unsigned cv_number, unsigned bit, bool desired);

/** Sets the packet to a DCC service mode packet in Paged Mode, setting the
* page register. This function does not need a DCC address. Includes the
* checksum.
* @param page Page to set, 1 is the default page, zero is reserved, 255
* max.
*/
void set_dcc_svc_paged_set_page(unsigned page = 1)
{
set_dcc_svc_paged_write_reg(PAGE_REGISTER_ID, page);
}

/** Sets the packet to a DCC service mode packet in Paged Mode, setting any
* register. This function does not need a DCC address. Includes the
* checksum.
* @param reg register, 0 to 7. On the default page register 0 is CV1
* (address).
* @param value Payload to write to that register. 0 to 255.
*/
void set_dcc_svc_paged_write_reg(uint8_t reg, uint8_t value);

/** Sets the packet to a DCC service mode packet in Paged Mode, setting the
* page register. This function does not need a DCC address. Includes the
* checksum.
* @param reg register, 0 to 7. On the default page register 0 is CV1
* (address).
* @param value Payload to check on that register.
*/
void set_dcc_svc_paged_verify_reg(uint8_t reg, uint8_t value);

/** Adds a DCC basic accessory decoder command packet and the checksum
* byte.
* @param address is the unencoded 12-bit address, containing both the A
Expand Down

0 comments on commit 8e9690d

Please sign in to comment.