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 35namespace genesys { 36 37template<class Value> 38struct Register 39{ 40 std::uint16_t address = 0; 41 Value value = 0; 42}; 43 44using GenesysRegister = Register<std::uint8_t>; 45 46template<class Value> 47inline bool operator<(const Register<Value>& lhs, const Register<Value>& rhs) 48{ 49 return lhs.address < rhs.address; 50} 51 52struct 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 60template<class Value> 61class RegisterContainer 62{ 63public: 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 76 RegisterContainer(Options opts) : RegisterContainer() 77 { 78 if ((opts & SEQUENTIAL) == SEQUENTIAL) { 79 sorted_ = false; 80 } 81 } 82 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 97 bool has_reg(std::uint16_t address) const 98 { 99 return find_reg_index(address) >= 0; 100 } 101 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 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 120 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 129 void set(std::uint16_t address, Value value) 130 { 131 find_reg(address).value = value; 132 } 133 134 Value get(std::uint16_t address) const 135 { 136 return find_reg(address).value; 137 } 138 139 void reserve(std::size_t size) { registers_.reserve(size); } 140 void clear() { registers_.clear(); } 141 std::size_t size() const { return registers_.size(); } 142 143 iterator begin() { return registers_.begin(); } 144 const_iterator begin() const { return registers_.begin(); } 145 146 iterator end() { return registers_.end(); } 147 const_iterator end() const { return registers_.end(); } 148 149private: 150 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 176template<class Value> 177std::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 196class Genesys_Register_Set 197{ 198public: 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 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 219 Genesys_Register_Set(Options opts) : registers_{static_cast<ContainerType::Options>(opts)} 220 { 221 registers_.reserve(MAX_REGS); 222 } 223 224 const ContainerType& registers() const 225 { 226 return registers_; 227 } 228 229 void init_reg(std::uint16_t address, std::uint8_t default_value) 230 { 231 registers_.init_reg(address, default_value); 232 } 233 234 bool has_reg(std::uint16_t address) const { return registers_.has_reg(address); } 235 236 void remove_reg(std::uint16_t address) { registers_.remove_reg(address); } 237 238 GenesysRegister& find_reg(std::uint16_t address) 239 { 240 return registers_.find_reg(address); 241 } 242 243 const GenesysRegister& find_reg(std::uint16_t address) const 244 { 245 return registers_.find_reg(address); 246 } 247 248 GenesysRegister* find_reg_address(std::uint16_t address) 249 { 250 return &find_reg(address); 251 } 252 253 const GenesysRegister* find_reg_address(std::uint16_t address) const 254 { 255 return &find_reg(address); 256 } 257 258 void set8(std::uint16_t address, std::uint8_t value) 259 { 260 find_reg(address).value = value; 261 } 262 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 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 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 282 std::uint8_t get8(std::uint16_t address) const 283 { 284 return find_reg(address).value; 285 } 286 287 std::uint16_t get16(std::uint16_t address) const 288 { 289 return (find_reg(address).value << 8) | find_reg(address + 1).value; 290 } 291 292 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 299 void clear() { registers_.clear(); } 300 std::size_t size() const { return registers_.size(); } 301 302 iterator begin() { return registers_.begin(); } 303 const_iterator begin() const { return registers_.begin(); } 304 305 iterator end() { return registers_.end(); } 306 const_iterator end() const { return registers_.end(); } 307 308private: 309 310 // registers are stored in a sorted vector 311 ContainerType registers_; 312}; 313 314inline std::ostream& operator<<(std::ostream& out, const Genesys_Register_Set& regs) 315{ 316 out << regs.registers(); 317 return out; 318} 319 320template<class Value> 321struct RegisterSetting 322{ 323 using ValueType = Value; 324 using AddressType = std::uint16_t; 325 326 RegisterSetting() = default; 327 328 RegisterSetting(AddressType p_address, ValueType p_value) : 329 address(p_address), value(p_value) 330 {} 331 332 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 340 bool operator==(const RegisterSetting& other) const 341 { 342 return address == other.address && value == other.value && mask == other.mask; 343 } 344}; 345 346using GenesysRegisterSetting = RegisterSetting<std::uint8_t>; 347using GenesysRegisterSetting16 = RegisterSetting<std::uint16_t>; 348 349template<class Stream, class Value> 350void serialize(Stream& str, RegisterSetting<Value>& reg) 351{ 352 serialize(str, reg.address); 353 serialize(str, reg.value); 354 serialize(str, reg.mask); 355} 356 357template<class Value> 358class RegisterSettingSet 359{ 360public: 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; 370 RegisterSettingSet(std::initializer_list<SettingType> ilist) : 371 registers_(ilist) 372 {} 373 374 iterator begin() { return registers_.begin(); } 375 const_iterator begin() const { return registers_.begin(); } 376 iterator end() { return registers_.end(); } 377 const_iterator end() const { return registers_.end(); } 378 379 SettingType& operator[](std::size_t i) { return registers_[i]; } 380 const SettingType& operator[](std::size_t i) const { return registers_[i]; } 381 382 std::size_t size() const { return registers_.size(); } 383 bool empty() const { return registers_.empty(); } 384 void clear() { registers_.clear(); } 385 386 void push_back(SettingType reg) { registers_.push_back(reg); } 387 388 void merge(const RegisterSettingSet& other) 389 { 390 for (const auto& reg : other) { 391 set_value(reg.address, reg.value); 392 } 393 } 394 395 bool has_reg(AddressType address) const 396 { 397 return find_reg_index(address) != -1; 398 } 399 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 409 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 418 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 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 442 bool operator==(const RegisterSettingSet& other) const 443 { 444 return registers_ == other.registers_; 445 } 446 447private: 448 449 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 462using GenesysRegisterSettingSet = RegisterSettingSet<std::uint8_t>; 463using GenesysRegisterSettingSet16 = RegisterSettingSet<std::uint16_t>; 464 465template<class Value> 466std::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 487template<class Value> 488inline 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 497template<class Value> 498inline void serialize(std::ostream& str, RegisterSettingSet<Value>& reg) 499{ 500 serialize(str, reg.registers_); 501} 502 503template<class F, class Value> 504void 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