1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci
3141cc406Sopenharmony_ci   Copyright (C) 2019 Povilas Kanapickas <povilas@radix.lt>
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This file is part of the SANE package.
6141cc406Sopenharmony_ci
7141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
8141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
9141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
10141cc406Sopenharmony_ci   License, or (at your option) any later version.
11141cc406Sopenharmony_ci
12141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
13141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
14141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15141cc406Sopenharmony_ci   General Public License for more details.
16141cc406Sopenharmony_ci
17141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
18141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
19141cc406Sopenharmony_ci*/
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci#ifndef BACKEND_GENESYS_REGISTER_H
22141cc406Sopenharmony_ci#define BACKEND_GENESYS_REGISTER_H
23141cc406Sopenharmony_ci
24141cc406Sopenharmony_ci#include "enums.h"
25141cc406Sopenharmony_ci#include "utilities.h"
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci#include <algorithm>
28141cc406Sopenharmony_ci#include <climits>
29141cc406Sopenharmony_ci#include <cstdint>
30141cc406Sopenharmony_ci#include <iostream>
31141cc406Sopenharmony_ci#include <iomanip>
32141cc406Sopenharmony_ci#include <stdexcept>
33141cc406Sopenharmony_ci#include <vector>
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_cinamespace genesys {
36141cc406Sopenharmony_ci
37141cc406Sopenharmony_citemplate<class Value>
38141cc406Sopenharmony_cistruct Register
39141cc406Sopenharmony_ci{
40141cc406Sopenharmony_ci    std::uint16_t address = 0;
41141cc406Sopenharmony_ci    Value value = 0;
42141cc406Sopenharmony_ci};
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ciusing GenesysRegister = Register<std::uint8_t>;
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_citemplate<class Value>
47141cc406Sopenharmony_ciinline bool operator<(const Register<Value>& lhs, const Register<Value>& rhs)
48141cc406Sopenharmony_ci{
49141cc406Sopenharmony_ci    return lhs.address < rhs.address;
50141cc406Sopenharmony_ci}
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_cistruct GenesysRegisterSetState
53141cc406Sopenharmony_ci{
54141cc406Sopenharmony_ci    bool is_lamp_on = false;
55141cc406Sopenharmony_ci    bool is_xpa_on = false;
56141cc406Sopenharmony_ci    bool is_motor_on = false;
57141cc406Sopenharmony_ci    MotorMode motor_mode = MotorMode::PRIMARY;
58141cc406Sopenharmony_ci};
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_citemplate<class Value>
61141cc406Sopenharmony_ciclass RegisterContainer
62141cc406Sopenharmony_ci{
63141cc406Sopenharmony_cipublic:
64141cc406Sopenharmony_ci
65141cc406Sopenharmony_ci    enum Options {
66141cc406Sopenharmony_ci        SEQUENTIAL = 1
67141cc406Sopenharmony_ci    };
68141cc406Sopenharmony_ci
69141cc406Sopenharmony_ci    using RegisterType = Register<Value>;
70141cc406Sopenharmony_ci    using ContainerType = std::vector<RegisterType>;
71141cc406Sopenharmony_ci    using iterator = typename ContainerType::iterator;
72141cc406Sopenharmony_ci    using const_iterator = typename ContainerType::const_iterator;
73141cc406Sopenharmony_ci
74141cc406Sopenharmony_ci    RegisterContainer() = default;
75141cc406Sopenharmony_ci
76141cc406Sopenharmony_ci    RegisterContainer(Options opts) : RegisterContainer()
77141cc406Sopenharmony_ci    {
78141cc406Sopenharmony_ci        if ((opts & SEQUENTIAL) == SEQUENTIAL) {
79141cc406Sopenharmony_ci            sorted_ = false;
80141cc406Sopenharmony_ci        }
81141cc406Sopenharmony_ci    }
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_ci    void init_reg(std::uint16_t address, Value default_value)
84141cc406Sopenharmony_ci    {
85141cc406Sopenharmony_ci        if (find_reg_index(address) >= 0) {
86141cc406Sopenharmony_ci            set(address, default_value);
87141cc406Sopenharmony_ci            return;
88141cc406Sopenharmony_ci        }
89141cc406Sopenharmony_ci        RegisterType reg;
90141cc406Sopenharmony_ci        reg.address = address;
91141cc406Sopenharmony_ci        reg.value = default_value;
92141cc406Sopenharmony_ci        registers_.push_back(reg);
93141cc406Sopenharmony_ci        if (sorted_)
94141cc406Sopenharmony_ci            std::sort(registers_.begin(), registers_.end());
95141cc406Sopenharmony_ci    }
96141cc406Sopenharmony_ci
97141cc406Sopenharmony_ci    bool has_reg(std::uint16_t address) const
98141cc406Sopenharmony_ci    {
99141cc406Sopenharmony_ci        return find_reg_index(address) >= 0;
100141cc406Sopenharmony_ci    }
101141cc406Sopenharmony_ci
102141cc406Sopenharmony_ci    void remove_reg(std::uint16_t address)
103141cc406Sopenharmony_ci    {
104141cc406Sopenharmony_ci        int i = find_reg_index(address);
105141cc406Sopenharmony_ci        if (i < 0) {
106141cc406Sopenharmony_ci            throw std::runtime_error("the register does not exist");
107141cc406Sopenharmony_ci        }
108141cc406Sopenharmony_ci        registers_.erase(registers_.begin() + i);
109141cc406Sopenharmony_ci    }
110141cc406Sopenharmony_ci
111141cc406Sopenharmony_ci    RegisterType& find_reg(std::uint16_t address)
112141cc406Sopenharmony_ci    {
113141cc406Sopenharmony_ci        int i = find_reg_index(address);
114141cc406Sopenharmony_ci        if (i < 0) {
115141cc406Sopenharmony_ci            throw std::runtime_error("the register does not exist");
116141cc406Sopenharmony_ci        }
117141cc406Sopenharmony_ci        return registers_[i];
118141cc406Sopenharmony_ci    }
119141cc406Sopenharmony_ci
120141cc406Sopenharmony_ci    const RegisterType& find_reg(std::uint16_t address) const
121141cc406Sopenharmony_ci    {
122141cc406Sopenharmony_ci        int i = find_reg_index(address);
123141cc406Sopenharmony_ci        if (i < 0) {
124141cc406Sopenharmony_ci            throw std::runtime_error("the register does not exist");
125141cc406Sopenharmony_ci        }
126141cc406Sopenharmony_ci        return registers_[i];
127141cc406Sopenharmony_ci    }
128141cc406Sopenharmony_ci
129141cc406Sopenharmony_ci    void set(std::uint16_t address, Value value)
130141cc406Sopenharmony_ci    {
131141cc406Sopenharmony_ci        find_reg(address).value = value;
132141cc406Sopenharmony_ci    }
133141cc406Sopenharmony_ci
134141cc406Sopenharmony_ci    Value get(std::uint16_t address) const
135141cc406Sopenharmony_ci    {
136141cc406Sopenharmony_ci        return find_reg(address).value;
137141cc406Sopenharmony_ci    }
138141cc406Sopenharmony_ci
139141cc406Sopenharmony_ci    void reserve(std::size_t size) { registers_.reserve(size); }
140141cc406Sopenharmony_ci    void clear() { registers_.clear(); }
141141cc406Sopenharmony_ci    std::size_t size() const { return registers_.size(); }
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_ci    iterator begin() { return registers_.begin(); }
144141cc406Sopenharmony_ci    const_iterator begin() const { return registers_.begin(); }
145141cc406Sopenharmony_ci
146141cc406Sopenharmony_ci    iterator end() { return registers_.end(); }
147141cc406Sopenharmony_ci    const_iterator end() const { return registers_.end(); }
148141cc406Sopenharmony_ci
149141cc406Sopenharmony_ciprivate:
150141cc406Sopenharmony_ci    int find_reg_index(std::uint16_t address) const
151141cc406Sopenharmony_ci    {
152141cc406Sopenharmony_ci        if (!sorted_) {
153141cc406Sopenharmony_ci            for (std::size_t i = 0; i < registers_.size(); i++) {
154141cc406Sopenharmony_ci                if (registers_[i].address == address) {
155141cc406Sopenharmony_ci                    return i;
156141cc406Sopenharmony_ci                }
157141cc406Sopenharmony_ci            }
158141cc406Sopenharmony_ci            return -1;
159141cc406Sopenharmony_ci        }
160141cc406Sopenharmony_ci
161141cc406Sopenharmony_ci        RegisterType search;
162141cc406Sopenharmony_ci        search.address = address;
163141cc406Sopenharmony_ci        auto it = std::lower_bound(registers_.begin(), registers_.end(), search);
164141cc406Sopenharmony_ci        if (it == registers_.end())
165141cc406Sopenharmony_ci            return -1;
166141cc406Sopenharmony_ci        if (it->address != address)
167141cc406Sopenharmony_ci            return -1;
168141cc406Sopenharmony_ci        return std::distance(registers_.begin(), it);
169141cc406Sopenharmony_ci    }
170141cc406Sopenharmony_ci
171141cc406Sopenharmony_ci    // registers are stored in a sorted vector
172141cc406Sopenharmony_ci    bool sorted_ = true;
173141cc406Sopenharmony_ci    std::vector<RegisterType> registers_;
174141cc406Sopenharmony_ci};
175141cc406Sopenharmony_ci
176141cc406Sopenharmony_citemplate<class Value>
177141cc406Sopenharmony_cistd::ostream& operator<<(std::ostream& out, const RegisterContainer<Value>& container)
178141cc406Sopenharmony_ci{
179141cc406Sopenharmony_ci    StreamStateSaver state_saver{out};
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci    out << "RegisterContainer{\n";
182141cc406Sopenharmony_ci    out << std::hex;
183141cc406Sopenharmony_ci    out.fill('0');
184141cc406Sopenharmony_ci
185141cc406Sopenharmony_ci    for (const auto& reg : container) {
186141cc406Sopenharmony_ci        unsigned address_width = sizeof(reg.address) * 2;
187141cc406Sopenharmony_ci        unsigned value_width = sizeof(reg.value) * 2;
188141cc406Sopenharmony_ci
189141cc406Sopenharmony_ci        out << "    0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
190141cc406Sopenharmony_ci            << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value) << '\n';
191141cc406Sopenharmony_ci    }
192141cc406Sopenharmony_ci    out << "}";
193141cc406Sopenharmony_ci    return out;
194141cc406Sopenharmony_ci}
195141cc406Sopenharmony_ci
196141cc406Sopenharmony_ciclass Genesys_Register_Set
197141cc406Sopenharmony_ci{
198141cc406Sopenharmony_cipublic:
199141cc406Sopenharmony_ci    static constexpr unsigned MAX_REGS = 256;
200141cc406Sopenharmony_ci
201141cc406Sopenharmony_ci    using ContainerType = RegisterContainer<std::uint8_t>;
202141cc406Sopenharmony_ci    using iterator = typename ContainerType::iterator;
203141cc406Sopenharmony_ci    using const_iterator = typename ContainerType::const_iterator;
204141cc406Sopenharmony_ci
205141cc406Sopenharmony_ci    // FIXME: this shouldn't live here, but in a separate struct that contains Genesys_Register_Set
206141cc406Sopenharmony_ci    GenesysRegisterSetState state;
207141cc406Sopenharmony_ci
208141cc406Sopenharmony_ci    enum Options {
209141cc406Sopenharmony_ci        SEQUENTIAL = 1
210141cc406Sopenharmony_ci    };
211141cc406Sopenharmony_ci
212141cc406Sopenharmony_ci    Genesys_Register_Set()
213141cc406Sopenharmony_ci    {
214141cc406Sopenharmony_ci        registers_.reserve(MAX_REGS);
215141cc406Sopenharmony_ci    }
216141cc406Sopenharmony_ci
217141cc406Sopenharmony_ci    // by default the register set is sorted by address. In certain cases it's importand to send
218141cc406Sopenharmony_ci    // the registers in certain order: use the SEQUENTIAL option for that
219141cc406Sopenharmony_ci    Genesys_Register_Set(Options opts) : registers_{static_cast<ContainerType::Options>(opts)}
220141cc406Sopenharmony_ci    {
221141cc406Sopenharmony_ci        registers_.reserve(MAX_REGS);
222141cc406Sopenharmony_ci    }
223141cc406Sopenharmony_ci
224141cc406Sopenharmony_ci    const ContainerType& registers() const
225141cc406Sopenharmony_ci    {
226141cc406Sopenharmony_ci        return registers_;
227141cc406Sopenharmony_ci    }
228141cc406Sopenharmony_ci
229141cc406Sopenharmony_ci    void init_reg(std::uint16_t address, std::uint8_t default_value)
230141cc406Sopenharmony_ci    {
231141cc406Sopenharmony_ci        registers_.init_reg(address, default_value);
232141cc406Sopenharmony_ci    }
233141cc406Sopenharmony_ci
234141cc406Sopenharmony_ci    bool has_reg(std::uint16_t address) const { return registers_.has_reg(address); }
235141cc406Sopenharmony_ci
236141cc406Sopenharmony_ci    void remove_reg(std::uint16_t address) { registers_.remove_reg(address); }
237141cc406Sopenharmony_ci
238141cc406Sopenharmony_ci    GenesysRegister& find_reg(std::uint16_t address)
239141cc406Sopenharmony_ci    {
240141cc406Sopenharmony_ci        return registers_.find_reg(address);
241141cc406Sopenharmony_ci    }
242141cc406Sopenharmony_ci
243141cc406Sopenharmony_ci    const GenesysRegister& find_reg(std::uint16_t address) const
244141cc406Sopenharmony_ci    {
245141cc406Sopenharmony_ci        return registers_.find_reg(address);
246141cc406Sopenharmony_ci    }
247141cc406Sopenharmony_ci
248141cc406Sopenharmony_ci    GenesysRegister* find_reg_address(std::uint16_t address)
249141cc406Sopenharmony_ci    {
250141cc406Sopenharmony_ci        return &find_reg(address);
251141cc406Sopenharmony_ci    }
252141cc406Sopenharmony_ci
253141cc406Sopenharmony_ci    const GenesysRegister* find_reg_address(std::uint16_t address) const
254141cc406Sopenharmony_ci    {
255141cc406Sopenharmony_ci        return &find_reg(address);
256141cc406Sopenharmony_ci    }
257141cc406Sopenharmony_ci
258141cc406Sopenharmony_ci    void set8(std::uint16_t address, std::uint8_t value)
259141cc406Sopenharmony_ci    {
260141cc406Sopenharmony_ci        find_reg(address).value = value;
261141cc406Sopenharmony_ci    }
262141cc406Sopenharmony_ci
263141cc406Sopenharmony_ci    void set8_mask(std::uint16_t address, std::uint8_t value, std::uint8_t mask)
264141cc406Sopenharmony_ci    {
265141cc406Sopenharmony_ci        auto& reg = find_reg(address);
266141cc406Sopenharmony_ci        reg.value = (reg.value & ~mask) | value;
267141cc406Sopenharmony_ci    }
268141cc406Sopenharmony_ci
269141cc406Sopenharmony_ci    void set16(std::uint16_t address, std::uint16_t value)
270141cc406Sopenharmony_ci    {
271141cc406Sopenharmony_ci        find_reg(address).value = (value >> 8) & 0xff;
272141cc406Sopenharmony_ci        find_reg(address + 1).value = value & 0xff;
273141cc406Sopenharmony_ci    }
274141cc406Sopenharmony_ci
275141cc406Sopenharmony_ci    void set24(std::uint16_t address, std::uint32_t value)
276141cc406Sopenharmony_ci    {
277141cc406Sopenharmony_ci        find_reg(address).value = (value >> 16) & 0xff;
278141cc406Sopenharmony_ci        find_reg(address + 1).value = (value >> 8) & 0xff;
279141cc406Sopenharmony_ci        find_reg(address + 2).value = value & 0xff;
280141cc406Sopenharmony_ci    }
281141cc406Sopenharmony_ci
282141cc406Sopenharmony_ci    std::uint8_t get8(std::uint16_t address) const
283141cc406Sopenharmony_ci    {
284141cc406Sopenharmony_ci        return find_reg(address).value;
285141cc406Sopenharmony_ci    }
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci    std::uint16_t get16(std::uint16_t address) const
288141cc406Sopenharmony_ci    {
289141cc406Sopenharmony_ci        return (find_reg(address).value << 8) | find_reg(address + 1).value;
290141cc406Sopenharmony_ci    }
291141cc406Sopenharmony_ci
292141cc406Sopenharmony_ci    std::uint32_t get24(std::uint16_t address) const
293141cc406Sopenharmony_ci    {
294141cc406Sopenharmony_ci        return (find_reg(address).value << 16) |
295141cc406Sopenharmony_ci               (find_reg(address + 1).value << 8) |
296141cc406Sopenharmony_ci                find_reg(address + 2).value;
297141cc406Sopenharmony_ci    }
298141cc406Sopenharmony_ci
299141cc406Sopenharmony_ci    void clear() { registers_.clear(); }
300141cc406Sopenharmony_ci    std::size_t size() const { return registers_.size(); }
301141cc406Sopenharmony_ci
302141cc406Sopenharmony_ci    iterator begin() { return registers_.begin(); }
303141cc406Sopenharmony_ci    const_iterator begin() const { return registers_.begin(); }
304141cc406Sopenharmony_ci
305141cc406Sopenharmony_ci    iterator end() { return registers_.end(); }
306141cc406Sopenharmony_ci    const_iterator end() const { return registers_.end(); }
307141cc406Sopenharmony_ci
308141cc406Sopenharmony_ciprivate:
309141cc406Sopenharmony_ci
310141cc406Sopenharmony_ci    // registers are stored in a sorted vector
311141cc406Sopenharmony_ci    ContainerType registers_;
312141cc406Sopenharmony_ci};
313141cc406Sopenharmony_ci
314141cc406Sopenharmony_ciinline std::ostream& operator<<(std::ostream& out, const Genesys_Register_Set& regs)
315141cc406Sopenharmony_ci{
316141cc406Sopenharmony_ci    out << regs.registers();
317141cc406Sopenharmony_ci    return out;
318141cc406Sopenharmony_ci}
319141cc406Sopenharmony_ci
320141cc406Sopenharmony_citemplate<class Value>
321141cc406Sopenharmony_cistruct RegisterSetting
322141cc406Sopenharmony_ci{
323141cc406Sopenharmony_ci    using ValueType = Value;
324141cc406Sopenharmony_ci    using AddressType = std::uint16_t;
325141cc406Sopenharmony_ci
326141cc406Sopenharmony_ci    RegisterSetting() = default;
327141cc406Sopenharmony_ci
328141cc406Sopenharmony_ci    RegisterSetting(AddressType p_address, ValueType p_value) :
329141cc406Sopenharmony_ci        address(p_address), value(p_value)
330141cc406Sopenharmony_ci    {}
331141cc406Sopenharmony_ci
332141cc406Sopenharmony_ci    RegisterSetting(AddressType p_address, ValueType p_value, ValueType p_mask) :
333141cc406Sopenharmony_ci        address(p_address), value(p_value), mask(p_mask)
334141cc406Sopenharmony_ci    {}
335141cc406Sopenharmony_ci
336141cc406Sopenharmony_ci    AddressType address = 0;
337141cc406Sopenharmony_ci    ValueType value = 0;
338141cc406Sopenharmony_ci    ValueType mask = 0xff;
339141cc406Sopenharmony_ci
340141cc406Sopenharmony_ci    bool operator==(const RegisterSetting& other) const
341141cc406Sopenharmony_ci    {
342141cc406Sopenharmony_ci        return address == other.address && value == other.value && mask == other.mask;
343141cc406Sopenharmony_ci    }
344141cc406Sopenharmony_ci};
345141cc406Sopenharmony_ci
346141cc406Sopenharmony_ciusing GenesysRegisterSetting = RegisterSetting<std::uint8_t>;
347141cc406Sopenharmony_ciusing GenesysRegisterSetting16 = RegisterSetting<std::uint16_t>;
348141cc406Sopenharmony_ci
349141cc406Sopenharmony_citemplate<class Stream, class Value>
350141cc406Sopenharmony_civoid serialize(Stream& str, RegisterSetting<Value>& reg)
351141cc406Sopenharmony_ci{
352141cc406Sopenharmony_ci    serialize(str, reg.address);
353141cc406Sopenharmony_ci    serialize(str, reg.value);
354141cc406Sopenharmony_ci    serialize(str, reg.mask);
355141cc406Sopenharmony_ci}
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_citemplate<class Value>
358141cc406Sopenharmony_ciclass RegisterSettingSet
359141cc406Sopenharmony_ci{
360141cc406Sopenharmony_cipublic:
361141cc406Sopenharmony_ci    using ValueType = Value;
362141cc406Sopenharmony_ci    using SettingType = RegisterSetting<ValueType>;
363141cc406Sopenharmony_ci    using AddressType = typename SettingType::AddressType;
364141cc406Sopenharmony_ci
365141cc406Sopenharmony_ci    using container = std::vector<SettingType>;
366141cc406Sopenharmony_ci    using iterator = typename container::iterator;
367141cc406Sopenharmony_ci    using const_iterator = typename container::const_iterator;
368141cc406Sopenharmony_ci
369141cc406Sopenharmony_ci    RegisterSettingSet() = default;
370141cc406Sopenharmony_ci    RegisterSettingSet(std::initializer_list<SettingType> ilist) :
371141cc406Sopenharmony_ci        registers_(ilist)
372141cc406Sopenharmony_ci    {}
373141cc406Sopenharmony_ci
374141cc406Sopenharmony_ci    iterator begin() { return registers_.begin(); }
375141cc406Sopenharmony_ci    const_iterator begin() const { return registers_.begin(); }
376141cc406Sopenharmony_ci    iterator end() { return registers_.end(); }
377141cc406Sopenharmony_ci    const_iterator end() const { return registers_.end(); }
378141cc406Sopenharmony_ci
379141cc406Sopenharmony_ci    SettingType& operator[](std::size_t i) { return registers_[i]; }
380141cc406Sopenharmony_ci    const SettingType& operator[](std::size_t i) const { return registers_[i]; }
381141cc406Sopenharmony_ci
382141cc406Sopenharmony_ci    std::size_t size() const { return registers_.size(); }
383141cc406Sopenharmony_ci    bool empty() const { return registers_.empty(); }
384141cc406Sopenharmony_ci    void clear() { registers_.clear(); }
385141cc406Sopenharmony_ci
386141cc406Sopenharmony_ci    void push_back(SettingType reg) { registers_.push_back(reg); }
387141cc406Sopenharmony_ci
388141cc406Sopenharmony_ci    void merge(const RegisterSettingSet& other)
389141cc406Sopenharmony_ci    {
390141cc406Sopenharmony_ci        for (const auto& reg : other) {
391141cc406Sopenharmony_ci            set_value(reg.address, reg.value);
392141cc406Sopenharmony_ci        }
393141cc406Sopenharmony_ci    }
394141cc406Sopenharmony_ci
395141cc406Sopenharmony_ci    bool has_reg(AddressType address) const
396141cc406Sopenharmony_ci    {
397141cc406Sopenharmony_ci        return find_reg_index(address) != -1;
398141cc406Sopenharmony_ci    }
399141cc406Sopenharmony_ci
400141cc406Sopenharmony_ci    SettingType& find_reg(AddressType address)
401141cc406Sopenharmony_ci    {
402141cc406Sopenharmony_ci        int i = find_reg_index(address);
403141cc406Sopenharmony_ci        if (i < 0) {
404141cc406Sopenharmony_ci            throw std::runtime_error("the register does not exist");
405141cc406Sopenharmony_ci        }
406141cc406Sopenharmony_ci        return registers_[i];
407141cc406Sopenharmony_ci    }
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ci    const SettingType& find_reg(AddressType address) const
410141cc406Sopenharmony_ci    {
411141cc406Sopenharmony_ci        int i = find_reg_index(address);
412141cc406Sopenharmony_ci        if (i < 0) {
413141cc406Sopenharmony_ci            throw std::runtime_error("the register does not exist");
414141cc406Sopenharmony_ci        }
415141cc406Sopenharmony_ci        return registers_[i];
416141cc406Sopenharmony_ci    }
417141cc406Sopenharmony_ci
418141cc406Sopenharmony_ci    ValueType get_value(AddressType address) const
419141cc406Sopenharmony_ci    {
420141cc406Sopenharmony_ci        int index = find_reg_index(address);
421141cc406Sopenharmony_ci        if (index >= 0) {
422141cc406Sopenharmony_ci            return registers_[index].value;
423141cc406Sopenharmony_ci        }
424141cc406Sopenharmony_ci        throw std::out_of_range("Unknown register");
425141cc406Sopenharmony_ci    }
426141cc406Sopenharmony_ci
427141cc406Sopenharmony_ci    void set_value(AddressType address, ValueType value)
428141cc406Sopenharmony_ci    {
429141cc406Sopenharmony_ci        int index = find_reg_index(address);
430141cc406Sopenharmony_ci        if (index >= 0) {
431141cc406Sopenharmony_ci            registers_[index].value = value;
432141cc406Sopenharmony_ci            return;
433141cc406Sopenharmony_ci        }
434141cc406Sopenharmony_ci        push_back(SettingType(address, value));
435141cc406Sopenharmony_ci    }
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci    template<class V>
438141cc406Sopenharmony_ci    friend void serialize(std::istream& str, RegisterSettingSet<V>& reg);
439141cc406Sopenharmony_ci    template<class V>
440141cc406Sopenharmony_ci    friend void serialize(std::ostream& str, RegisterSettingSet<V>& reg);
441141cc406Sopenharmony_ci
442141cc406Sopenharmony_ci    bool operator==(const RegisterSettingSet& other) const
443141cc406Sopenharmony_ci    {
444141cc406Sopenharmony_ci        return registers_ == other.registers_;
445141cc406Sopenharmony_ci    }
446141cc406Sopenharmony_ci
447141cc406Sopenharmony_ciprivate:
448141cc406Sopenharmony_ci
449141cc406Sopenharmony_ci    int find_reg_index(AddressType address) const
450141cc406Sopenharmony_ci    {
451141cc406Sopenharmony_ci        for (std::size_t i = 0; i < registers_.size(); i++) {
452141cc406Sopenharmony_ci            if (registers_[i].address == address) {
453141cc406Sopenharmony_ci                return i;
454141cc406Sopenharmony_ci            }
455141cc406Sopenharmony_ci        }
456141cc406Sopenharmony_ci        return -1;
457141cc406Sopenharmony_ci    }
458141cc406Sopenharmony_ci
459141cc406Sopenharmony_ci    std::vector<SettingType> registers_;
460141cc406Sopenharmony_ci};
461141cc406Sopenharmony_ci
462141cc406Sopenharmony_ciusing GenesysRegisterSettingSet = RegisterSettingSet<std::uint8_t>;
463141cc406Sopenharmony_ciusing GenesysRegisterSettingSet16 = RegisterSettingSet<std::uint16_t>;
464141cc406Sopenharmony_ci
465141cc406Sopenharmony_citemplate<class Value>
466141cc406Sopenharmony_cistd::ostream& operator<<(std::ostream& out, const RegisterSettingSet<Value>& container)
467141cc406Sopenharmony_ci{
468141cc406Sopenharmony_ci    StreamStateSaver state_saver{out};
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci    out << "RegisterSettingSet{\n";
471141cc406Sopenharmony_ci    out << std::hex;
472141cc406Sopenharmony_ci    out.fill('0');
473141cc406Sopenharmony_ci
474141cc406Sopenharmony_ci    for (const auto& reg : container) {
475141cc406Sopenharmony_ci        unsigned address_width = sizeof(reg.address) * 2;
476141cc406Sopenharmony_ci        unsigned value_width = sizeof(reg.value) * 2;
477141cc406Sopenharmony_ci        unsigned mask_width = sizeof(reg.mask) * 2;
478141cc406Sopenharmony_ci
479141cc406Sopenharmony_ci        out << "    0x" << std::setw(address_width) << static_cast<unsigned>(reg.address)
480141cc406Sopenharmony_ci            << " = 0x" << std::setw(value_width) << static_cast<unsigned>(reg.value)
481141cc406Sopenharmony_ci            << " & 0x" << std::setw(mask_width) << static_cast<unsigned>(reg.mask) << '\n';
482141cc406Sopenharmony_ci    }
483141cc406Sopenharmony_ci    out << "}";
484141cc406Sopenharmony_ci    return out;
485141cc406Sopenharmony_ci}
486141cc406Sopenharmony_ci
487141cc406Sopenharmony_citemplate<class Value>
488141cc406Sopenharmony_ciinline void serialize(std::istream& str, RegisterSettingSet<Value>& reg)
489141cc406Sopenharmony_ci{
490141cc406Sopenharmony_ci    using AddressType = typename RegisterSetting<Value>::AddressType;
491141cc406Sopenharmony_ci
492141cc406Sopenharmony_ci    reg.clear();
493141cc406Sopenharmony_ci    const std::size_t max_register_address = 1 << (sizeof(AddressType) * CHAR_BIT);
494141cc406Sopenharmony_ci    serialize(str, reg.registers_, max_register_address);
495141cc406Sopenharmony_ci}
496141cc406Sopenharmony_ci
497141cc406Sopenharmony_citemplate<class Value>
498141cc406Sopenharmony_ciinline void serialize(std::ostream& str, RegisterSettingSet<Value>& reg)
499141cc406Sopenharmony_ci{
500141cc406Sopenharmony_ci    serialize(str, reg.registers_);
501141cc406Sopenharmony_ci}
502141cc406Sopenharmony_ci
503141cc406Sopenharmony_citemplate<class F, class Value>
504141cc406Sopenharmony_civoid apply_registers_ordered(const RegisterSettingSet<Value>& set,
505141cc406Sopenharmony_ci                             std::initializer_list<std::uint16_t> order, F f)
506141cc406Sopenharmony_ci{
507141cc406Sopenharmony_ci    for (std::uint16_t addr : order) {
508141cc406Sopenharmony_ci        f(set.find_reg(addr));
509141cc406Sopenharmony_ci    }
510141cc406Sopenharmony_ci    for (const auto& reg : set) {
511141cc406Sopenharmony_ci        if (std::find(order.begin(), order.end(), reg.address) != order.end()) {
512141cc406Sopenharmony_ci            continue;
513141cc406Sopenharmony_ci        }
514141cc406Sopenharmony_ci        f(reg);
515141cc406Sopenharmony_ci    }
516141cc406Sopenharmony_ci}
517141cc406Sopenharmony_ci
518141cc406Sopenharmony_ci} // namespace genesys
519141cc406Sopenharmony_ci
520141cc406Sopenharmony_ci#endif // BACKEND_GENESYS_REGISTER_H
521