1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4
5 This file is part of the SANE package.
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <https://www.gnu.org/licenses/>.
19
20 As a special exception, the authors of SANE give permission for
21 additional uses of the libraries contained in this release of SANE.
22
23 The exception is that, if you link a SANE library with other files
24 to produce an executable, this does not by itself cause the
25 resulting executable to be covered by the GNU General Public
26 License. Your use of that executable is in no way restricted on
27 account of linking the SANE library code into it.
28
29 This exception does not, however, invalidate any other reasons why
30 the executable file might be covered by the GNU General Public
31 License.
32
33 If you submit changes to SANE to the maintainers to be included in
34 a subsequent release, you agree by submitting the changes that
35 those changes may be distributed with this exception intact.
36
37 If you write modifications of your own for SANE, it is your choice
38 whether to permit this exception to apply to your modifications.
39 If you do not wish that, delete this exception notice.
40 */
41
42 #ifndef BACKEND_GENESYS_REGISTER_H
43 #define BACKEND_GENESYS_REGISTER_H
44
45 #include "enums.h"
46 #include "utilities.h"
47
48 #include <algorithm>
49 #include <climits>
50 #include <cstdint>
51 #include <iostream>
52 #include <iomanip>
53 #include <stdexcept>
54 #include <vector>
55
56 namespace genesys {
57
58 template<class Value>
59 struct Register
60 {
61 std::uint16_t address = 0;
62 Value value = 0;
63 };
64
65 using GenesysRegister = Register<std::uint8_t>;
66
67 template<class Value>
68 inline bool operator<(const Register<Value>& lhs, const Register<Value>& rhs)
69 {
70 return lhs.address < rhs.address;
71 }
72
73 struct GenesysRegisterSetState
74 {
75 bool is_lamp_on = false;
76 bool is_xpa_on = false;
77 bool is_motor_on = false;
78 MotorMode motor_mode = MotorMode::PRIMARY;
79 };
80
81 template<class Value>
82 class RegisterContainer
83 {
84 public:
85
86 enum Options {
87 SEQUENTIAL = 1
88 };
89
90 using RegisterType = Register<Value>;
91 using ContainerType = std::vector<RegisterType>;
92 using iterator = typename ContainerType::iterator;
93 using const_iterator = typename ContainerType::const_iterator;
94
95 RegisterContainer() = default;
96
RegisterContainer(Options opts)97 RegisterContainer(Options opts) : RegisterContainer()
98 {
99 if ((opts & SEQUENTIAL) == SEQUENTIAL) {
100 sorted_ = false;
101 }
102 }
103
init_reg(std::uint16_t address,Value default_value)104 void init_reg(std::uint16_t address, Value default_value)
105 {
106 if (find_reg_index(address) >= 0) {
107 set(address, default_value);
108 return;
109 }
110 RegisterType reg;
111 reg.address = address;
112 reg.value = default_value;
113 registers_.push_back(reg);
114 if (sorted_)
115 std::sort(registers_.begin(), registers_.end());
116 }
117
has_reg(std::uint16_t address)118 bool has_reg(std::uint16_t address) const
119 {
120 return find_reg_index(address) >= 0;
121 }
122
remove_reg(std::uint16_t address)123 void remove_reg(std::uint16_t address)
124 {
125 int i = find_reg_index(address);
126 if (i < 0) {
127 throw std::runtime_error("the register does not exist");
128 }
129 registers_.erase(registers_.begin() + i);
130 }
131
find_reg(std::uint16_t address)132 RegisterType& find_reg(std::uint16_t address)
133 {
134 int i = find_reg_index(address);
135 if (i < 0) {
136 throw std::runtime_error("the register does not exist");
137 }
138 return registers_[i];
139 }
140
find_reg(std::uint16_t address)141 const RegisterType& find_reg(std::uint16_t address) const
142 {
143 int i = find_reg_index(address);
144 if (i < 0) {
145 throw std::runtime_error("the register does not exist");
146 }
147 return registers_[i];
148 }
149
set(std::uint16_t address,Value value)150 void set(std::uint16_t address, Value value)
151 {
152 find_reg(address).value = value;
153 }
154
get(std::uint16_t address)155 Value get(std::uint16_t address) const
156 {
157 return find_reg(address).value;
158 }
159
reserve(std::size_t size)160 void reserve(std::size_t size) { registers_.reserve(size); }
clear()161 void clear() { registers_.clear(); }
size()162 std::size_t size() const { return registers_.size(); }
163
begin()164 iterator begin() { return registers_.begin(); }
begin()165 const_iterator begin() const { return registers_.begin(); }
166
end()167 iterator end() { return registers_.end(); }
end()168 const_iterator end() const { return registers_.end(); }
169
170 private:
find_reg_index(std::uint16_t address)171 int find_reg_index(std::uint16_t address) const
172 {
173 if (!sorted_) {
174 for (std::size_t i = 0; i < registers_.size(); i++) {
175 if (registers_[i].address == address) {
176 return i;
177 }
178 }
179 return -1;
180 }
181
182 RegisterType search;
183 search.address = address;
184 auto it = std::lower_bound(registers_.begin(), registers_.end(), search);
185 if (it == registers_.end())
186 return -1;
187 if (it->address != address)
188 return -1;
189 return std::distance(registers_.begin(), it);
190 }
191
192 // registers are stored in a sorted vector
193 bool sorted_ = true;
194 std::vector<RegisterType> registers_;
195 };
196
197 template<class Value>
198 std::ostream& operator<<(std::ostream& out, const RegisterContainer<Value>& container)
199 {
200 StreamStateSaver state_saver{out};
201
202 out << "RegisterContainer{\n";
203 out << std::hex;
204 out.fill('0');
205
206 for (const auto& reg : container) {
207 unsigned address_width = sizeof(reg.address) * 2;
208 unsigned value_width = sizeof(reg.value) * 2;
209
210 out << " 0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
211 << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value) << '\n';
212 }
213 out << "}";
214 return out;
215 }
216
217 class Genesys_Register_Set
218 {
219 public:
220 static constexpr unsigned MAX_REGS = 256;
221
222 using ContainerType = RegisterContainer<std::uint8_t>;
223 using iterator = typename ContainerType::iterator;
224 using const_iterator = typename ContainerType::const_iterator;
225
226 // FIXME: this shouldn't live here, but in a separate struct that contains Genesys_Register_Set
227 GenesysRegisterSetState state;
228
229 enum Options {
230 SEQUENTIAL = 1
231 };
232
Genesys_Register_Set()233 Genesys_Register_Set()
234 {
235 registers_.reserve(MAX_REGS);
236 }
237
238 // by default the register set is sorted by address. In certain cases it's importand to send
239 // the registers in certain order: use the SEQUENTIAL option for that
Genesys_Register_Set(Options opts)240 Genesys_Register_Set(Options opts) : registers_{static_cast<ContainerType::Options>(opts)}
241 {
242 registers_.reserve(MAX_REGS);
243 }
244
registers()245 const ContainerType& registers() const
246 {
247 return registers_;
248 }
249
init_reg(std::uint16_t address,std::uint8_t default_value)250 void init_reg(std::uint16_t address, std::uint8_t default_value)
251 {
252 registers_.init_reg(address, default_value);
253 }
254
has_reg(std::uint16_t address)255 bool has_reg(std::uint16_t address) const { return registers_.has_reg(address); }
256
remove_reg(std::uint16_t address)257 void remove_reg(std::uint16_t address) { registers_.remove_reg(address); }
258
find_reg(std::uint16_t address)259 GenesysRegister& find_reg(std::uint16_t address)
260 {
261 return registers_.find_reg(address);
262 }
263
find_reg(std::uint16_t address)264 const GenesysRegister& find_reg(std::uint16_t address) const
265 {
266 return registers_.find_reg(address);
267 }
268
find_reg_address(std::uint16_t address)269 GenesysRegister* find_reg_address(std::uint16_t address)
270 {
271 return &find_reg(address);
272 }
273
find_reg_address(std::uint16_t address)274 const GenesysRegister* find_reg_address(std::uint16_t address) const
275 {
276 return &find_reg(address);
277 }
278
set8(std::uint16_t address,std::uint8_t value)279 void set8(std::uint16_t address, std::uint8_t value)
280 {
281 find_reg(address).value = value;
282 }
283
set8_mask(std::uint16_t address,std::uint8_t value,std::uint8_t mask)284 void set8_mask(std::uint16_t address, std::uint8_t value, std::uint8_t mask)
285 {
286 auto& reg = find_reg(address);
287 reg.value = (reg.value & ~mask) | value;
288 }
289
set16(std::uint16_t address,std::uint16_t value)290 void set16(std::uint16_t address, std::uint16_t value)
291 {
292 find_reg(address).value = (value >> 8) & 0xff;
293 find_reg(address + 1).value = value & 0xff;
294 }
295
set24(std::uint16_t address,std::uint32_t value)296 void set24(std::uint16_t address, std::uint32_t value)
297 {
298 find_reg(address).value = (value >> 16) & 0xff;
299 find_reg(address + 1).value = (value >> 8) & 0xff;
300 find_reg(address + 2).value = value & 0xff;
301 }
302
get8(std::uint16_t address)303 std::uint8_t get8(std::uint16_t address) const
304 {
305 return find_reg(address).value;
306 }
307
get16(std::uint16_t address)308 std::uint16_t get16(std::uint16_t address) const
309 {
310 return (find_reg(address).value << 8) | find_reg(address + 1).value;
311 }
312
get24(std::uint16_t address)313 std::uint32_t get24(std::uint16_t address) const
314 {
315 return (find_reg(address).value << 16) |
316 (find_reg(address + 1).value << 8) |
317 find_reg(address + 2).value;
318 }
319
clear()320 void clear() { registers_.clear(); }
size()321 std::size_t size() const { return registers_.size(); }
322
begin()323 iterator begin() { return registers_.begin(); }
begin()324 const_iterator begin() const { return registers_.begin(); }
325
end()326 iterator end() { return registers_.end(); }
end()327 const_iterator end() const { return registers_.end(); }
328
329 private:
330
331 // registers are stored in a sorted vector
332 ContainerType registers_;
333 };
334
335 inline std::ostream& operator<<(std::ostream& out, const Genesys_Register_Set& regs)
336 {
337 out << regs.registers();
338 return out;
339 }
340
341 template<class Value>
342 struct RegisterSetting
343 {
344 using ValueType = Value;
345 using AddressType = std::uint16_t;
346
347 RegisterSetting() = default;
348
RegisterSettingRegisterSetting349 RegisterSetting(AddressType p_address, ValueType p_value) :
350 address(p_address), value(p_value)
351 {}
352
RegisterSettingRegisterSetting353 RegisterSetting(AddressType p_address, ValueType p_value, ValueType p_mask) :
354 address(p_address), value(p_value), mask(p_mask)
355 {}
356
357 AddressType address = 0;
358 ValueType value = 0;
359 ValueType mask = 0xff;
360
361 bool operator==(const RegisterSetting& other) const
362 {
363 return address == other.address && value == other.value && mask == other.mask;
364 }
365 };
366
367 using GenesysRegisterSetting = RegisterSetting<std::uint8_t>;
368 using GenesysRegisterSetting16 = RegisterSetting<std::uint16_t>;
369
370 template<class Stream, class Value>
serialize(Stream & str,RegisterSetting<Value> & reg)371 void serialize(Stream& str, RegisterSetting<Value>& reg)
372 {
373 serialize(str, reg.address);
374 serialize(str, reg.value);
375 serialize(str, reg.mask);
376 }
377
378 template<class Value>
379 class RegisterSettingSet
380 {
381 public:
382 using ValueType = Value;
383 using SettingType = RegisterSetting<ValueType>;
384 using AddressType = typename SettingType::AddressType;
385
386 using container = std::vector<SettingType>;
387 using iterator = typename container::iterator;
388 using const_iterator = typename container::const_iterator;
389
390 RegisterSettingSet() = default;
RegisterSettingSet(std::initializer_list<SettingType> ilist)391 RegisterSettingSet(std::initializer_list<SettingType> ilist) :
392 registers_(ilist)
393 {}
394
begin()395 iterator begin() { return registers_.begin(); }
begin()396 const_iterator begin() const { return registers_.begin(); }
end()397 iterator end() { return registers_.end(); }
end()398 const_iterator end() const { return registers_.end(); }
399
400 SettingType& operator[](std::size_t i) { return registers_[i]; }
401 const SettingType& operator[](std::size_t i) const { return registers_[i]; }
402
size()403 std::size_t size() const { return registers_.size(); }
empty()404 bool empty() const { return registers_.empty(); }
clear()405 void clear() { registers_.clear(); }
406
push_back(SettingType reg)407 void push_back(SettingType reg) { registers_.push_back(reg); }
408
merge(const RegisterSettingSet & other)409 void merge(const RegisterSettingSet& other)
410 {
411 for (const auto& reg : other) {
412 set_value(reg.address, reg.value);
413 }
414 }
415
has_reg(AddressType address)416 bool has_reg(AddressType address) const
417 {
418 return find_reg_index(address) != -1;
419 }
420
find_reg(AddressType address)421 SettingType& find_reg(AddressType address)
422 {
423 int i = find_reg_index(address);
424 if (i < 0) {
425 throw std::runtime_error("the register does not exist");
426 }
427 return registers_[i];
428 }
429
find_reg(AddressType address)430 const SettingType& find_reg(AddressType address) const
431 {
432 int i = find_reg_index(address);
433 if (i < 0) {
434 throw std::runtime_error("the register does not exist");
435 }
436 return registers_[i];
437 }
438
get_value(AddressType address)439 ValueType get_value(AddressType address) const
440 {
441 int index = find_reg_index(address);
442 if (index >= 0) {
443 return registers_[index].value;
444 }
445 throw std::out_of_range("Unknown register");
446 }
447
set_value(AddressType address,ValueType value)448 void set_value(AddressType address, ValueType value)
449 {
450 int index = find_reg_index(address);
451 if (index >= 0) {
452 registers_[index].value = value;
453 return;
454 }
455 push_back(SettingType(address, value));
456 }
457
458 template<class V>
459 friend void serialize(std::istream& str, RegisterSettingSet<V>& reg);
460 template<class V>
461 friend void serialize(std::ostream& str, RegisterSettingSet<V>& reg);
462
463 bool operator==(const RegisterSettingSet& other) const
464 {
465 return registers_ == other.registers_;
466 }
467
468 private:
469
find_reg_index(AddressType address)470 int find_reg_index(AddressType address) const
471 {
472 for (std::size_t i = 0; i < registers_.size(); i++) {
473 if (registers_[i].address == address) {
474 return i;
475 }
476 }
477 return -1;
478 }
479
480 std::vector<SettingType> registers_;
481 };
482
483 using GenesysRegisterSettingSet = RegisterSettingSet<std::uint8_t>;
484 using GenesysRegisterSettingSet16 = RegisterSettingSet<std::uint16_t>;
485
486 template<class Value>
487 std::ostream& operator<<(std::ostream& out, const RegisterSettingSet<Value>& container)
488 {
489 StreamStateSaver state_saver{out};
490
491 out << "RegisterSettingSet{\n";
492 out << std::hex;
493 out.fill('0');
494
495 for (const auto& reg : container) {
496 unsigned address_width = sizeof(reg.address) * 2;
497 unsigned value_width = sizeof(reg.value) * 2;
498 unsigned mask_width = sizeof(reg.mask) * 2;
499
500 out << " 0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
501 << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value)
502 << " & 0x" << std::setw(mask_width) << static_cast<unsigned>(reg.mask) << '\n';
503 }
504 out << "}";
505 return out;
506 }
507
508 template<class Value>
serialize(std::istream & str,RegisterSettingSet<Value> & reg)509 inline void serialize(std::istream& str, RegisterSettingSet<Value>& reg)
510 {
511 using AddressType = typename RegisterSetting<Value>::AddressType;
512
513 reg.clear();
514 const std::size_t max_register_address = 1 << (sizeof(AddressType) * CHAR_BIT);
515 serialize(str, reg.registers_, max_register_address);
516 }
517
518 template<class Value>
serialize(std::ostream & str,RegisterSettingSet<Value> & reg)519 inline void serialize(std::ostream& str, RegisterSettingSet<Value>& reg)
520 {
521 serialize(str, reg.registers_);
522 }
523
524 template<class F, class Value>
apply_registers_ordered(const RegisterSettingSet<Value> & set,std::initializer_list<std::uint16_t> order,F f)525 void apply_registers_ordered(const RegisterSettingSet<Value>& set,
526 std::initializer_list<std::uint16_t> order, F f)
527 {
528 for (std::uint16_t addr : order) {
529 f(set.find_reg(addr));
530 }
531 for (const auto& reg : set) {
532 if (std::find(order.begin(), order.end(), reg.address) != order.end()) {
533 continue;
534 }
535 f(reg);
536 }
537 }
538
539 } // namespace genesys
540
541 #endif // BACKEND_GENESYS_REGISTER_H
542