1 #include "seatalk_reader.hpp"
8 seatalk_reader::seatalk_reader(std::unique_ptr
<device
> && dev
)
11 std::fill_n(reinterpret_cast<uint8_t *>(&ctx
), sizeof(ctx
), 0);
13 ctx
.state
= State::READ
;
18 seatalk_reader::~seatalk_reader() {}
20 void seatalk_reader::close()
27 uint8_t seatalk_reader::parity(uint8_t a
) const
31 for (int i
= 0; i
< 8; ++i
) {
39 void seatalk_reader::write_cmd(uint8_t c
)
41 if (ctx
.remaining
> 0 && ctx
.remaining
< 254) {
50 /// Writes data into the read context buffer.
51 void seatalk_reader::write_data(uint8_t c
)
53 if (ctx
.index
>= sizeof(ctx
.data
))
56 if (ctx
.remaining
== 0)
59 if (ctx
.remaining
== 255) // not yet in sync
62 if (ctx
.remaining
== 254) {
63 // attribute byte, -1 because cmd is already consumed
64 ctx
.remaining
= 3 + (c
& 0x0f) - 1;
67 ctx
.data
[ctx
.index
] = c
;
72 /// Processes SeaTalk data read from the device.
74 /// This function contains a state machine, which does the handling
75 /// of the SeaTalk specific feature: misusing the parity bit as
76 /// indicator for command bytes.
77 /// Since termios is in use, which provides parity error information
78 /// as quoting bytes, a non-trivial implementation is needed to
79 /// distinguish between normal and command bytes. Also, collision
80 /// detection on this pseudo-bus (SeaTalk) is handled.
82 /// @exception std::runtime_error Bus read error.
83 void seatalk_reader::process_seatalk()
87 if (ctx
.raw
== 0xff) {
88 ctx
.state
= State::ESCAPE
;
90 if (parity(ctx
.raw
)) {
94 if (ctx
.remaining
== 0)
101 if (ctx
.raw
== 0x00) {
102 ctx
.state
= State::PARITY
;
103 } else if (ctx
.raw
== 0xff) {
105 if (ctx
.remaining
== 0)
107 ctx
.state
= State::READ
;
109 throw std::runtime_error
{"SeaTalk bus read error."};
114 if (parity(ctx
.raw
)) {
116 if (ctx
.remaining
== 0)
121 ctx
.state
= State::READ
;
126 /// Reads data from the device.
128 /// @retval true Success.
129 /// @retval false End of file.
130 /// @exception std::runtime_error The device was invalid or read error.
131 bool seatalk_reader::read_data()
134 throw std::runtime_error
{"device invalid"};
135 int rc
= dev
->read(reinterpret_cast<char *>(&ctx
.raw
), sizeof(ctx
.raw
));
139 throw std::runtime_error
{"read error"};
140 if (rc
!= sizeof(ctx
.raw
))
141 throw std::runtime_error
{"read error"};
145 /// Reads data from the device and processes it. If a complete SeaTalk
146 /// message was received the method process_message will be executed.
147 /// This method automatcially synchronizes with the SeaTalk bus.
149 /// @retval true Success.
150 /// @retval false End of file.
151 /// @exception std::runtime_error Device or processing error.
152 bool seatalk_reader::read()
160 void seatalk_reader::emit_message()
162 process_message(std::vector
<uint8_t>{ctx
.data
, ctx
.data
+ ctx
.index
});