|
| 1 | +# The MIT License (MIT) |
| 2 | +# |
| 3 | +# Copyright (c) 2019 Bryan Siepert for Adafruit Industries |
| 4 | +# |
| 5 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | +# of this software and associated documentation files (the "Software"), to deal |
| 7 | +# in the Software without restriction, including without limitation the rights |
| 8 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 9 | +# copies of the Software, and to permit persons to whom the Software is |
| 10 | +# furnished to do so, subject to the following conditions: |
| 11 | +# |
| 12 | +# The above copyright notice and this permission notice shall be included in |
| 13 | +# all copies or substantial portions of the Software. |
| 14 | +# |
| 15 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 16 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 17 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 18 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 19 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 21 | +# THE SOFTWARE. |
| 22 | +""" |
| 23 | +`adafruit_bd3491fs` |
| 24 | +================================================================================ |
| 25 | +
|
| 26 | +A driver for the Rohm BD3491FS audio processor |
| 27 | +
|
| 28 | +* Author(s): Bryan Siepert |
| 29 | +
|
| 30 | +Implementation Notes |
| 31 | +-------------------- |
| 32 | +
|
| 33 | +**Hardware:** |
| 34 | +
|
| 35 | +**Software and Dependencies:** |
| 36 | + * Adafruit CircuitPython firmware for the supported boards: |
| 37 | + https://github.com/adafruit/circuitpython/releases |
| 38 | + * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice |
| 39 | + * Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register |
| 40 | +
|
| 41 | +""" |
| 42 | + |
| 43 | +# imports |
| 44 | + |
| 45 | +__version__ = "0.0.0-auto.0" |
| 46 | +__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BD3491FS.git" |
| 47 | + |
| 48 | +from micropython import const |
| 49 | +import adafruit_bus_device.i2c_device as i2cdevice |
| 50 | +from adafruit_register.i2c_struct import UnaryStruct |
| 51 | +from adafruit_register.i2c_bits import RWBits, ROBits |
| 52 | +from adafruit_register.i2c_bit import RWBit |
| 53 | +# pylint: disable=bad-whitespace |
| 54 | +_INPUT_SELECTOR = const(0x04) |
| 55 | +_INPUT_GAIN = const(0x06) |
| 56 | +_VOLUME_GAIN_CH1 = const(0x21) |
| 57 | +_VOLUME_GAIN_CH2 = const(0x22) |
| 58 | +_BASS_GAIN = const(0x51) |
| 59 | +_TREBLE_GAIN = const(0x57) |
| 60 | +_SURROUND_GAIN = const(0x78) |
| 61 | +_TEST_MODE = const(0xF0) |
| 62 | +_SYSTEM_RESET = const(0xFE) |
| 63 | +# pylint: enable=bad-whitespace |
| 64 | + |
| 65 | +class Input: # pylint: disable=too-few-public-methods |
| 66 | + """Options for ``active_input`` |
| 67 | +
|
| 68 | + +---------------+------------------+ |
| 69 | + | ``Input`` | Input Pair | |
| 70 | + +===============+==================+ |
| 71 | + | ``Input.A`` | Inputs A1 and A2 | |
| 72 | + +-----------------+------------------+ |
| 73 | + | ``Input.B`` | Inputs B1 and B2 | |
| 74 | + +-----------------+------------------+ |
| 75 | + | ``Input.C`` | Inputs C1 and C2 | |
| 76 | + +-----------------+------------------+ |
| 77 | + | ``Input.D`` | Inputs D1 and D2 | |
| 78 | + +-----------------+------------------+ |
| 79 | + | ``Input.E`` | Inputs E1 and E2 | |
| 80 | + +-----------------+------------------+ |
| 81 | + | ``Input.F`` | Inputs F1 and F2 | |
| 82 | + +-----------------+------------------+ |
| 83 | + | ``Input.SHORT`` | Short inputs | |
| 84 | + +-----------------+------------------+ |
| 85 | + | ``Input.MUTE`` | Mute all | |
| 86 | + +-----------------+------------------+ |
| 87 | +
|
| 88 | + """ |
| 89 | + A = const(0x00) |
| 90 | + B = const(0x01) |
| 91 | + C = const(0x02) |
| 92 | + D = const(0x03) |
| 93 | + E = const(0x04) |
| 94 | + F = const(0x06) |
| 95 | + SHORT = const(0x05) |
| 96 | + MUTE = const(0x07) |
| 97 | +class InputGain: # pylint: disable=too-few-public-methods |
| 98 | + """Options for ``active_input`` |
| 99 | +
|
| 100 | + +---------------+------------------+ |
| 101 | + | ``Input`` | Input Pair | |
| 102 | + +===============+==================+ |
| 103 | + | ``Input.A`` | Inputs A1 and A2 | |
| 104 | + +-----------------+------------------+ |
| 105 | + | ``Input.B`` | Inputs B1 and B2 | |
| 106 | + +-----------------+------------------+ |
| 107 | + | ``Input.C`` | Inputs C1 and C2 | |
| 108 | + +-----------------+------------------+ |
| 109 | + | ``Input.D`` | Inputs D1 and D2 | |
| 110 | + +-----------------+------------------+ |
| 111 | + | ``Input.E`` | Inputs E1 and E2 | |
| 112 | + +-----------------+------------------+ |
| 113 | + | ``Input.F`` | Inputs F1 and F2 | |
| 114 | + +-----------------+------------------+ |
| 115 | + | ``Input.SHORT`` | Short inputs | |
| 116 | + +-----------------+------------------+ |
| 117 | + | ``Input.MUTE`` | Mute all | |
| 118 | +
|
| 119 | + """ |
| 120 | + GAIN_0DB = const(0x00) |
| 121 | + GAIN_2DB = const(0x01) |
| 122 | + GAIN_4DB = const(0x02) |
| 123 | + GAIN_6DB = const(0x03) |
| 124 | + GAIN_8DB = const(0x04) |
| 125 | + GAIN_10DB = const(0x05) |
| 126 | + GAIN_12DB = const(0x06) |
| 127 | + GAIN_14DB = const(0x07) |
| 128 | + GAIN_16DB = const(0x08) |
| 129 | + GAIN_20DB = const(0x0A) |
| 130 | + GAIN_OFF = const(0x00) |
| 131 | + GAIN_LOW = const(0x05) |
| 132 | + GAIN_MED = const(0x0A) |
| 133 | + GAIN_HIGH = const(0x0F) |
| 134 | + |
| 135 | + |
| 136 | +class BD3491FS: # pylint: disable=too-many-instance-attributes |
| 137 | + """Driver for the Rohm BD3491FS audio processor |
| 138 | +
|
| 139 | + :param ~busio.I2C i2c_bus: The I2C bus the BD3491FS is connected to. |
| 140 | + :param address: The I2C device address for the sensor. Default is ``WAKKA WAKKA WAKKA`` but will accept |
| 141 | + ``WAKKA WAKKA WAKKA`` when the ``SDO`` pin is connected to Ground. |
| 142 | +
|
| 143 | + """ |
| 144 | + |
| 145 | + _input_selector = RWBits(3, _INPUT_SELECTOR, 0, 1) |
| 146 | + _input_gain = RWBits(4, _INPUT_GAIN, 1, 1) |
| 147 | + _volume_gain_ch1 = RWBits(7, _VOLUME_GAIN_CH1, 0, 1) |
| 148 | + _volume_gain_ch2 = RWBits(7, _VOLUME_GAIN_CH2, 0, 1) |
| 149 | + _bass_gain = RWBits(3, _BASS_GAIN, 1, 1) |
| 150 | + bass_gain_cut = RWBit(_BASS_GAIN, 7) |
| 151 | + """Bass gain direcrtion. Set to True to cut the bass by the amount set in ``bass_gain``, or false |
| 152 | + to boost the bass by the given amount""" |
| 153 | + |
| 154 | + _treble_gain = RWBits(3, _TREBLE_GAIN, 1, 1) |
| 155 | + _treble_gain_cut = RWBit(_TREBLE_GAIN, 7) |
| 156 | + _surround_gain = RWBits(4, _SURROUND_GAIN, 0, 1) |
| 157 | + _surround_mode = RWBit(_SURROUND_GAIN, 7) |
| 158 | + |
| 159 | + _test_mode = UnaryStruct(_TEST_MODE, "<B") |
| 160 | + _system_reset = UnaryStruct(_SYSTEM_RESET, "<B") |
| 161 | + # _reset = RWBit(_CTRL_REG2, 2) |
| 162 | + # _reset_filter = ROBits(8, _LPFP_RES, 0, 1) |
| 163 | + # _chip_id = UnaryStruct(_WHO_AM_I, "<B") |
| 164 | + |
| 165 | + def __init__(self, i2c_bus, address=0x41): |
| 166 | + self.i2c_device = i2cdevice.I2CDevice(i2c_bus, address) |
| 167 | + # if self._chip_id != 0xb1: |
| 168 | + # raise RuntimeError('Failed to find BD3491FS! Chip ID 0x%x' % self._chip_id) |
| 169 | + |
| 170 | + # self.reset() |
| 171 | + |
| 172 | + |
| 173 | + |
| 174 | + self._block_updates = True |
| 175 | + self._interrupt_latch = True |
| 176 | + |
| 177 | + def reset(self): |
| 178 | + """Reset the sensor, restoring all configuration registers to their defaults""" |
| 179 | + self._reset = True |
| 180 | + # wait for the reset to finish |
| 181 | + while self._reset: |
| 182 | + pass |
| 183 | + |
| 184 | + @property |
| 185 | + def active_input(self): |
| 186 | + """The currently selected input""" |
| 187 | + return self._input_selector |
| 188 | + |
| 189 | + @active_input.setter |
| 190 | + def active_input(self, value): |
| 191 | + self._input_selector = value |
| 192 | + |
| 193 | + @property |
| 194 | + def input_gain(self): |
| 195 | + """The gain applied to all inputs equally""" |
| 196 | + return self._input_gain |
| 197 | + |
| 198 | + @input_gain.setter |
| 199 | + def input_gain(self, value): |
| 200 | + allowed_gains = [0, 1, 2, 3, 4, 6, 8, 10] |
| 201 | + if not( value in allowed_gains): |
| 202 | + raise ValueError("input gain must be one of 0, 2, 4, 6, 8, 12, 16, 20 dB") |
| 203 | + |
| 204 | + |
| 205 | + @property |
| 206 | + def channel_1_gain(self): |
| 207 | + "The gain applied to channel 1 of the currently selected input pair in -dB" |
| 208 | + self._volume_gain_ch1 |
| 209 | + |
| 210 | + @channel_1_gain.setter |
| 211 | + def channel_1_gain(self, value): |
| 212 | + if ((value < 0 ) or (value > 87)): |
| 213 | + raise ArgumentError("channel gain must be from 0-87db") |
| 214 | + self._volume_gain_ch1 = value |
| 215 | + |
| 216 | + @property |
| 217 | + def channel_2_gain(self): |
| 218 | + "The gain applied to channel 2 of the currently selected input pair in -dB" |
| 219 | + return self._volume_gain_ch2 |
| 220 | + |
| 221 | + @channel_2_gain.setter |
| 222 | + def channel_2_gain(self, value): |
| 223 | + if ((value < 0 ) or (value > 87)): |
| 224 | + raise ArgumentError("channel gain must be from 0-87db") |
| 225 | + self._volume_gain_ch2 = value |
| 226 | + |
| 227 | + @property |
| 228 | + def bass_gain(self): |
| 229 | + """The amount of gain applied to the bass channel in dB""" |
| 230 | + return self._bass_gain |
| 231 | + |
| 232 | + @bass_gain.setter |
| 233 | + def bass_gain(self, value): |
| 234 | + allowed_gains = [0, 1, 2, 3, 4, 6, 7] |
| 235 | + if not( value in allowed_gains): |
| 236 | + raise ValueError("input gain must be one of 0, 2, 4, 6, 8, 12, 14 dB") |
| 237 | + self._bass_gain = value |
| 238 | + |
| 239 | + @property |
| 240 | + def treble_gain(self): |
| 241 | + """The amount of gain applied to the treble channel in dB""" |
| 242 | + return self._treble_gain |
| 243 | + |
| 244 | + @treble_gain.setter |
| 245 | + def treble_gain(self, value): |
| 246 | + allowed_gains = [0, 1, 2, 3, 4, 6, 7] |
| 247 | + if not( value in allowed_gains): |
| 248 | + raise ValueError("input gain must be one of 0, 2, 4, 6, 8, 12, 14 dB") |
| 249 | + self._treble_gain = value |
| 250 | + |
0 commit comments