Simple test
Ensure your device works with this simple test.
examples/tlv320_simpletest.py
1# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
2#
3# SPDX-License-Identifier: MIT
4
5import array
6import math
7import time
8
9import audiobusio
10import audiocore
11import board
12import digitalio
13
14import adafruit_tlv320
15
16# Reset the DAC before use
17reset_pin = digitalio.DigitalInOut(board.D12)
18reset_pin.direction = digitalio.Direction.OUTPUT
19reset_pin.value = False # Set low to reset
20time.sleep(0.1) # Pause 100ms
21reset_pin.value = True # Set high to release from reset
22
23i2c = board.I2C()
24dac = adafruit_tlv320.TLV320DAC3100(i2c)
25
26# set sample rate & bit depth, use bclk
27dac.configure_clocks(sample_rate=44100, bit_depth=16)
28
29# use headphones
30dac.headphone_output = True
31dac.dac_volume = -10 # dB
32# or use speaker
33# dac.speaker_output = True
34# dac.speaker_volume = -20 # dB
35
36if "I2S_BCLK" and "I2S_WS" in dir(board):
37 audio = audiobusio.I2SOut(board.I2S_BCLK, board.I2S_WS, board.I2S_DIN)
38else:
39 audio = audiobusio.I2SOut(board.D9, board.D10, board.D11)
40# generate a sine wave
41tone_volume = 0.5
42frequency = 440
43sample_rate = dac.sample_rate
44length = sample_rate // frequency
45sine_wave = array.array("h", [0] * length)
46for i in range(length):
47 sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * tone_volume * (2**15 - 1))
48sine_wave_sample = audiocore.RawSample(sine_wave, sample_rate=sample_rate)
49
50while True:
51 audio.stop()
52 time.sleep(1)
53 audio.play(sine_wave_sample, loop=True)
54 time.sleep(1)
Full test
Demos advanced features of the library.
examples/tlv320_fulltest.py
1# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
2#
3# SPDX-License-Identifier: MIT
4
5"""
6Full TLV320DAC3100 Test
7Demo all features in the library
8Shows advanced control for DAC, headphone and speaker
9beyond basic headphone_output & speaker_output helpers
10in simpletest.
11"""
12
13import time
14
15import board
16import digitalio
17
18from adafruit_tlv320 import (
19 DAC_PATH_MIXED,
20 DAC_PATH_NORMAL,
21 DAC_PATH_OFF,
22 DAC_PATH_SWAPPED,
23 DAC_ROUTE_HP,
24 DAC_ROUTE_MIXER,
25 DAC_ROUTE_NONE,
26 GPIO1_CLKOUT,
27 GPIO1_DISABLED,
28 GPIO1_GPI,
29 GPIO1_GPO,
30 GPIO1_INPUT_MODE,
31 HP_COMMON_1_35V,
32 HP_COMMON_1_50V,
33 HP_COMMON_1_65V,
34 HP_COMMON_1_80V,
35 SPK_GAIN_6DB,
36 SPK_GAIN_12DB,
37 SPK_GAIN_18DB,
38 SPK_GAIN_24DB,
39 TLV320DAC3100,
40 VOL_INDEPENDENT,
41 VOL_LEFT_TO_RIGHT,
42 VOL_RIGHT_TO_LEFT,
43)
44
45# Reset the DAC before use
46reset_pin = digitalio.DigitalInOut(board.D12)
47reset_pin.direction = digitalio.Direction.OUTPUT
48reset_pin.value = False # Set low to reset
49time.sleep(0.1) # Pause 100ms
50reset_pin.value = True # Set high to release from reset
51
52print("Initializing I2C and TLV320DAC3100...")
53i2c = board.I2C()
54dac = TLV320DAC3100(i2c)
55
56# Display basic information
57print("\n=== Basic Information ===")
58print(f"Sample rate: {dac.sample_rate} Hz")
59print(f"Bit depth: {dac.bit_depth}-bit")
60print(f"Overtemperature condition: {dac.overtemperature}")
61
62# I2S Config
63dac.configure_clocks(sample_rate=44000, bit_depth=16)
64print(f"Sample rate: {dac.sample_rate} Hz")
65print(f"Bit depth: {dac.bit_depth}-bit")
66time.sleep(0.2)
67
68# Headphone Output Setup
69print("\n=== Headphone Output Setup ===")
70print("Setting up headphone output...")
71dac.headphone_output = True # This conveniently sets up multiple parameters
72print(f"Headphone output enabled: {dac.headphone_output}")
73
74# Adjust headphone volume (in dB where 0dB is max, negative values reduce volume)
75print("\nAdjusting headphone volume...")
76print(f"Current headphone volume: {dac.headphone_volume} dB")
77dac.headphone_volume = -10 # Set to -10 dB (moderate volume)
78print(f"New headphone volume: {dac.headphone_volume} dB")
79
80# Fine-tune left and right channels individually
81print("\nAdjusting left and right headphone gain...")
82print(f"Left headphone gain: {dac.headphone_left_gain}")
83print(f"Right headphone gain: {dac.headphone_right_gain}")
84dac.headphone_left_gain = 3 # Increase left channel gain
85dac.headphone_right_gain = 3 # Increase right channel gain
86print(f"New left headphone gain: {dac.headphone_left_gain}")
87print(f"New right headphone gain: {dac.headphone_right_gain}")
88
89# Mute/unmute the headphones
90print("\nDemonstrating headphone mute functionality...")
91print(f"Left headphone muted: {dac.headphone_left_mute}")
92print(f"Right headphone muted: {dac.headphone_right_mute}")
93dac.headphone_left_mute = True # Mute left channel
94dac.headphone_right_mute = False # Ensure right channel is unmuted
95print(f"Left headphone now muted: {dac.headphone_left_mute}")
96print(f"Right headphone still unmuted: {dac.headphone_right_mute}")
97time.sleep(1) # Listen to right channel only
98dac.headphone_left_mute = False # Unmute left channel
99print(f"Left headphone now unmuted: {dac.headphone_left_mute}")
100dac.headphone_output = False # turn off before speaker test
101
102# Speaker Output Setup
103print("\n=== Speaker Output Setup ===")
104print("Setting up speaker output...")
105dac.speaker_output = True # This conveniently sets up multiple parameters
106print(f"Speaker output enabled: {dac.speaker_output}")
107
108# Adjust speaker volume (in dB where 0dB is max, negative values reduce volume)
109print("\nAdjusting speaker volume...")
110print(f"Current speaker volume: {dac.speaker_volume} dB")
111dac.speaker_volume = -6 # Set to -6 dB (louder than headphones)
112print(f"New speaker volume: {dac.speaker_volume} dB")
113
114# Set speaker amplifier gain
115print("\nAdjusting speaker gain...")
116print(f"Current speaker gain: {dac.speaker_gain}")
117dac.speaker_gain = SPK_GAIN_12DB # 12dB amplification
118print(f"New speaker gain: {dac.speaker_gain}")
119
120# Mute/unmute the speaker
121print("\nDemonstrating speaker mute functionality...")
122print(f"Speaker muted: {dac.speaker_mute}")
123dac.speaker_mute = True # Mute speaker
124print(f"Speaker now muted: {dac.speaker_mute}")
125time.sleep(1)
126dac.speaker_mute = False # Unmute speaker
127print(f"Speaker now unmuted: {dac.speaker_mute}")
128
129# DAC Signal Routing
130print("\n=== Advanced DAC Signal Routing ===")
131print("\nCurrent DAC Status:")
132print(f"Left DAC enabled: {dac.left_dac}")
133print(f"Right DAC enabled: {dac.right_dac}")
134print(f"Left DAC path: {dac.left_dac_path}")
135print(f"Right DAC path: {dac.right_dac_path}")
136
137print("\nSetting up swapped stereo (left and right channels swapped)...")
138dac.left_dac_path = DAC_PATH_SWAPPED
139dac.right_dac_path = DAC_PATH_SWAPPED
140print(f"New left DAC path: {dac.left_dac_path}")
141print(f"New right DAC path: {dac.right_dac_path}")
142
143print("\nSetting up mono output (mixed left and right channels)...")
144dac.left_dac_path = DAC_PATH_MIXED
145dac.right_dac_path = DAC_PATH_MIXED
146print(f"New left DAC path: {dac.left_dac_path}")
147print(f"New right DAC path: {dac.right_dac_path}")
148
149print("\nRestoring normal stereo...")
150dac.left_dac_path = DAC_PATH_NORMAL
151dac.right_dac_path = DAC_PATH_NORMAL
152print(f"New left DAC path: {dac.left_dac_path}")
153print(f"New right DAC path: {dac.right_dac_path}")
154
155# DAC Volume Controls
156print("\n=== DAC Volume Control Configuration ===")
157print(f"Left DAC muted: {dac.left_dac_mute}")
158print(f"Right DAC muted: {dac.right_dac_mute}")
159print(f"Volume control mode: {dac.dac_volume_control_mode}")
160
161print("\nSetting volume control mode where left channel controls right...")
162dac.dac_volume_control_mode = VOL_LEFT_TO_RIGHT
163print(f"New volume control mode: {dac.dac_volume_control_mode}")
164
165print("\nSetting independent volume control mode (default)...")
166dac.dac_volume_control_mode = VOL_INDEPENDENT
167print(f"New volume control mode: {dac.dac_volume_control_mode}")
168
169# DAC Channel Volume
170print("\n=== DAC Channel Volume ===")
171print(f"Left DAC channel volume: {dac.left_dac_channel_volume} dB")
172print(f"Right DAC channel volume: {dac.right_dac_channel_volume} dB")
173
174print("\nSetting different volumes for left and right channels...")
175dac.left_dac_channel_volume = -3
176dac.right_dac_channel_volume = -9
177print(f"New left DAC channel volume: {dac.left_dac_channel_volume} dB")
178print(f"New right DAC channel volume: {dac.right_dac_channel_volume} dB")
179
180# Headphone as Line-Out
181print("\n=== Configure Headphone as Line-Out ===")
182print(f"Headphone configured as line-out: {dac.headphone_lineout}")
183
184# Safety Features
185print("\n=== Safety Features ===")
186print(f"Reset speaker on short circuit: {dac.reset_speaker_on_scd}")
187print(f"Reset headphone on short circuit: {dac.reset_headphone_on_scd}")
188
189# Getting status flags
190print("\n=== Status Information ===")
191flags = dac.dac_flags
192print(f"Left DAC powered: {flags['left_dac_powered']}")
193print(f"Right DAC powered: {flags['right_dac_powered']}")
194print(f"Headphone left (HPL) powered: {flags['hpl_powered']}")
195print(f"Headphone right (HPR) powered: {flags['hpr_powered']}")
196print(f"Left Class-D amplifier powered: {flags['left_classd_powered']}")
197print(f"Right Class-D amplifier powered: {flags['right_classd_powered']}")
198print(f"Left PGA gain OK: {flags['left_pga_gain_ok']}")
199print(f"Right PGA gain OK: {flags['right_pga_gain_ok']}")
200
201# Additional status checks via dedicated properties
202print("\nStatus via dedicated properties:")
203print(f"Speaker shorted: {dac.speaker_shorted}")
204print(f"HPL gain fully applied: {dac.hpl_gain_applied}")
205print(f"HPR gain fully applied: {dac.hpr_gain_applied}")
206print(f"Speaker gain fully applied: {dac.speaker_gain_applied}")
207
208# Higher-level shortcut methods
209print("\n=== Using Higher-Level Shortcuts ===")
210print("Demonstrating on/off control of primary outputs:")
211
212print("\nTurning off headphone output...")
213dac.headphone_output = False
214print(f"Headphone output now: {dac.headphone_output}")
215
216print("\nTurning off speaker output...")
217dac.speaker_output = True
218print(f"Speaker output now: {dac.speaker_output}")
219
220print("\nSwapping outputs...")
221dac.speaker_output = False
222dac.headphone_output = True
223print(f"Headphone output now: {dac.headphone_output}")
224print(f"Speaker output now: {dac.speaker_output}")
225
226# Pop Removal Setting
227print("\n=== Headphone Pop Removal Settings ===")
228dac.configure_headphone_pop(
229 wait_for_powerdown=True, # Wait for amp powerdown before DAC powerdown
230 powerup_time=7, # Power-on time setting (0-11)
231 ramp_time=3, # Ramp-up step time (0-3)
232)
233print("Headphone pop removal configured")
234
235# External Settings (like GPIO)
236print("\n=== GPIO Configuration ===")
237print(f"Current GPIO1 mode: {dac.gpio1_mode}")
238dac.gpio1_mode = GPIO1_GPO # Set GPIO1 as general purpose output
239print(f"New GPIO1 mode: {dac.gpio1_mode}")
240dac.gpio1_mode = GPIO1_DISABLED # Disable GPIO1
241print(f"Disabled GPIO1 mode: {dac.gpio1_mode}")
242
243# Volume Control ADC
244print("\n=== Volume Control ADC ===")
245print(f"Volume ADC reading: {dac.vol_adc_db} dB")
246
247print("\nAll examples completed!")
Volume test
Test tone generator with interactive serial console volume controls.
examples/tlv320_volumetest.py
1# SPDX-License-Identifier: MIT
2# SPDX-FileCopyrightText: Copyright 2025 Sam Blenny
3#
4import gc
5import os
6import sys
7import time
8
9import displayio
10import supervisor
11import synthio
12from audiobusio import I2SOut
13from board import I2C, I2S_BCLK, I2S_DIN, I2S_MCLK, I2S_WS, PERIPH_RESET
14from digitalio import DigitalInOut, Direction, Pull
15from micropython import const
16
17from adafruit_tlv320 import TLV320DAC3100
18
19# DAC and Synthesis parameters
20SAMPLE_RATE = const(11025)
21CHAN_COUNT = const(2)
22BUFFER_SIZE = const(1024)
23
24# DAC volume limits
25DV_MIN = -63.5
26DV_MAX = 24.0
27
28# Headphone volume limits
29HV_MIN = -78.3
30HV_MAX = 0
31
32# Headphone gain limits
33HG_MIN = 0
34HG_MAX = 9
35
36# Speaker volume limits
37SV_MIN = -78.3
38SV_MAX = 0
39
40# Speaker amp gain limits
41SG_MIN = 6
42SG_MAX = 24
43SG_STEP = 6
44
45
46def init_dac_audio_synth(i2c):
47 """Configure TLV320 I2S DAC for audio output and make a Synthesizer.
48
49 :param i2c: a reference to board.I2C()
50 :return: tuple(dac: TLV320DAC3100, audio: I2SOut, synth: Synthesizer)
51 """
52 # 1. Reset DAC (reset is active low)
53 rst = DigitalInOut(PERIPH_RESET)
54 rst.direction = Direction.OUTPUT
55 rst.value = False
56 time.sleep(0.1)
57 rst.value = True
58 time.sleep(0.05)
59 # 2. Configure sample rate, bit depth, and output port
60 dac = TLV320DAC3100(i2c)
61 dac.configure_clocks(sample_rate=SAMPLE_RATE, bit_depth=16)
62 dac.speaker_output = True
63 dac.headphone_output = True
64 # 4. Initialize I2S for Fruit Jam rev D
65 audio = I2SOut(bit_clock=I2S_BCLK, word_select=I2S_WS, data=I2S_DIN)
66 # 5. Configure synthio patch to generate audio
67 vca = synthio.Envelope(
68 attack_time=0, decay_time=0, sustain_level=1.0, release_time=0, attack_level=1.0
69 )
70 synth = synthio.Synthesizer(sample_rate=SAMPLE_RATE, channel_count=CHAN_COUNT, envelope=vca)
71 return (dac, audio, synth)
72
73
74def main(): # noqa: PLR0912, PLR0915, allow long function and long if statement
75 # Turn off the default DVI display to free up CPU
76 displayio.release_displays()
77 gc.collect()
78
79 # Set up the audio stuff for a basic synthesizer
80 i2c = I2C()
81 (dac, audio, synth) = init_dac_audio_synth(i2c)
82 audio.play(synth)
83
84 dv = dac.dac_volume # default DAC volume
85 hv = dac.headphone_volume # default headphone analog volume
86 hg = dac.headphone_left_gain # default headphone amp gain
87 sv = dac.speaker_volume # default speaker analog volume
88 sg = dac.speaker_gain # default speaker amp gain
89 note = 60
90 synth.press(note)
91
92 # Check for unbuffered keystroke input on the USB serial console
93 print("""
94=== TLV320DAC Volume Tester ===
95
96Controls:
97 q/z: dac_volume +/- 1
98 w/x: headphone_volume +/- 1
99 e/c: headphone_left_gain headphone_right_gain +/- 1
100 r/v: speaker_volume +/- 1
101 t/b: speaker_gain +/- 6
102 space: toggle speaker_output (amp power), this will reset volume & gain
103
104For less headphone noise, turn off the speaker amp (spacebar)
105""")
106 while True:
107 time.sleep(0.01)
108 if supervisor.runtime.serial_bytes_available:
109 while supervisor.runtime.serial_bytes_available:
110 c = sys.stdin.read(1)
111 if c == "q":
112 # Q = DAC Volume UP
113 dv = min(DV_MAX, max(DV_MIN, dv + 1))
114 dac.dac_volume = dv
115 print(f"dv = {dv:.1f} ({dac.dac_volume:.1f})")
116 elif c == "z":
117 # Z = DAC Volume DOWN
118 dv = min(DV_MAX, max(DV_MIN, dv - 1))
119 dac.dac_volume = dv
120 print(f"dv = {dv:.1f} ({dac.dac_volume:.1f})")
121 elif c == "w":
122 # W = Headphone Volume UP
123 hv = min(HV_MAX, max(HV_MIN, hv + 1))
124 dac.headphone_volume = hv
125 print(f"hv = {hv:.1f} ({dac.headphone_volume:.1f})")
126 elif c == "x":
127 # X = Headphone Volume DOWN
128 hv = min(HV_MAX, max(HV_MIN, hv - 1))
129 dac.headphone_volume = hv
130 print(f"hv = {hv:.1f} ({dac.headphone_volume:.1f})")
131 elif c == "e":
132 # E = Headphone Amp Gain UP
133 hg = min(HG_MAX, max(HG_MIN, hg + 1))
134 dac.headphone_left_gain = hg
135 dac.headphone_right_gain = hg
136 print(f"hg = {hg:.1f} ({dac.headphone_left_gain})")
137 elif c == "c":
138 # C = Headphone Amp Gain DOWN
139 hg = min(HG_MAX, max(HG_MIN, hg - 1))
140 dac.headphone_left_gain = hg
141 dac.headphone_right_gain = hg
142 print(f"hg = {hg:.1f} ({dac.headphone_left_gain})")
143
144 if c == "r":
145 # R = Speaker Volume UP
146 sv = min(SV_MAX, max(SV_MIN, sv + 1))
147 dac.speaker_volume = sv
148 print(f"sv = {sv:.1f} ({dac.speaker_volume:.1f})")
149 elif c == "v":
150 # V = Speaker Volume DOWN
151 sv = min(SV_MAX, max(SV_MIN, sv - 1))
152 dac.speaker_volume = sv
153 print(f"sv = {sv:.1f} ({dac.speaker_volume:.1f})")
154 elif c == "t":
155 # T = Speaker Amp Gain UP
156 sg = min(SG_MAX, max(SG_MIN, sg + SG_STEP))
157 dac.speaker_gain = sg
158 print(f"sg = {sg:.1f} ({dac.speaker_gain})")
159 elif c == "b":
160 # B = Speaker Amp Gain DOWN
161 sg = min(SG_MAX, max(SG_MIN, sg - SG_STEP))
162 dac.speaker_gain = sg
163 print(f"sg = {sg:.1f} ({dac.speaker_gain})")
164 elif c == " ":
165 # Space = Toggle speaker amp enable/disable
166 en = not dac.speaker_output
167 dac.speaker_output = en
168 print(f"speaker_output = {en}")
169
170
171main()
Fruit Jam sample rates demo
Try different sample rates and PLL clocking options on a Fruit Jam board.
examples/sample_rates_demo.py
1# SPDX-License-Identifier: MIT
2# SPDX-FileCopyrightText: Copyright 2025 Sam Blenny
3#
4# WAV file beep demo for Fruit Jam (adjust pins as needed for other boards)
5#
6import time
7
8import audiocore
9from audiobusio import I2SOut
10from board import I2C, I2S_BCLK, I2S_DIN, I2S_MCLK, I2S_WS
11from digitalio import DigitalInOut, Direction, Pull
12from micropython import const
13from pwmio import PWMOut
14
15from adafruit_tlv320 import TLV320DAC3100
16
17# I2S MCLK clock frequency
18MCLK_HZ = const(15_000_000)
19
20
21def configure_dac(i2c, sample_rate, mclk_hz):
22 # Configure TLV320DAC.
23 # When mclk_hz is not None, you must provide a 15 MHz PWMOut clock to the
24 # DAC's MCLK pin.
25
26 # 1. Initialize DAC (this includes a soft reset and sets minimum volumes)
27 dac = TLV320DAC3100(i2c)
28
29 # 2. Configure headphone/speaker routing and volumes (order matters here)
30 #
31 # CAUTION: The TLV320 includes a DSP oversampling filter in the signal
32 # chain before the dac.dac_volume setting is applied. The filter may
33 # boost the gain of loud samples (near 0 dBfs) to the point that they
34 # clip and distort if you have dac.dac_volume set too high. To prevent
35 # clipping, it's best to set dac.dac_volume to no more than -3 or -6 dB.
36 # If you want more gain without distortion, you can turn up the analog
37 # headphone amplifiers with dac.headphone_volume. For line level, try
38 # dac.dac_volume = -3 and dac.headphone_volume = 0.
39 #
40 dac.speaker_output = False
41 dac.headphone_output = True
42 dac.dac_volume = -3 # Keep this below 0 to avoid DSP filter clipping
43 dac.headphone_volume = 0 # CAUTION! Line level. Too loud for headphones!
44
45 # 3. Configure the right PLL and CODEC settings for our sample rate
46 dac.configure_clocks(sample_rate=sample_rate, mclk_freq=MCLK_HZ)
47
48 # 4. Wait for power-on volume ramp-up to finish
49 time.sleep(0.35)
50 return dac
51
52
53# Set up I2C and I2S buses
54i2c = I2C()
55audio = I2SOut(bit_clock=I2S_BCLK, word_select=I2S_WS, data=I2S_DIN)
56
57# To hear how MCLK improves audio when even using PLL_CLKIN=BCLK, uncomment
58# the next line and comment out the `if mclk_hz_:` blocks in the loop below.
59# mclk_pwm = PWMOut(I2S_MCLK, frequency=MCLK_HZ, duty_cycle=2**15)
60
61# Loop through all the sample rate and clock source options
62mclk_rates = (
63 (8000, "sinewave_8kHz.wav", 2), # 8000 gets 2 beeps
64 (11025, "sinewave_11kHz.wav", 3), # 11025 gets 3 beeps
65 (22050, "sinewave_22kHz.wav", 4), # 4 beeps
66 (44100, "sinewave_44kHz.wav", 5), # ...
67 (48000, "sinewave_48kHz.wav", 6),
68)
69while True:
70 # First do MCLK = 15 MHz, then do MCLK = None (meaning use BCLK)
71 for mclk_hz_ in (MCLK_HZ, None):
72 if mclk_hz_:
73 # Set up 15 MHz MCLK PWM clock output for less hiss and distortion
74 mclk_pwm = PWMOut(I2S_MCLK, frequency=MCLK_HZ, duty_cycle=2**15)
75
76 # Play beeps at all supported sample rates
77 print(f"Using MCLK = {mclk_hz_}:")
78 for (
79 sample_rate,
80 filename,
81 beeps,
82 ) in mclk_rates:
83 # Reset and re-configure DAC for the current sample rate
84 dac = configure_dac(i2c, sample_rate, mclk_hz_)
85
86 # Load wav file with 650 Hz beep at this sample rate
87 sample = audiocore.WaveFile(filename)
88
89 # Play beeps
90 print(f" sample rate {sample_rate} Hz: {beeps} beeps...")
91 for _ in range(beeps):
92 audio.play(sample)
93 time.sleep(0.19)
94
95 # Pause before switching to next sample rate
96 time.sleep(0.7)
97
98 # Mute before next loop iteration resets DAC (reduce popping noise)
99 dac.headphone_left_mute = True
100 dac.headphone_right_mute = True
101 time.sleep(0.1)
102
103 if mclk_hz_:
104 # When switching to BCLK, stop sending the PWM clock signal to MCLK
105 mclk_pwm.deinit()
106
107 # Pause before next clock source
108 time.sleep(0.8)
109
110 # Pause before starting over
111 print()
112 time.sleep(3)