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