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
21 #ifndef BACKEND_GENESYS_REGISTER_H
22 #define BACKEND_GENESYS_REGISTER_H
23
24 #include "enums.h"
25 #include "utilities.h"
26
27 #include <algorithm>
28 #include <climits>
29 #include <cstdint>
30 #include <iostream>
31 #include <iomanip>
32 #include <stdexcept>
33 #include <vector>
34
35 namespace genesys {
36
37 template<class Value>
38 struct Register
39 {
40 std::uint16_t address = 0;
41 Value value = 0;
42 };
43
44 using GenesysRegister = Register<std::uint8_t>;
45
46 template<class Value>
operator <(const Register<Value>& lhs, const Register<Value>& rhs)47 inline bool operator<(const Register<Value>& lhs, const Register<Value>& rhs)
48 {
49 return lhs.address < rhs.address;
50 }
51
52 struct GenesysRegisterSetState
53 {
54 bool is_lamp_on = false;
55 bool is_xpa_on = false;
56 bool is_motor_on = false;
57 MotorMode motor_mode = MotorMode::PRIMARY;
58 };
59
60 template<class Value>
61 class RegisterContainer
62 {
63 public:
64
65 enum Options {
66 SEQUENTIAL = 1
67 };
68
69 using RegisterType = Register<Value>;
70 using ContainerType = std::vector<RegisterType>;
71 using iterator = typename ContainerType::iterator;
72 using const_iterator = typename ContainerType::const_iterator;
73
74 RegisterContainer() = default;
75
RegisterContainer(Options opts)76 RegisterContainer(Options opts) : RegisterContainer()
77 {
78 if ((opts & SEQUENTIAL) == SEQUENTIAL) {
79 sorted_ = false;
80 }
81 }
82
init_reg(std::uint16_t address, Value default_value)83 void init_reg(std::uint16_t address, Value default_value)
84 {
85 if (find_reg_index(address) >= 0) {
86 set(address, default_value);
87 return;
88 }
89 RegisterType reg;
90 reg.address = address;
91 reg.value = default_value;
92 registers_.push_back(reg);
93 if (sorted_)
94 std::sort(registers_.begin(), registers_.end());
95 }
96
has_reg(std::uint16_t address) const97 bool has_reg(std::uint16_t address) const
98 {
99 return find_reg_index(address) >= 0;
100 }
101
remove_reg(std::uint16_t address)102 void remove_reg(std::uint16_t address)
103 {
104 int i = find_reg_index(address);
105 if (i < 0) {
106 throw std::runtime_error("the register does not exist");
107 }
108 registers_.erase(registers_.begin() + i);
109 }
110
find_reg(std::uint16_t address)111 RegisterType& find_reg(std::uint16_t address)
112 {
113 int i = find_reg_index(address);
114 if (i < 0) {
115 throw std::runtime_error("the register does not exist");
116 }
117 return registers_[i];
118 }
119
find_reg(std::uint16_t address) const120 const RegisterType& find_reg(std::uint16_t address) const
121 {
122 int i = find_reg_index(address);
123 if (i < 0) {
124 throw std::runtime_error("the register does not exist");
125 }
126 return registers_[i];
127 }
128
set(std::uint16_t address, Value value)129 void set(std::uint16_t address, Value value)
130 {
131 find_reg(address).value = value;
132 }
133
get(std::uint16_t address) const134 Value get(std::uint16_t address) const
135 {
136 return find_reg(address).value;
137 }
138
reserve(std::size_t size)139 void reserve(std::size_t size) { registers_.reserve(size); }
clear()140 void clear() { registers_.clear(); }
size() const141 std::size_t size() const { return registers_.size(); }
142
begin()143 iterator begin() { return registers_.begin(); }
begin() const144 const_iterator begin() const { return registers_.begin(); }
145
end()146 iterator end() { return registers_.end(); }
end() const147 const_iterator end() const { return registers_.end(); }
148
149 private:
find_reg_index(std::uint16_t address) const150 int find_reg_index(std::uint16_t address) const
151 {
152 if (!sorted_) {
153 for (std::size_t i = 0; i < registers_.size(); i++) {
154 if (registers_[i].address == address) {
155 return i;
156 }
157 }
158 return -1;
159 }
160
161 RegisterType search;
162 search.address = address;
163 auto it = std::lower_bound(registers_.begin(), registers_.end(), search);
164 if (it == registers_.end())
165 return -1;
166 if (it->address != address)
167 return -1;
168 return std::distance(registers_.begin(), it);
169 }
170
171 // registers are stored in a sorted vector
172 bool sorted_ = true;
173 std::vector<RegisterType> registers_;
174 };
175
176 template<class Value>
operator <<(std::ostream& out, const RegisterContainer<Value>& container)177 std::ostream& operator<<(std::ostream& out, const RegisterContainer<Value>& container)
178 {
179 StreamStateSaver state_saver{out};
180
181 out << "RegisterContainer{\n";
182 out << std::hex;
183 out.fill('0');
184
185 for (const auto& reg : container) {
186 unsigned address_width = sizeof(reg.address) * 2;
187 unsigned value_width = sizeof(reg.value) * 2;
188
189 out << " 0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
190 << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value) << '\n';
191 }
192 out << "}";
193 return out;
194 }
195
196 class Genesys_Register_Set
197 {
198 public:
199 static constexpr unsigned MAX_REGS = 256;
200
201 using ContainerType = RegisterContainer<std::uint8_t>;
202 using iterator = typename ContainerType::iterator;
203 using const_iterator = typename ContainerType::const_iterator;
204
205 // FIXME: this shouldn't live here, but in a separate struct that contains Genesys_Register_Set
206 GenesysRegisterSetState state;
207
208 enum Options {
209 SEQUENTIAL = 1
210 };
211
Genesys_Register_Set()212 Genesys_Register_Set()
213 {
214 registers_.reserve(MAX_REGS);
215 }
216
217 // by default the register set is sorted by address. In certain cases it's importand to send
218 // the registers in certain order: use the SEQUENTIAL option for that
Genesys_Register_Set(Options opts)219 Genesys_Register_Set(Options opts) : registers_{static_cast<ContainerType::Options>(opts)}
220 {
221 registers_.reserve(MAX_REGS);
222 }
223
registers() const224 const ContainerType& registers() const
225 {
226 return registers_;
227 }
228
init_reg(std::uint16_t address, std::uint8_t default_value)229 void init_reg(std::uint16_t address, std::uint8_t default_value)
230 {
231 registers_.init_reg(address, default_value);
232 }
233
has_reg(std::uint16_t address) const234 bool has_reg(std::uint16_t address) const { return registers_.has_reg(address); }
235
remove_reg(std::uint16_t address)236 void remove_reg(std::uint16_t address) { registers_.remove_reg(address); }
237
find_reg(std::uint16_t address)238 GenesysRegister& find_reg(std::uint16_t address)
239 {
240 return registers_.find_reg(address);
241 }
242
find_reg(std::uint16_t address) const243 const GenesysRegister& find_reg(std::uint16_t address) const
244 {
245 return registers_.find_reg(address);
246 }
247
find_reg_address(std::uint16_t address)248 GenesysRegister* find_reg_address(std::uint16_t address)
249 {
250 return &find_reg(address);
251 }
252
find_reg_address(std::uint16_t address) const253 const GenesysRegister* find_reg_address(std::uint16_t address) const
254 {
255 return &find_reg(address);
256 }
257
set8(std::uint16_t address, std::uint8_t value)258 void set8(std::uint16_t address, std::uint8_t value)
259 {
260 find_reg(address).value = value;
261 }
262
set8_mask(std::uint16_t address, std::uint8_t value, std::uint8_t mask)263 void set8_mask(std::uint16_t address, std::uint8_t value, std::uint8_t mask)
264 {
265 auto& reg = find_reg(address);
266 reg.value = (reg.value & ~mask) | value;
267 }
268
set16(std::uint16_t address, std::uint16_t value)269 void set16(std::uint16_t address, std::uint16_t value)
270 {
271 find_reg(address).value = (value >> 8) & 0xff;
272 find_reg(address + 1).value = value & 0xff;
273 }
274
set24(std::uint16_t address, std::uint32_t value)275 void set24(std::uint16_t address, std::uint32_t value)
276 {
277 find_reg(address).value = (value >> 16) & 0xff;
278 find_reg(address + 1).value = (value >> 8) & 0xff;
279 find_reg(address + 2).value = value & 0xff;
280 }
281
get8(std::uint16_t address) const282 std::uint8_t get8(std::uint16_t address) const
283 {
284 return find_reg(address).value;
285 }
286
get16(std::uint16_t address) const287 std::uint16_t get16(std::uint16_t address) const
288 {
289 return (find_reg(address).value << 8) | find_reg(address + 1).value;
290 }
291
get24(std::uint16_t address) const292 std::uint32_t get24(std::uint16_t address) const
293 {
294 return (find_reg(address).value << 16) |
295 (find_reg(address + 1).value << 8) |
296 find_reg(address + 2).value;
297 }
298
clear()299 void clear() { registers_.clear(); }
size() const300 std::size_t size() const { return registers_.size(); }
301
begin()302 iterator begin() { return registers_.begin(); }
begin() const303 const_iterator begin() const { return registers_.begin(); }
304
end()305 iterator end() { return registers_.end(); }
end() const306 const_iterator end() const { return registers_.end(); }
307
308 private:
309
310 // registers are stored in a sorted vector
311 ContainerType registers_;
312 };
313
operator <<(std::ostream& out, const Genesys_Register_Set& regs)314 inline std::ostream& operator<<(std::ostream& out, const Genesys_Register_Set& regs)
315 {
316 out << regs.registers();
317 return out;
318 }
319
320 template<class Value>
321 struct RegisterSetting
322 {
323 using ValueType = Value;
324 using AddressType = std::uint16_t;
325
326 RegisterSetting() = default;
327
RegisterSettinggenesys::RegisterSetting328 RegisterSetting(AddressType p_address, ValueType p_value) :
329 address(p_address), value(p_value)
330 {}
331
RegisterSettinggenesys::RegisterSetting332 RegisterSetting(AddressType p_address, ValueType p_value, ValueType p_mask) :
333 address(p_address), value(p_value), mask(p_mask)
334 {}
335
336 AddressType address = 0;
337 ValueType value = 0;
338 ValueType mask = 0xff;
339
operator ==genesys::RegisterSetting340 bool operator==(const RegisterSetting& other) const
341 {
342 return address == other.address && value == other.value && mask == other.mask;
343 }
344 };
345
346 using GenesysRegisterSetting = RegisterSetting<std::uint8_t>;
347 using GenesysRegisterSetting16 = RegisterSetting<std::uint16_t>;
348
349 template<class Stream, class Value>
serialize(Stream& str, RegisterSetting<Value>& reg)350 void serialize(Stream& str, RegisterSetting<Value>& reg)
351 {
352 serialize(str, reg.address);
353 serialize(str, reg.value);
354 serialize(str, reg.mask);
355 }
356
357 template<class Value>
358 class RegisterSettingSet
359 {
360 public:
361 using ValueType = Value;
362 using SettingType = RegisterSetting<ValueType>;
363 using AddressType = typename SettingType::AddressType;
364
365 using container = std::vector<SettingType>;
366 using iterator = typename container::iterator;
367 using const_iterator = typename container::const_iterator;
368
369 RegisterSettingSet() = default;
RegisterSettingSet(std::initializer_list<SettingType> ilist)370 RegisterSettingSet(std::initializer_list<SettingType> ilist) :
371 registers_(ilist)
372 {}
373
begin()374 iterator begin() { return registers_.begin(); }
begin() const375 const_iterator begin() const { return registers_.begin(); }
end()376 iterator end() { return registers_.end(); }
end() const377 const_iterator end() const { return registers_.end(); }
378
operator [](std::size_t i)379 SettingType& operator[](std::size_t i) { return registers_[i]; }
operator [](std::size_t i) const380 const SettingType& operator[](std::size_t i) const { return registers_[i]; }
381
size() const382 std::size_t size() const { return registers_.size(); }
empty() const383 bool empty() const { return registers_.empty(); }
clear()384 void clear() { registers_.clear(); }
385
push_back(SettingType reg)386 void push_back(SettingType reg) { registers_.push_back(reg); }
387
merge(const RegisterSettingSet& other)388 void merge(const RegisterSettingSet& other)
389 {
390 for (const auto& reg : other) {
391 set_value(reg.address, reg.value);
392 }
393 }
394
has_reg(AddressType address) const395 bool has_reg(AddressType address) const
396 {
397 return find_reg_index(address) != -1;
398 }
399
find_reg(AddressType address)400 SettingType& find_reg(AddressType address)
401 {
402 int i = find_reg_index(address);
403 if (i < 0) {
404 throw std::runtime_error("the register does not exist");
405 }
406 return registers_[i];
407 }
408
find_reg(AddressType address) const409 const SettingType& find_reg(AddressType address) const
410 {
411 int i = find_reg_index(address);
412 if (i < 0) {
413 throw std::runtime_error("the register does not exist");
414 }
415 return registers_[i];
416 }
417
get_value(AddressType address) const418 ValueType get_value(AddressType address) const
419 {
420 int index = find_reg_index(address);
421 if (index >= 0) {
422 return registers_[index].value;
423 }
424 throw std::out_of_range("Unknown register");
425 }
426
set_value(AddressType address, ValueType value)427 void set_value(AddressType address, ValueType value)
428 {
429 int index = find_reg_index(address);
430 if (index >= 0) {
431 registers_[index].value = value;
432 return;
433 }
434 push_back(SettingType(address, value));
435 }
436
437 template<class V>
438 friend void serialize(std::istream& str, RegisterSettingSet<V>& reg);
439 template<class V>
440 friend void serialize(std::ostream& str, RegisterSettingSet<V>& reg);
441
operator ==(const RegisterSettingSet& other) const442 bool operator==(const RegisterSettingSet& other) const
443 {
444 return registers_ == other.registers_;
445 }
446
447 private:
448
find_reg_index(AddressType address) const449 int find_reg_index(AddressType address) const
450 {
451 for (std::size_t i = 0; i < registers_.size(); i++) {
452 if (registers_[i].address == address) {
453 return i;
454 }
455 }
456 return -1;
457 }
458
459 std::vector<SettingType> registers_;
460 };
461
462 using GenesysRegisterSettingSet = RegisterSettingSet<std::uint8_t>;
463 using GenesysRegisterSettingSet16 = RegisterSettingSet<std::uint16_t>;
464
465 template<class Value>
operator <<(std::ostream& out, const RegisterSettingSet<Value>& container)466 std::ostream& operator<<(std::ostream& out, const RegisterSettingSet<Value>& container)
467 {
468 StreamStateSaver state_saver{out};
469
470 out << "RegisterSettingSet{\n";
471 out << std::hex;
472 out.fill('0');
473
474 for (const auto& reg : container) {
475 unsigned address_width = sizeof(reg.address) * 2;
476 unsigned value_width = sizeof(reg.value) * 2;
477 unsigned mask_width = sizeof(reg.mask) * 2;
478
479 out << " 0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
480 << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value)
481 << " & 0x" << std::setw(mask_width) << static_cast<unsigned>(reg.mask) << '\n';
482 }
483 out << "}";
484 return out;
485 }
486
487 template<class Value>
serialize(std::istream& str, RegisterSettingSet<Value>& reg)488 inline void serialize(std::istream& str, RegisterSettingSet<Value>& reg)
489 {
490 using AddressType = typename RegisterSetting<Value>::AddressType;
491
492 reg.clear();
493 const std::size_t max_register_address = 1 << (sizeof(AddressType) * CHAR_BIT);
494 serialize(str, reg.registers_, max_register_address);
495 }
496
497 template<class Value>
serialize(std::ostream& str, RegisterSettingSet<Value>& reg)498 inline void serialize(std::ostream& str, RegisterSettingSet<Value>& reg)
499 {
500 serialize(str, reg.registers_);
501 }
502
503 template<class F, class Value>
apply_registers_ordered(const RegisterSettingSet<Value>& set, std::initializer_list<std::uint16_t> order, F f)504 void apply_registers_ordered(const RegisterSettingSet<Value>& set,
505 std::initializer_list<std::uint16_t> order, F f)
506 {
507 for (std::uint16_t addr : order) {
508 f(set.find_reg(addr));
509 }
510 for (const auto& reg : set) {
511 if (std::find(order.begin(), order.end(), reg.address) != order.end()) {
512 continue;
513 }
514 f(reg);
515 }
516 }
517
518 } // namespace genesys
519
520 #endif // BACKEND_GENESYS_REGISTER_H
521