diff options
| author | robert-hh <robert@hammelrath.com> | 2022-02-10 13:51:48 +0100 |
|---|---|---|
| committer | Damien George <damien@micropython.org> | 2022-04-04 16:31:17 +1000 |
| commit | 56b331ace6b7f01bacdb8b5c66f0f517670abfdc (patch) | |
| tree | d1a1d1bd2d80ed1a7608fc2db0b73e15ab4aae7c /docs/library | |
| parent | 7a447e08b23f47fac6ebcbe5d60c4e1d0fe0d157 (diff) | |
drivers/codec: Add driver for the WM8960 codec.
This codec is assembled for the MIMXRT1xxx_DEV boards and available for
WM8960 breakout boards as well.
The driver itself has been tested as working with the MIMXRT boards and a
Sparkfun WM6890 breakout board. It implements the initialization, basic
methods and some enhanced methods like 3D, ALC, soft-mute and deemphasis.
Diffstat (limited to 'docs/library')
| -rw-r--r-- | docs/library/index.rst | 7 | ||||
| -rw-r--r-- | docs/library/machine.I2S.rst | 7 | ||||
| -rw-r--r-- | docs/library/wm8960.rst | 397 |
3 files changed, 411 insertions, 0 deletions
diff --git a/docs/library/index.rst b/docs/library/index.rst index 2b1d6b965..ffd373a4d 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -97,6 +97,13 @@ the following libraries. network.rst uctypes.rst +The following libraries provide drivers for hardware components. + +.. toctree:: + :maxdepth: 1 + + wm8960.rst + Port-specific libraries ----------------------- diff --git a/docs/library/machine.I2S.rst b/docs/library/machine.I2S.rst index e68a863d7..b602ac650 100644 --- a/docs/library/machine.I2S.rst +++ b/docs/library/machine.I2S.rst @@ -72,6 +72,13 @@ uasyncio:: sreader = uasyncio.StreamReader(audio_in) num_read = await sreader.readinto(buf) +Some codec devices like the WM8960 or SGTL5000 require separate initialization +before they can operate with the I2S class. For these, separate drivers are +supplied, which also offer methods for controlling volume, audio processing and +other things. For these drivers see: + +- :ref:`wm8960` + Constructor ----------- diff --git a/docs/library/wm8960.rst b/docs/library/wm8960.rst new file mode 100644 index 000000000..add003630 --- /dev/null +++ b/docs/library/wm8960.rst @@ -0,0 +1,397 @@ +.. _wm8960: + +:mod:`WM8960` -- Driver for the WM8960 codec +============================================ + +This driver is used to control a WM8960 codec chip. It is a Python +translation of the C-Code provided by NXP/Freescale for their i.MX RT series of +MCUs. Very little has been added, and just a few API related names were changed +or added to cope with the naming style of MicroPython. + +The primary purpose of the driver is initialization and setting operation modes +of the codec. It does not do the audio data processing for the codec. That is +the task of a separate driver. + +The WM8960 supports an I2C interface, in addition to the audio interface. The +connection depends on the interface used and the number of devices in the +system. For the I2C interface, SCL and SDA have to be connected, and of course +GND and Vcc. The I2C default address is ``0x1A``. + +Constructor +----------- + +.. class:: WM8960(i2c, sample_rate, *, bits=16, swap=SWAP_NONE, route=ROUTE_PLAYBACK_RECORD, left_input=INPUT_MIC3, right_input=INPUT_MIC2, sysclk_source=SYSCLK_MCLK, mclk_freq=None, primary=False, adc_sync=SYNC_DAC, protocol=BUS_I2S, i2c_address=WM8960_I2C_ADDR) + + Create a WM8960 driver object, initialize the device with default settings and return the + WM8960 object. + + Only the first two arguments are mandatory. All others are optional. The arguments are: + + - *i2c* is the I2C bus object. + - *sample_rate* is the audio sample rate. Acceptable values are 8000, + 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 96000, 192000 + and 384000. Note that not every I2S hardware will support all values. + - *bits* is the number of bits per audio word. Acceptable value are 16, + 20, 24, and 32. + - *swap* swaps the left & right channel, if set; see below for options. + - *route* Setting the audio path in the codec; see below for options. + - *left_input* sets the audio source for the left input channel; + see below for options. + - *right_input* sets the audio source for the right input channel; + see below for options. + - *play_source* sets the audio target for the output audio; + see below for options. + - *sysclk_source* controls whether the internal master clock called + "sysclk" is directly taken from the MCLK input or derived from it + using an internal PLL. It is usually not required to change this. + - *mclk_freq* sets the mclk frequency applied to the MCLK pin of the + codec. If not set, default values are used. + - *primary* lets the WM8960 act as primary or secondary device. The + default setting is ``False``. When set to ``False``, + *sample_rate* and *bits* are controlled by the MCU. + - *adc_sync* sets which input is used for the ADC sync signal. + The default is using the DACLRC pin. + - *protocol* sets the communication protocol. The default is I2S. + See below for all options. + - *i2c_address* sets the I2C address of the WM8960, with default ``0x1A``. + + If *mclk_freq* is not set the following default values are used: + + - sysclk_source == SYSCLK_PLL: 11.2896 MHz for sample rates of 44100, + 22050 and 11015 Hz, and 12.288 Mhz for sample rates < 48000, otherwise + sample_rate * 256. + - sysclk_source == SYSCLK_MCLK: sample_rate * 256. + + If the MCLK signal is applied using, for example,. a separate oscillator, + it must be specified for proper operation. + +Tables of parameter constants +----------------------------- + +.. table:: **Swap Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SWAP_NONE + 1 SWAP_INPUT + 2 SWAP_OUTPUT + ===== ==== + +.. table:: **Protocol Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 2 BUS_I2S + 1 BUS_LEFT_JUSTIFIED + 0 BUS_RIGHT_JUSTIFIED + 3 BUS_PCMA + 19 BUS_PCMB + ===== ==== + +.. table:: **Input Source Parameter** + :widths: auto + :align: left + + ===== ============ ==== + Value Name Type + ===== ============ ==== + 0 INPUT_CLOSED + 1 INPUT_MIC1 Single ended + 2 INPUT_MIC2 Differential + 3 INPUT_MIC3 Differential + 4 INPUT_LINE2 + 5 INPUT_LINE3 + ===== ============ ==== + +.. table:: **Route Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 ROUTE_BYPASS + 1 ROUTE_PLAYBACK + 2 ROUTE_PLAYBACK_RECORD + 5 ROUTE_RECORD + ===== ==== + +.. table:: **Master Clock Source Parameter** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SYSCLK_MCLK + 1 SYSCLK_PLL + ===== ==== + +.. table:: **Module Names** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 MODULE_ADC + 1 MODULE_DAC + 2 MODULE_VREF + 3 MODULE_HEADPHONE + 4 MODULE_MIC_BIAS + 5 MODULE_MIC + 6 MODULE_LINE_IN + 7 MODULE_LINE_OUT + 8 MODULE_SPEAKER + 9 MODULE_OMIX + 10 MODULE_MONO_OUT + ===== ==== + +.. table:: **Play Channel Names** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 1 PLAY_HEADPHONE_LEFT + 2 PLAY_HEADPHONE_RIGHT + 4 PLAY_SPEAKER_LEFT + 8 PLAY_SPEAKER_RIGHT + ===== ==== + +.. table:: **adc_sync Parameters** + :widths: auto + :align: left + + ===== ==== + Value Name + ===== ==== + 0 SYNC_ADC + 1 SYNC_DAC + ===== ==== + + +Methods +------- + +In addition to initialization, the driver provides some useful methods for +controlling its operation: + +.. method:: WM8960.set_left_input(input_source) + + Specify the source for the left input. The input source names are listed above. + +.. method:: WM8960.set_right_input(input_source) + + Specify the source for the right input. The input source names are listed above. + +.. method:: WM8960.volume(module, volume_l=None, volume_r=None) + + Sets or gets the volume of a certain module. + + If no volume values are supplied, the actual volume tuple is returned. + + If one or two values are supplied, it sets the volume of a certain module. + If two values are provided, the first one is used for the left channel, + the second for the right channel. If only one value is supplied, it is used + for both channels. The value range is normalized to 0.0-100.0 with a + logarithmic scale. + + For a list of suitable modules and db/step, see the table below. + +.. table:: **Module Names and dB steps** + :widths: auto + :align: center + + ======= ==== + dB/Step Name + ======= ==== + 1.28 MODULE_ADC + 1.28 MODULE_DAC + 0.8 MODULE_HEADPHONE + 0.475 MODULE_LINE_IN + 0.8 MODULE_SPEAKER + ======= ==== + +.. method:: WM8960.mute(module, mute, soft=True, ramp=wm8960.MUTE_FAST) + + Mute or unmute the output. If *mute* is True, the output is muted, if ``False`` + it is unmuted. + + If *soft* is set as True, muting will happen as a soft transition. The time for + the transition is defined by *ramp*, which is either ``MUTE_FAST`` or ``MUTE_SLOW``. + +.. method:: WM8960.set_data_route(route) + + Set the audio data route. For the parameter value/names, see the table above. + +.. method:: WM8960.set_module(module, active) + + Enable or disable a module, with *active* being ``False`` or ``True``. For + the list of module names, see the table above. + + Note that enabling ``MODULE_MONO_OUT`` is different from the `WM8960.mono` + method. The first enables output 3, while the `WM8960.mono` method sends a + mono mix to the left and right output. + +.. method:: WM8960.enable_module(module) + + Enable a module. For the list of module names, see the table above. + +.. method:: WM8960.disable_module(module) + + Disable a module. For the list of module names, see the table above. + +.. method:: WM8960.expand_3d(level) + + Enable Stereo 3D exansion. *level* is a number between 0 and 15. + A value of 0 disables the expansion. + +.. method:: WM8960.mono(active) + + If *active* is ``True``, a Mono mix is sent to the left and right output + channel. This is different from enabling the ``MODULE_MONO_MIX``, which + enables output 3. + +.. method:: WM8960.alc_mode(channel, mode=ALC_MODE) + + Enables or disables ALC mode. Parameters are: + + - *channel* enables and sets the channel for ALC. The parameter values are: + + - ALC_OFF: Switch ALC off + - ALS_RIGHT: Use the right input channel + - ALC_LEFT: Use the left input channel + - ALC_STEREO: Use both input channels. + + - *mode* sets the ALC mode. Input values are: + + - ALC_MODE: act as ALC + - ALC_LIMITER: act as limiter. + +.. method:: WM8960.alc_gain(target=-12, max_gain=30, min_gain=-17.25, noise_gate=-78) + + Set the target level, highest and lowest gain levels and the noise gate as dB level. + Permitted ranges are: + + - *target*: -22.5 to -1.5 dB + - *max_gain*: -12 to 30 dB + - *min_gain*: -17 to 25 dB + - *noise_gate*: -78 to -30 dB + + Excess values are limited to the permitted ranges. A value of -78 or less + for *noise_gate* disables the noise gate function. + +.. method:: WM8960.alc_time(attack=24, decay=192, hold=0) + + Set the dynamic characteristic of ALC. The times are given as millisecond + values. Permitted ranges are: + + - *attack*: 6 to 6140 + - *decay*: 24 to 24580 + - *hold*: 0 to 43000 + + Excess values are limited within the permitted ranges. + +.. method:: WM8960.deemphasis(active) + + Enables or disables a deemphasis filter for playback, with *active* being + ``False`` or ``True``. This filter is applied only for sample rates of + 32000, 44100 and 48000. For other sample rates, the filter setting + is silently ignored. + +.. method:: WM8960.deinit() + + Disable all modules. + + +Examples +-------- + +Run WM8960 in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Slave mode using the default settings + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, 32000, left_input=wm8960.INPUT_MIC1) + wm.set_volume(wm8960.MODULE_HEADPHONE, 100) + + +Run WM8960 in primary mode:: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Master mode using specific audio format settings + # + from machine import Pin, I2C + import wm8960 + + i2c = I2C(0) + wm=wm8960.WM8960(i2c, 44100, primary=True, bits=16) + + +Run WM8960 on a MIMXRT10xx_DEV board in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # Setting the driver to Slave mode using the default settings + # swap the input channels such that a MIMXRT Dev board mic, which + # is connected to the right input, is assigned to the left audio channel. + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, sample_rate=16_000, + adc_sync=wm8960.SYNC_DAC, + swap=wm8960.SWAP_INPUT, + sysclk_source=wm8960.SYSCLK_MCLK) + + +Record with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):: + + # Micro_python WM8960 Codec driver + # + # The breakout board uses a fixed 24MHz MCLK. Therefore the internal + # PLL must be used as sysclk, which is the master audio clock. + # The Sparkfun board has the WS pins for RX and TX connected on the + # board. Therefore adc_sync must be set to sync_adc, to configure + # it's ADCLRC pin as input. + # + from machine import Pin, I2C + import wm8960 + i2c = I2C(0) + wm=wm8960.WM8960(i2c, sample_rate=16_000, + adc_sync=wm8960.SYNC_ADC, + sysclk_source=wm8960.SYSCLK_PLL, + mclk_freq=24_000_000, + left_input=wm8960.INPUT_MIC1, + right_input=wm8960.INPUT_CLOSED) + + +Play with a Sparkfun WM8960 breakout board with Teensy in secondary mode (default):: + + # The breakout board uses a fixed 24MHz MCLK. Therefore the internal + # PLL must be used as sysclk, which is the master audio clock. + # The Sparkfun board has the WS pins for RX and TX connected on the + # board. Therefore adc_sync must be set to sync_adc, to configure + # it's ADCLRC pin as input. + + from machine import I2C + i2c=I2C(0) + import wm8960 + wm=wm8960.WM8960(i2c, sample_rate=44_100, + adc_sync=wm8960.SYNC_ADC, + sysclk_source=wm8960.SYSCLK_PLL, + mclk_freq=24_000_000) + wm.set_volume(wm8960.MODULE_HEADPHONE, 100) |
