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