2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.rotel.internal.communication;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.rotel.internal.RotelException;
19 * Class managing the mapping of message flags with indicators
21 * @author Laurent Garnier - Initial contribution
24 public class RotelFlagsMapping {
26 public static final RotelFlagsMapping MAPPING1 = new RotelFlagsMapping(3, 1, 5, 0, -1, -1, -1, -1, 8, 6, 8, 4, 8,
28 public static final RotelFlagsMapping MAPPING2 = new RotelFlagsMapping(-1, -1, 4, 7, -1, -1, -1, -1, 5, 6, 5, 4, 5,
30 public static final RotelFlagsMapping MAPPING3 = new RotelFlagsMapping(4, 7, 1, 7, 2, 7, 6, 2, 5, 6, 5, 4, 5, 3);
31 public static final RotelFlagsMapping MAPPING4 = new RotelFlagsMapping(3, 1, 1, 7, 2, 7, 6, 2, 8, 6, 8, 4, 8, 3);
32 public static final RotelFlagsMapping MAPPING5 = new RotelFlagsMapping(-1, -1, 3, 2, 4, 2, 4, 1, 5, 6, 5, 4, 5, 3);
33 public static final RotelFlagsMapping NO_MAPPING = new RotelFlagsMapping(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36 private int multiInputFlagNumber;
37 private int multiInputBitNumber;
38 private int zone2FlagNumber;
39 private int zone2BitNumber;
40 private int zone3FlagNumber;
41 private int zone3BitNumber;
42 private int zone4FlagNumber;
43 private int zone4BitNumber;
44 private int centerFlagNumber;
45 private int centerBitNumber;
46 private int surroundLeftFlagNumber;
47 private int surroundLeftBitNumber;
48 private int surroundRightFlagNumber;
49 private int surroundRightBitNumber;
54 * For each flag number, value 1 means the first flag; a negative value is used for an undefined indicator.
55 * For each bit number, value is from 0 to 7; a negative value is used for an undefined indicator.
57 * @param multiInputFlagNumber the flag number in the standard feedback message in which to find the multi input
59 * @param multiInputBitNumber the bit number in the flag in which to find the multi input indicator
60 * @param zone2FlagNumber the flag number in the standard feedback message in which to find the zone 2 indicator
61 * @param zone2BitNumber the bit number in the flag in which to find the zone 2 indicator
62 * @param zone3FlagNumber the flag number in the standard feedback message in which to find the zone 3 indicator
63 * @param zone3BitNumber the bit number in the flag in which to find the zone 3 indicator
64 * @param zone4FlagNumber the flag number in the standard feedback message in which to find the zone 4 indicator
65 * @param zone4BitNumber the bit number in the flag in which to find the zone 4 indicator
66 * @param centerFlagNumber the flag number in the standard feedback message in which to find the center channel
68 * @param centerBitNumber the bit number in the flag in which to find the center channel indicator
69 * @param surroundLeftFlagNumber the flag number in the standard feedback message in which to find the surround left
71 * @param surroundLeftBitNumber the bit number in the flag in which to find the surround left channel indicator
72 * @param surroundRightFlagNumber the flag number in the standard feedback message in which to find the surround
73 * right channel indicator
74 * @param surroundRightBitNumber the bit number in the flag in which to find the surround right channel indicator
76 private RotelFlagsMapping(int multiInputFlagNumber, int multiInputBitNumber, int zone2FlagNumber,
77 int zone2BitNumber, int zone3FlagNumber, int zone3BitNumber, int zone4FlagNumber, int zone4BitNumber,
78 int centerFlagNumber, int centerBitNumber, int surroundLeftFlagNumber, int surroundLeftBitNumber,
79 int surroundRightFlagNumber, int surroundRightBitNumber) {
80 this.multiInputFlagNumber = multiInputFlagNumber;
81 this.multiInputBitNumber = multiInputBitNumber;
82 this.zone2FlagNumber = zone2FlagNumber;
83 this.zone2BitNumber = zone2BitNumber;
84 this.zone3FlagNumber = zone3FlagNumber;
85 this.zone3BitNumber = zone3BitNumber;
86 this.zone4FlagNumber = zone4FlagNumber;
87 this.zone4BitNumber = zone4BitNumber;
88 this.centerFlagNumber = centerFlagNumber;
89 this.centerBitNumber = centerBitNumber;
90 this.surroundLeftFlagNumber = surroundLeftFlagNumber;
91 this.surroundLeftBitNumber = surroundLeftBitNumber;
92 this.surroundRightFlagNumber = surroundRightFlagNumber;
93 this.surroundRightBitNumber = surroundRightBitNumber;
97 * Get the multi input indicator
99 * @param flags the table of flags
101 * @return true if the indicator is ON in the flags or false if OFF
103 * @throws RotelException in case the multi input indicator is undefined
105 public boolean isMultiInputOn(byte[] flags) throws RotelException {
106 return RotelFlagsMapping.isBitFlagOn(flags, multiInputFlagNumber, multiInputBitNumber);
110 * Set the multi input indicator
112 * @param flags the table of flags
113 * @param on true to set the indicator to ON or false to set it to OFF
115 * @throws RotelException in case the multi input indicator is undefined
117 public void setMultiInput(byte[] flags, boolean on) throws RotelException {
118 RotelFlagsMapping.setBitFlag(flags, multiInputFlagNumber, multiInputBitNumber, on);
122 * Get the zone 2 indicator
124 * @param flags the table of flags
126 * @return true if the indicator is ON in the flags or false if OFF
128 * @throws RotelException in case the zone 2 indicator is undefined
130 public boolean isZone2On(byte[] flags) throws RotelException {
131 return RotelFlagsMapping.isBitFlagOn(flags, zone2FlagNumber, zone2BitNumber);
135 * Set the zone 2 indicator
137 * @param flags the table of flags
138 * @param on true to set the indicator to ON or false to set it to OFF
140 * @throws RotelException in case the zone 2 indicator is undefined
142 public void setZone2(byte[] flags, boolean on) throws RotelException {
143 RotelFlagsMapping.setBitFlag(flags, zone2FlagNumber, zone2BitNumber, on);
147 * Get the zone 3 indicator
149 * @param flags the table of flags
151 * @return true if the indicator is ON in the flags or false if OFF
153 * @throws RotelException in case the zone 3 indicator is undefined
155 public boolean isZone3On(byte[] flags) throws RotelException {
156 return RotelFlagsMapping.isBitFlagOn(flags, zone3FlagNumber, zone3BitNumber);
160 * Set the zone 3 indicator
162 * @param flags the table of flags
163 * @param on true to set the indicator to ON or false to set it to OFF
165 * @throws RotelException in case the zone 3 indicator is undefined
167 public void setZone3(byte[] flags, boolean on) throws RotelException {
168 RotelFlagsMapping.setBitFlag(flags, zone3FlagNumber, zone3BitNumber, on);
172 * Get the zone 4 indicator
174 * @param flags the table of flags
176 * @return true if the indicator is ON in the flags or false if OFF
178 * @throws RotelException in case the zone 4 indicator is undefined
180 public boolean isZone4On(byte[] flags) throws RotelException {
181 return RotelFlagsMapping.isBitFlagOn(flags, zone4FlagNumber, zone4BitNumber);
185 * Set the zone 4 indicator
187 * @param flags the table of flags
188 * @param on true to set the indicator to ON or false to set it to OFF
190 * @throws RotelException in case the zone 4 indicator is undefined
192 public void setZone4(byte[] flags, boolean on) throws RotelException {
193 RotelFlagsMapping.setBitFlag(flags, zone4FlagNumber, zone4BitNumber, on);
197 * Check whether more than front channels are ON
199 * @param flags the table of flags
201 * @return true if the indicators show that center or surround channels are ON in the flags
203 * @throws RotelException in case the center or surround channel indicators are undefined
205 public boolean isMoreThan2Channels(byte[] flags) throws RotelException {
206 return (centerFlagNumber >= 1 && centerFlagNumber <= flags.length
207 && RotelFlagsMapping.isBitFlagOn(flags, centerFlagNumber, centerBitNumber))
208 || (surroundLeftFlagNumber >= 1 && surroundLeftFlagNumber <= flags.length
209 && RotelFlagsMapping.isBitFlagOn(flags, surroundLeftFlagNumber, surroundLeftBitNumber))
210 || (surroundRightFlagNumber >= 1 && surroundRightFlagNumber <= flags.length
211 && RotelFlagsMapping.isBitFlagOn(flags, surroundRightFlagNumber, surroundRightBitNumber));
215 * Get a bit value inside the provided table of flags
217 * @param flags the table of flags
218 * @param flagNumber the flag number to consider
219 * @param bitNumber the bit number in the flag to consider
221 * @return true if the bit value in the flag is 1 or false if 0
223 * @throws RotelException in case of out of bounds value for the flag number or the bit number
225 public static boolean isBitFlagOn(byte[] flags, int flagNumber, int bitNumber) throws RotelException {
226 if (flagNumber < 1 || flagNumber > flags.length) {
227 throw new RotelException("Flag number out of bounds");
229 if (bitNumber < 0 || bitNumber > 7) {
230 throw new RotelException("Bit number out of bounds");
232 int val = flags[flagNumber - 1] & 0x000000FF;
233 return (val & (1 << bitNumber)) != 0;
237 * Set a bit value to 1 or 0 in the provided table of flags
239 * @param flags the table of flags
240 * @param flagNumber the flag number to consider
241 * @param bitNumber the bit number in the flag to consider
242 * @param on true to set the bit value to 1 or false to set it to 0
244 * @throws RotelException in case of out of bounds value for the flag number or the bit number
246 private static void setBitFlag(byte[] flags, int flagNumber, int bitNumber, boolean on) throws RotelException {
247 if (flagNumber < 1 || flagNumber > flags.length) {
248 throw new RotelException("Flag number out of bounds");
250 if (bitNumber < 0 || bitNumber > 7) {
251 throw new RotelException("Bit number out of bounds");
254 flags[flagNumber - 1] |= (1 << bitNumber);
256 flags[flagNumber - 1] &= ~(1 << bitNumber);