*: use more constexpr
[xcsoar.git] / src / Device / Driver / LX / Protocol.hpp
blobd1f8e15f5fba8a248e3491d497167ec04cc4eaf6
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #ifndef XCSOAR_DEVICE_DRIVER_LX_PROTOCOL_HPP
25 #define XCSOAR_DEVICE_DRIVER_LX_PROTOCOL_HPP
27 #include "Device/Port/Port.hpp"
28 #include "Compiler.h"
30 #include <stddef.h>
31 #include <stdint.h>
33 class OperationEnvironment;
35 namespace LX {
36 static constexpr unsigned NUMTPS = 12;
38 enum Command {
39 PREFIX = 0x02,
40 ACK = 0x06,
41 SYN = 0x16,
42 WRITE_FLIGHT_INFO = 0xCA,
43 READ_MEMORY_SECTION = 0xcc,
44 READ_FLIGHT_LIST = 0xcd,
45 SEEK_MEMORY = 0xce,
46 WRITE_CONTEST_CLASS = 0xD0,
47 READ_LOGGER_DATA = 0xe6,
50 #pragma pack(push, 1) // force byte alignment
52 /**
53 * Strings have extra byte for NULL.
55 struct Pilot {
56 uint8_t unknown1[3];
57 char PilotName[19];
58 char GliderType[12];
59 char GliderID[8];
60 char CompetitionID[4];
61 uint8_t unknown2[73];
62 } gcc_packed;
64 /**
65 * Strings have extra byte for NULL.
67 struct Declaration {
68 uint8_t unknown1[5];
69 uint8_t dayinput;
70 uint8_t monthinput;
71 uint8_t yearinput;
72 uint8_t dayuser;
73 uint8_t monthuser;
74 uint8_t yearuser;
75 int16_t taskid;
76 uint8_t numtps;
77 uint8_t tptypes[NUMTPS];
78 int32_t Longitudes[NUMTPS];
79 int32_t Latitudes[NUMTPS];
80 char WaypointNames[NUMTPS][9];
81 } gcc_packed;
83 struct MemoryAddress32 {
84 uint8_t address1;
85 uint8_t address0;
86 uint8_t address3;
87 uint8_t address2;
88 } gcc_packed;
90 struct MemoryAddress24 {
91 uint8_t address[3];
93 MemoryAddress24 &operator=(const MemoryAddress32 &other) {
94 address[0] = other.address0;
95 address[1] = other.address1;
96 address[2] = other.address2;
97 return *this;
100 MemoryAddress24 &operator=(const uint8_t other[3]) {
101 address[0] = other[0];
102 address[1] = other[1];
103 address[2] = other[2];
104 return *this;
106 } gcc_packed;
108 struct FlightInfo {
109 uint8_t valid;
110 MemoryAddress32 start_address;
111 MemoryAddress32 end_address;
112 char date[9];
113 char start_time[9];
114 char stop_time[9];
115 uint8_t dummy0[4];
116 char pilot[52];
117 uint16_t logger_id;
118 uint8_t flight_no; /* ? */
120 bool IsValid() const {
121 return valid == 1 && date[8] == 0 && start_time[8] == 0 &&
122 stop_time[8] == 0;
124 } gcc_packed;
126 struct SeekMemory {
127 MemoryAddress24 start_address, end_address;
128 } gcc_packed;
130 struct MemorySection {
131 static constexpr unsigned N = 0x10;
133 uint16_t lengths[N];
134 } gcc_packed;
137 * Strings have extra byte for NULL.
139 struct ContestClass {
140 char contest_class[9];
141 } gcc_packed;
143 #pragma pack(pop)
145 static inline bool
146 SendSYN(Port &port)
148 return port.Write(SYN);
151 static inline bool
152 ExpectACK(Port &port, OperationEnvironment &env, unsigned timeout_ms=2000)
154 return port.WaitForChar(ACK, env, timeout_ms) == Port::WaitResult::READY;
158 * Send SYN and wait for ACK.
160 * @return true on success
162 static inline bool
163 Connect(Port &port, OperationEnvironment &env, unsigned timeout_ms=500)
165 return SendSYN(port) && ExpectACK(port, env, timeout_ms);
169 * Enter command mode: flush all buffers, configure a sensible
170 * receive timeout, sends SYN three times and waits for ACK.
172 bool
173 CommandMode(Port &port, OperationEnvironment &env);
176 * Enter command mode without waiting for ACK.
178 void
179 CommandModeQuick(Port &port, OperationEnvironment &env);
181 static inline bool
182 SendCommand(Port &port, Command command)
184 return port.Write(PREFIX) &&
185 port.Write(command);
188 bool
189 SendPacket(Port &port, Command command,
190 const void *data, size_t length,
191 OperationEnvironment &env, unsigned timeout_ms=5000);
193 bool
194 ReceivePacket(Port &port, Command command,
195 void *data, size_t length, OperationEnvironment &env,
196 unsigned timeout_ms=5000);
198 gcc_const
199 uint8_t
200 calc_crc_char(uint8_t d, uint8_t crc);
202 gcc_pure
203 uint8_t
204 calc_crc(const void *p0, size_t len, uint8_t crc);
206 bool
207 ReadCRC(Port &port, void *buffer, size_t length, OperationEnvironment &env,
208 unsigned timeout_ms = 5000);
211 * Writes data to a #Port, and keeps track of the CRC.
213 class CRCWriter {
214 Port &port;
215 uint8_t crc;
217 public:
218 CRCWriter(Port &_port):port(_port), crc(0xff) {}
220 bool Write(const void *data, size_t length,
221 OperationEnvironment &env, unsigned timeout_ms=5000) {
222 if (!port.FullWrite(data, length, env, timeout_ms))
223 return false;
225 crc = calc_crc((const uint8_t *)data, length, crc);
226 return true;
229 bool Write(uint8_t value) {
230 if (!port.Write(value))
231 return false;
233 crc = calc_crc_char(value, crc);
234 return true;
238 * Write the CRC, and reset it, so the object can be reused.
240 bool Flush() {
241 bool success = port.Write(crc);
242 crc = 0xff;
243 return success;
248 #endif