Compare commits
19 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c7d358468 | ||
|
|
0063bdc27e | ||
|
|
49f95b2a6a | ||
|
|
bc20f0b3c0 | ||
|
|
81c00085ec | ||
|
|
bd24ba5e46 | ||
|
|
12d09409be | ||
|
|
522f615ffe | ||
|
|
76d1cad3f4 | ||
|
|
e1f10ab7df | ||
|
|
5e076772c1 | ||
|
|
f694d14682 | ||
|
|
71294d0145 | ||
|
|
f24788d94a | ||
|
|
1fa7603d77 | ||
|
|
ef1cc7633f | ||
|
|
995ae32c2a | ||
|
|
588bcfecff | ||
|
|
1c7a72dd05 |
8 changed files with 899 additions and 288 deletions
14
README.rst
14
README.rst
|
|
@ -94,9 +94,17 @@ Usage Example
|
||||||
import audiobusio
|
import audiobusio
|
||||||
import audiocore
|
import audiocore
|
||||||
import board
|
import board
|
||||||
|
import digitalio
|
||||||
|
|
||||||
import adafruit_tlv320
|
import adafruit_tlv320
|
||||||
|
|
||||||
|
# Reset the DAC before use
|
||||||
|
reset_pin = digitalio.DigitalInOut(board.D12)
|
||||||
|
reset_pin.direction = digitalio.Direction.OUTPUT
|
||||||
|
reset_pin.value = False # Set low to reset
|
||||||
|
time.sleep(0.1) # Pause 100ms
|
||||||
|
reset_pin.value = True # Set high to release from reset
|
||||||
|
|
||||||
i2c = board.I2C()
|
i2c = board.I2C()
|
||||||
dac = adafruit_tlv320.TLV320DAC3100(i2c)
|
dac = adafruit_tlv320.TLV320DAC3100(i2c)
|
||||||
|
|
||||||
|
|
@ -106,11 +114,7 @@ Usage Example
|
||||||
# use headphones
|
# use headphones
|
||||||
# helper function for default settings
|
# helper function for default settings
|
||||||
dac.headphone_output = True
|
dac.headphone_output = True
|
||||||
dac.headphone_volume = -20 # dB
|
dac.dac_volume = -20 # dB
|
||||||
# or use speaker
|
|
||||||
# helper function for default settings
|
|
||||||
# dac.speaker_output = True
|
|
||||||
# dac.speaker_volume = -15 # dB
|
|
||||||
|
|
||||||
audio = audiobusio.I2SOut(board.I2S_BCLK, board.I2S_WS, board.I2S_DIN)
|
audio = audiobusio.I2SOut(board.I2S_BCLK, board.I2S_WS, board.I2S_DIN)
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
8
docs/_static/custom.css
vendored
Normal file
8
docs/_static/custom.css
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
/* SPDX-FileCopyrightText: 2025 Sam Blenny
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Monkey patch the rtd theme to prevent horizontal stacking of short items
|
||||||
|
* see https://github.com/readthedocs/sphinx_rtd_theme/issues/1301
|
||||||
|
*/
|
||||||
|
.py.property{display: block !important;}
|
||||||
|
|
@ -29,6 +29,9 @@ autodoc_mock_imports = ["digitalio", "busio", "adafruit_bus_device", "micropytho
|
||||||
|
|
||||||
autodoc_preserve_defaults = True
|
autodoc_preserve_defaults = True
|
||||||
|
|
||||||
|
# Override the default config in which autodoc sorts things alphabetically
|
||||||
|
autodoc_member_order = "groupwise"
|
||||||
|
|
||||||
intersphinx_mapping = {
|
intersphinx_mapping = {
|
||||||
"python": ("https://docs.python.org/3", None),
|
"python": ("https://docs.python.org/3", None),
|
||||||
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
|
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
|
||||||
|
|
@ -117,6 +120,9 @@ html_theme = "sphinx_rtd_theme"
|
||||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
html_static_path = ["_static"]
|
html_static_path = ["_static"]
|
||||||
|
|
||||||
|
# Include extra css to work around rtd theme glitches
|
||||||
|
html_css_files = ["custom.css"]
|
||||||
|
|
||||||
# The name of an image file (relative to this directory) to use as a favicon of
|
# The name of an image file (relative to this directory) to use as a favicon of
|
||||||
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
# pixels large.
|
# pixels large.
|
||||||
|
|
|
||||||
|
|
@ -15,3 +15,12 @@ Demos advanced features of the library.
|
||||||
.. literalinclude:: ../examples/tlv320_fulltest.py
|
.. literalinclude:: ../examples/tlv320_fulltest.py
|
||||||
:caption: examples/tlv320_fulltest.py
|
:caption: examples/tlv320_fulltest.py
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
Volume test
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Test tone generator with interactive serial console volume controls
|
||||||
|
|
||||||
|
.. literalinclude:: ../examples/tlv320_volumetest.py
|
||||||
|
:caption: examples/tlv320_volumetest.py
|
||||||
|
:linenos:
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ in simpletest.
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import board
|
import board
|
||||||
|
import digitalio
|
||||||
|
|
||||||
from adafruit_tlv320 import (
|
from adafruit_tlv320 import (
|
||||||
DAC_PATH_MIXED,
|
DAC_PATH_MIXED,
|
||||||
|
|
@ -41,6 +42,13 @@ from adafruit_tlv320 import (
|
||||||
VOL_RIGHT_TO_LEFT,
|
VOL_RIGHT_TO_LEFT,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Reset the DAC before use
|
||||||
|
reset_pin = digitalio.DigitalInOut(board.D12)
|
||||||
|
reset_pin.direction = digitalio.Direction.OUTPUT
|
||||||
|
reset_pin.value = False # Set low to reset
|
||||||
|
time.sleep(0.1) # Pause 100ms
|
||||||
|
reset_pin.value = True # Set high to release from reset
|
||||||
|
|
||||||
print("Initializing I2C and TLV320DAC3100...")
|
print("Initializing I2C and TLV320DAC3100...")
|
||||||
i2c = board.I2C()
|
i2c = board.I2C()
|
||||||
dac = TLV320DAC3100(i2c)
|
dac = TLV320DAC3100(i2c)
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,17 @@ import time
|
||||||
import audiobusio
|
import audiobusio
|
||||||
import audiocore
|
import audiocore
|
||||||
import board
|
import board
|
||||||
|
import digitalio
|
||||||
|
|
||||||
import adafruit_tlv320
|
import adafruit_tlv320
|
||||||
|
|
||||||
|
# Reset the DAC before use
|
||||||
|
reset_pin = digitalio.DigitalInOut(board.D12)
|
||||||
|
reset_pin.direction = digitalio.Direction.OUTPUT
|
||||||
|
reset_pin.value = False # Set low to reset
|
||||||
|
time.sleep(0.1) # Pause 100ms
|
||||||
|
reset_pin.value = True # Set high to release from reset
|
||||||
|
|
||||||
i2c = board.I2C()
|
i2c = board.I2C()
|
||||||
dac = adafruit_tlv320.TLV320DAC3100(i2c)
|
dac = adafruit_tlv320.TLV320DAC3100(i2c)
|
||||||
|
|
||||||
|
|
@ -20,7 +28,7 @@ dac.configure_clocks(sample_rate=44100, bit_depth=16)
|
||||||
|
|
||||||
# use headphones
|
# use headphones
|
||||||
dac.headphone_output = True
|
dac.headphone_output = True
|
||||||
dac.headphone_volume = -15 # dB
|
dac.dac_volume = -10 # dB
|
||||||
# or use speaker
|
# or use speaker
|
||||||
# dac.speaker_output = True
|
# dac.speaker_output = True
|
||||||
# dac.speaker_volume = -20 # dB
|
# dac.speaker_volume = -20 # dB
|
||||||
|
|
|
||||||
171
examples/tlv320_volumetest.py
Normal file
171
examples/tlv320_volumetest.py
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2025 Sam Blenny
|
||||||
|
#
|
||||||
|
import gc
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
import displayio
|
||||||
|
import supervisor
|
||||||
|
import synthio
|
||||||
|
from audiobusio import I2SOut
|
||||||
|
from board import I2C, I2S_BCLK, I2S_DIN, I2S_MCLK, I2S_WS, PERIPH_RESET
|
||||||
|
from digitalio import DigitalInOut, Direction, Pull
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
from adafruit_tlv320 import TLV320DAC3100
|
||||||
|
|
||||||
|
# DAC and Synthesis parameters
|
||||||
|
SAMPLE_RATE = const(11025)
|
||||||
|
CHAN_COUNT = const(2)
|
||||||
|
BUFFER_SIZE = const(1024)
|
||||||
|
|
||||||
|
# DAC volume limits
|
||||||
|
DV_MIN = -63.5
|
||||||
|
DV_MAX = 24.0
|
||||||
|
|
||||||
|
# Headphone volume limits
|
||||||
|
HV_MIN = -78.3
|
||||||
|
HV_MAX = 0
|
||||||
|
|
||||||
|
# Headphone gain limits
|
||||||
|
HG_MIN = 0
|
||||||
|
HG_MAX = 9
|
||||||
|
|
||||||
|
# Speaker volume limits
|
||||||
|
SV_MIN = -78.3
|
||||||
|
SV_MAX = 0
|
||||||
|
|
||||||
|
# Speaker amp gain limits
|
||||||
|
SG_MIN = 6
|
||||||
|
SG_MAX = 24
|
||||||
|
SG_STEP = 6
|
||||||
|
|
||||||
|
|
||||||
|
def init_dac_audio_synth(i2c):
|
||||||
|
"""Configure TLV320 I2S DAC for audio output and make a Synthesizer.
|
||||||
|
|
||||||
|
:param i2c: a reference to board.I2C()
|
||||||
|
:return: tuple(dac: TLV320DAC3100, audio: I2SOut, synth: Synthesizer)
|
||||||
|
"""
|
||||||
|
# 1. Reset DAC (reset is active low)
|
||||||
|
rst = DigitalInOut(PERIPH_RESET)
|
||||||
|
rst.direction = Direction.OUTPUT
|
||||||
|
rst.value = False
|
||||||
|
time.sleep(0.1)
|
||||||
|
rst.value = True
|
||||||
|
time.sleep(0.05)
|
||||||
|
# 2. Configure sample rate, bit depth, and output port
|
||||||
|
dac = TLV320DAC3100(i2c)
|
||||||
|
dac.configure_clocks(sample_rate=SAMPLE_RATE, bit_depth=16)
|
||||||
|
dac.speaker_output = True
|
||||||
|
dac.headphone_output = True
|
||||||
|
# 4. Initialize I2S for Fruit Jam rev D
|
||||||
|
audio = I2SOut(bit_clock=I2S_BCLK, word_select=I2S_WS, data=I2S_DIN)
|
||||||
|
# 5. Configure synthio patch to generate audio
|
||||||
|
vca = synthio.Envelope(
|
||||||
|
attack_time=0, decay_time=0, sustain_level=1.0, release_time=0, attack_level=1.0
|
||||||
|
)
|
||||||
|
synth = synthio.Synthesizer(sample_rate=SAMPLE_RATE, channel_count=CHAN_COUNT, envelope=vca)
|
||||||
|
return (dac, audio, synth)
|
||||||
|
|
||||||
|
|
||||||
|
def main(): # noqa: PLR0912, PLR0915, allow long function and long if statement
|
||||||
|
# Turn off the default DVI display to free up CPU
|
||||||
|
displayio.release_displays()
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
# Set up the audio stuff for a basic synthesizer
|
||||||
|
i2c = I2C()
|
||||||
|
(dac, audio, synth) = init_dac_audio_synth(i2c)
|
||||||
|
audio.play(synth)
|
||||||
|
|
||||||
|
dv = dac.dac_volume # default DAC volume
|
||||||
|
hv = dac.headphone_volume # default headphone analog volume
|
||||||
|
hg = dac.headphone_left_gain # default headphone amp gain
|
||||||
|
sv = dac.speaker_volume # default speaker analog volume
|
||||||
|
sg = dac.speaker_gain # default speaker amp gain
|
||||||
|
note = 60
|
||||||
|
synth.press(note)
|
||||||
|
|
||||||
|
# Check for unbuffered keystroke input on the USB serial console
|
||||||
|
print("""
|
||||||
|
=== TLV320DAC Volume Tester ===
|
||||||
|
|
||||||
|
Controls:
|
||||||
|
q/z: dac_volume +/- 1
|
||||||
|
w/x: headphone_volume +/- 1
|
||||||
|
e/c: headphone_left_gain headphone_right_gain +/- 1
|
||||||
|
r/v: speaker_volume +/- 1
|
||||||
|
t/b: speaker_gain +/- 6
|
||||||
|
space: toggle speaker_output (amp power), this will reset volume & gain
|
||||||
|
|
||||||
|
For less headphone noise, turn off the speaker amp (spacebar)
|
||||||
|
""")
|
||||||
|
while True:
|
||||||
|
time.sleep(0.01)
|
||||||
|
if supervisor.runtime.serial_bytes_available:
|
||||||
|
while supervisor.runtime.serial_bytes_available:
|
||||||
|
c = sys.stdin.read(1)
|
||||||
|
if c == "q":
|
||||||
|
# Q = DAC Volume UP
|
||||||
|
dv = min(DV_MAX, max(DV_MIN, dv + 1))
|
||||||
|
dac.dac_volume = dv
|
||||||
|
print(f"dv = {dv:.1f} ({dac.dac_volume:.1f})")
|
||||||
|
elif c == "z":
|
||||||
|
# Z = DAC Volume DOWN
|
||||||
|
dv = min(DV_MAX, max(DV_MIN, dv - 1))
|
||||||
|
dac.dac_volume = dv
|
||||||
|
print(f"dv = {dv:.1f} ({dac.dac_volume:.1f})")
|
||||||
|
elif c == "w":
|
||||||
|
# W = Headphone Volume UP
|
||||||
|
hv = min(HV_MAX, max(HV_MIN, hv + 1))
|
||||||
|
dac.headphone_volume = hv
|
||||||
|
print(f"hv = {hv:.1f} ({dac.headphone_volume:.1f})")
|
||||||
|
elif c == "x":
|
||||||
|
# X = Headphone Volume DOWN
|
||||||
|
hv = min(HV_MAX, max(HV_MIN, hv - 1))
|
||||||
|
dac.headphone_volume = hv
|
||||||
|
print(f"hv = {hv:.1f} ({dac.headphone_volume:.1f})")
|
||||||
|
elif c == "e":
|
||||||
|
# E = Headphone Amp Gain UP
|
||||||
|
hg = min(HG_MAX, max(HG_MIN, hg + 1))
|
||||||
|
dac.headphone_left_gain = hg
|
||||||
|
dac.headphone_right_gain = hg
|
||||||
|
print(f"hg = {hg:.1f} ({dac.headphone_left_gain})")
|
||||||
|
elif c == "c":
|
||||||
|
# C = Headphone Amp Gain DOWN
|
||||||
|
hg = min(HG_MAX, max(HG_MIN, hg - 1))
|
||||||
|
dac.headphone_left_gain = hg
|
||||||
|
dac.headphone_right_gain = hg
|
||||||
|
print(f"hg = {hg:.1f} ({dac.headphone_left_gain})")
|
||||||
|
|
||||||
|
if c == "r":
|
||||||
|
# R = Speaker Volume UP
|
||||||
|
sv = min(SV_MAX, max(SV_MIN, sv + 1))
|
||||||
|
dac.speaker_volume = sv
|
||||||
|
print(f"sv = {sv:.1f} ({dac.speaker_volume:.1f})")
|
||||||
|
elif c == "v":
|
||||||
|
# V = Speaker Volume DOWN
|
||||||
|
sv = min(SV_MAX, max(SV_MIN, sv - 1))
|
||||||
|
dac.speaker_volume = sv
|
||||||
|
print(f"sv = {sv:.1f} ({dac.speaker_volume:.1f})")
|
||||||
|
elif c == "t":
|
||||||
|
# T = Speaker Amp Gain UP
|
||||||
|
sg = min(SG_MAX, max(SG_MIN, sg + SG_STEP))
|
||||||
|
dac.speaker_gain = sg
|
||||||
|
print(f"sg = {sg:.1f} ({dac.speaker_gain})")
|
||||||
|
elif c == "b":
|
||||||
|
# B = Speaker Amp Gain DOWN
|
||||||
|
sg = min(SG_MAX, max(SG_MIN, sg - SG_STEP))
|
||||||
|
dac.speaker_gain = sg
|
||||||
|
print(f"sg = {sg:.1f} ({dac.speaker_gain})")
|
||||||
|
elif c == " ":
|
||||||
|
# Space = Toggle speaker amp enable/disable
|
||||||
|
en = not dac.speaker_output
|
||||||
|
dac.speaker_output = en
|
||||||
|
print(f"speaker_output = {en}")
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
Loading…
Reference in a new issue