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