summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorrobert-hh <robert@hammelrath.com>2022-02-10 13:51:48 +0100
committerDamien George <damien@micropython.org>2022-04-04 16:31:17 +1000
commit56b331ace6b7f01bacdb8b5c66f0f517670abfdc (patch)
treed1a1d1bd2d80ed1a7608fc2db0b73e15ab4aae7c /docs
parent7a447e08b23f47fac6ebcbe5d60c4e1d0fe0d157 (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')
-rw-r--r--docs/library/index.rst7
-rw-r--r--docs/library/machine.I2S.rst7
-rw-r--r--docs/library/wm8960.rst397
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)